001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.EExpressionType;
006import gudusoft.gsqlparser.ESetOperatorType;
007import gudusoft.gsqlparser.TCustomSqlStatement;
008import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
009import gudusoft.gsqlparser.dlineage.util.Pair;
010import gudusoft.gsqlparser.dlineage.util.Pair3;
011import gudusoft.gsqlparser.dlineage.util.SHA256;
012import gudusoft.gsqlparser.nodes.*;
013import gudusoft.gsqlparser.sqlenv.TSQLEnv;
014import gudusoft.gsqlparser.stmt.*;
015import gudusoft.gsqlparser.stmt.mssql.TMssqlDeclare;
016import gudusoft.gsqlparser.util.IndexedLinkedHashMap;
017import gudusoft.gsqlparser.util.Logger;
018import gudusoft.gsqlparser.util.LoggerFactory;
019import gudusoft.gsqlparser.util.SQLUtil;
020
021import java.util.*;
022
023@SuppressWarnings({ "unchecked", "rawtypes" })
024public class ModelBindingManager {
025
026        private static final Logger logger = LoggerFactory.getLogger(ModelBindingManager.class);
027
028        private final Map modelBindingMap = new LinkedHashMap();
029        private final Map processModelBindingMap = new LinkedHashMap();
030        private final Map viewModelBindingMap = new LinkedHashMap();
031        private final Map insertModelBindingMap = new LinkedHashMap();
032        private final Map createModelBindingMap = new LinkedHashMap();
033        private final Map createModelQuickBindingMap = new LinkedHashMap();
034        private final Map mergeModelBindingMap = new LinkedHashMap();
035        private final Map updateModelBindingMap = new LinkedHashMap();
036        private final Map cursorModelBindingMap = new LinkedHashMap();
037        private final Map functionTableMap = new LinkedHashMap<>();
038        private final Map tableNamesMap = new LinkedHashMap();
039        private final Set<Table> dropTables = new HashSet<Table>();
040        private final Map procedureNamesMap = new LinkedHashMap();
041        private final Map oraclePackageNamesMap = new LinkedHashMap();
042        private final Set<Relationship> relationHolder = Collections.synchronizedSet(new LinkedHashSet<Relationship>());
043        private final Map<String, TTable> tableAliasMap = new LinkedHashMap();
044        private final Map<TCustomSqlStatement, String> tableHashMap = new LinkedHashMap();
045        private final Map<TCustomSqlStatement, String> topStmtHashMap = new HashMap();
046        private final Map hashSQLMap = new HashMap();
047        private final Map dynamicSQLMap = new HashMap();
048        private final Set tableSet = new LinkedHashSet();
049        private final Set resultSetSet = new LinkedHashSet();
050        private final Set<String> dblinkTableSet = new LinkedHashSet();
051
052        // Pipelined function stitching state
053        private final Map<String, List<String>> objectTypeIndex = new LinkedHashMap<>();
054        private final Map<String, String> collectionToElementTypeIndex = new LinkedHashMap<>();
055        private final Map<String, List<PipelinedFunctionSignature>> pipelinedSignatures = new LinkedHashMap<>();
056        private final List<PendingPipelinedCallSite> pendingPipelinedCallSites = new ArrayList<>();
057        private final Set<String> resolvingPipelinedFunctions = new HashSet<>();
058
059        public Map<String, Long> DISPLAY_ID = new LinkedHashMap<String, Long>();
060        public Map<Long, String> DISPLAY_NAME = new LinkedHashMap<Long, String>();
061        public Map<String, String> virtualTableNames = new LinkedHashMap<String, String>();
062
063        public long TABLE_COLUMN_ID = 0;
064        public long RELATION_ID = 0;
065        public int virtualTableIndex = -1;
066
067        private final static ThreadLocal localManager = new ThreadLocal();
068        private final static ThreadLocal globalDatabase = new ThreadLocal();
069        private final static ThreadLocal globalSchema = new ThreadLocal();
070        private final static ThreadLocal globalVendor = new ThreadLocal();
071        private final static ThreadLocal globalSQLEnv = new ThreadLocal();
072        private final static ThreadLocal globalHash = new ThreadLocal();
073        private final static ThreadLocal globalStmtStack = new ThreadLocal();
074        private final static ThreadLocal globalSqlInfo = new ThreadLocal();
075        private final static ThreadLocal globalOption = new ThreadLocal();
076        private final static ThreadLocal globalOraclePackage = new ThreadLocal();
077        private final static ThreadLocal globalProcedure = new ThreadLocal();
078
079        public static void set(ModelBindingManager modelManager) {
080                if (modelManager != null) {
081                        localManager.set(modelManager);
082                }
083        }
084
085        public static ModelBindingManager get() {
086                return (ModelBindingManager) localManager.get();
087        }
088
089        public static void setGlobalDatabase(String database) {
090                if (database != null) {
091                        globalDatabase.set(database);
092                }
093        }
094
095        public static String getGlobalDatabase() {
096                return (String) globalDatabase.get();
097        }
098
099        public static void removeGlobalDatabase() {
100                globalDatabase.remove();
101        }
102
103        public static void setGlobalSchema(String schema) {
104                if (schema != null) {
105                        globalSchema.set(schema);
106                }
107        }
108
109        public static void removeGlobalSchema() {
110                globalSchema.remove();
111        }
112
113        public static String getGlobalSchema() {
114                return (String) globalSchema.get();
115        }
116
117        public static void setGlobalHash(String hash) {
118                if (hash != null) {
119                        globalHash.set(hash);
120                }
121        }
122
123        public static void removeGlobalHash() {
124                globalHash.remove();
125        }
126
127        public static String getGlobalHash() {
128                return (String) globalHash.get();
129        }
130
131        public static void setGlobalOraclePackage(OraclePackage currentOraclePackage) {
132                if (currentOraclePackage != null) {
133                        globalOraclePackage.set(currentOraclePackage);
134                }
135        }
136
137        public static void removeGlobalOraclePackage() {
138                globalOraclePackage.remove();
139        }
140
141        public static OraclePackage getGlobalOraclePackage() {
142                return (OraclePackage) globalOraclePackage.get();
143        }
144        
145        public static void setGlobalProcedure(TStoredProcedureSqlStatement procedureSqlStatement) {
146                if (procedureSqlStatement != null) {
147                        globalProcedure.set(procedureSqlStatement);
148                }
149        }
150
151        public static void removeGlobalProcedure() {
152                globalProcedure.remove();
153                ModelBindingManager.get().cleanTempTable();
154        }
155
156        public static TStoredProcedureSqlStatement getGlobalProcedure() {
157                return (TStoredProcedureSqlStatement) globalProcedure.get();
158        }
159        
160        public static void setGlobalVendor(EDbVendor vendor) {
161                if (vendor != null) {
162                        globalVendor.set(vendor);
163                }
164        }
165
166        public static void removeGlobalVendor() {
167                globalVendor.remove();
168        }
169
170        public static EDbVendor getGlobalVendor() {
171                return (EDbVendor) globalVendor.get();
172        }
173
174        public static void setGlobalSQLEnv(TSQLEnv sqlenv) {
175                if (sqlenv != null) {
176                        globalSQLEnv.set(sqlenv);
177                }
178        }
179
180        public static void removeGlobalSQLEnv() {
181                globalSQLEnv.remove();
182        }
183
184        public static TSQLEnv getGlobalSQLEnv() {
185                return (TSQLEnv) globalSQLEnv.get();
186        }
187
188        public static String getGlobalServer() {
189                TSQLEnv sqlEnv = getGlobalSQLEnv();
190                if (sqlEnv != null)
191                        return TSQLEnv.DEFAULT_SERVER_NAME.equals(sqlEnv.getDefaultServerName()) ? null : sqlEnv.getDefaultServerName();
192                return null;
193        }
194
195        public static void setGlobalStmtStack(Stack<TCustomSqlStatement> stack) {
196                if (stack != null) {
197                        globalStmtStack.set(stack);
198                }
199        }
200
201        public static void removeGlobalStmtStack() {
202                globalStmtStack.remove();
203        }
204        
205        public static void setGlobalSqlInfo(IndexedLinkedHashMap<String, List<SqlInfo>> sqlInfoMap) {
206                if (sqlInfoMap != null) {
207                        globalSqlInfo.set(sqlInfoMap);
208                }
209        }
210
211        public static void removeGlobalSqlInfo() {
212                globalSqlInfo.remove();
213        }
214
215        public static IndexedLinkedHashMap<String, List<SqlInfo>> getGlobalSqlInfo() {
216                return (IndexedLinkedHashMap<String, List<SqlInfo>>) globalSqlInfo.get();
217        }
218
219        public static void setGlobalOption(Option option) {
220                if (option != null) {
221                        globalOption.set(option);
222                }
223        }
224        
225        public static Option getGlobalOption() {
226                return (Option) globalOption.get();
227        }
228
229        public static void removeGlobalOption() {
230                globalOption.remove();
231        }
232
233        public static Stack<TCustomSqlStatement> getGlobalStmtStack() {
234                return (Stack<TCustomSqlStatement>) globalStmtStack.get();
235        }
236
237        public static void remove() {
238                localManager.remove();
239                globalDatabase.remove();
240                globalSchema.remove();
241                globalVendor.remove();
242                globalSQLEnv.remove();
243                globalHash.remove();
244                globalStmtStack.remove();
245                globalOption.remove();
246                globalSqlInfo.remove();
247        }
248
249        public void bindModel(Object gspModel, Object relationModel) {
250                if(gspModel == null) {
251                        return;
252                }
253                modelBindingMap.put(gspModel, relationModel);
254
255                TTable table = null;
256                if (gspModel instanceof TTable && !(gspModel instanceof TCTE)) {
257                        table = ((TTable) gspModel);
258                } else if (gspModel instanceof Table) {
259                        table = ((Table) gspModel).getTableObject();
260                } else if (gspModel instanceof QueryTable) {
261                        table = ((QueryTable) gspModel).getTableObject();
262                } else if (gspModel instanceof TCTE) {
263                        TTableList tables = ((TCTE) gspModel).getPreparableStmt().tables;
264                        for (int j = 0; j < tables.size(); j++) {
265                                TTable item = tables.getTable(j);
266                                if (item != null && !SQLUtil.isEmpty(item.getAliasName())) {
267                                        TCustomSqlStatement stmt = ((TCTE) gspModel).getPreparableStmt();
268                                        if (tableHashMap.containsKey(stmt)) {
269                                                tableAliasMap.put(
270                                                                tableHashMap.get(stmt) + ":" + DlineageUtil.getIdentifierNormalTableName(item.getAliasName()),
271                                                                item);
272                                        } else {
273                                                String sql = stmt.toString();
274                                                if(sql == null){
275                                                        System.err.println("Current statement toString() returns null.");
276                                                        continue;
277                                                }
278                                                String hash = SHA256.getMd5(sql);
279                                                tableHashMap.put(stmt, hash);
280                                                tableAliasMap.put(hash + ":" + DlineageUtil.getIdentifierNormalTableName(item.getAliasName()), item);
281                                        }
282                                }
283
284                                if (item != null) {
285                                        tableSet.add(item);
286                                }
287                        }
288                } else if (gspModel instanceof Pair && ((Pair) gspModel).first instanceof Table) {
289                        table = ((Table) ((Pair) gspModel).first).getTableObject();
290                }
291
292                if (table == null && relationModel instanceof QueryTable) {
293                        table = ((QueryTable) relationModel).getTableObject();
294                }
295
296                updateTableAliasMap(table);
297
298                if (table != null) {
299                        tableSet.add(table);
300                }
301                
302                if(relationModel instanceof ResultSet) {
303                        resultSetSet.add(relationModel);
304                }
305        }
306
307        protected void updateTableAliasMap(TTable table) {
308                if (table != null && !SQLUtil.isEmpty(table.getAliasName())) {
309                        TCustomSqlStatement stmt = ModelBindingManager.getGlobalStmtStack().peek();
310                        if (tableHashMap.containsKey(stmt)) {
311                                tableAliasMap.put(tableHashMap.get(stmt) + ":" + DlineageUtil.getIdentifierNormalTableName(table.getAliasName()),
312                                                table);
313                        } else {
314                                String sql = stmt.toString();
315                                if(sql == null){
316                                        System.err.println("Current statement toString() returns null.");
317                                }
318                                else {
319                                        String hash = SHA256.getMd5(sql);
320                                        tableHashMap.put(stmt, hash);
321                                        tableAliasMap.put(hash + ":" + DlineageUtil.getIdentifierNormalTableName(table.getAliasName()),
322                                                        table);
323                                }
324                        }
325                }
326        }
327
328        public Object getModel(Object gspModel) {
329                if (gspModel == null) {
330                        return null;
331                }
332
333                if (gspModel instanceof TTable && !(gspModel instanceof TCTE)) {
334                        TTable table = (TTable) gspModel;
335                        if (table.getCTE() != null) {
336                                Object result =  modelBindingMap.get(table.getCTE());
337                                if (result != null) {
338                                        return result;
339                                }
340                        }
341                        if (table.getAliasClause() != null && table.getAliasClause().getColumns() != null) {
342                                Object result = modelBindingMap.get(table.getAliasClause().getColumns());
343                                if (result != null) {
344                                        return result;
345                                }
346                        }
347                        if (table.getSubquery() != null && !table.getSubquery().isCombinedQuery()) {
348                                Object result =  modelBindingMap.get(table.getSubquery().getResultColumnList());
349                                if (result != null) {
350                                        return result;
351                                }
352                        }
353                }
354                if (gspModel instanceof TSelectSqlStatement) {
355                        TSelectSqlStatement select = (TSelectSqlStatement) gspModel;
356                        if (!select.isCombinedQuery()) {
357                                if (select.getResultColumnList() != null) {
358                                        Object result = modelBindingMap.get(select.getResultColumnList());
359                                        if (result != null) {
360                                                return result;
361                                        }
362                                }
363                                else if (select.getTransformClause() != null) {
364                                        Object result = modelBindingMap.get(select.getTransformClause());
365                                        if (result != null) {
366                                                return result;
367                                        }
368                                }
369                        }
370                }
371                Object result = modelBindingMap.get(gspModel);
372                if (result == null) {
373                        result = createModelBindingMap.get(gspModel);
374                }
375                if (result == null) {
376                        result = insertModelBindingMap.get(gspModel);
377                }
378                if (result == null) {
379                        result = updateModelBindingMap.get(gspModel);
380                }
381                if (result == null) {
382                        result = mergeModelBindingMap.get(gspModel);
383                }
384                if (result == null) {
385                        result = viewModelBindingMap.get(gspModel);
386                }
387                if (result == null) {
388                        result = cursorModelBindingMap.get(gspModel);
389                }
390
391                if (result == null && gspModel instanceof TTable) {
392                        result = getCreateTable((TTable) gspModel);
393                }
394
395                if (result == null && gspModel instanceof TTable) {
396                        result = (Table) getCreateModel((TTable) gspModel);
397                }
398
399                if (result == null && gspModel instanceof TTable) {
400                        TTable table = (TTable) gspModel;
401                        if (table.getLinkTable() != null) {
402                                result = (Table) getTableByName(
403                                                DlineageUtil.getTableFullName(table.getLinkTable().getTableName().toString()));
404                                if (result == null) {
405                                        result = (Table) getTableByName(
406                                                        DlineageUtil.getTableFullNameWithDefaultSchema(table.getLinkTable().getTableName().toString()));
407                                }
408                        } else {
409                                result = (Table) getTableByName(
410                                                DlineageUtil.getTableFullName(((TTable) gspModel).getTableName().toString()));
411                                if (result == null) {
412                                        result = (Table) getTableByName(
413                                                        DlineageUtil.getTableFullNameWithDefaultSchema(((TTable) gspModel).getTableName().toString()));
414                                }
415                        }
416                }
417                
418                if (result == null && gspModel instanceof TTable) {
419                        TTable table = (TTable) gspModel;
420                        if(table.getFuncCall()!=null) {
421                                result = getModel(table.getFuncCall());
422                        }
423                }
424                
425                if (result == null && gspModel instanceof TTable) {
426                        TTable table = (TTable) gspModel;
427                        Table tableModel = new Table(table);
428                        result = (Table) getTableByName(DlineageUtil.getTableFullName(tableModel.getName()));
429                }
430
431                return result;
432        }
433
434        public List<Procedure> getProcedureModels(){
435                List<Procedure> procedures = new ArrayList<Procedure>();
436                for (Object obj : modelBindingMap.values()) {
437                        if(obj instanceof Procedure && !procedures.contains(obj)){
438                                procedures.add((Procedure)obj);
439                        }
440                }
441                return procedures;
442        }
443        
444        public List<OraclePackage> getOraclePackageModels(){
445                List<OraclePackage> oraclePackages = new ArrayList<OraclePackage>();
446                for (Object obj : modelBindingMap.values()) {
447                        if(obj instanceof OraclePackage && !oraclePackages.contains(obj)){
448                                oraclePackages.add((OraclePackage)obj);
449                        }
450                }
451                return oraclePackages;
452        }
453        
454        public List<Process> getProcessModels(){
455                List<Process> processes = new ArrayList<Process>();
456                for (Object obj : processModelBindingMap.values()) {
457                        if(obj instanceof Process && !processes.contains(obj)){
458                                processes.add((Process)obj);
459                        }
460                }
461                return processes;
462        }
463        
464        public void bindProcessModel(TParseTreeNode gspModel, Object relationModel) {
465                processModelBindingMap.put(gspModel, relationModel);
466        }
467
468        public void unbindProcessModel(TParseTreeNode gspModel) {
469                processModelBindingMap.remove(gspModel);
470        }
471
472        public Process getProcessModel(TParseTreeNode gspModel) {
473                return (Process)processModelBindingMap.get(gspModel);
474        }
475        
476        public void bindViewModel(Object gspModel, Object relationModel) {
477                viewModelBindingMap.put(gspModel, relationModel);
478        }
479        
480        public Object getViewModel(Object gspModel) {
481                return viewModelBindingMap.get(gspModel);
482        }
483
484        public void bindUpdateModel(Object gspModel, Object relationModel) {
485                updateModelBindingMap.put(gspModel, relationModel);
486        }
487
488        public Object getUpdateModel(Object gspModel) {
489                return updateModelBindingMap.get(gspModel);
490        }
491
492        public void bindMergeModel(Object gspModel, Object relationModel) {
493                mergeModelBindingMap.put(gspModel, relationModel);
494        }
495
496        public Object getMergeModel(Object gspModel) {
497                return mergeModelBindingMap.get(gspModel);
498        }
499
500        public void bindInsertModel(Object gspModel, Object relationModel) {
501                insertModelBindingMap.put(gspModel, relationModel);
502        }
503
504        public Object getInsertModel(Object gspModel) {
505                return insertModelBindingMap.get(gspModel);
506        }
507
508        public void bindTableFunction(Object gspModel, Object functionTable) {
509                if (functionTableMap.containsKey(gspModel)) {
510                        ((Set) functionTableMap.get(gspModel)).add(functionTable);
511                } else {
512                        Set tableSet = new LinkedHashSet();
513                        tableSet.add(functionTable);
514                        functionTableMap.put(gspModel, tableSet);
515                }
516        }
517
518        public Set<Object> getFunctionTable(Object gspModel) {
519                Set<Object> result = (Set<Object>)functionTableMap.get(gspModel);
520                if (result == null && gspModel instanceof String) {
521                        for (Object key : functionTableMap.keySet()) {
522                                if(!(key instanceof String)) {
523                                        continue;
524                                }
525                                String keyString = (String) key;
526                                String modelString = (String) gspModel;
527                                
528                                if (keyString.indexOf(".") != -1 && modelString.indexOf(".") == -1) {
529                                        keyString = keyString.substring(keyString.lastIndexOf(".") + 1);
530                                        if (keyString.equalsIgnoreCase(modelString)) {
531                                                return (Set<Object>)functionTableMap.get(key);
532                                        }
533                                }
534                                if (keyString.indexOf(".") == -1 && modelString.indexOf(".") != -1) {
535                                        modelString = modelString.substring(modelString.lastIndexOf(".") + 1);
536                                        if (keyString.equalsIgnoreCase(modelString)) {
537                                                return (Set<Object>)functionTableMap.get(key);
538                                        }
539                                }
540                                
541                        }
542                }
543                return result;
544        }
545
546        public Table getCreateTable(TTable table) {
547                if (table != null && table.getFullName() != null) {
548                        return (Table) createModelQuickBindingMap.get(DlineageUtil.getTableFullName(table.getTableName().toString()));
549                }
550                if(modelBindingMap.get(table) instanceof Table) {
551                        return (Table)modelBindingMap.get(table);
552                }
553                return null;
554        }
555
556        public Table getCreateModel(TTable table) {
557                return (Table) createModelBindingMap.get(table);
558        }
559
560        public void bindCreateModel(TTable table, Table tableModel) {
561                createModelBindingMap.put(table, tableModel);
562                if (!createModelQuickBindingMap.containsKey(DlineageUtil.getTableFullName(table.getTableName().toString()))) {
563                        createModelQuickBindingMap.put(DlineageUtil.getTableFullName(table.getTableName().toString()), tableModel);
564                }
565        }
566
567        public void bindCreateModel(TObjectName tableName, Table tableModel) {
568                if (!createModelQuickBindingMap.containsKey(DlineageUtil.getTableFullName(tableName.toString()))) {
569                        createModelQuickBindingMap.put(DlineageUtil.getTableFullName(tableName.toString()), tableModel);
570                }
571        }
572        
573        public void bindCreateModel(String tableName, Table tableModel) {
574                if (!createModelQuickBindingMap.containsKey(DlineageUtil.getTableFullName(tableName))) {
575                        createModelQuickBindingMap.put(DlineageUtil.getTableFullName(tableName), tableModel);
576                }
577        }
578
579        public TObjectName[] getTableColumns(TTable table) {
580                Table createTable = getCreateTable(table);
581                if (createTable != null) {
582                        List<TableColumn> columnList = createTable.getColumns();
583                        TObjectName[] columns = new TObjectName[columnList.size()];
584                        for (int i = 0; i < columns.length; i++) {
585                                columns[i] = columnList.get(i).getColumnObject();
586                        }
587                        Arrays.sort(columns, new Comparator<TObjectName>() {
588
589                                @Override
590                                public int compare(TObjectName o1, TObjectName o2) {
591                                        if (o1 == null) {
592                                                return -1;
593                                        }
594                                        if (o2 == null) {
595                                                return 1;
596                                        }
597                                        return o1.getStartToken().posinlist - o2.getStartToken().posinlist;
598                                }
599                        });
600                        return columns;
601                }
602                else if(modelBindingMap.get(table) instanceof QueryTable) {
603                        QueryTable queryTable = (QueryTable)modelBindingMap.get(table);
604                        List<TObjectName> columns = new ArrayList<TObjectName>();
605                        for (ResultColumn resultColumn : queryTable.getColumns()) {
606                                if(resultColumn.hasStarLinkColumn()) {
607                                        for(TObjectName column: resultColumn.getStarLinkColumnList()) {
608                                                columns.add(column);
609                                        }
610                                }
611                                else if (resultColumn.getColumnObject() instanceof TResultColumn) {
612                                        TResultColumn columnObject = ((TResultColumn) resultColumn.getColumnObject());
613                                        TAliasClause alias = columnObject.getAliasClause();
614                                        if (alias != null && alias.getAliasName() != null) {
615                                                columns.add(alias.getAliasName());
616                                        } else {
617                                                if (columnObject.getFieldAttr() != null) {
618                                                        columns.add(columnObject.getFieldAttr());
619                                                } else {
620                                                        TObjectName column = new TObjectName();
621                                                        if (columnObject.getExpr().getExpressionType() == EExpressionType.typecast_t) {
622                                                                column.setString(columnObject.getExpr().getLeftOperand().toString());
623                                                        } else {
624                                                                column.setString(columnObject.toString());
625                                                        }
626                                                        columns.add(column);
627                                                }
628                                        }
629                                } else if (resultColumn.getColumnObject() instanceof TObjectName) {
630                                        columns.add((TObjectName) resultColumn.getColumnObject());
631                                }
632                        }
633                        return columns.toArray(new TObjectName[0]);
634                }
635
636                TObjectNameList list = table.getLinkedColumns();
637                List<TObjectName> columns = new ArrayList<TObjectName>();
638
639                if (table.getCTE() != null) {
640                        ResultSet resultSet = (ResultSet) getModel(table.getCTE());
641                        if (resultSet != null) {
642                                List<ResultColumn> columnList = resultSet.getColumns();
643                                for (int i = 0; i < columnList.size(); i++) {
644                                        ResultColumn resultColumn = columnList.get(i);
645                                        if (resultColumn.getColumnObject() instanceof TResultColumn) {
646                                                TResultColumn columnObject = ((TResultColumn) resultColumn.getColumnObject());
647                                                TAliasClause alias = columnObject.getAliasClause();
648                                                if (alias != null && alias.getAliasName() != null) {
649                                                        columns.add(alias.getAliasName());
650                                                } else {
651                                                        if (columnObject.getFieldAttr() != null) {
652                                                                columns.add(columnObject.getFieldAttr());
653                                                        } else {
654                                                                continue;
655                                                        }
656                                                }
657                                        } else if (resultColumn.getColumnObject() instanceof TObjectName) {
658                                                columns.add((TObjectName) resultColumn.getColumnObject());
659                                        }
660                                }
661                        }
662                } else if (list.size() == 1 && list.toString().indexOf("*") != -1 && table.getSubquery() != null) {
663                        addSubqueryColumns(table, columns);
664                } else {
665                        for (int i = 0; i < list.size(); i++) {
666                                TObjectName object = list.getObjectName(i);
667                                if (object.toString().indexOf("*") != -1 && table.getSubquery() != null) {
668                                        addSubqueryColumns(table, columns);
669                                }
670                                else 
671                                        columns.add(object);
672                        }
673                }
674                Collections.sort(columns, new Comparator<TObjectName>() {
675
676                        @Override
677                        public int compare(TObjectName o1, TObjectName o2) {
678                                return o1.getStartToken().posinlist - o2.getStartToken().posinlist;
679                        }
680                });
681                return columns.toArray(new TObjectName[0]);
682        }
683
684        private void addSubqueryColumns(TTable table, List<TObjectName> columns) {
685                ResultSet resultSet = (ResultSet) getModel(table.getSubquery());
686                if (resultSet != null) {
687                        List<ResultColumn> columnList = resultSet.getColumns();
688                        for (int i = 0; i < columnList.size(); i++) {
689                                ResultColumn resultColumn = columnList.get(i);
690                                if (resultColumn.getColumnObject() instanceof TResultColumn) {
691                                        TResultColumn columnObject = ((TResultColumn) resultColumn.getColumnObject());
692                                        TAliasClause alias = columnObject.getAliasClause();
693                                        if (alias != null && alias.getAliasName() != null) {
694                                                columns.add(alias.getAliasName());
695                                        } else {
696                                                if (columnObject.getFieldAttr() != null) {
697                                                        columns.add(columnObject.getFieldAttr());
698                                                } else {
699                                                        TObjectName column = new TObjectName();
700                                                        if (columnObject.getExpr().getExpressionType() == EExpressionType.typecast_t) {
701                                                                column.setString(columnObject.getExpr().getLeftOperand().toString());
702                                                        } else {
703                                                                column.setString(columnObject.toString());
704                                                        }
705                                                        columns.add(column);
706                                                }
707                                        }
708                                } else if (resultColumn.getColumnObject() instanceof TObjectName) {
709                                        columns.add((TObjectName) resultColumn.getColumnObject());
710                                }
711                        }
712                }
713        }
714
715        public TTable getTableFromColumn(TObjectName column) {
716                if (column.getSourceTable() != null) {
717                        return column.getSourceTable();
718                }
719
720                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
721                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
722                        while (peekStmt != null) {
723                                TTable table = null;
724                                if (tableHashMap.containsKey(peekStmt)) {
725                                        table = tableAliasMap.get(tableHashMap.get(peekStmt) + ":"
726                                                        + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
727                                }
728                                if (table != null) {
729                                        return table;
730                                } else {
731                                        peekStmt = peekStmt.getParentStmt();
732                                }
733                        }
734                }
735                return null;
736        }
737        
738        public TTable getTable(TCustomSqlStatement stmt, TObjectName column) {
739                if (column.getSourceTable() != null) {
740                        return column.getSourceTable();
741                }
742
743                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
744                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
745                        while (peekStmt != null) {
746                                TTable table = null;
747                                if (tableHashMap.containsKey(peekStmt)) {
748                                        table = tableAliasMap.get(tableHashMap.get(peekStmt) + ":"
749                                                        + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
750                                }
751                                if (table != null && table.getSubquery() != stmt)
752                                        return table;
753                                
754                                if (peekStmt.getTables() != null) {
755                                        for (TTable tableItem : peekStmt.getTables()) {
756                                                if (DlineageUtil.getIdentifierNormalTableName(tableItem.getTableName().toString())
757                                                                .equals(DlineageUtil.getIdentifierNormalTableName(column.getTableString()))) {
758                                                        return tableItem;
759                                                }
760                                        }
761                                }
762                                
763                                peekStmt = peekStmt.getParentStmt();
764                        }
765                }
766
767                if (stmt.getTables() != null) {
768                        for (int j = 0; j < stmt.getTables().size(); j++) {
769                                TTable table = (TTable) stmt.getTables().getTable(j);
770                                if (table.getSubquery() == stmt)
771                                        continue;
772
773                                TObjectName[] columns = getTableColumns(table);
774                                for (int i = 0; i < columns.length; i++) {
775                                        TObjectName columnName = columns[i];
776                                        if (columnName == null || "*".equals(columnName.getColumnNameOnly()))
777                                                continue;
778                                        if (DlineageUtil.getIdentifierNormalColumnName(columnName.toString())
779                                                        .equals(DlineageUtil.getIdentifierNormalColumnName(column.toString()))) {
780                                                if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
781                                                        return table;
782                                                }
783                                        }
784                                        if (!SQLUtil.isEmpty(columnName.getColumnNameOnly())
785                                                        && DlineageUtil.getIdentifierNormalColumnName(columnName.getColumnNameOnly())
786                                                                        .equals(DlineageUtil.getIdentifierNormalColumnName(column.getColumnNameOnly()))) {
787                                                if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
788                                                        return table;
789                                                }
790                                        }
791                                }
792                        }
793                }
794
795                // Iterator iter = tableSet.iterator();
796                // while (iter.hasNext()) {
797                // TTable table = (TTable) iter.next();
798                //
799                // if (table.getSubquery() == stmt)
800                // continue;
801                //
802                // if (table.getSubquery() != null) {
803                // int start = table.getSubquery().getStartToken().posinlist;
804                // int end = table.getSubquery().getEndToken().posinlist;
805                // if (start <= stmt.getStartToken().posinlist && end >=
806                // stmt.getEndToken().posinlist) {
807                // continue;
808                // }
809                // }
810                //
811                // TObjectName[] columns = getTableColumns(table);
812                // for (int i = 0; i < columns.length; i++) {
813                // TObjectName columnName = columns[i];
814                // if (columnName == null || "*".equals(columnName.getColumnNameOnly()))
815                // continue;
816                // if
817                // (DlineageUtil.getIdentifierNormalName(columnName.toString()).equals(DlineageUtil.getIdentifierNormalName(column.toString())))
818                // {
819                // if (columnName.getSourceTable() == null
820                // || columnName.getSourceTable() == table) {
821                // return table;
822                // }
823                // }
824                // if (columnName.getColumnNameOnly()!=null &&
825                // DlineageUtil.getIdentifierNormalName(columnName.getColumnNameOnly()).equals(DlineageUtil.getIdentifierNormalName(column.getColumnNameOnly())))
826                // {
827                // if (columnName.getSourceTable() == null
828                // || columnName.getSourceTable() == table) {
829                // return table;
830                // }
831                // }
832                // }
833                // }
834                return null;
835        }
836
837        public TTable guessTable(TCustomSqlStatement stmt, TObjectName column) {
838                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
839                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
840                        TTable table = null;
841                        if (tableHashMap.containsKey(peekStmt)) {
842                                table = tableAliasMap.get(
843                                                tableHashMap.get(peekStmt) + ":" + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
844                        }
845                        if (table != null && table.getSubquery() != stmt)
846                                return table;
847                }
848
849                Iterator iter = tableSet.iterator();
850                while (iter.hasNext()) {
851                        TTable table = (TTable) iter.next();
852
853                        if (table.getSubquery() == stmt)
854                                continue;
855
856                        TObjectName[] columns = getTableColumns(table);
857                        for (int i = 0; i < columns.length; i++) {
858                                TObjectName columnName = columns[i];
859                                if ("*".equals(columnName.getColumnNameOnly()))
860                                        continue;
861                                if (columnName.toString().equalsIgnoreCase(column.toString())) {
862                                        if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
863                                                return table;
864                                        }
865                                }
866                        }
867                }
868                return null;
869        }
870
871        public List<Table> getTablesByName() {
872                List<Table> tables = new ArrayList<Table>();
873                Iterator iter = tableNamesMap.values().iterator();
874                while (iter.hasNext()) {
875                        tables.add((Table) iter.next());
876                }
877                return tables;
878        }
879
880        public List<TTable> getBaseTables() {
881                List<TTable> tables = new ArrayList<TTable>();
882
883                Iterator iter = modelBindingMap.keySet().iterator();
884                while (iter.hasNext()) {
885                        Object key = iter.next();
886                        if (!(key instanceof TTable)) {
887                                continue;
888                        }
889                        TTable table = (TTable) key;
890                        if (table.getSubquery() == null) {
891                                tables.add(table);
892                        }
893                }
894
895                iter = createModelBindingMap.keySet().iterator();
896                while (iter.hasNext()) {
897                        Object key = iter.next();
898                        if (!(key instanceof TTable)) {
899                                continue;
900                        }
901                        TTable table = (TTable) key;
902                        tables.add(table);
903                }
904
905                iter = insertModelBindingMap.keySet().iterator();
906                while (iter.hasNext()) {
907                        Object key = iter.next();
908                        if (!(key instanceof TTable)) {
909                                continue;
910                        }
911                        TTable table = (TTable) key;
912                        tables.add(table);
913                }
914
915                iter = mergeModelBindingMap.keySet().iterator();
916                while (iter.hasNext()) {
917                        Object key = iter.next();
918                        if (!(key instanceof TTable)) {
919                                continue;
920                        }
921                        TTable table = (TTable) key;
922                        tables.add(table);
923                }
924
925                iter = updateModelBindingMap.keySet().iterator();
926                while (iter.hasNext()) {
927                        Object key = iter.next();
928                        if (!(key instanceof TTable)) {
929                                continue;
930                        }
931                        TTable table = (TTable) key;
932                        if (!tables.contains(table)) {
933                                tables.add(table);
934                        }
935                }
936
937                return tables;
938        }
939
940        public List<TCustomSqlStatement> getViews() {
941                List<TCustomSqlStatement> views = new ArrayList<TCustomSqlStatement>();
942
943                Iterator iter = viewModelBindingMap.keySet().iterator();
944                while (iter.hasNext()) {
945                        Object key = iter.next();
946                        if (!(key instanceof TCreateViewSqlStatement) && !(key instanceof TCreateMaterializedSqlStatement)) {
947                                continue;
948                        }
949                        TCustomSqlStatement view = (TCustomSqlStatement) key;
950                        if (!views.contains(view)) {
951                                views.add(view);
952                        }
953                }
954                return views;
955        }
956
957        public List<TResultColumnList> getSelectResultSets() {
958                List<TResultColumnList> resultSets = new ArrayList<TResultColumnList>();
959
960                Iterator iter = modelBindingMap.keySet().iterator();
961                while (iter.hasNext()) {
962                        Object key = iter.next();
963                        if (!(key instanceof TResultColumnList)) {
964                                continue;
965                        }
966                        TResultColumnList resultset = (TResultColumnList) key;
967                        resultSets.add(resultset);
968                }
969                return resultSets;
970        }
971
972        public List<TObjectNameList> getQueryAliasTables() {
973                List<TObjectNameList> resultSets = new ArrayList<TObjectNameList>();
974
975                Iterator iter = modelBindingMap.keySet().iterator();
976                while (iter.hasNext()) {
977                        Object key = iter.next();
978                        if (!(key instanceof TObjectNameList)) {
979                                continue;
980                        }
981                        TObjectNameList resultset = (TObjectNameList) key;
982                        resultSets.add(resultset);
983                }
984                return resultSets;
985        }
986
987        public List<TSelectSqlStatement> getSelectSetResultSets() {
988                List<TSelectSqlStatement> resultSets = new ArrayList<TSelectSqlStatement>();
989
990                Iterator iter = modelBindingMap.keySet().iterator();
991                while (iter.hasNext()) {
992                        Object key = iter.next();
993                        if (!(key instanceof TSelectSqlStatement)) {
994                                continue;
995                        }
996
997                        TSelectSqlStatement stmt = (TSelectSqlStatement) key;
998                        if (stmt.getSetOperatorType() == ESetOperatorType.none)
999                                continue;
1000
1001                        resultSets.add(stmt);
1002                }
1003                return resultSets;
1004        }
1005
1006        public List<TCTE> getCTEs() {
1007                List<TCTE> resultSets = new ArrayList<TCTE>();
1008
1009                Iterator iter = modelBindingMap.keySet().iterator();
1010                while (iter.hasNext()) {
1011                        Object key = iter.next();
1012                        if (!(key instanceof TCTE)) {
1013                                continue;
1014                        }
1015
1016                        TCTE cte = (TCTE) key;
1017                        resultSets.add(cte);
1018                }
1019                return resultSets;
1020        }
1021
1022        public List<TTable> getTableWithSelectSetResultSets() {
1023                List<TTable> resultSets = new ArrayList<TTable>();
1024
1025                Iterator iter = modelBindingMap.keySet().iterator();
1026                while (iter.hasNext()) {
1027                        Object key = iter.next();
1028                        if (!(key instanceof TTable)) {
1029                                continue;
1030                        }
1031
1032                        if (((TTable) key).getSubquery() == null)
1033                                continue;
1034                        TSelectSqlStatement stmt = ((TTable) key).getSubquery();
1035                        if (stmt.getSetOperatorType() == ESetOperatorType.none)
1036                                continue;
1037
1038                        resultSets.add((TTable) key);
1039                }
1040                return resultSets;
1041        }
1042
1043        public List<TParseTreeNode> getMergeResultSets() {
1044                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1045
1046                Iterator iter = modelBindingMap.keySet().iterator();
1047                while (iter.hasNext()) {
1048                        Object key = iter.next();
1049                        if (!(key instanceof TMergeUpdateClause) && !(key instanceof TMergeInsertClause)) {
1050                                continue;
1051                        }
1052                        TParseTreeNode resultset = (TParseTreeNode) key;
1053                        resultSets.add(resultset);
1054                }
1055                return resultSets;
1056        }
1057
1058        public List<TParseTreeNode> getOutputResultSets() {
1059                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1060
1061                Iterator iter = modelBindingMap.keySet().iterator();
1062                while (iter.hasNext()) {
1063                        Object key = iter.next();
1064                        if (!(key instanceof TOutputClause)) {
1065                                continue;
1066                        }
1067                        TParseTreeNode resultset = (TParseTreeNode) key;
1068                        resultSets.add(resultset);
1069                }
1070                return resultSets;
1071        }
1072
1073        public List<TParseTreeNode> getUpdateResultSets() {
1074                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1075
1076                Iterator iter = modelBindingMap.keySet().iterator();
1077                while (iter.hasNext()) {
1078                        Object key = iter.next();
1079                        if (!(key instanceof TUpdateSqlStatement)) {
1080                                continue;
1081                        }
1082                        TParseTreeNode resultset = (TParseTreeNode) key;
1083                        resultSets.add(resultset);
1084                }
1085                return resultSets;
1086        }
1087
1088        public List<TParseTreeNode> getFunctoinCalls() {
1089                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1090
1091                Iterator iter = modelBindingMap.keySet().iterator();
1092                while (iter.hasNext()) {
1093                        Object key = iter.next();
1094                        if (!(key instanceof TFunctionCall) && !(key instanceof TCaseExpression)) {
1095                                continue;
1096                        }
1097                        TParseTreeNode resultset = (TParseTreeNode) key;
1098                        resultSets.add(resultset);
1099                }
1100                return resultSets;
1101        }
1102
1103        public List<TParseTreeNode> getAliases() {
1104                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1105
1106                Iterator iter = modelBindingMap.keySet().iterator();
1107                while (iter.hasNext()) {
1108                        Object key = iter.next();
1109                        if (!(key instanceof TAliasClause)) {
1110                                continue;
1111                        }
1112                        TParseTreeNode resultset = (TParseTreeNode) key;
1113                        resultSets.add(resultset);
1114                }
1115                return resultSets;
1116        }
1117        
1118        public List<TParseTreeNode> getCursors() {
1119                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1120
1121                Iterator iter = modelBindingMap.keySet().iterator();
1122                while (iter.hasNext()) {
1123                        Object key = iter.next();
1124                        if (!(key instanceof TCursorDeclStmt) && !(key instanceof TOpenforStmt)) {
1125                                continue;
1126                        }
1127                        TParseTreeNode resultset = (TParseTreeNode) key;
1128                        resultSets.add(resultset);
1129                }
1130                return resultSets;
1131        }
1132        
1133        public List<TParseTreeNode> getPivotdTables() {
1134                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1135
1136                Iterator iter = modelBindingMap.keySet().iterator();
1137                while (iter.hasNext()) {
1138                        Object key = iter.next();
1139                        if (!(key instanceof TPivotClause)) {
1140                                continue;
1141                        }
1142                        TParseTreeNode resultset = (TParseTreeNode) key;
1143                        resultSets.add(resultset);
1144                }
1145                return resultSets;
1146        }
1147
1148        public void addRelation(Relationship relation) {
1149                if (relation != null && !relationHolder.contains(relation)) {
1150                        relationHolder.add(relation);
1151                }
1152        }
1153        
1154        public void removeRelation(ImpactRelationship relation) {
1155                if (relation != null) {
1156                        relationHolder.remove(relation);
1157                }
1158        }
1159
1160        public Relationship[] getRelations() {
1161                return relationHolder.toArray(new Relationship[0]);
1162        }
1163
1164        public void reset() {
1165                modelBindingMap.clear();
1166                processModelBindingMap.clear();
1167                viewModelBindingMap.clear();
1168                insertModelBindingMap.clear();
1169                createModelBindingMap.clear();
1170                createModelQuickBindingMap.clear();
1171                mergeModelBindingMap.clear();
1172                updateModelBindingMap.clear();
1173                cursorModelBindingMap.clear();
1174                functionTableMap.clear();
1175                tableNamesMap.clear();
1176                dropTables.clear();
1177                procedureNamesMap.clear();
1178                oraclePackageNamesMap.clear();
1179                relationHolder.clear();
1180                tableAliasMap.clear();
1181                tableHashMap.clear();
1182                topStmtHashMap.clear();
1183                hashSQLMap.clear();
1184                dynamicSQLMap.clear();
1185                tableSet.clear();
1186                resultSetSet.clear();
1187                dblinkTableSet.clear();
1188                objectTypeIndex.clear();
1189                collectionToElementTypeIndex.clear();
1190                pipelinedSignatures.clear();
1191                pendingPipelinedCallSites.clear();
1192                resolvingPipelinedFunctions.clear();
1193                DISPLAY_ID.clear();
1194                DISPLAY_NAME.clear();
1195                virtualTableNames.clear();
1196        }
1197
1198        public void bindCursorModel(TCursorDeclStmt stmt, Variable resultSet) {
1199                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1200                String variableString = stmt.getCursorName().toString();
1201                if (variableString.startsWith(":")) {
1202                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1203                }
1204                if (!SQLUtil.isEmpty(procedureName)) {
1205                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1206                }
1207                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1208        }
1209        
1210        public void bindCursorModel(TMssqlDeclare stmt, Variable resultSet) {
1211                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1212                String variableString = stmt.getCursorName().toString();
1213                if (variableString.startsWith(":")) {
1214                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1215                }
1216                if (!SQLUtil.isEmpty(procedureName)) {
1217                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1218                }
1219                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1220        }
1221        
1222        public void bindCursorModel(TOpenforStmt stmt, Variable resultSet) {
1223                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1224                String variableString = stmt.getCursorVariableName().toString();
1225                if (variableString.startsWith(":")) {
1226                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1227                }
1228                if (!SQLUtil.isEmpty(procedureName)) {
1229                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1230                }
1231                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1232        }
1233        
1234        public void bindCursorModel(TForStmt stmt, Variable resultSet) {
1235                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1236                String variableString = stmt.getCursorName().toString();
1237                if (variableString.startsWith(":")) {
1238                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1239                }
1240                if (!SQLUtil.isEmpty(procedureName)) {
1241                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1242                }
1243                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1244        }
1245        
1246        public void bindCursorModel(TLoopStmt stmt, Variable resultSet) {
1247                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1248                String variableString = stmt.getRecordName().toString();
1249                if (variableString.startsWith(":")) {
1250                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1251                }
1252                if (!SQLUtil.isEmpty(procedureName)) {
1253                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1254                }
1255                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1256        }
1257
1258        public void bindCursorIndex(TObjectName indexName, TObjectName cursorName) {
1259                TCustomSqlStatement stmt = getGlobalStmtStack().peek();
1260                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1261                String variableString = cursorName.toString();
1262                if (variableString.startsWith(":")) {
1263                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1264                }
1265                if (!SQLUtil.isEmpty(procedureName)) {
1266                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1267                }
1268                
1269                Cursor cursor = ((Cursor) createModelBindingMap
1270                                .get(DlineageUtil.getTableFullName(variableString)));
1271                if (cursor != null) {
1272                        String indexNameString = indexName.toString();
1273                        if (!SQLUtil.isEmpty(procedureName)) {
1274                                indexNameString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(indexNameString);
1275                        }
1276                        bindModel(DlineageUtil.getTableFullName(indexNameString),
1277                                        modelBindingMap.get(cursor.getResultColumnObject()));
1278                        bindTableByName(DlineageUtil.getTableFullName(indexNameString),
1279                                        cursor);
1280                }
1281        }
1282
1283        public List<TStoredProcedureSqlStatement> getProcedures() {
1284                List<TStoredProcedureSqlStatement> procedures = new ArrayList();
1285                Iterator iter = this.modelBindingMap.keySet().iterator();
1286
1287                while (iter.hasNext()) {
1288                        Object key = iter.next();
1289                        if (key instanceof TStoredProcedureSqlStatement) {
1290                                TStoredProcedureSqlStatement procedure = (TStoredProcedureSqlStatement) key;
1291                                procedures.add(procedure);
1292                        }
1293                }
1294
1295                return procedures;
1296        }
1297
1298        // public void bindTableByName(TObjectName tableName, Table tableModel) {
1299        // tableNamesMap.put(tableName, tableModel);
1300        //
1301        // }
1302        //
1303        public void bindTableByName(String tableName, Table tableModel) {
1304                tableNamesMap.put(tableName, tableModel);
1305
1306        }
1307
1308        // public Table getTableByName(TObjectName tableName) {
1309        // return (Table)tableNamesMap.get(tableName);
1310        // }
1311
1312        public Table getTableByName(String tableName) {
1313                Table table = (Table) tableNamesMap.get(tableName);
1314                if (table == null) {
1315                        TCustomSqlStatement stmt = getGlobalStmtStack().peek();
1316                        String procedureName = DlineageUtil.getProcedureParentName(stmt);
1317                        String variableString = tableName.toString();
1318                        if (!SQLUtil.isEmpty(procedureName)) {
1319                                String variableWithProcedure = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1320                                if(tableNamesMap.containsKey(DlineageUtil.getTableFullName(variableWithProcedure))) {
1321                                        return  (Table) tableNamesMap.get(DlineageUtil.getTableFullName(variableWithProcedure));
1322                                }
1323                        }
1324                        return (Table) tableNamesMap.get(DlineageUtil.getTableFullName(variableString));
1325                } else {
1326                        return table;
1327                }
1328        }
1329
1330
1331        public void bindProcedureByName(String procedureName, Procedure procedureModel) {
1332                procedureNamesMap.put(procedureName, procedureModel);
1333
1334        }
1335        
1336        public Procedure getProcedureByName(String procedureName) {
1337                if(procedureName == null){
1338                        return null;
1339                }
1340
1341                if (ModelBindingManager.getGlobalOraclePackage() != null
1342                                && !procedureName.startsWith(ModelBindingManager.getGlobalOraclePackage().getName())) {
1343                        procedureName = ModelBindingManager.getGlobalOraclePackage().getName() + "." + procedureName;
1344                }
1345                Procedure procedure = (Procedure) procedureNamesMap.get(procedureName);
1346                if (procedure == null) {
1347                        if (procedureName.indexOf("(") == -1) {
1348                                for (Object name : procedureNamesMap.keySet()) {
1349                                        String fuctionName = name.toString();
1350                                        if (fuctionName.startsWith(procedureName + "(")) {
1351                                                return (Procedure) procedureNamesMap.get(name);
1352                                        }
1353                                        if (fuctionName.indexOf(".") != -1 && procedureName.indexOf(".") == -1) {
1354                                                fuctionName = fuctionName.substring(fuctionName.lastIndexOf(".") + 1);
1355                                                if (fuctionName.startsWith(procedureName + "(")) {
1356                                                        return (Procedure) procedureNamesMap.get(name);
1357                                                }
1358                                        }
1359                                        if (fuctionName.indexOf(".") == -1 && procedureName.indexOf(".") != -1) {
1360                                                String procedureNameSubstring = procedureName.substring(procedureName.lastIndexOf(".") + 1);
1361                                                if (fuctionName.startsWith(procedureNameSubstring + "(")) {
1362                                                        return (Procedure) procedureNamesMap.get(name);
1363                                                }
1364                                        }
1365                                }
1366                        }
1367                        else {
1368                                for (Object name : procedureNamesMap.keySet()) {
1369                                        String fuctionName = name.toString();
1370                                        if (fuctionName.startsWith(procedureName)) {
1371                                                return (Procedure) procedureNamesMap.get(name);
1372                                        }
1373                                        if (fuctionName.indexOf(".") != -1 && procedureName.indexOf(".") == -1) {
1374                                                fuctionName = fuctionName.substring(fuctionName.lastIndexOf(".") + 1);
1375                                                if (fuctionName.equalsIgnoreCase(procedureName)) {
1376                                                        return (Procedure) procedureNamesMap.get(name);
1377                                                }
1378                                        }
1379                                        if (fuctionName.indexOf(".") == -1 && procedureName.indexOf(".") != -1) {
1380                                                String procedureNameSubstring = procedureName.substring(procedureName.lastIndexOf(".") + 1);
1381                                                if (fuctionName.equalsIgnoreCase(procedureNameSubstring)) {
1382                                                        return (Procedure) procedureNamesMap.get(name);
1383                                                }
1384                                        }
1385                                }
1386                        }
1387                }
1388                return procedure;
1389        }
1390        
1391        public void bindOraclePackageByName(String oraclePackageName, OraclePackage oraclePackageModel) {
1392                oraclePackageNamesMap.put(oraclePackageName, oraclePackageModel);
1393
1394        }
1395        
1396        public OraclePackage getOraclePackageByName(String oraclePackageName) {
1397                return (OraclePackage) oraclePackageNamesMap.get(oraclePackageName);
1398        }
1399
1400
1401        public String getSqlHash(TCustomSqlStatement stmt) {
1402                return topStmtHashMap.get(stmt);
1403        }
1404
1405        public Map getHashSQLMap() {
1406                return hashSQLMap;
1407        }
1408
1409        public Map getDynamicSQLMap() {
1410                return dynamicSQLMap;
1411        }
1412
1413        public void collectSqlHash(TCustomSqlStatement stmt) {
1414                if (getGlobalOption().getAnalyzeMode() == AnalyzeMode.crud) {
1415                        String sql = stmt.toString();
1416                        if (sql != null) {
1417                                sql = stmt.getStartToken().lineNo + ":" + sql;
1418                                String hash = SQLUtil.stringToMD5(sql);
1419                                topStmtHashMap.put(stmt, hash);
1420                                hashSQLMap.put(hash, new Pair3<Long, Long, String>(stmt.getStartToken().lineNo, stmt.getEndToken().lineNo, ModelBindingManager.getGlobalHash()));
1421                        }
1422                } else {
1423                        try {
1424                                String sql = stmt.asCanonical();
1425                                if (sql != null) {
1426                                        String hash = SQLUtil.stringToMD5(sql);
1427                                        topStmtHashMap.put(stmt, hash);
1428                                        hashSQLMap.put(hash, sql);
1429                                }
1430                        } catch (Exception e) {
1431                                logger.error("collectSqlHash error: " + e.getMessage(), e);
1432                        }
1433                }
1434        }
1435        
1436        public void collectDynamicSqlHash(TCustomSqlStatement stmt) {
1437                if (getGlobalOption().getAnalyzeMode() == AnalyzeMode.dynamic) {
1438                        String sql = stmt.toString();
1439                        if (sql != null) {
1440                                sql = stmt.getStartToken().lineNo + ":" + sql;
1441                                String hash = SQLUtil.stringToMD5(sql);
1442                                dynamicSQLMap.put(hash, new Pair3<Long, Long, String>(stmt.getStartToken().lineNo, stmt.getEndToken().lineNo, ModelBindingManager.getGlobalHash()));
1443                        }
1444                }
1445        }
1446
1447        public void appendDblinkTable(String name) {
1448                if (!SQLUtil.isEmpty(name)) {
1449                        dblinkTableSet.add(name);
1450                }
1451        }
1452        
1453        public boolean isDblinkTable(String name) {
1454                return dblinkTableSet.contains(name);
1455        }
1456
1457        public Set<ResultSet> getResultSets() {
1458                return resultSetSet;
1459        }
1460        
1461        public void dropTable(Table table) {
1462                List tableNames = new ArrayList(tableNamesMap.keySet());
1463                for (Object tableName : tableNames) {
1464                        if(tableNamesMap.get(tableName) == table) {
1465                                tableNamesMap.remove(tableName);
1466                                dropTables.add(table);
1467                        }
1468                }
1469        }
1470        
1471        public void cleanTempTable() {
1472                Iterator<String> iter = tableNamesMap.keySet().iterator();
1473                while(iter.hasNext()) {
1474                        String tableName = iter.next();
1475                        if(DlineageUtil.isTempTable((Table)tableNamesMap.get(tableName), getGlobalVendor())) {
1476                                dropTables.add((Table)tableNamesMap.get(tableName));
1477                                iter.remove();
1478                        }
1479                }
1480        }
1481
1482        public Set<Table> getDropTables() {
1483                return dropTables;
1484        }
1485
1486        // --- Pipelined function stitching methods ---
1487
1488        public void indexObjectType(String normalizedName, List<String> fieldNames) {
1489                objectTypeIndex.put(normalizedName, fieldNames);
1490        }
1491
1492        public List<String> getObjectTypeFields(String normalizedName) {
1493                return objectTypeIndex.get(normalizedName);
1494        }
1495
1496        public void indexCollectionType(String collectionName, String elementTypeName) {
1497                collectionToElementTypeIndex.put(collectionName, elementTypeName);
1498        }
1499
1500        public String getElementTypeName(String collectionName) {
1501                return collectionToElementTypeIndex.get(collectionName);
1502        }
1503
1504        public void addPipelinedSignature(PipelinedFunctionSignature sig) {
1505                pipelinedSignatures.computeIfAbsent(sig.getFunctionKey(), k -> new ArrayList<>()).add(sig);
1506                if (sig.getNakedKey() != null && !sig.getNakedKey().equals(sig.getFunctionKey())) {
1507                        pipelinedSignatures.computeIfAbsent(sig.getNakedKey(), k -> new ArrayList<>()).add(sig);
1508                }
1509        }
1510
1511        public PipelinedFunctionSignature findPipelinedSignature(List<String> candidates, int argCount) {
1512                for (String key : candidates) {
1513                        List<PipelinedFunctionSignature> sigs = pipelinedSignatures.get(key);
1514                        if (sigs != null) {
1515                                PipelinedFunctionSignature match = null;
1516                                for (PipelinedFunctionSignature sig : sigs) {
1517                                        if (sig.getArgCount() == argCount || argCount < 0) {
1518                                                if (match != null) {
1519                                                        return null; // ambiguous
1520                                                }
1521                                                match = sig;
1522                                        }
1523                                }
1524                                if (match != null) {
1525                                        return match;
1526                                }
1527                        }
1528                }
1529                return null;
1530        }
1531
1532        public PipelinedFunctionSignature findPipelinedSignatureAny(List<String> candidates) {
1533                for (String key : candidates) {
1534                        List<PipelinedFunctionSignature> sigs = pipelinedSignatures.get(key);
1535                        if (sigs != null && !sigs.isEmpty()) {
1536                                if (sigs.size() == 1) {
1537                                        return sigs.get(0);
1538                                }
1539                        }
1540                }
1541                return null;
1542        }
1543
1544        public void addPendingPipelinedCallSite(PendingPipelinedCallSite callSite) {
1545                pendingPipelinedCallSites.add(callSite);
1546        }
1547
1548        public List<PendingPipelinedCallSite> getPendingPipelinedCallSites() {
1549                return pendingPipelinedCallSites;
1550        }
1551
1552        public Set<String> getResolvingPipelinedFunctions() {
1553                return resolvingPipelinedFunctions;
1554        }
1555
1556        public Map<String, List<PipelinedFunctionSignature>> getPipelinedSignatures() {
1557                return pipelinedSignatures;
1558        }
1559
1560}