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}