001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.ETableKind;
006import gudusoft.gsqlparser.ETableSource;
007import gudusoft.gsqlparser.TCustomSqlStatement;
008import gudusoft.gsqlparser.TSourceToken;
009import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
010import gudusoft.gsqlparser.dlineage.util.Pair;
011import gudusoft.gsqlparser.dlineage.util.Pair3;
012import gudusoft.gsqlparser.nodes.TFunctionCall;
013import gudusoft.gsqlparser.nodes.TObjectName;
014import gudusoft.gsqlparser.nodes.TTable;
015import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType;
016import gudusoft.gsqlparser.sqlenv.TSQLCatalog;
017import gudusoft.gsqlparser.sqlenv.TSQLColumn;
018import gudusoft.gsqlparser.sqlenv.TSQLEnv;
019import gudusoft.gsqlparser.sqlenv.TSQLSchema;
020import gudusoft.gsqlparser.sqlenv.TSQLTable;
021import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement;
022import gudusoft.gsqlparser.stmt.TCreateViewSqlStatement;
023import gudusoft.gsqlparser.util.Logger;
024import gudusoft.gsqlparser.util.LoggerFactory;
025import gudusoft.gsqlparser.util.SQLUtil;
026
027import java.io.ByteArrayInputStream;
028import java.io.IOException;
029import java.util.*;
030
031public class Table {
032
033        private static final Logger logger = LoggerFactory.getLogger(Table.class);
034
035        private long id;
036        protected String server;
037        protected String database;
038        protected String schema;
039        protected String name;
040        protected String displayName;
041        protected String fullName;
042        protected Set<String> alias = new LinkedHashSet<String>();
043        protected Set<Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>>> positions = new LinkedHashSet<>();
044        protected String parent;
045        protected Pair3<Long, Long, String> startPosition;
046        protected Pair3<Long, Long, String> endPosition;
047        private List<TableColumn> columns = new ArrayList<TableColumn>();
048        private boolean subquery = false;
049
050        private TTable tableObject;
051        private TObjectName viewName;
052        private boolean isCreateTable;
053        private boolean isView;
054        private boolean isPseudo;
055        private boolean isExternal;
056        private boolean isStage;
057        private boolean isSequence;
058        private boolean isPath;
059        private boolean isStream;
060        private boolean isVariable;
061        private boolean isConstant;
062        private boolean isDatabase;
063        private boolean isSchema;
064        private boolean isDataSource;
065        private String location;
066        private String fileType;
067        private String fileFormat;
068        private List<Process> processes;
069        private SubType subType;
070        private String starStmt;
071        private boolean hasSQLEnv = false;
072        private String currentAlias;
073    private boolean isDetermined;
074
075        private boolean fromDDL;
076
077        private TableRelationRows relationRows = new TableRelationRows(this);
078
079        private TCustomSqlStatement stmt;
080
081        public Table(TCustomSqlStatement stmt, TObjectName viewName) {
082                this(viewName);
083                this.stmt = stmt;
084                if (stmt != null) {
085                        setPosition(stmt);
086                }
087        }
088
089        public TCustomSqlStatement getSqlStatement() {
090                return stmt;
091        }
092        
093        public Table(TTable table, String tableName) {
094                if (table == null) {
095                        throw new IllegalArgumentException("Table arguments can't be null.");
096                }
097
098                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
099
100                this.tableObject = table;
101
102                setPosition(table);
103
104                this.name = tableName;
105                this.fullName = tableName;
106                setAlias(table.getAliasName());
107                setCurrentAlias(table.getAliasName());
108                
109                if (name.startsWith("`") && name.endsWith("`") && name.indexOf(".") != -1
110                                && ModelBindingManager.getGlobalOption().getVendor() == EDbVendor.dbvbigquery) {
111                        this.name = SQLUtil.trimColumnStringQuote(name);
112                        this.fullName = SQLUtil.trimColumnStringQuote(fullName);
113                }
114
115                if (table.getSubquery() != null) {
116                        subquery = true;
117                }
118
119                EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
120                boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
121                boolean supportSchema = TSQLEnv.supportSchema(vendor);
122
123                if (table.getTableName().getDblink() == null) {
124                        this.server = DlineageUtil.getTableServer(table.getTableName().toString());
125                        this.database = DlineageUtil.getTableDatabase(table.getTableName().toString());
126                        this.schema = DlineageUtil.getTableSchema(table.getTableName().toString());
127                }
128                else {
129                        if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
130                                this.server = getDefaultServer();
131                        }
132                        this.database = SQLUtil.normalizeIdentifier(vendor, ESQLDataObjectType.dotDblink, table.getTableName().getDblink().toString());
133                        if (!SQLUtil.isEmpty(table.getTableName().getSchemaString())) {
134                                this.schema = table.getTableName().getSchemaString();
135                        }
136                        this.subType = SubType.dblink;
137                        this.name = this.name.replace(table.getTableName().getDblink().toString(), this.database);
138                        ModelBindingManager.get().appendDblinkTable(this.name);
139                        return;
140                }
141
142                fillSchemaInfo();
143
144                if (SQLUtil.isEmpty(this.database)) {
145                        this.database = DlineageUtil.getTableDatabase(table.getTableName().toString());
146                        if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
147                                        && !SQLUtil.isEmpty(table.getTableName().getImplictDatabaseString())) {
148                                this.database = table.getTableName().getImplictDatabaseString();
149                        }
150                }
151
152                if (SQLUtil.isEmpty(this.schema)) {
153                        this.schema = DlineageUtil.getTableSchema(table.getTableName().toString());
154                        if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
155                                        && !SQLUtil.isEmpty(table.getTableName().getImplictSchemaString())) {
156                                this.schema = table.getTableName().getImplictSchemaString();
157                        }
158                }
159
160                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
161                        if (!SQLUtil.isEmpty(table.getTableName().getImplictSchemaString())) {
162                                this.schema = table.getTableName().getImplictSchemaString();
163                        }
164                }
165
166                if (table.getTableType() == ETableSource.function) {
167                        subType = SubType.function;
168                }
169
170                if (!supportCatalog) {
171                        this.database = null;
172                } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
173                        this.database = getDefaultDatabase();
174                }
175
176                if (!supportSchema) {
177                        this.schema = null;
178                } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
179                        this.schema = getDefaultSchema();
180                }
181
182                updateTableName(supportCatalog, supportSchema);
183
184                if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
185                        this.server = getDefaultServer();
186                }
187        }
188
189        public Table(TTable table) {
190                if (table == null) {
191                        throw new IllegalArgumentException("Table arguments can't be null.");
192                }
193
194                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
195
196                this.tableObject = table;
197
198                setPosition(table);
199
200                if (table.getLinkTable() != null) {
201                        this.fullName = table.getLinkTable().getFullName();
202                        this.name = table.getLinkTable().getName();
203                        setAlias(table.getName());
204                        setCurrentAlias(table.getName());
205                } else if (table.getTableType() == ETableSource.function && table.getFuncCall() != null) {
206                        TFunctionCall function = table.getFuncCall();
207                        this.fullName = function.getFunctionName().toString();
208                        this.name = function.getFunctionName().toString();
209                        setAlias(table.getAliasName());
210                        setCurrentAlias(table.getAliasName());
211                } else {
212                        if (table.getSubquery() != null && table.getAliasClause() != null) {
213                                this.name = table.getAliasClause().getAliasName().toString();
214                                this.subType = SubType.alias_table;
215                        } else if (table.getTableName() != null) {
216                                this.name = table.getTableName().toString();
217                        } else {
218                                this.name = table.getName();
219                        }
220
221                        this.fullName = table.getFullName();
222                        if (this.fullName == null) {
223                                this.fullName = this.name;
224                        }
225
226                        setAlias(table.getAliasName());
227                        setCurrentAlias(table.getAliasName());
228                }
229
230                if (name.startsWith("`") && name.endsWith("`") && name.indexOf(".") != -1
231                                && ModelBindingManager.getGlobalOption().getVendor() == EDbVendor.dbvbigquery) {
232                        this.name = SQLUtil.trimColumnStringQuote(name);
233                        this.fullName = SQLUtil.trimColumnStringQuote(fullName);
234                }
235
236                if (table.getSubquery() != null) {
237                        subquery = true;
238                }
239
240                EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
241                boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
242                boolean supportSchema = TSQLEnv.supportSchema(vendor);
243
244                if (table.getTableName().getDblink() == null) {
245                        this.server = DlineageUtil.getTableServer(table.getTableName().toString());
246                        this.database = DlineageUtil.getTableDatabase(table.getTableName().toString());
247                        this.schema = DlineageUtil.getTableSchema(table.getTableName().toString());
248                }
249                else {
250                        if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
251                                this.server = getDefaultServer();
252                        }
253                        this.database = SQLUtil.normalizeIdentifier(vendor, ESQLDataObjectType.dotDblink, table.getTableName().getDblink().toString());
254                        if (!SQLUtil.isEmpty(table.getTableName().getSchemaString())) {
255                                this.schema = table.getTableName().getSchemaString();
256                        }
257                        this.subType = SubType.dblink;
258                        this.name = this.name.replace(table.getTableName().getDblink().toString(), this.database);
259                        ModelBindingManager.get().appendDblinkTable(this.name);
260                        return;
261                }
262
263                fillSchemaInfo();
264
265                if (SQLUtil.isEmpty(this.database)) {
266                        this.database = DlineageUtil.getTableDatabase(table.getTableName().toString());
267                        if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
268                                        && !SQLUtil.isEmpty(table.getTableName().getImplictDatabaseString())) {
269                                this.database = table.getTableName().getImplictDatabaseString();
270                        }
271                }
272
273                if (SQLUtil.isEmpty(this.schema)) {
274                        this.schema = DlineageUtil.getTableSchema(table.getTableName().toString());
275                        if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
276                                        && !SQLUtil.isEmpty(table.getTableName().getImplictSchemaString())) {
277                                this.schema = table.getTableName().getImplictSchemaString();
278                        }
279                }
280
281                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
282                        if (!SQLUtil.isEmpty(table.getTableName().getImplictSchemaString())) {
283                                this.schema = table.getTableName().getImplictSchemaString();
284                        }
285                }
286
287                if (table.getTableType() == ETableSource.function) {
288                        subType = SubType.function;
289                }
290
291                if (!supportCatalog) {
292                        this.database = null;
293                } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
294                        this.database = getDefaultDatabase();
295                }
296
297                if (!supportSchema) {
298                        this.schema = null;
299                } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
300                        this.schema = getDefaultSchema();
301                }
302
303                updateTableName(supportCatalog, supportSchema);
304
305                if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
306                        this.server = getDefaultServer();
307                }
308        }
309
310        public void addColumnsFromSQLEnv(){
311                TSQLEnv sqlEnv = ModelBindingManager.getGlobalSQLEnv();
312                if (sqlEnv == null) {
313                        return;
314                }
315                TSQLTable tsqlTable = sqlEnv.searchTable(ModelFactory.getQualifiedTableName(this));
316                if (tsqlTable != null && tsqlTable.getColumnList()!=null && !tsqlTable.getColumnList().isEmpty()) {
317                        for(TSQLColumn tsqlColumn: tsqlTable.getColumnList()){
318                                TObjectName columnName = new TObjectName();
319                                columnName.setString(tsqlColumn.getName());
320                                new TableColumn(this, columnName);
321                        }
322                        this.setCreateTable(true);
323                        this.setHasSQLEnv(true);
324                }
325        }
326
327        private void fillSchemaInfo() {
328                TCustomSqlStatement currentStmt = ModelBindingManager.getGlobalStmtStack().peek();
329                TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
330                
331                String sqlComment = null;
332                try {
333                        sqlComment = stmt.getCommentBeforeNode();
334                } catch (Exception e) {
335                }
336                if (!SQLUtil.isEmpty(sqlComment) && (sqlComment.indexOf("db") != -1 || sqlComment.indexOf("schema") != -1)) {
337                        Properties properties = new Properties();
338                        try {
339                                properties.load(
340                                                new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
341                                if (SQLUtil.isEmpty(this.server) && properties.containsKey("db-instance")) {
342                                        this.server = properties.getProperty("db-instance");
343                                }
344                                if (SQLUtil.isEmpty(this.database) && properties.containsKey("db")) {
345                                        this.database = properties.getProperty("db");
346                                        if(this.database.indexOf(".")!=-1) {
347                                                String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
348                                                this.database = delimitedChar + SQLUtil.trimColumnStringQuote(this.database) + delimitedChar;
349                                        }
350                                }
351                                if (SQLUtil.isEmpty(this.schema) && properties.containsKey("schema")) {
352                                        this.schema = properties.getProperty("schema");
353                                        if(this.schema.indexOf(".")!=-1) {
354                                                String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
355                                                this.schema = delimitedChar + SQLUtil.trimColumnStringQuote(this.schema) + delimitedChar;
356                                        }
357                                }
358                        } catch (IOException e) {
359                                logger.error("load sql comment properties failed.", e);
360                        }
361                }
362                
363                if(stmt instanceof TCreateTableSqlStatement) {
364                        TCreateTableSqlStatement createTableStmt = (TCreateTableSqlStatement)stmt;
365                        if (createTableStmt.getTableKinds() != null 
366                                        && (createTableStmt.getTableKinds().contains(ETableKind.etkTemporary) 
367                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkTemp)
368                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkLocalTemporary)
369                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkLocalTemp)
370                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkGlobalTemporary)
371                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkGlobalTemp))) {
372                                if (this.tableObject == createTableStmt.getTargetTable()) {
373                                        setSubType(SubType.temp_table);
374                                        return;
375                                }
376                        }
377                }
378                
379                if(currentStmt instanceof TCreateTableSqlStatement) {
380                        TCreateTableSqlStatement createTableStmt = (TCreateTableSqlStatement)currentStmt;
381                        if (createTableStmt.getTableKinds() != null 
382                                        && (createTableStmt.getTableKinds().contains(ETableKind.etkTemporary) 
383                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkTemp)
384                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkLocalTemporary)
385                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkLocalTemp)
386                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkGlobalTemporary)
387                                                        || createTableStmt.getTableKinds().contains(ETableKind.etkGlobalTemp))) {
388                                if (this.tableObject == createTableStmt.getTargetTable()) {
389                                        setSubType(SubType.temp_table);
390                                        return;
391                                }
392                        }
393                }
394                
395                if(stmt instanceof TCreateViewSqlStatement) {
396                        TCreateViewSqlStatement createViewStmt = (TCreateViewSqlStatement)stmt;
397                        if (createViewStmt.getTableKind() != null 
398                                        && (createViewStmt.getTableKind() == (ETableKind.etkTemporary) 
399                                                        || createViewStmt.getTableKind() == (ETableKind.etkTemp)
400                                                        || createViewStmt.getTableKind() == (ETableKind.etkLocalTemporary)
401                                                        || createViewStmt.getTableKind() == (ETableKind.etkLocalTemp)
402                                                        || createViewStmt.getTableKind() == (ETableKind.etkGlobalTemporary)
403                                                        || createViewStmt.getTableKind() == (ETableKind.etkGlobalTemp))) {
404                                if (this.viewName == createViewStmt.getViewName()) {
405                                        setSubType(SubType.temp_table);
406                                        return;
407                                }
408                        }
409                }
410                
411                if(currentStmt instanceof TCreateViewSqlStatement) {
412                        TCreateViewSqlStatement createViewStmt = (TCreateViewSqlStatement)currentStmt;
413                        if (createViewStmt.getTableKind() != null 
414                                        && (createViewStmt.getTableKind() == (ETableKind.etkTemporary) 
415                                                        || createViewStmt.getTableKind() == (ETableKind.etkTemp)
416                                                        || createViewStmt.getTableKind() == (ETableKind.etkLocalTemporary)
417                                                        || createViewStmt.getTableKind() == (ETableKind.etkLocalTemp)
418                                                        || createViewStmt.getTableKind() == (ETableKind.etkGlobalTemporary)
419                                                        || createViewStmt.getTableKind() == (ETableKind.etkGlobalTemp))) {
420                                if (this.viewName == createViewStmt.getViewName()) {
421                                        setSubType(SubType.temp_table);
422                                        return;
423                                }
424                        }
425                }
426                
427
428                if (SQLUtil.isEmpty(this.database) || this.database.equals(ModelBindingManager.getGlobalDatabase())) {
429                        TSQLEnv sqlEnv = ModelBindingManager.getGlobalSQLEnv();
430                        if (sqlEnv == null) {
431                                return;
432                        }
433                        int occurrence = 0;
434                        int maxPriority = -1;
435                        String tableDatabase = null;
436                        String tableSchema = null;
437                        Map<Integer, List<String>> databaseSchemasMap = new HashMap<Integer, List<String>>();
438                        for (TSQLCatalog catalog : sqlEnv.getCatalogList()) {
439                                if (SQLUtil.isEmpty(schema) || this.schema.equals(ModelBindingManager.getGlobalSchema())) {
440                                        for (TSQLSchema schema : catalog.getSchemaList()) {
441                                                TSQLTable tsqlTable = schema.findTable(DlineageUtil.getSimpleTableName(this.name));
442                                                if (tsqlTable != null) {
443                                                        occurrence += 1;
444                                                        if (tsqlTable.getPriority() > maxPriority
445                                                                        || (maxPriority > 0 && tsqlTable.getPriority() == maxPriority)) {
446                                                                tableDatabase = catalog.getName();
447                                                                if(tableDatabase.indexOf(".")!=-1) {
448                                                                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
449                                                                        tableDatabase = delimitedChar + SQLUtil.trimColumnStringQuote(tableDatabase) + delimitedChar;
450                                                                }
451                                                                tableSchema = schema.getName();
452                                                                if(tableSchema.indexOf(".")!=-1) {
453                                                                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
454                                                                        tableSchema = delimitedChar + SQLUtil.trimColumnStringQuote(tableSchema) + delimitedChar;
455                                                                }
456                                                                maxPriority = tsqlTable.getPriority();
457                                                                if(!databaseSchemasMap.containsKey(maxPriority)) {
458                                                                        databaseSchemasMap.put(maxPriority, new ArrayList<String>());
459                                                                }
460                                                                databaseSchemasMap.get(maxPriority).add(tableDatabase + "___" + tableSchema);
461                                                        }
462                                                }
463                                        }
464//                                      if (occurrence > 1) {
465//                                              break;
466//                                      }
467                                } else {
468                                        TSQLSchema schema = catalog.getSchema(this.schema, false);
469                                        if (schema != null) {
470                                                TSQLTable tsqlTable = schema.findTable(DlineageUtil.getSimpleTableName(this.name));
471                                                if (tsqlTable != null) {
472                                                        occurrence += 1;
473                                                        if (tsqlTable.getPriority() > maxPriority
474                                                                        || (maxPriority > 0 && tsqlTable.getPriority() == maxPriority)) {
475                                                                tableDatabase = catalog.getName();
476                                                                if(tableDatabase.indexOf(".")!=-1) {
477                                                                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
478                                                                        tableDatabase = delimitedChar + SQLUtil.trimColumnStringQuote(tableDatabase) + delimitedChar;
479                                                                }
480                                                                tableSchema = schema.getName();
481                                                                if(tableSchema.indexOf(".")!=-1) {
482                                                                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
483                                                                        tableSchema = delimitedChar + SQLUtil.trimColumnStringQuote(tableSchema) + delimitedChar;
484                                                                }
485                                                                maxPriority = tsqlTable.getPriority();
486                                                                if(!databaseSchemasMap.containsKey(maxPriority)) {
487                                                                        databaseSchemasMap.put(maxPriority, new ArrayList<String>());
488                                                                }
489                                                                databaseSchemasMap.get(maxPriority).add(tableDatabase + "___" + tableSchema);
490                                                        }
491                                                }
492                                        }
493                                }
494                        }
495                        if (occurrence == 1 || (maxPriority > 0 && databaseSchemasMap.get(maxPriority).size() == 1)) {
496                                if (this.database == null && tableDatabase != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(tableDatabase)) {
497                                        this.database = tableDatabase;
498                                }
499                                if (this.schema == null && tableSchema != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(tableSchema)) {
500                                        this.schema = tableSchema;
501                                }
502                        }
503                } else if (SQLUtil.isEmpty(this.schema) || this.schema.equals(ModelBindingManager.getGlobalSchema())) {
504                        TSQLEnv sqlEnv = ModelBindingManager.getGlobalSQLEnv();
505                        if (sqlEnv == null) {
506                                return;
507                        }
508                        int occurrence = 0;
509                        int maxPriority = -1;
510                        String tableDatabase = null;
511                        String tableSchema = null;
512                        Map<Integer, List<String>> databaseSchemasMap = new HashMap<Integer, List<String>>();
513                        TSQLCatalog catalog = sqlEnv.searchCatalog(this.database);
514                        if (catalog != null) {
515                                for (TSQLSchema schema : catalog.getSchemaList()) {
516                                        TSQLTable tsqlTable = schema.findTable(DlineageUtil.getSimpleTableName(this.name));
517                                        if (tsqlTable != null) {
518                                                occurrence += 1;
519                                                if (tsqlTable.getPriority() > maxPriority
520                                                                || (maxPriority > 0 && tsqlTable.getPriority() == maxPriority)) {
521                                                        tableDatabase = catalog.getName();
522                                                        if (tableDatabase.indexOf(".") != -1) {
523                                                                String delimitedChar = TSQLEnv
524                                                                                .delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
525                                                                tableDatabase = delimitedChar + SQLUtil.trimColumnStringQuote(tableDatabase)
526                                                                                + delimitedChar;
527                                                        }
528                                                        tableSchema = schema.getName();
529                                                        if (tableSchema.indexOf(".") != -1) {
530                                                                String delimitedChar = TSQLEnv
531                                                                                .delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
532                                                                tableSchema = delimitedChar + SQLUtil.trimColumnStringQuote(tableSchema)
533                                                                                + delimitedChar;
534                                                        }
535                                                        maxPriority = tsqlTable.getPriority();
536                                                        if(!databaseSchemasMap.containsKey(maxPriority)) {
537                                                                databaseSchemasMap.put(maxPriority, new ArrayList<String>());
538                                                        }
539                                                        databaseSchemasMap.get(maxPriority).add(tableDatabase + "___" + tableSchema);
540                                                }
541                                        }
542                                }
543                        }
544
545                        if (occurrence == 1 || (maxPriority > 0 && databaseSchemasMap.get(maxPriority).size() == 1)) {
546                                if (this.database == null && tableDatabase != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(tableDatabase)) {
547                                        this.database = tableDatabase;
548                                }
549                                if (this.schema == null && tableSchema != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(tableSchema)) {
550                                        this.schema = tableSchema;
551                                }
552                        }
553
554                        if (SQLUtil.isEmpty(this.schema) && !SQLUtil.isEmpty(this.database)) {
555                                this.schema = getDefaultSchema();
556                        }
557                }
558        }
559
560        public Table(TObjectName tableName) {
561                if (tableName == null) {
562                        throw new IllegalArgumentException("Table arguments can't be null.");
563                }
564
565                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
566                
567                this.viewName = tableName;
568
569                setPosition(tableName);
570
571                this.fullName = tableName.toString();
572                this.name = tableName.toString();
573                if (SQLUtil.isEmpty(name)) {
574                        name = tableName.toString();
575                }
576
577                if (name.startsWith("`") && name.endsWith("`") && name.indexOf(".") != -1
578                                && ModelBindingManager.getGlobalOption().getVendor() == EDbVendor.dbvbigquery) {
579                        this.name = SQLUtil.trimColumnStringQuote(name);
580                        this.fullName = SQLUtil.trimColumnStringQuote(fullName);
581                }
582
583                this.server = DlineageUtil.getTableServer(tableName.toString());
584                this.database = DlineageUtil.getTableDatabase(tableName.toString());
585                this.schema = DlineageUtil.getTableSchema(tableName.toString());
586
587                fillSchemaInfo();
588
589                EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
590                boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
591                boolean supportSchema = TSQLEnv.supportSchema(vendor);
592
593                if (supportCatalog && SQLUtil.isEmpty(this.database)) {
594                        this.database = DlineageUtil.getTableDatabase(tableName.toString());
595                        if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
596                                        && !SQLUtil.isEmpty(tableName.getImplictDatabaseString())) {
597                                this.database = tableName.getImplictDatabaseString();
598                        }
599                }
600
601                if (supportSchema && SQLUtil.isEmpty(this.schema)) {
602                        this.schema = DlineageUtil.getTableSchema(tableName.toString());
603                        if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
604                                        && !SQLUtil.isEmpty(tableName.getImplictSchemaString())) {
605                                this.schema = tableName.getImplictSchemaString();
606                        }
607                }
608
609                if (supportSchema && !SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
610                        if (!SQLUtil.isEmpty(tableName.getImplictSchemaString())) {
611                                this.schema = tableName.getImplictSchemaString();
612                        } else {
613                                this.schema = getDefaultSchema();
614                        }
615                }
616
617                if (!supportCatalog) {
618                        this.database = null;
619                } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
620                        this.database = getDefaultDatabase();
621                }
622
623                if (!supportSchema) {
624                        this.schema = null;
625                } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
626                        this.schema = getDefaultSchema();
627                }
628
629                updateTableName(supportCatalog, supportSchema);
630
631                if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
632                        this.server = getDefaultServer();
633                }
634        }
635
636        protected String getDefaultServer() {
637                String defaultServer = null;
638                if (ModelBindingManager.getGlobalSQLEnv() != null) {
639                        defaultServer = ModelBindingManager.getGlobalSQLEnv().getDefaultServerName();
640                }
641                if (!SQLUtil.isEmpty(defaultServer))
642                        return defaultServer;
643                return TSQLEnv.DEFAULT_SERVER_NAME;
644        }
645
646        protected String getDefaultSchema() {
647                String defaultSchema = null;
648                if (ModelBindingManager.getGlobalSQLEnv() != null) {
649                        defaultSchema = ModelBindingManager.getGlobalSQLEnv().getDefaultSchemaName();
650                }
651                if (!SQLUtil.isEmpty(defaultSchema))
652                        return defaultSchema;
653                return TSQLEnv.DEFAULT_SCHEMA_NAME;
654        }
655
656        protected String getDefaultDatabase() {
657                String defaultDatabase = null;
658                if (ModelBindingManager.getGlobalSQLEnv() != null) {
659                        defaultDatabase = ModelBindingManager.getGlobalSQLEnv().getDefaultCatalogName();
660                }
661                if (!SQLUtil.isEmpty(defaultDatabase))
662                        return defaultDatabase;
663                return TSQLEnv.DEFAULT_DB_NAME;
664        }
665
666        public Table(String tableName) {
667                if (tableName == null) {
668                        throw new IllegalArgumentException("Table arguments can't be null.");
669                }
670
671                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
672
673                this.startPosition = new Pair3<Long, Long, String>(-1L, -1L, ModelBindingManager.getGlobalHash());
674                this.endPosition = new Pair3<Long, Long, String>(-1L, -1L, ModelBindingManager.getGlobalHash());
675
676                this.fullName = tableName;
677                this.name = tableName;
678                if (SQLUtil.isEmpty(name)) {
679                        name = tableName;
680                }
681
682                if (name.startsWith("`") && name.endsWith("`") && name.indexOf(".") != -1
683                                && ModelBindingManager.getGlobalOption().getVendor() == EDbVendor.dbvbigquery) {
684                        this.name = SQLUtil.trimColumnStringQuote(name);
685                        this.fullName = SQLUtil.trimColumnStringQuote(fullName);
686                }
687
688                EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
689                boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
690                boolean supportSchema = TSQLEnv.supportSchema(vendor);
691
692                fillSchemaInfo();
693
694                this.server = DlineageUtil.getTableServer(tableName);
695
696                if (supportCatalog && SQLUtil.isEmpty(this.database)) {
697                        this.database = DlineageUtil.getTableDatabase(tableName);
698                }
699                if (supportSchema && SQLUtil.isEmpty(this.schema)) {
700                        this.schema = DlineageUtil.getTableSchema(tableName);
701                }
702                if (supportSchema && !SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
703                        this.schema = getDefaultSchema();
704                }
705
706                if (!supportCatalog) {
707                        this.database = null;
708                } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
709                        this.database = getDefaultDatabase();
710                }
711
712                if (!supportSchema) {
713                        this.schema = null;
714                } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
715                        this.schema = getDefaultSchema();
716                }
717
718                updateTableName(supportCatalog, supportSchema);
719
720                if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
721                        this.server = getDefaultServer();
722                }
723        }
724
725        protected void updateTableName(boolean supportCatalog, boolean supportSchema) {
726                List<String> segments = SQLUtil.parseNames(this.name);
727                this.name = segments.get(segments.size() - 1);
728                if (supportCatalog && supportSchema) {
729                        StringBuilder builder = new StringBuilder();
730                        if (segments.size() > 2) {
731                                builder.append(segments.get(segments.size() - 3)).append(".");
732                        } else {
733                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
734                                        builder.append(this.database).append(".");
735                                }
736                        }
737                        if (segments.size() > 1) {
738                                builder.append(segments.get(segments.size() - 2)).append(".");
739                        } else {
740                                if (builder.length() > 0) {
741                                        if (this.schema == null) {
742                                                if (ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
743                                                        this.schema = "dbo";
744                                                } else {
745                                                        this.schema = getDefaultSchema();
746                                                }
747                                        }
748                                        else if (TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)
749                                                        && ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
750                                                this.schema = "dbo";
751                                        }
752                                        builder.append(this.schema).append(".");
753                                } else {
754                                        if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
755                                                builder.append(this.schema).append(".");
756                                        }
757                                }
758                        }
759                        builder.append(this.name);
760                        this.name = builder.toString();
761                } else if (supportCatalog) {
762                        if (segments.size() > 1) {
763                                this.name = segments.get(segments.size() - 2) + "." + this.name;
764                        }
765                        else {
766                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
767                                        this.name = this.database + "." + this.name;
768                                }
769                        }
770                } else if (supportSchema) {
771                        if (segments.size() > 1) {
772                                this.name = segments.get(segments.size() - 2) + "." + this.name;
773                        } else {
774                                if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
775                                        this.name = this.schema + "." + this.name;
776                                }
777                        }
778                }
779
780                if (this.server != null && !this.server.equals(getDefaultServer())) {
781                        this.name = this.server + "." + this.name;
782                }
783        }
784
785        public long getId() {
786                return id;
787        }
788
789        public String getName() {
790                return name;
791        }
792
793        public void setName(String name) {
794                EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
795                boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
796                boolean supportSchema = TSQLEnv.supportSchema(vendor);
797                if (!supportCatalog) {
798                        this.database = null;
799                } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
800                        this.database = getDefaultDatabase();
801                }
802
803                if (!supportSchema) {
804                        this.schema = null;
805                } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
806                        this.schema = getDefaultSchema();
807                }
808                
809                this.name = name;
810                
811                updateTableName(supportCatalog, supportSchema);
812        }
813
814        public Pair3<Long, Long, String> getStartPosition() {
815                return startPosition;
816        }
817
818        public Pair3<Long, Long, String> getEndPosition() {
819                return endPosition;
820        }
821
822        public List<TableColumn> getColumns() {
823                return columns;
824        }
825
826        public void addColumn(TableColumn column) {
827                if (column != null && !this.columns.contains(column)) {
828                        this.columns.add(column);
829                }
830        }
831
832        public TTable getTableObject() {
833                return tableObject;
834        }
835
836        public String getAlias() {
837                String aliasString = Arrays.toString(this.alias.toArray(new String[0]));
838                return aliasString.substring(1, aliasString.length() - 1);
839        }
840
841        public void setAlias(String alias) {
842                if (!SQLUtil.isEmpty(alias)) {
843                        this.alias.add(alias);
844                }
845        }
846
847        public String getFullName() {
848                return fullName;
849        }
850
851        public boolean hasSubquery() {
852                return subquery;
853        }
854
855        public String getParent() {
856                return parent;
857        }
858
859        public void setParent(String parent) {
860                this.parent = parent;
861        }
862
863//      public TObjectName getTableName() {
864//              return tableName;
865//      }
866
867        public String getDatabase() {
868                return database;
869        }
870
871        public String getSchema() {
872                return schema;
873        }
874
875        public TableRelationRows getRelationRows() {
876                return relationRows;
877        }
878
879        public boolean isCreateTable() {
880                return isCreateTable;
881        }
882
883        public void setCreateTable(boolean isCreateTable, boolean fromDDL) {
884                TCustomSqlStatement stmt = ModelBindingManager.getGlobalStmtStack().peek();
885                if (stmt != null && stmt.getClass().getSimpleName().startsWith("TCreate")) {
886                        Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> position = setPosition(stmt);
887                        if (position != null) {
888                                this.startPosition = position.first;
889                                this.endPosition = position.second;
890                        }
891                }
892                this.isCreateTable = isCreateTable;
893                if (isCreateTable) {
894                        for (TableColumn column : columns) {
895                                column.setShowStar(false);
896                        }
897                        setDetermined(true);
898                        if (fromDDL) {
899                                setFromDDL(true);
900                        }
901                }
902        }
903        
904        public void setCreateTable(boolean isCreateTable) {
905                setCreateTable(isCreateTable, false);
906        }
907
908        public boolean isView() {
909                return isView;
910        }
911
912        public void setView(boolean isView) {
913                this.isView = isView;
914        }
915
916        public boolean isPseudo() {
917                return isPseudo;
918        }
919
920        public void setPseudo(boolean isPseudo) {
921                this.isPseudo = isPseudo;
922        }
923
924        public boolean isExternal() {
925                return isExternal;
926        }
927
928        public void setExternal(boolean isExternal) {
929                this.isExternal = isExternal;
930        }
931
932        public boolean isStage() {
933                return isStage;
934        }
935
936        public void setStage(boolean isStage) {
937                this.isStage = isStage;
938        }
939
940        public boolean isSequence() {
941                return isSequence;
942        }
943
944        public void setSequence(boolean sequence) {
945                isSequence = sequence;
946        }
947
948        public boolean isVariable() {
949                return isVariable;
950        }
951
952        public void setVariable(boolean isVariable) {
953                this.isVariable = isVariable;
954        }
955
956        public boolean isConstant() {
957                return isConstant;
958        }
959
960        public void setConstant(boolean isConstant) {
961                this.isConstant = isConstant;
962        }
963
964        public boolean isPath() {
965                return isPath;
966        }
967
968        public void setPath(boolean isPath) {
969                this.isPath = isPath;
970                if(isPath) {
971                        String filePathDatabase = ModelBindingManager.getGlobalOption().getFilePathDatabase();
972                        String filePathSchema = ModelBindingManager.getGlobalOption().getFilePathSchema();
973                        if(SQLUtil.isEmpty(filePathDatabase)) {
974                                this.database = null;
975                        }
976                        else {
977                                this.database = filePathDatabase;
978                        }
979                        if(SQLUtil.isEmpty(filePathSchema)) {
980                                this.schema = null;
981                        }
982                        else {
983                                this.schema = filePathSchema;
984                        }
985
986                        EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
987                        boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
988                        boolean supportSchema = TSQLEnv.supportSchema(vendor);
989                        if (!supportCatalog) {
990                                this.database = null;
991                        } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
992                                this.database = getDefaultDatabase();
993                        }
994
995                        if (!supportSchema) {
996                                this.schema = null;
997                        } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
998                                this.schema = getDefaultSchema();
999                        }
1000
1001                        updateTableName(supportCatalog, supportSchema);
1002                }
1003        }
1004
1005        public boolean isCursor() {
1006                return isVariable && getSubType() == SubType.cursor;
1007        }
1008
1009        public String getLocation() {
1010                return location;
1011        }
1012
1013        public void setLocation(String location) {
1014                this.location = location;
1015        }
1016
1017        public String getFileType() {
1018                return fileType;
1019        }
1020
1021        public void setFileType(String fileType) {
1022                this.fileType = fileType;
1023        }
1024
1025        public String getDisplayName() {
1026                return displayName;
1027        }
1028
1029        public void setDisplayName(String displayName) {
1030                this.displayName = displayName;
1031        }
1032
1033        public String getFileFormat() {
1034                return fileFormat;
1035        }
1036
1037        public void setFileFormat(String fileFormat) {
1038                this.fileFormat = fileFormat;
1039        }
1040
1041        public List<Process> getProcesses() {
1042                return processes;
1043        }
1044
1045        public void addProcess(Process process) {
1046                if (processes == null) {
1047                        processes = new ArrayList<Process>();
1048                }
1049                if (process != null && !processes.contains(process)) {
1050                        processes.add(process);
1051                }
1052        }
1053        
1054        public void removeProcess(Process process) {
1055                if (processes == null) {
1056                        processes = new ArrayList<Process>();
1057                }
1058                if (process != null && processes.contains(process)) {
1059                        processes.remove(process);
1060                }
1061        }
1062
1063        public void setSubType(SubType subType) {
1064                if (this.subType == null || subType == SubType.record_type) {
1065                        this.subType = subType;
1066                }
1067        }
1068
1069        public SubType getSubType() {
1070                return subType;
1071        }
1072
1073        public boolean isStream() {
1074                return isStream;
1075        }
1076
1077        public void setStream(boolean isStream) {
1078                this.isStream = isStream;
1079        }
1080
1081        public boolean isSchema() {
1082                return isSchema;
1083        }
1084
1085        public void setSchema(boolean isSchema) {
1086                this.isSchema = isSchema;
1087        }
1088
1089        public void setDatabase(String database) {
1090                this.database = database;
1091        }
1092
1093        public boolean isDatabase() {
1094                return isDatabase;
1095        }
1096
1097        public void setDatabase(boolean isDatabase) {
1098                this.isDatabase = isDatabase;
1099        }
1100
1101        public boolean isDataSource() {
1102                return isDataSource;
1103        }
1104
1105        public void setDataSource(boolean dataSource) {
1106                isDataSource = dataSource;
1107        }
1108
1109        public String getStarStmt() {
1110                return starStmt;
1111        }
1112
1113        public void setStarStmt(String starStmt) {
1114                this.starStmt = starStmt;
1115        }
1116
1117        public void setHasSQLEnv(boolean hasSQLEnv) {
1118                this.hasSQLEnv = hasSQLEnv;
1119        }
1120
1121        public boolean hasSQLEnv() {
1122                return hasSQLEnv;
1123        }
1124
1125        public String getCurrentAlias() {
1126                return currentAlias;
1127        }
1128
1129        public void setCurrentAlias(String currentAlias) {
1130                if (SQLUtil.isEmpty(currentAlias)) {
1131                        this.currentAlias = null;
1132                } else
1133                        this.currentAlias = currentAlias;
1134        }
1135
1136        public Set<String> getAliasList() {
1137                return alias;
1138        }
1139
1140        public String getServer() {
1141                return server;
1142        }
1143
1144        public boolean isDetermined() {
1145                return isDetermined;
1146        }
1147
1148        public void setDetermined(boolean isDetermined) {
1149                this.isDetermined = isDetermined;
1150        }
1151
1152        public boolean isFromDDL() {
1153                return fromDDL;
1154        }
1155
1156        public void setFromDDL(boolean fromDDL) {
1157                this.fromDDL = fromDDL;
1158        }
1159
1160        private Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> setPositionInternal(TSourceToken startToken, TSourceToken endToken) {
1161                if (startToken == null || endToken == null) {
1162                        return null;
1163                }
1164
1165                Pair3<Long, Long, String> startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
1166                                ModelBindingManager.getGlobalHash());
1167                Pair3<Long, Long, String> endPosition = new Pair3<Long, Long, String>(endToken.lineNo, endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
1168                                ModelBindingManager.getGlobalHash());
1169
1170                if(this.startPosition == null && this.endPosition == null) {
1171                        this.startPosition = startPosition;
1172                        this.endPosition = endPosition;
1173                }
1174
1175                boolean traceTablePosition = ModelBindingManager.getGlobalOption().isTraceTablePosition();
1176
1177                
1178                Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> position = Pair.create(startPosition, endPosition);
1179                
1180                if (traceTablePosition) {
1181                        positions.add(position);
1182                }
1183                
1184                return position;
1185        }
1186
1187        public Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> setPosition(TTable table) {
1188                if (table == null) {
1189                        return null;
1190                }
1191                
1192                TSourceToken startToken = table.getStartToken();
1193                TSourceToken endToken = table.getEndToken();
1194                if (startToken == null && table.getSubquery() != null) {
1195                        startToken = table.getSubquery().getStartToken();
1196                        endToken = table.getSubquery().getEndToken();
1197                }
1198
1199                return setPositionInternal(startToken, endToken);
1200        }
1201
1202        public Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> setPosition(TObjectName tableName) {
1203                if (tableName == null) {
1204                        return null;
1205                }
1206                
1207                TSourceToken startToken = tableName.getStartToken();
1208                TSourceToken endToken = tableName.getEndToken();
1209                
1210                return setPositionInternal(startToken, endToken);
1211        }
1212
1213        public Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>> setPosition(TCustomSqlStatement stmt) {
1214                if (stmt == null) {
1215                        return null;
1216                }
1217                
1218                TSourceToken startToken = stmt.getStartToken();
1219                TSourceToken endToken = stmt.getEndToken();
1220                
1221                return setPositionInternal(startToken, endToken);
1222        }
1223
1224        public Set<Pair<Pair3<Long, Long, String>, Pair3<Long, Long, String>>> getPositions() {
1225                return positions;
1226        }
1227}