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                                                if(resultColumn.isStruct() && resultColumn.getName().endsWith("*")) {
616                                                        TObjectName structColumn = new TObjectName();
617                                                        structColumn.setString("*");
618                                                        columns.add(structColumn);
619                                                }
620                                                else {
621                                                        columns.add(alias.getAliasName());
622                                                }
623                                        } else {
624                                                if (columnObject.getFieldAttr() != null) {
625                                                        columns.add(columnObject.getFieldAttr());
626                                                } else {
627                                                        TObjectName column = new TObjectName();
628                                                        if (columnObject.getExpr().getExpressionType() == EExpressionType.typecast_t) {
629                                                                column.setString(columnObject.getExpr().getLeftOperand().toString());
630                                                        } else {
631                                                                column.setString(columnObject.toString());
632                                                        }
633                                                        columns.add(column);
634                                                }
635                                        }
636                                } else if (resultColumn.getColumnObject() instanceof TObjectName) {
637                                        columns.add((TObjectName) resultColumn.getColumnObject());
638                                }
639                        }
640                        return columns.toArray(new TObjectName[0]);
641                }
642
643                TObjectNameList list = table.getLinkedColumns();
644                List<TObjectName> columns = new ArrayList<TObjectName>();
645
646                if (table.getCTE() != null) {
647                        ResultSet resultSet = (ResultSet) getModel(table.getCTE());
648                        if (resultSet != null) {
649                                List<ResultColumn> columnList = resultSet.getColumns();
650                                for (int i = 0; i < columnList.size(); i++) {
651                                        ResultColumn resultColumn = columnList.get(i);
652                                        if (resultColumn.getColumnObject() instanceof TResultColumn) {
653                                                TResultColumn columnObject = ((TResultColumn) resultColumn.getColumnObject());
654                                                TAliasClause alias = columnObject.getAliasClause();
655                                                if (alias != null && alias.getAliasName() != null) {
656                                                        columns.add(alias.getAliasName());
657                                                } else {
658                                                        if (columnObject.getFieldAttr() != null) {
659                                                                columns.add(columnObject.getFieldAttr());
660                                                        } else {
661                                                                continue;
662                                                        }
663                                                }
664                                        } else if (resultColumn.getColumnObject() instanceof TObjectName) {
665                                                columns.add((TObjectName) resultColumn.getColumnObject());
666                                        }
667                                }
668                        }
669                } else if (list.size() == 1 && list.toString().indexOf("*") != -1 && table.getSubquery() != null) {
670                        addSubqueryColumns(table, columns);
671                } else {
672                        for (int i = 0; i < list.size(); i++) {
673                                TObjectName object = list.getObjectName(i);
674                                if (object.toString().indexOf("*") != -1 && table.getSubquery() != null) {
675                                        addSubqueryColumns(table, columns);
676                                }
677                                else 
678                                        columns.add(object);
679                        }
680                }
681                Collections.sort(columns, new Comparator<TObjectName>() {
682
683                        @Override
684                        public int compare(TObjectName o1, TObjectName o2) {
685                                return o1.getStartToken().posinlist - o2.getStartToken().posinlist;
686                        }
687                });
688                return columns.toArray(new TObjectName[0]);
689        }
690
691        private void addSubqueryColumns(TTable table, List<TObjectName> columns) {
692                ResultSet resultSet = (ResultSet) getModel(table.getSubquery());
693                if (resultSet != null) {
694                        List<ResultColumn> columnList = resultSet.getColumns();
695                        for (int i = 0; i < columnList.size(); i++) {
696                                ResultColumn resultColumn = columnList.get(i);
697                                if (resultColumn.getColumnObject() instanceof TResultColumn) {
698                                        TResultColumn columnObject = ((TResultColumn) resultColumn.getColumnObject());
699                                        TAliasClause alias = columnObject.getAliasClause();
700                                        if (alias != null && alias.getAliasName() != null) {
701                                                columns.add(alias.getAliasName());
702                                        } else {
703                                                if (columnObject.getFieldAttr() != null) {
704                                                        columns.add(columnObject.getFieldAttr());
705                                                } else {
706                                                        TObjectName column = new TObjectName();
707                                                        if (columnObject.getExpr().getExpressionType() == EExpressionType.typecast_t) {
708                                                                column.setString(columnObject.getExpr().getLeftOperand().toString());
709                                                        } else {
710                                                                column.setString(columnObject.toString());
711                                                        }
712                                                        columns.add(column);
713                                                }
714                                        }
715                                } else if (resultColumn.getColumnObject() instanceof TObjectName) {
716                                        columns.add((TObjectName) resultColumn.getColumnObject());
717                                }
718                        }
719                }
720        }
721
722        public TTable getTableFromColumn(TObjectName column) {
723                if (column.getSourceTable() != null) {
724                        return column.getSourceTable();
725                }
726
727                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
728                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
729                        while (peekStmt != null) {
730                                TTable table = null;
731                                if (tableHashMap.containsKey(peekStmt)) {
732                                        table = tableAliasMap.get(tableHashMap.get(peekStmt) + ":"
733                                                        + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
734                                }
735                                if (table != null) {
736                                        return table;
737                                } else {
738                                        peekStmt = peekStmt.getParentStmt();
739                                }
740                        }
741                }
742                return null;
743        }
744        
745        public TTable getTable(TCustomSqlStatement stmt, TObjectName column) {
746                if (column.getSourceTable() != null) {
747                        return column.getSourceTable();
748                }
749
750                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
751                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
752                        while (peekStmt != null) {
753                                TTable table = null;
754                                if (tableHashMap.containsKey(peekStmt)) {
755                                        table = tableAliasMap.get(tableHashMap.get(peekStmt) + ":"
756                                                        + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
757                                }
758                                if (table != null && table.getSubquery() != stmt)
759                                        return table;
760                                
761                                if (peekStmt.getTables() != null) {
762                                        for (TTable tableItem : peekStmt.getTables()) {
763                                                if (DlineageUtil.getIdentifierNormalTableName(tableItem.getTableName().toString())
764                                                                .equals(DlineageUtil.getIdentifierNormalTableName(column.getTableString()))) {
765                                                        return tableItem;
766                                                }
767                                        }
768                                }
769                                
770                                peekStmt = peekStmt.getParentStmt();
771                        }
772                }
773
774                if (stmt.getTables() != null) {
775                        for (int j = 0; j < stmt.getTables().size(); j++) {
776                                TTable table = (TTable) stmt.getTables().getTable(j);
777                                if (table.getSubquery() == stmt)
778                                        continue;
779
780                                TObjectName[] columns = getTableColumns(table);
781                                for (int i = 0; i < columns.length; i++) {
782                                        TObjectName columnName = columns[i];
783                                        if (columnName == null || "*".equals(columnName.getColumnNameOnly()))
784                                                continue;
785                                        if (DlineageUtil.getIdentifierNormalColumnName(columnName.toString())
786                                                        .equals(DlineageUtil.getIdentifierNormalColumnName(column.toString()))) {
787                                                if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
788                                                        return table;
789                                                }
790                                        }
791                                        if (!SQLUtil.isEmpty(columnName.getColumnNameOnly())
792                                                        && DlineageUtil.getIdentifierNormalColumnName(columnName.getColumnNameOnly())
793                                                                        .equals(DlineageUtil.getIdentifierNormalColumnName(column.getColumnNameOnly()))) {
794                                                if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
795                                                        return table;
796                                                }
797                                        }
798                                }
799                        }
800                }
801
802                // Iterator iter = tableSet.iterator();
803                // while (iter.hasNext()) {
804                // TTable table = (TTable) iter.next();
805                //
806                // if (table.getSubquery() == stmt)
807                // continue;
808                //
809                // if (table.getSubquery() != null) {
810                // int start = table.getSubquery().getStartToken().posinlist;
811                // int end = table.getSubquery().getEndToken().posinlist;
812                // if (start <= stmt.getStartToken().posinlist && end >=
813                // stmt.getEndToken().posinlist) {
814                // continue;
815                // }
816                // }
817                //
818                // TObjectName[] columns = getTableColumns(table);
819                // for (int i = 0; i < columns.length; i++) {
820                // TObjectName columnName = columns[i];
821                // if (columnName == null || "*".equals(columnName.getColumnNameOnly()))
822                // continue;
823                // if
824                // (DlineageUtil.getIdentifierNormalName(columnName.toString()).equals(DlineageUtil.getIdentifierNormalName(column.toString())))
825                // {
826                // if (columnName.getSourceTable() == null
827                // || columnName.getSourceTable() == table) {
828                // return table;
829                // }
830                // }
831                // if (columnName.getColumnNameOnly()!=null &&
832                // DlineageUtil.getIdentifierNormalName(columnName.getColumnNameOnly()).equals(DlineageUtil.getIdentifierNormalName(column.getColumnNameOnly())))
833                // {
834                // if (columnName.getSourceTable() == null
835                // || columnName.getSourceTable() == table) {
836                // return table;
837                // }
838                // }
839                // }
840                // }
841                return null;
842        }
843
844        public TTable guessTable(TCustomSqlStatement stmt, TObjectName column) {
845                if (column.getTableString() != null && column.getTableString().trim().length() > 0) {
846                        TCustomSqlStatement peekStmt = ModelBindingManager.getGlobalStmtStack().peek();
847                        TTable table = null;
848                        if (tableHashMap.containsKey(peekStmt)) {
849                                table = tableAliasMap.get(
850                                                tableHashMap.get(peekStmt) + ":" + DlineageUtil.getIdentifierNormalTableName(column.getTableString()));
851                        }
852                        if (table != null && table.getSubquery() != stmt)
853                                return table;
854                }
855
856                Iterator iter = tableSet.iterator();
857                while (iter.hasNext()) {
858                        TTable table = (TTable) iter.next();
859
860                        if (table.getSubquery() == stmt)
861                                continue;
862
863                        TObjectName[] columns = getTableColumns(table);
864                        for (int i = 0; i < columns.length; i++) {
865                                TObjectName columnName = columns[i];
866                                if ("*".equals(columnName.getColumnNameOnly()))
867                                        continue;
868                                if (columnName.toString().equalsIgnoreCase(column.toString())) {
869                                        if (columnName.getSourceTable() == null || columnName.getSourceTable() == table) {
870                                                return table;
871                                        }
872                                }
873                        }
874                }
875                return null;
876        }
877
878        public List<Table> getTablesByName() {
879                List<Table> tables = new ArrayList<Table>();
880                Iterator iter = tableNamesMap.values().iterator();
881                while (iter.hasNext()) {
882                        tables.add((Table) iter.next());
883                }
884                return tables;
885        }
886
887        public List<TTable> getBaseTables() {
888                List<TTable> tables = new ArrayList<TTable>();
889
890                Iterator iter = modelBindingMap.keySet().iterator();
891                while (iter.hasNext()) {
892                        Object key = iter.next();
893                        if (!(key instanceof TTable)) {
894                                continue;
895                        }
896                        TTable table = (TTable) key;
897                        if (table.getSubquery() == null) {
898                                tables.add(table);
899                        }
900                }
901
902                iter = createModelBindingMap.keySet().iterator();
903                while (iter.hasNext()) {
904                        Object key = iter.next();
905                        if (!(key instanceof TTable)) {
906                                continue;
907                        }
908                        TTable table = (TTable) key;
909                        tables.add(table);
910                }
911
912                iter = insertModelBindingMap.keySet().iterator();
913                while (iter.hasNext()) {
914                        Object key = iter.next();
915                        if (!(key instanceof TTable)) {
916                                continue;
917                        }
918                        TTable table = (TTable) key;
919                        tables.add(table);
920                }
921
922                iter = mergeModelBindingMap.keySet().iterator();
923                while (iter.hasNext()) {
924                        Object key = iter.next();
925                        if (!(key instanceof TTable)) {
926                                continue;
927                        }
928                        TTable table = (TTable) key;
929                        tables.add(table);
930                }
931
932                iter = updateModelBindingMap.keySet().iterator();
933                while (iter.hasNext()) {
934                        Object key = iter.next();
935                        if (!(key instanceof TTable)) {
936                                continue;
937                        }
938                        TTable table = (TTable) key;
939                        if (!tables.contains(table)) {
940                                tables.add(table);
941                        }
942                }
943
944                return tables;
945        }
946
947        public List<TCustomSqlStatement> getViews() {
948                List<TCustomSqlStatement> views = new ArrayList<TCustomSqlStatement>();
949
950                Iterator iter = viewModelBindingMap.keySet().iterator();
951                while (iter.hasNext()) {
952                        Object key = iter.next();
953                        if (!(key instanceof TCreateViewSqlStatement) && !(key instanceof TCreateMaterializedSqlStatement)) {
954                                continue;
955                        }
956                        TCustomSqlStatement view = (TCustomSqlStatement) key;
957                        if (!views.contains(view)) {
958                                views.add(view);
959                        }
960                }
961                return views;
962        }
963
964        public List<TResultColumnList> getSelectResultSets() {
965                List<TResultColumnList> resultSets = new ArrayList<TResultColumnList>();
966
967                Iterator iter = modelBindingMap.keySet().iterator();
968                while (iter.hasNext()) {
969                        Object key = iter.next();
970                        if (!(key instanceof TResultColumnList)) {
971                                continue;
972                        }
973                        TResultColumnList resultset = (TResultColumnList) key;
974                        resultSets.add(resultset);
975                }
976                return resultSets;
977        }
978
979        public List<TObjectNameList> getQueryAliasTables() {
980                List<TObjectNameList> resultSets = new ArrayList<TObjectNameList>();
981
982                Iterator iter = modelBindingMap.keySet().iterator();
983                while (iter.hasNext()) {
984                        Object key = iter.next();
985                        if (!(key instanceof TObjectNameList)) {
986                                continue;
987                        }
988                        TObjectNameList resultset = (TObjectNameList) key;
989                        resultSets.add(resultset);
990                }
991                return resultSets;
992        }
993
994        public List<TSelectSqlStatement> getSelectSetResultSets() {
995                List<TSelectSqlStatement> resultSets = new ArrayList<TSelectSqlStatement>();
996
997                Iterator iter = modelBindingMap.keySet().iterator();
998                while (iter.hasNext()) {
999                        Object key = iter.next();
1000                        if (!(key instanceof TSelectSqlStatement)) {
1001                                continue;
1002                        }
1003
1004                        TSelectSqlStatement stmt = (TSelectSqlStatement) key;
1005                        if (stmt.getSetOperatorType() == ESetOperatorType.none)
1006                                continue;
1007
1008                        resultSets.add(stmt);
1009                }
1010                return resultSets;
1011        }
1012
1013        public List<TCTE> getCTEs() {
1014                List<TCTE> resultSets = new ArrayList<TCTE>();
1015
1016                Iterator iter = modelBindingMap.keySet().iterator();
1017                while (iter.hasNext()) {
1018                        Object key = iter.next();
1019                        if (!(key instanceof TCTE)) {
1020                                continue;
1021                        }
1022
1023                        TCTE cte = (TCTE) key;
1024                        resultSets.add(cte);
1025                }
1026                return resultSets;
1027        }
1028
1029        public List<TTable> getTableWithSelectSetResultSets() {
1030                List<TTable> resultSets = new ArrayList<TTable>();
1031
1032                Iterator iter = modelBindingMap.keySet().iterator();
1033                while (iter.hasNext()) {
1034                        Object key = iter.next();
1035                        if (!(key instanceof TTable)) {
1036                                continue;
1037                        }
1038
1039                        if (((TTable) key).getSubquery() == null)
1040                                continue;
1041                        TSelectSqlStatement stmt = ((TTable) key).getSubquery();
1042                        if (stmt.getSetOperatorType() == ESetOperatorType.none)
1043                                continue;
1044
1045                        resultSets.add((TTable) key);
1046                }
1047                return resultSets;
1048        }
1049
1050        public List<TParseTreeNode> getMergeResultSets() {
1051                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1052
1053                Iterator iter = modelBindingMap.keySet().iterator();
1054                while (iter.hasNext()) {
1055                        Object key = iter.next();
1056                        if (!(key instanceof TMergeUpdateClause) && !(key instanceof TMergeInsertClause)) {
1057                                continue;
1058                        }
1059                        TParseTreeNode resultset = (TParseTreeNode) key;
1060                        resultSets.add(resultset);
1061                }
1062                return resultSets;
1063        }
1064
1065        public List<TParseTreeNode> getOutputResultSets() {
1066                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1067
1068                Iterator iter = modelBindingMap.keySet().iterator();
1069                while (iter.hasNext()) {
1070                        Object key = iter.next();
1071                        if (!(key instanceof TOutputClause)) {
1072                                continue;
1073                        }
1074                        TParseTreeNode resultset = (TParseTreeNode) key;
1075                        resultSets.add(resultset);
1076                }
1077                return resultSets;
1078        }
1079
1080        public List<TParseTreeNode> getUpdateResultSets() {
1081                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1082
1083                Iterator iter = modelBindingMap.keySet().iterator();
1084                while (iter.hasNext()) {
1085                        Object key = iter.next();
1086                        if (!(key instanceof TUpdateSqlStatement)) {
1087                                continue;
1088                        }
1089                        TParseTreeNode resultset = (TParseTreeNode) key;
1090                        resultSets.add(resultset);
1091                }
1092                return resultSets;
1093        }
1094
1095        public List<TParseTreeNode> getFunctoinCalls() {
1096                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1097
1098                Iterator iter = modelBindingMap.keySet().iterator();
1099                while (iter.hasNext()) {
1100                        Object key = iter.next();
1101                        if (!(key instanceof TFunctionCall) && !(key instanceof TCaseExpression)) {
1102                                continue;
1103                        }
1104                        TParseTreeNode resultset = (TParseTreeNode) key;
1105                        resultSets.add(resultset);
1106                }
1107                return resultSets;
1108        }
1109
1110        public List<TParseTreeNode> getAliases() {
1111                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1112
1113                Iterator iter = modelBindingMap.keySet().iterator();
1114                while (iter.hasNext()) {
1115                        Object key = iter.next();
1116                        if (!(key instanceof TAliasClause)) {
1117                                continue;
1118                        }
1119                        TParseTreeNode resultset = (TParseTreeNode) key;
1120                        resultSets.add(resultset);
1121                }
1122                return resultSets;
1123        }
1124        
1125        public List<TParseTreeNode> getCursors() {
1126                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1127
1128                Iterator iter = modelBindingMap.keySet().iterator();
1129                while (iter.hasNext()) {
1130                        Object key = iter.next();
1131                        if (!(key instanceof TCursorDeclStmt) && !(key instanceof TOpenforStmt)) {
1132                                continue;
1133                        }
1134                        TParseTreeNode resultset = (TParseTreeNode) key;
1135                        resultSets.add(resultset);
1136                }
1137                return resultSets;
1138        }
1139        
1140        public List<TParseTreeNode> getPivotdTables() {
1141                List<TParseTreeNode> resultSets = new ArrayList<TParseTreeNode>();
1142
1143                Iterator iter = modelBindingMap.keySet().iterator();
1144                while (iter.hasNext()) {
1145                        Object key = iter.next();
1146                        if (!(key instanceof TPivotClause)) {
1147                                continue;
1148                        }
1149                        TParseTreeNode resultset = (TParseTreeNode) key;
1150                        resultSets.add(resultset);
1151                }
1152                return resultSets;
1153        }
1154
1155        public void addRelation(Relationship relation) {
1156                if (relation != null && !relationHolder.contains(relation)) {
1157                        relationHolder.add(relation);
1158                }
1159        }
1160        
1161        public void removeRelation(ImpactRelationship relation) {
1162                if (relation != null) {
1163                        relationHolder.remove(relation);
1164                }
1165        }
1166
1167        public Relationship[] getRelations() {
1168                return relationHolder.toArray(new Relationship[0]);
1169        }
1170
1171        public void reset() {
1172                modelBindingMap.clear();
1173                processModelBindingMap.clear();
1174                viewModelBindingMap.clear();
1175                insertModelBindingMap.clear();
1176                createModelBindingMap.clear();
1177                createModelQuickBindingMap.clear();
1178                mergeModelBindingMap.clear();
1179                updateModelBindingMap.clear();
1180                cursorModelBindingMap.clear();
1181                functionTableMap.clear();
1182                tableNamesMap.clear();
1183                dropTables.clear();
1184                procedureNamesMap.clear();
1185                oraclePackageNamesMap.clear();
1186                relationHolder.clear();
1187                tableAliasMap.clear();
1188                tableHashMap.clear();
1189                topStmtHashMap.clear();
1190                hashSQLMap.clear();
1191                dynamicSQLMap.clear();
1192                tableSet.clear();
1193                resultSetSet.clear();
1194                dblinkTableSet.clear();
1195                objectTypeIndex.clear();
1196                collectionToElementTypeIndex.clear();
1197                pipelinedSignatures.clear();
1198                pendingPipelinedCallSites.clear();
1199                resolvingPipelinedFunctions.clear();
1200                DISPLAY_ID.clear();
1201                DISPLAY_NAME.clear();
1202                virtualTableNames.clear();
1203        }
1204
1205        public void bindCursorModel(TCursorDeclStmt stmt, Variable resultSet) {
1206                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1207                String variableString = stmt.getCursorName().toString();
1208                if (variableString.startsWith(":")) {
1209                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1210                }
1211                if (!SQLUtil.isEmpty(procedureName)) {
1212                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1213                }
1214                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1215        }
1216        
1217        public void bindCursorModel(TMssqlDeclare stmt, Variable resultSet) {
1218                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1219                String variableString = stmt.getCursorName().toString();
1220                if (variableString.startsWith(":")) {
1221                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1222                }
1223                if (!SQLUtil.isEmpty(procedureName)) {
1224                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1225                }
1226                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1227        }
1228        
1229        public void bindCursorModel(TOpenforStmt stmt, Variable resultSet) {
1230                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1231                String variableString = stmt.getCursorVariableName().toString();
1232                if (variableString.startsWith(":")) {
1233                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1234                }
1235                if (!SQLUtil.isEmpty(procedureName)) {
1236                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1237                }
1238                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1239        }
1240        
1241        public void bindCursorModel(TForStmt stmt, Variable resultSet) {
1242                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1243                String variableString = stmt.getCursorName().toString();
1244                if (variableString.startsWith(":")) {
1245                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1246                }
1247                if (!SQLUtil.isEmpty(procedureName)) {
1248                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1249                }
1250                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1251        }
1252        
1253        public void bindCursorModel(TLoopStmt stmt, Variable resultSet) {
1254                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1255                String variableString = stmt.getRecordName().toString();
1256                if (variableString.startsWith(":")) {
1257                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1258                }
1259                if (!SQLUtil.isEmpty(procedureName)) {
1260                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1261                }
1262                createModelBindingMap.put(DlineageUtil.getTableFullName(variableString), resultSet);
1263        }
1264
1265        public void bindCursorIndex(TObjectName indexName, TObjectName cursorName) {
1266                TCustomSqlStatement stmt = getGlobalStmtStack().peek();
1267                String procedureName = DlineageUtil.getProcedureParentName(stmt);
1268                String variableString = cursorName.toString();
1269                if (variableString.startsWith(":")) {
1270                        variableString = variableString.substring(variableString.indexOf(":") + 1);
1271                }
1272                if (!SQLUtil.isEmpty(procedureName)) {
1273                        variableString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1274                }
1275                
1276                Cursor cursor = ((Cursor) createModelBindingMap
1277                                .get(DlineageUtil.getTableFullName(variableString)));
1278                if (cursor != null) {
1279                        String indexNameString = indexName.toString();
1280                        if (!SQLUtil.isEmpty(procedureName)) {
1281                                indexNameString = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(indexNameString);
1282                        }
1283                        bindModel(DlineageUtil.getTableFullName(indexNameString),
1284                                        modelBindingMap.get(cursor.getResultColumnObject()));
1285                        bindTableByName(DlineageUtil.getTableFullName(indexNameString),
1286                                        cursor);
1287                }
1288        }
1289
1290        public List<TStoredProcedureSqlStatement> getProcedures() {
1291                List<TStoredProcedureSqlStatement> procedures = new ArrayList();
1292                Iterator iter = this.modelBindingMap.keySet().iterator();
1293
1294                while (iter.hasNext()) {
1295                        Object key = iter.next();
1296                        if (key instanceof TStoredProcedureSqlStatement) {
1297                                TStoredProcedureSqlStatement procedure = (TStoredProcedureSqlStatement) key;
1298                                procedures.add(procedure);
1299                        }
1300                }
1301
1302                return procedures;
1303        }
1304
1305        // public void bindTableByName(TObjectName tableName, Table tableModel) {
1306        // tableNamesMap.put(tableName, tableModel);
1307        //
1308        // }
1309        //
1310        public void bindTableByName(String tableName, Table tableModel) {
1311                tableNamesMap.put(tableName, tableModel);
1312
1313        }
1314
1315        // public Table getTableByName(TObjectName tableName) {
1316        // return (Table)tableNamesMap.get(tableName);
1317        // }
1318
1319        public Table getTableByName(String tableName) {
1320                Table table = (Table) tableNamesMap.get(tableName);
1321                if (table == null) {
1322                        TCustomSqlStatement stmt = getGlobalStmtStack().peek();
1323                        String procedureName = DlineageUtil.getProcedureParentName(stmt);
1324                        String variableString = tableName.toString();
1325                        if (!SQLUtil.isEmpty(procedureName)) {
1326                                String variableWithProcedure = DlineageUtil.getTableFullName(procedureName) + "." + SQLUtil.getIdentifierNormalTableName(variableString);
1327                                if(tableNamesMap.containsKey(DlineageUtil.getTableFullName(variableWithProcedure))) {
1328                                        return  (Table) tableNamesMap.get(DlineageUtil.getTableFullName(variableWithProcedure));
1329                                }
1330                        }
1331                        return (Table) tableNamesMap.get(DlineageUtil.getTableFullName(variableString));
1332                } else {
1333                        return table;
1334                }
1335        }
1336
1337
1338        public void bindProcedureByName(String procedureName, Procedure procedureModel) {
1339                procedureNamesMap.put(procedureName, procedureModel);
1340
1341        }
1342        
1343        public Procedure getProcedureByName(String procedureName) {
1344                if(procedureName == null){
1345                        return null;
1346                }
1347
1348                if (ModelBindingManager.getGlobalOraclePackage() != null
1349                                && !procedureName.startsWith(ModelBindingManager.getGlobalOraclePackage().getName())) {
1350                        procedureName = ModelBindingManager.getGlobalOraclePackage().getName() + "." + procedureName;
1351                }
1352                Procedure procedure = (Procedure) procedureNamesMap.get(procedureName);
1353                if (procedure == null) {
1354                        if (procedureName.indexOf("(") == -1) {
1355                                for (Object name : procedureNamesMap.keySet()) {
1356                                        String fuctionName = name.toString();
1357                                        if (fuctionName.startsWith(procedureName + "(")) {
1358                                                return (Procedure) procedureNamesMap.get(name);
1359                                        }
1360                                        if (fuctionName.indexOf(".") != -1 && procedureName.indexOf(".") == -1) {
1361                                                fuctionName = fuctionName.substring(fuctionName.lastIndexOf(".") + 1);
1362                                                if (fuctionName.startsWith(procedureName + "(")) {
1363                                                        return (Procedure) procedureNamesMap.get(name);
1364                                                }
1365                                        }
1366                                        if (fuctionName.indexOf(".") == -1 && procedureName.indexOf(".") != -1) {
1367                                                String procedureNameSubstring = procedureName.substring(procedureName.lastIndexOf(".") + 1);
1368                                                if (fuctionName.startsWith(procedureNameSubstring + "(")) {
1369                                                        return (Procedure) procedureNamesMap.get(name);
1370                                                }
1371                                        }
1372                                }
1373                        }
1374                        else {
1375                                for (Object name : procedureNamesMap.keySet()) {
1376                                        String fuctionName = name.toString();
1377                                        if (fuctionName.startsWith(procedureName)) {
1378                                                return (Procedure) procedureNamesMap.get(name);
1379                                        }
1380                                        if (fuctionName.indexOf(".") != -1 && procedureName.indexOf(".") == -1) {
1381                                                fuctionName = fuctionName.substring(fuctionName.lastIndexOf(".") + 1);
1382                                                if (fuctionName.equalsIgnoreCase(procedureName)) {
1383                                                        return (Procedure) procedureNamesMap.get(name);
1384                                                }
1385                                        }
1386                                        if (fuctionName.indexOf(".") == -1 && procedureName.indexOf(".") != -1) {
1387                                                String procedureNameSubstring = procedureName.substring(procedureName.lastIndexOf(".") + 1);
1388                                                if (fuctionName.equalsIgnoreCase(procedureNameSubstring)) {
1389                                                        return (Procedure) procedureNamesMap.get(name);
1390                                                }
1391                                        }
1392                                }
1393                        }
1394                }
1395                return procedure;
1396        }
1397        
1398        public void bindOraclePackageByName(String oraclePackageName, OraclePackage oraclePackageModel) {
1399                oraclePackageNamesMap.put(oraclePackageName, oraclePackageModel);
1400
1401        }
1402        
1403        public OraclePackage getOraclePackageByName(String oraclePackageName) {
1404                return (OraclePackage) oraclePackageNamesMap.get(oraclePackageName);
1405        }
1406
1407
1408        public String getSqlHash(TCustomSqlStatement stmt) {
1409                return topStmtHashMap.get(stmt);
1410        }
1411
1412        public Map getHashSQLMap() {
1413                return hashSQLMap;
1414        }
1415
1416        public Map getDynamicSQLMap() {
1417                return dynamicSQLMap;
1418        }
1419
1420        public void collectSqlHash(TCustomSqlStatement stmt) {
1421                if (getGlobalOption().getAnalyzeMode() == AnalyzeMode.crud) {
1422                        String sql = stmt.toString();
1423                        if (sql != null) {
1424                                sql = stmt.getStartToken().lineNo + ":" + sql;
1425                                String hash = SQLUtil.stringToMD5(sql);
1426                                topStmtHashMap.put(stmt, hash);
1427                                hashSQLMap.put(hash, new Pair3<Long, Long, String>(stmt.getStartToken().lineNo, stmt.getEndToken().lineNo, ModelBindingManager.getGlobalHash()));
1428                        }
1429                } else {
1430                        try {
1431                                String sql = stmt.asCanonical();
1432                                if (sql != null) {
1433                                        String hash = SQLUtil.stringToMD5(sql);
1434                                        topStmtHashMap.put(stmt, hash);
1435                                        hashSQLMap.put(hash, sql);
1436                                }
1437                        } catch (Exception e) {
1438                                logger.error("collectSqlHash error: " + e.getMessage(), e);
1439                        }
1440                }
1441        }
1442        
1443        public void collectDynamicSqlHash(TCustomSqlStatement stmt) {
1444                if (getGlobalOption().getAnalyzeMode() == AnalyzeMode.dynamic) {
1445                        String sql = stmt.toString();
1446                        if (sql != null) {
1447                                sql = stmt.getStartToken().lineNo + ":" + sql;
1448                                String hash = SQLUtil.stringToMD5(sql);
1449                                dynamicSQLMap.put(hash, new Pair3<Long, Long, String>(stmt.getStartToken().lineNo, stmt.getEndToken().lineNo, ModelBindingManager.getGlobalHash()));
1450                        }
1451                }
1452        }
1453
1454        public void appendDblinkTable(String name) {
1455                if (!SQLUtil.isEmpty(name)) {
1456                        dblinkTableSet.add(name);
1457                }
1458        }
1459        
1460        public boolean isDblinkTable(String name) {
1461                return dblinkTableSet.contains(name);
1462        }
1463
1464        public Set<ResultSet> getResultSets() {
1465                return resultSetSet;
1466        }
1467        
1468        public void dropTable(Table table) {
1469                List tableNames = new ArrayList(tableNamesMap.keySet());
1470                for (Object tableName : tableNames) {
1471                        if(tableNamesMap.get(tableName) == table) {
1472                                tableNamesMap.remove(tableName);
1473                                dropTables.add(table);
1474                        }
1475                }
1476        }
1477        
1478        public void cleanTempTable() {
1479                Iterator<String> iter = tableNamesMap.keySet().iterator();
1480                while(iter.hasNext()) {
1481                        String tableName = iter.next();
1482                        if(DlineageUtil.isTempTable((Table)tableNamesMap.get(tableName), getGlobalVendor())) {
1483                                dropTables.add((Table)tableNamesMap.get(tableName));
1484                                iter.remove();
1485                        }
1486                }
1487        }
1488
1489        public Set<Table> getDropTables() {
1490                return dropTables;
1491        }
1492
1493        // --- Pipelined function stitching methods ---
1494
1495        public void indexObjectType(String normalizedName, List<String> fieldNames) {
1496                objectTypeIndex.put(normalizedName, fieldNames);
1497        }
1498
1499        public List<String> getObjectTypeFields(String normalizedName) {
1500                return objectTypeIndex.get(normalizedName);
1501        }
1502
1503        public void indexCollectionType(String collectionName, String elementTypeName) {
1504                collectionToElementTypeIndex.put(collectionName, elementTypeName);
1505        }
1506
1507        public String getElementTypeName(String collectionName) {
1508                return collectionToElementTypeIndex.get(collectionName);
1509        }
1510
1511        public void addPipelinedSignature(PipelinedFunctionSignature sig) {
1512                pipelinedSignatures.computeIfAbsent(sig.getFunctionKey(), k -> new ArrayList<>()).add(sig);
1513                if (sig.getNakedKey() != null && !sig.getNakedKey().equals(sig.getFunctionKey())) {
1514                        pipelinedSignatures.computeIfAbsent(sig.getNakedKey(), k -> new ArrayList<>()).add(sig);
1515                }
1516        }
1517
1518        public PipelinedFunctionSignature findPipelinedSignature(List<String> candidates, int argCount) {
1519                for (String key : candidates) {
1520                        List<PipelinedFunctionSignature> sigs = pipelinedSignatures.get(key);
1521                        if (sigs != null) {
1522                                PipelinedFunctionSignature match = null;
1523                                for (PipelinedFunctionSignature sig : sigs) {
1524                                        if (sig.getArgCount() == argCount || argCount < 0) {
1525                                                if (match != null) {
1526                                                        return null; // ambiguous
1527                                                }
1528                                                match = sig;
1529                                        }
1530                                }
1531                                if (match != null) {
1532                                        return match;
1533                                }
1534                        }
1535                }
1536                return null;
1537        }
1538
1539        public PipelinedFunctionSignature findPipelinedSignatureAny(List<String> candidates) {
1540                for (String key : candidates) {
1541                        List<PipelinedFunctionSignature> sigs = pipelinedSignatures.get(key);
1542                        if (sigs != null && !sigs.isEmpty()) {
1543                                if (sigs.size() == 1) {
1544                                        return sigs.get(0);
1545                                }
1546                        }
1547                }
1548                return null;
1549        }
1550
1551        public void addPendingPipelinedCallSite(PendingPipelinedCallSite callSite) {
1552                pendingPipelinedCallSites.add(callSite);
1553        }
1554
1555        public List<PendingPipelinedCallSite> getPendingPipelinedCallSites() {
1556                return pendingPipelinedCallSites;
1557        }
1558
1559        public Set<String> getResolvingPipelinedFunctions() {
1560                return resolvingPipelinedFunctions;
1561        }
1562
1563        public Map<String, List<PipelinedFunctionSignature>> getPipelinedSignatures() {
1564                return pipelinedSignatures;
1565        }
1566
1567}