001package gudusoft.gsqlparser.sqlenv; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.EExpressionType; 005import gudusoft.gsqlparser.TCustomSqlStatement; 006import gudusoft.gsqlparser.TGSqlParser; 007import gudusoft.gsqlparser.dlineage.util.DlineageUtil; 008import gudusoft.gsqlparser.dlineage.util.Pair3; 009import gudusoft.gsqlparser.nodes.TColumnDefinition; 010import gudusoft.gsqlparser.nodes.TDeclareVariable; 011import gudusoft.gsqlparser.nodes.TDeclareVariableList; 012import gudusoft.gsqlparser.nodes.TFunctionCall; 013import gudusoft.gsqlparser.nodes.TObjectName; 014import gudusoft.gsqlparser.nodes.TParseTreeNode; 015import gudusoft.gsqlparser.nodes.TResultColumn; 016import gudusoft.gsqlparser.nodes.TTableElement; 017import gudusoft.gsqlparser.nodes.TTableElementList; 018import gudusoft.gsqlparser.nodes.TTypeName; 019import gudusoft.gsqlparser.nodes.TViewAliasItem; 020import gudusoft.gsqlparser.stmt.TCreateFunctionStmt; 021import gudusoft.gsqlparser.stmt.TCreateProcedureStmt; 022import gudusoft.gsqlparser.stmt.TCreateSchemaSqlStatement; 023import gudusoft.gsqlparser.stmt.TCreateSynonymStmt; 024import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement; 025import gudusoft.gsqlparser.stmt.TCreateTriggerStmt; 026import gudusoft.gsqlparser.stmt.TCreateViewSqlStatement; 027import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement; 028import gudusoft.gsqlparser.stmt.TUseDatabase; 029import gudusoft.gsqlparser.stmt.mssql.TMssqlCreateFunction; 030import gudusoft.gsqlparser.stmt.mssql.TMssqlDeclare; 031import gudusoft.gsqlparser.stmt.oracle.TPlsqlCreateFunction; 032import gudusoft.gsqlparser.stmt.oracle.TPlsqlCreatePackage; 033import gudusoft.gsqlparser.stmt.oracle.TPlsqlCreateProcedure; 034import gudusoft.gsqlparser.stmt.oracle.TPlsqlCreateTrigger; 035import gudusoft.gsqlparser.stmt.teradata.TTeradataCreateProcedure; 036import gudusoft.gsqlparser.stmt.snowflake.TUseSchema; 037import gudusoft.gsqlparser.util.SQLUtil; 038 039import java.io.ByteArrayInputStream; 040import java.io.IOException; 041import java.util.ArrayList; 042import java.util.List; 043import java.util.Properties; 044import java.util.Stack; 045 046public class TDDLSQLEnv extends TSQLEnv { 047 048 private String sql; 049 050 private TSQLEnv metadataSQLEnv; 051 052 private String globalDatabase = null; 053 054 private String globalSchema = null; 055 /** 056 * A Snowflake {@code USE <database>} unset the current schema. Distinct from 057 * {@code globalSchema == null} ("never set"), which is allowed to fall back 058 * to the batch-global {@link #getDefaultSchemaName()}. See GitHub #715. 059 */ 060 private boolean schemaUnsetByDatabaseSwitch = false; 061 062 private boolean init = false; 063 064 private Stack<TCustomSqlStatement> stmtStack = new Stack<TCustomSqlStatement>(); 065 066 public boolean isInit() { 067 return init; 068 } 069 070 public TDDLSQLEnv(String defaultServer, String defaultDatabase, String defaultSchema, EDbVendor dbVendor, String sql) { 071 super(dbVendor); 072 if(!SQLUtil.isEmpty(defaultServer) && !defaultServer.equals(TSQLEnv.DEFAULT_SERVER_NAME)) { 073 setDefaultServerName(defaultServer); 074 } 075 if(!SQLUtil.isEmpty(defaultDatabase) && !defaultDatabase.equals(TSQLEnv.DEFAULT_DB_NAME)) { 076 setDefaultCatalogName(defaultDatabase); 077 } 078 if(!SQLUtil.isEmpty(defaultSchema) && !defaultSchema.equals(TSQLEnv.DEFAULT_SCHEMA_NAME)) { 079 setDefaultSchemaName(defaultSchema); 080 } 081 this.sql = sql; 082 } 083 084 public TDDLSQLEnv(String defaultServer, String defaultDatabase, String defaultSchema, TSQLEnv metadataSQLEnv, EDbVendor dbVendor, String sql) { 085 super(dbVendor); 086 if(!SQLUtil.isEmpty(defaultServer) && !defaultServer.equals(TSQLEnv.DEFAULT_SERVER_NAME)) { 087 setDefaultServerName(defaultServer); 088 } 089 if(!SQLUtil.isEmpty(defaultDatabase) && !defaultDatabase.equals(TSQLEnv.DEFAULT_DB_NAME)) { 090 setDefaultCatalogName(defaultDatabase); 091 } 092 if(!SQLUtil.isEmpty(defaultSchema) && !defaultSchema.equals(TSQLEnv.DEFAULT_SCHEMA_NAME)) { 093 setDefaultSchemaName(defaultSchema); 094 } 095 this.sql = sql; 096 this.metadataSQLEnv = metadataSQLEnv; 097 if(metadataSQLEnv!=null) { 098 this.setDefaultServerName(metadataSQLEnv.getDefaultServerName()); 099 } 100 } 101 102 @Override 103 public void initSQLEnv() { 104 synchronized (this) { 105 if (sql == null || init) 106 return; 107 TGSqlParser sqlparser = new TGSqlParser(getDBVendor()); 108 try { 109 sqlparser.setSqlEnv(metadataSQLEnv); 110 sqlparser.sqltext = sql; 111 sqlparser.parse(); 112 } catch (Exception e) { 113 // Parse failure - log and continue with whatever statements were parsed 114 } 115 List<TCustomSqlStatement> stmts = new ArrayList<TCustomSqlStatement>(); 116 if (sqlparser.sqlstatements != null) { 117 for (int j = 0; j < sqlparser.sqlstatements.size(); j++) { 118 TCustomSqlStatement stmt = sqlparser.sqlstatements.get(j); 119 extractDDLStmts(stmts, stmt); 120 } 121 } 122 123 if (!stmts.isEmpty()) { 124 for (int j = 0; j < stmts.size(); j++) { 125 TCustomSqlStatement stmt = stmts.get(j); 126 analyzeSQLEnv(stmt); 127 } 128 init = true; 129 } 130 stmts.clear(); 131 sql = null; 132 } 133 } 134 135 private void extractDDLStmts(List<TCustomSqlStatement> stmts, TCustomSqlStatement stmt) { 136 if (stmt instanceof TUseDatabase || stmt instanceof TUseSchema 137 || stmt instanceof TCreateSchemaSqlStatement 138 || stmt instanceof TCreateTableSqlStatement || stmt instanceof TMssqlDeclare 139 || stmt instanceof TStoredProcedureSqlStatement 140 || (stmt instanceof TMssqlCreateFunction 141 && ((TMssqlCreateFunction) stmt).getReturnTableDefinitions() != null)) { 142 stmts.add(stmt); 143 } else if (stmt instanceof TCreateViewSqlStatement) { 144 stmts.add(stmt); 145 } else if (stmt instanceof TCreateSynonymStmt) { 146 stmts.add(stmt); 147 } else if (stmt.getStatements() != null && stmt.getStatements().size() > 0) { 148 for (int i = 0; i < stmt.getStatements().size(); i++) { 149 extractDDLStmts(stmts, stmt.getStatements().get(i)); 150 } 151 } 152 } 153 154 private void analyzeSQLEnv(TCustomSqlStatement stmt) { 155 stmtStack.push(stmt); 156 if (stmt instanceof TUseDatabase) { 157 TUseDatabase useDatabase = (TUseDatabase) stmt; 158 analyzeUseDatabase(useDatabase); 159 } else if (stmt instanceof TUseSchema) { 160 // A Snowflake schema switch parses to its own statement class, not to 161 // TUseDatabase, so it has to be seen here or the "schema was unset by 162 // a database switch" flag would survive a subsequent USE SCHEMA and 163 // register later objects under DEFAULT instead of the schema the 164 // script just named. We only lift the flag: the schema name itself 165 // still comes from getDefaultSchemaName(), exactly as before, so this 166 // restores the previous behaviour rather than changing it. 167 schemaUnsetByDatabaseSwitch = false; 168 } else if (stmt instanceof TMssqlDeclare) { 169 TMssqlDeclare declare = (TMssqlDeclare) stmt; 170 analyzeMssqlDeclare(declare); 171 } else if (stmt instanceof TMssqlCreateFunction) { 172 TMssqlCreateFunction createFunction = (TMssqlCreateFunction) stmt; 173 analyzeMssqlCreateFunction(createFunction); 174 } else if (stmt instanceof TCreateSchemaSqlStatement) { 175 TCreateSchemaSqlStatement createSchema = (TCreateSchemaSqlStatement) stmt; 176 analyzeCreateSchema(createSchema); 177 } else if (stmt instanceof TCreateTableSqlStatement) { 178 TCreateTableSqlStatement createTable = (TCreateTableSqlStatement) stmt; 179 analyzeCreateTable(createTable); 180 } else if (stmt instanceof TCreateViewSqlStatement) { 181 TCreateViewSqlStatement createView = (TCreateViewSqlStatement) stmt; 182 analyzeCreateView(createView); 183 } else if (stmt instanceof TCreateSynonymStmt) { 184 TCreateSynonymStmt createSynonym = (TCreateSynonymStmt) stmt; 185 analyzeCreateSynonym(createSynonym); 186 } else if (stmt instanceof TStoredProcedureSqlStatement) { 187 TStoredProcedureSqlStatement procedure = (TStoredProcedureSqlStatement) stmt; 188 analyzeStoredProcedureStmt(procedure); 189 } 190 stmtStack.pop(); 191 } 192 193 private void analyzeStoredProcedureStmt(TStoredProcedureSqlStatement procedure) { 194 if (procedure instanceof TPlsqlCreatePackage) { 195 analyzeProcedure(procedure, ESQLDataObjectType.dotOraclePackage); 196 return; 197 } 198 if (procedure instanceof TCreateTriggerStmt) { 199 analyzeProcedure(procedure, ESQLDataObjectType.dotTrigger); 200 return; 201 } 202 if (procedure instanceof TCreateFunctionStmt) { 203 analyzeProcedure(procedure, ESQLDataObjectType.dotFunction); 204 return; 205 } 206 if (procedure instanceof TCreateProcedureStmt) { 207 analyzeProcedure(procedure, ESQLDataObjectType.dotProcedure); 208 return; 209 } 210 } 211 212 private void analyzeProcedure(TStoredProcedureSqlStatement procedure, ESQLDataObjectType type) { 213 TObjectName procedureName = getProcedureName(procedure); 214 if(procedureName == null){ 215 return; 216 } 217 TSQLRoutine sqlProcedure = addSQLRoutineToSQLEnv(procedureName, type); 218 sqlProcedure.setDefinition(procedure.toString()); 219 220 if(procedure instanceof TPlsqlCreatePackage) { 221 TPlsqlCreatePackage oraclePackage = (TPlsqlCreatePackage)procedure; 222 if (oraclePackage.getDeclareStatements() != null) { 223 for (int i = 0; i < oraclePackage.getDeclareStatements().size(); ++i) { 224 TCustomSqlStatement stmt = oraclePackage.getDeclareStatements().get(i); 225 if (stmt instanceof TPlsqlCreateTrigger) { 226 analyzePackageProcedure((TSQLOraclePackage) sqlProcedure, (TStoredProcedureSqlStatement)stmt, 227 ESQLDataObjectType.dotTrigger); 228 } 229 if (stmt instanceof TPlsqlCreateFunction) { 230 analyzePackageProcedure((TSQLOraclePackage) sqlProcedure, (TStoredProcedureSqlStatement)stmt, 231 ESQLDataObjectType.dotFunction); 232 } 233 if (stmt instanceof TPlsqlCreateProcedure) { 234 analyzePackageProcedure((TSQLOraclePackage) sqlProcedure, (TStoredProcedureSqlStatement)stmt, 235 ESQLDataObjectType.dotProcedure); 236 } 237 } 238 } 239 } 240 } 241 242 private void analyzePackageProcedure(TSQLOraclePackage oraclePackage, TStoredProcedureSqlStatement procedure, ESQLDataObjectType type) { 243 TObjectName procedureName = getProcedureName(procedure); 244 if(procedureName == null){ 245 return; 246 } 247 TSQLProcedure object = (TSQLProcedure) oraclePackage 248 .createSchemaObject(getQualifiedTableName(procedureName), type); 249 object.setDefinition(procedure.toString()); 250 } 251 252 253 private TObjectName getProcedureName(TParseTreeNode procedureObject) { 254 if(procedureObject instanceof TTeradataCreateProcedure) 255 { 256 return ((TTeradataCreateProcedure)procedureObject).getProcedureName(); 257 } 258 if(procedureObject instanceof TStoredProcedureSqlStatement) 259 { 260 return ((TStoredProcedureSqlStatement)procedureObject).getStoredProcedureName(); 261 } 262 if(procedureObject instanceof TFunctionCall) 263 { 264 return ((TFunctionCall)procedureObject).getFunctionName(); 265 } 266 return null; 267 } 268 269 private void analyzeCreateTable(TCreateTableSqlStatement createTable) { 270 if (createTable.getTables() != null && createTable.getTables().size() > 0) { 271 if (createTable.getColumnList() != null && createTable.getColumnList().size() > 0) { 272 TObjectName tableName = createTable.getTableName(); 273 TSQLTable table = addTableToSQLEnv(tableName); 274 for (int i = 0; i < createTable.getColumnList().size(); i++) { 275 TColumnDefinition column = createTable.getColumnList().getColumn(i); 276 if (column != null && column.getColumnName() != null) { 277 TObjectName columnName = column.getColumnName(); 278 addTableColumnToSQLEnv(table, columnName, column.getDatatype()); 279 } 280 } 281 table.setPriority(2); 282 } else if (createTable.getSubQuery() != null && createTable.getSubQuery().getResultColumnList() != null) { 283 if(createTable.getSubQuery().getResultColumnList().toString().indexOf("*") != -1) { 284 return; 285 } 286 TSQLTable table = addTableToSQLEnv(createTable.getTargetTable().getTableName()); 287 if (table.getColumns(true) == null || table.getColumns(true).isEmpty()) { 288 for (int i = 0; i < createTable.getSubQuery().getResultColumnList().size(); i++) { 289 TResultColumn resultColumn = createTable.getSubQuery().getResultColumnList().getResultColumn(i); 290 addTableColumnToSQLEnv(table, getObjectName(resultColumn)); 291 } 292 } 293 } 294 } 295 } 296 297 private void analyzeCreateView(TCreateViewSqlStatement createView) { 298 if (createView.getViewName() != null) { 299 if (createView.getViewAliasClause() != null) { 300 TSQLTable table = addTableToSQLEnv(createView.getViewName()); 301 table.setView(true); 302 for (int i = 0; i < createView.getViewAliasClause().getViewAliasItemList().size(); i++) { 303 TViewAliasItem column = createView.getViewAliasClause().getViewAliasItemList().getViewAliasItem(i); 304 if (column != null && column.getAlias() != null) { 305 TObjectName columnName = column.getAlias(); 306 addTableColumnToSQLEnv(table, columnName); 307 } 308 } 309 table.setPriority(2); 310 } else if (createView.getSubquery().getResultColumnList() != null) { 311 if(createView.getSubquery().getResultColumnList().toString().indexOf("*") != -1) { 312 return; 313 } 314 TSQLTable table = addTableToSQLEnv(createView.getViewName()); 315 table.setView(true); 316 for (int i = 0; i < createView.getSubquery().getResultColumnList().size(); i++) { 317 TResultColumn resultColumn = createView.getSubquery().getResultColumnList().getResultColumn(i); 318 addTableColumnToSQLEnv(table, getObjectName(resultColumn)); 319 } 320 } 321 } 322 } 323 324 private void analyzeCreateSynonym(TCreateSynonymStmt createSynonym) { 325 TObjectName synonymName = createSynonym.getSynonymName(); 326 TObjectName forName = createSynonym.getForName(); 327 if (synonymName == null || forName == null) { 328 return; 329 } 330 if (!isEnableGetMetadataFromDDL()) { 331 return; 332 } 333 String qualifiedSynonymName = buildFullyQualifiedTableName(synonymName); 334 TSQLSchemaObject schemaObject = doAddSchemaObject(qualifiedSynonymName, ESQLDataObjectType.dotSynonyms); 335 if (!(schemaObject instanceof TSQLSynonyms)) { 336 return; 337 } 338 TSQLSynonyms synonym = (TSQLSynonyms) schemaObject; 339 synonym.setBaseTarget( 340 TSQLEnv.getDatabaseName(forName), 341 TSQLEnv.getSchemaName(forName), 342 TSQLEnv.getObjectName(forName)); 343 synonym.setPriority(2); 344 } 345 346 private TObjectName getObjectName(TResultColumn resultColumn) { 347 if (resultColumn.getAliasClause() != null && resultColumn.getAliasClause().getAliasName() != null) { 348 return resultColumn.getAliasClause().getAliasName(); 349 } 350 if (resultColumn.getFieldAttr() != null) { 351 return resultColumn.getFieldAttr(); 352 } 353 if (resultColumn.getExpr() != null 354 && resultColumn.getExpr().getExpressionType() == EExpressionType.simple_object_name_t) { 355 return resultColumn.getExpr().getObjectOperand(); 356 } else if (!SQLUtil.isEmpty(resultColumn.getColumnNameOnly())) { 357 TObjectName objectName = new TObjectName(); 358 objectName.setString(resultColumn.getColumnNameOnly()); 359 return objectName; 360 } else { 361 return null; 362 } 363 } 364 365 private void analyzeUseDatabase(TUseDatabase useDatabase) { 366 TObjectName databaseName = useDatabase.getDatabaseName(); 367 368 if (databaseName == null) { 369 return; 370 } 371 372 // MantisBT 4677 — Snowflake states the form outright, so do not re-guess 373 // it from catalog contents. There, USE <name> with an unqualified name 374 // is a DATABASE switch and USE <db>.<schema> is a SCHEMA switch; the 375 // splitter and the grammar already classified the statement on that 376 // rule. Guessing here would silently flip a bare USE back to a schema 377 // whenever the current database happens to contain a same-named schema 378 // — a wrong session context with nothing to flag it. Other vendors, 379 // whose bare USE really is ambiguous, keep the catalog-based guess. 380 if (getDBVendor() == EDbVendor.dbvsnowflake) { 381 if (useDatabase.isSchema()) { 382 globalSchema = databaseName.toString(); 383 schemaUnsetByDatabaseSwitch = false; 384 } else { 385 String catalogName = databaseName.toString(); 386 getSQLCatalog(catalogName, true); 387 globalDatabase = catalogName; 388 // The schema carried over from the PREVIOUS database is no 389 // longer valid once the database changes; leaving it would 390 // qualify later names as <newdb>.<oldschema>. See the matching 391 // note in DatabaseContextTracker. 392 globalSchema = null; 393 // Nulling globalSchema alone is not enough: getCurrentSchemaName 394 // falls back to getDefaultSchemaName(), which TUseSchema wrote 395 // while PARSING and which therefore holds the last USE SCHEMA of 396 // the whole script - the very value this switch invalidated. The 397 // flag says "unset", as opposed to "never set", so the fallback 398 // is skipped and objects created after the switch register under 399 // DEFAULT_SCHEMA_NAME instead of the old database's schema. 400 // GitHub #715. 401 schemaUnsetByDatabaseSwitch = true; 402 } 403 return; 404 } 405 String qualifiedSchemaName = databaseName.toString(); 406 if (getNumberOfPart(databaseName) == 1) { 407 qualifiedSchemaName = getCurrentDatabaseName() + "." + qualifiedSchemaName; 408 } 409 if (getSQLSchema(qualifiedSchemaName, false) != null) { 410 globalSchema = databaseName.toString(); 411 } else { 412 String catalogName = databaseName.toString(); 413 getSQLCatalog(catalogName, true); 414 globalDatabase = catalogName; 415 } 416 } 417 418 private int getNumberOfPart(TObjectName name) { 419 return SQLUtil.parseNames(name.toString()).size(); 420 } 421 422 private int getNumberOfPart(String tableName) { 423 return SQLUtil.parseNames(tableName).size(); 424 } 425 426 private void analyzeCreateSchema(TCreateSchemaSqlStatement createSchema) { 427 TObjectName schemaName = createSchema.getSchemaName(); 428 if (schemaName != null) { 429 String qualifiedSchemaName = schemaName.toString(); 430 if (getNumberOfPart(schemaName) == 1) { 431 qualifiedSchemaName = getCurrentDatabaseName() + "." + qualifiedSchemaName; 432 } 433 getSQLSchema(qualifiedSchemaName, true); 434 } 435 } 436 437 private String getCurrentDatabaseName() { 438 Pair3<String, String, String> info = fillSchemaInfo(); 439 if(!SQLUtil.isEmpty(info.second)) { 440 return info.second; 441 } 442 if (!SQLUtil.isEmpty(globalDatabase)) { 443 return globalDatabase; 444 } else if (!SQLUtil.isEmpty(getDefaultCatalogName())) { 445 return getDefaultCatalogName(); 446 } else 447 getSQLCatalog(DEFAULT_DB_NAME, true); 448 return DEFAULT_DB_NAME; 449 } 450 451 private String getCurrentSchemaName() { 452 Pair3<String, String, String> info = fillSchemaInfo(); 453 if(!SQLUtil.isEmpty(info.third)) { 454 return info.third; 455 } 456 if (!SQLUtil.isEmpty(globalSchema)) { 457 return globalSchema; 458 } else if (schemaUnsetByDatabaseSwitch) { 459 // Unset - unless this catalog proves the new database has a PUBLIC, 460 // which is what Snowflake makes current. See 461 // TSQLEnv.findSchemaAfterDatabaseSwitch. 462 String afterSwitch = findSchemaAfterDatabaseSwitch(getCurrentDatabaseName()); 463 return SQLUtil.isEmpty(afterSwitch) ? DEFAULT_SCHEMA_NAME : afterSwitch; 464 } else if (!SQLUtil.isEmpty(getDefaultSchemaName())) { 465 return getDefaultSchemaName(); 466 } else 467 return DEFAULT_SCHEMA_NAME; 468 } 469 470 private Pair3<String, String, String> fillSchemaInfo() { 471 String server = null; 472 String database = null; 473 String schema = null; 474 475 TCustomSqlStatement stmt = DlineageUtil.getTopStmt(stmtStack.peek()); 476 String sqlComment = null; 477 try { 478 sqlComment = stmt.getCommentBeforeNode(); 479 } catch (Exception e) { 480 // e.printStackTrace(); 481 } 482 if (!SQLUtil.isEmpty(sqlComment) && (sqlComment.indexOf("db") != -1 || sqlComment.indexOf("schema") != -1)) { 483 Properties properties = new Properties(); 484 try { 485 properties.load( 486 new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes())); 487 if (SQLUtil.isEmpty(server) && properties.containsKey("db-instance")) { 488 server = properties.getProperty("db-instance"); 489 if (!SQLUtil.isEmpty(server) && !server.equals(TSQLEnv.DEFAULT_SERVER_NAME)) { 490 if (SQLUtil.isEmpty(this.getDefaultServerName()) 491 || this.getDefaultServerName().equals(TSQLEnv.DEFAULT_SERVER_NAME)) { 492 this.setDefaultServerName(server); 493 } 494 } 495 } 496 if (SQLUtil.isEmpty(database) && properties.containsKey("db")) { 497 database = properties.getProperty("db"); 498 if (database.indexOf(".") != -1) { 499 database = SQLUtil.quoteDottedName(getDBVendor(), ESQLDataObjectType.dotCatalog, database); 500 } 501 } 502 if (SQLUtil.isEmpty(schema) && properties.containsKey("schema")) { 503 schema = properties.getProperty("schema"); 504 if (schema.indexOf(".") != -1) { 505 schema = SQLUtil.quoteDottedName(getDBVendor(), ESQLDataObjectType.dotSchema, schema); 506 } 507 } 508 } catch (IOException e) { 509 e.printStackTrace(); 510 } 511 } 512 513 Pair3<String, String, String> info = new Pair3<String, String, String>(server, database, schema); 514 return info; 515 } 516 517 518 private void analyzeMssqlCreateFunction(TMssqlCreateFunction createFunction) { 519 if (createFunction.getReturnTableVaraible() != null && createFunction.getReturnTableDefinitions() != null) { 520 TObjectName tableName = createFunction.getReturnTableVaraible(); 521 TSQLTable table = addTableToSQLEnv(tableName); 522 523 for (int j = 0; j < createFunction.getReturnTableDefinitions().size(); j++) { 524 TTableElement tableElement = createFunction.getReturnTableDefinitions().getTableElement(j); 525 TColumnDefinition column = tableElement.getColumnDefinition(); 526 if (column != null && column.getColumnName() != null) { 527 TObjectName columnName = column.getColumnName(); 528 addTableColumnToSQLEnv(table, columnName); 529 } 530 } 531 } 532 } 533 534 private void addTableColumnToSQLEnv(TSQLTable table, TObjectName columnName) { 535 if (columnName == null) { 536 return; 537 } 538 String column = columnName.getColumnNameOnly(); 539 if (!SQLUtil.isEmpty(column)) { 540 table.addColumn(column); 541 } else { 542 column = columnName.toString(); 543 if (column.indexOf(".") != -1) { 544 List<String> splits = SQLUtil.parseNames(column); 545 column = splits.get(splits.size() - 1); 546 } 547 table.addColumn(column); 548 } 549 } 550 551 private void addTableColumnToSQLEnv(TSQLTable table, TObjectName columnName, TTypeName dataType) { 552 if(columnName == null){ 553 return; 554 } 555 String column = columnName.getColumnNameOnly(); 556 if (!SQLUtil.isEmpty(column)) { 557 table.addColumn(column, dataType); 558 } else { 559 column = columnName.toString(); 560 if (column.indexOf(".") != -1) { 561 List<String> splits = SQLUtil.parseNames(column); 562 column = splits.get(splits.size() - 1); 563 } 564 table.addColumn(column, dataType); 565 } 566 } 567 568 private TSQLTable addTableToSQLEnv(TObjectName tableName) { 569 return addTable(buildFullyQualifiedTableName(tableName), true); 570 } 571 572 private String buildFullyQualifiedTableName(TObjectName tableName) { 573 String qualifiedTableName = getQualifiedTableName(tableName); 574 if (getNumberOfPart(qualifiedTableName) == 1) { 575 if(!TSQLEnv.supportSchema(getDBVendor())){ 576 qualifiedTableName = TSQLEnv.DEFAULT_DB_NAME + "." + getCurrentDatabaseName() + "." + qualifiedTableName; 577 } 578 else { 579 qualifiedTableName = getCurrentDatabaseName() + "." + getCurrentSchemaName() + "." + qualifiedTableName; 580 } 581 } else if (getNumberOfPart(qualifiedTableName) == 2) { 582 if(!TSQLEnv.supportSchema(getDBVendor())){ 583 qualifiedTableName = TSQLEnv.DEFAULT_DB_NAME + "." + qualifiedTableName; 584 } 585 else { 586 qualifiedTableName = getCurrentDatabaseName() + "." + qualifiedTableName; 587 } 588 } 589 return qualifiedTableName; 590 } 591 592 private TSQLRoutine addSQLRoutineToSQLEnv(TObjectName procedureName, ESQLDataObjectType type) { 593 String qualifiedProcedureName = getQualifiedTableName(procedureName); 594 if (getNumberOfPart(qualifiedProcedureName) == 1) { 595 if(!TSQLEnv.supportSchema(getDBVendor())){ 596 qualifiedProcedureName = TSQLEnv.DEFAULT_DB_NAME + "." + getCurrentDatabaseName() + "." + qualifiedProcedureName; 597 } 598 else { 599 qualifiedProcedureName = getCurrentDatabaseName() + "." + getCurrentSchemaName() + "." + qualifiedProcedureName; 600 } 601 } else if (getNumberOfPart(qualifiedProcedureName) == 2) { 602 if(!TSQLEnv.supportSchema(getDBVendor())){ 603 qualifiedProcedureName = TSQLEnv.DEFAULT_DB_NAME + "." + qualifiedProcedureName; 604 } 605 else { 606 qualifiedProcedureName = getCurrentDatabaseName() + "." + qualifiedProcedureName; 607 } 608 } 609 return addSQLRoutine(qualifiedProcedureName, true, type); 610 } 611 612 private String getQualifiedTableName(TObjectName table) { 613 String tableName = table.toString(); 614 if (metadataSQLEnv == null) { 615 return tableName; 616 } 617 List<String> segments = SQLUtil.parseNames(tableName); 618 if (segments.size() > 2) { 619 return tableName; 620 } 621 String schemaName = null; 622 if (segments.size() > 1) { 623 schemaName = segments.get(segments.size() - 2); 624 } 625 int occurrence = 0; 626 int maxPriority = -1; 627 String tableDatabase = null; 628 String tableSchema = null; 629 String simpleTableName = DlineageUtil.getSimpleTableName(tableName); 630 for (TSQLCatalog catalog : metadataSQLEnv.getCatalogList()) { 631 if (SQLUtil.isEmpty(schemaName)) { 632 for (TSQLSchema schema : catalog.getSchemaList()) { 633 TSQLTable tsqlTable = schema.findTable(simpleTableName); 634 if (tsqlTable != null) { 635 occurrence += 1; 636 if (tsqlTable.getPriority() > maxPriority) { 637 tableDatabase = catalog.getName(); 638 tableSchema = schema.getName(); 639 maxPriority = tsqlTable.getPriority(); 640 } 641 } 642 } 643 if (occurrence > 1) { 644 break; 645 } 646 } else { 647 TSQLSchema schema = catalog.getSchema(schemaName, false); 648 if (schema != null) { 649 TSQLTable tsqlTable = schema.findTable(simpleTableName); 650 if (tsqlTable != null) { 651 occurrence += 1; 652 if (tsqlTable.getPriority() > maxPriority) { 653 tableDatabase = catalog.getName(); 654 tableSchema = schema.getName(); 655 maxPriority = tsqlTable.getPriority(); 656 } 657 } 658 } 659 } 660 } 661 if (occurrence == 1 || maxPriority > 0) { 662 StringBuilder qualifiedTableName = new StringBuilder(); 663 if (tableDatabase != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(tableDatabase)) { 664 qualifiedTableName.append(tableDatabase).append("."); 665 } 666 if (tableSchema != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(tableSchema)) { 667 qualifiedTableName.append(tableSchema).append("."); 668 } 669 return qualifiedTableName.append(simpleTableName).toString(); 670 } 671 return tableName; 672 } 673 674 private void analyzeMssqlDeclare(TMssqlDeclare declare) { 675 TDeclareVariableList variables = declare.getVariables(); 676 if (variables == null) { 677 return; 678 } 679 for (int i = 0; i < variables.size(); i++) { 680 TDeclareVariable variable = variables.getDeclareVariable(i); 681 if (variable.getTableTypeDefinitions() == null || variable.getTableTypeDefinitions().size() == 0) { 682 continue; 683 } 684 685 TObjectName tableName = variable.getVariableName(); 686 TSQLTable table = addTableToSQLEnv(tableName); 687 688 TTableElementList columns = variable.getTableTypeDefinitions(); 689 for (int j = 0; j < columns.size(); j++) { 690 TTableElement tableElement = columns.getTableElement(j); 691 TColumnDefinition column = tableElement.getColumnDefinition(); 692 if (column != null && column.getColumnName() != null) { 693 TObjectName columnName = column.getColumnName(); 694 addTableColumnToSQLEnv(table, columnName); 695 } 696 } 697 } 698 } 699 700 public static void main(String[] args) { 701 TSQLEnv sqlenv = new TDDLSQLEnv("deawirddap001", "mio", "public", EDbVendor.dbvredshift, SQLUtil.getFileContent("C:\\Users\\KK\\Desktop\\ddl.sql")); 702 sqlenv.initSQLEnv(); 703 System.out.println(sqlenv.toString()); 704 } 705}