001package gudusoft.gsqlparser;
002
003
004import gudusoft.gsqlparser.compiler.*;
005import gudusoft.gsqlparser.nodes.*;
006import gudusoft.gsqlparser.nodes.dax.TDaxFunction;
007import gudusoft.gsqlparser.scriptWriter.TScriptGenerator;
008import gudusoft.gsqlparser.sqlenv.TSQLEnv;
009import gudusoft.gsqlparser.sqlenv.TSQLFunction;
010import gudusoft.gsqlparser.stmt.*;
011import gudusoft.gsqlparser.stmt.dax.TDaxStmt;
012import gudusoft.gsqlparser.stmt.oracle.*;
013import gudusoft.gsqlparser.util.functionChecker;
014import gudusoft.gsqlparser.util.keywordChecker;
015
016import java.util.ArrayList;
017import java.util.Stack;
018import java.util.TreeMap;
019
020/**
021 * TCustomSqlStatement is the root class for all SQL statements.
022 */
023public class TCustomSqlStatement extends TParseTreeNode implements IRelation{
024
025    public void setUsingVariableList(TColumnDefinitionList usingVariableList) {
026        this.usingVariableList = usingVariableList;
027    }
028
029    private TColumnDefinitionList usingVariableList;
030
031    /*
032    * Variables defined in teradata using clause.
033    * */
034    public TColumnDefinitionList getUsingVariableList() {
035        return usingVariableList;
036    }
037
038    protected ArrayList<TAttributeNode> relationAttributes = new ArrayList<>();
039
040    @Override
041    public ArrayList<TAttributeNode> getAttributes(){
042       // if (relationAttributes.size() != 0) return relationAttributes;
043        relationAttributes.clear();
044        for(TTable table:relations){
045            //relationAttributes.addAll(table.getAttributes());
046            TAttributeNode.addAllNodesToList(table.getAttributes(),relationAttributes);
047        }
048
049        return relationAttributes;
050    }
051
052    @Override
053    public String getRelationName(){
054        return null;
055    }
056
057    @Override
058    public int size(){
059        return relationAttributes.size();
060    }
061
062    @Override
063    public String toScript(){
064        String ret = super.toScript();
065        if ((ret == null)||(ret.isEmpty())){
066            ret = this.toString();
067        }else{
068            if ((this.getEndToken() != null) && (this.getEndToken().tokencode == ';')) {
069                if (!ret.endsWith(";")){
070                    ret = ret + ";";
071                }
072            }
073        }
074        return ret;
075    }
076
077    protected TFromClause fromClause;
078
079    public void setFromClause(TFromClause fromClause) {
080        this.fromClause = fromClause;
081    }
082
083    public TFromClause getFromClause() {
084        return fromClause;
085    }
086
087    /**
088     * Relations that used in from clause of select statement.
089     * Or tables of other statements such as insert, update, delete and etc
090     *
091     * Please use this property to get the relations instead of {@link #getTables()} and {@link #getJoins()}after version 2.7.4.0
092     *
093     * when a join is used in from clause, then the table in getRelations() is type of ETableSource.join, and you can
094     * use TTable.getJoinExpr() to get this join.
095     *
096     * @return
097     */
098    public ArrayList<TTable> getRelations() {
099        return relations;
100    }
101
102    private ArrayList<TTable> relations = new ArrayList<>();
103
104    protected TTable fromSourceTable;
105
106    /**
107     * This is table in from clause if only one table is listed in the from clause,
108     * If more than one table is listed in from clause, please check {@link #getFromSourceJoin()} instead.
109     *
110     * @return table in from clause
111     */
112    public TTable getFromSourceTable() {
113        return fromSourceTable;
114    }
115
116    /**
117     * This is a join in from clause, including left and right relation.
118     * If only a single table is listed in from clause, please use {@link #getFromSourceTable()} instead
119     * @return
120     */
121    public TJoinExpr getFromSourceJoin() {
122        return fromSourceJoin;
123    }
124
125    protected TJoinExpr fromSourceJoin;
126
127    private String asCanonicalText = null;
128
129    /**
130     *  this method return a canonical form of a SQL statement in plan text.
131     *  <br>1. remove all comment inside SQL query.
132     *  <br>2. remove redundant parenthesis at the begin/end of a select statement.
133     *  <br>3. replace all number in where clause with 999 constant
134     *  <br>4. replace all string constant in where clause with 'placeholder_str'
135     *  <br>5. all number elements in a list such as (1,2,3,4) will be change to a single element (999)
136     *  <br>6. all string elements in a list such as ('a','b','c','d') will be change to a single element ('placeholder_str')
137     *
138     * @return a canonical form of a SQL statement in plan text.
139     */
140    public String asCanonical(){
141        if (asCanonicalText != null) return asCanonicalText;
142
143        String ret = null;
144        TSourceToken lcStartToken = getStartToken();
145        if (lcStartToken ==  null) return toString();
146        TSourceToken lcEndToken = getEndToken();
147        if (lcEndToken ==  null) return toString();
148
149        // remove the ; token at the end of statement
150        if (lcEndToken.tokencode == ';') lcEndToken.tokenstatus = ETokenStatus.tsdeleted;
151
152
153        // remove ( ) at the begin and end of the statement
154        TSourceToken lcCurrentToken = lcStartToken;
155        while (lcCurrentToken != null){
156            if (lcCurrentToken.tokencode != '(') {
157                break;
158            }else{
159                if (lcCurrentToken.getLinkToken() != null){
160                    lcCurrentToken.tokenstatus  = ETokenStatus.tsdeleted;
161                    lcCurrentToken.getLinkToken().tokenstatus  = ETokenStatus.tsdeleted;
162                }
163            }
164
165            if (lcCurrentToken.equals(lcEndToken)){
166                break;
167            }else{
168                lcCurrentToken = lcCurrentToken.getNextTokenInChain();
169            }
170        }
171
172        // change constant to placeholder, all number change to 999 and string constant change to placeholder_str
173        constantVisitor cv = new constantVisitor();
174        this.acceptChildren(cv);
175
176
177        boolean chainUnchanged = true, includingComment = false;
178        StringBuffer sb = new StringBuffer("");
179        TSourceToken lcPrevSt = null;
180        boolean ignoreNextReturnToken = false, isChainModified = false;
181
182        lcCurrentToken = lcStartToken;
183        while (lcCurrentToken != null){
184            if((lcCurrentToken.tokenstatus == ETokenStatus.tsdeleted)
185                    ||(!includingComment  && ((lcCurrentToken.tokencode == TBaseType.cmtslashstar) ||(lcCurrentToken.tokencode == TBaseType.cmtdoublehyphen)))
186            ){
187                // ignore this token, do nothing
188                //System.out.println("out: ignore deleted token:"+lcCurrentToken.astext);
189            }else{
190                //
191                sb.append(lcCurrentToken.toString());
192                if (lcCurrentToken.isChangedInAsCanonical()){
193                    lcCurrentToken.restoreText();
194                }
195            }
196
197            if (lcCurrentToken.equals(lcEndToken)){
198                break;
199            }else{
200                lcCurrentToken = lcCurrentToken.getNextTokenInChain();
201            }
202
203        }
204        asCanonicalText = sb.toString();
205        return asCanonicalText;
206    }
207
208    private TCTE cteIncludeThisStmt = null;
209
210    public void setCteIncludeThisStmt(TCTE cteIncludeThisStmt) {
211        this.cteIncludeThisStmt = cteIncludeThisStmt;
212    }
213
214    public TCTE getCteIncludeThisStmt() {
215        return cteIncludeThisStmt;
216    }
217
218    private TreeMap<String,TResultColumn> expandedResultColumns = null;
219
220    public TreeMap<String,TResultColumn> getExpandedResultColumns() {
221        if (expandedResultColumns == null){
222            expandedResultColumns = new TreeMap<>();
223        }
224        return expandedResultColumns;
225    }
226
227    public TSQLFunction searchFunctionInSQLEnv(String functionName){
228        if (getSqlEnv() == null) return null;
229        return getSqlEnv().searchFunction(functionName);
230    }
231
232    public TSQLEnv getSqlEnv() {
233        if (getGlobalScope() == null) return null;
234        return getGlobalScope().getSqlEnv();
235    }
236
237    public TGlobalScope getGlobalScope() {
238        TGlobalScope lcResult = null;
239        if (frameStack != null){
240            if (frameStack.get(0) != null){
241                lcResult = (TGlobalScope)frameStack.get(0).getScope();
242            }
243        }
244        return lcResult;
245    }
246
247    private Stack<TFrame> frameStack;
248
249    public void setFrameStack(Stack<TFrame> frameStack) {
250        this.frameStack = frameStack;
251    }
252
253    public Stack<TFrame> getFrameStack() {
254        return frameStack;
255    }
256
257    private TPTNodeList<TColumnWithSortOrder> indexColumns = null;
258
259    public TPTNodeList<TColumnWithSortOrder> getIndexColumns() {
260        return indexColumns;
261    }
262
263    private Stack<TObjectName> variableStack = null;
264
265    public void setVariableStack(Stack<TObjectName> variableStack) {
266        this.variableStack = variableStack;
267    }
268
269    public Stack<TObjectName> getVariableStack() {
270        if (variableStack == null){
271            variableStack = new Stack<TObjectName>();
272        }
273
274        return variableStack;
275    }
276
277    private Stack<TDaxFunction> daxFunctionStack = null;
278
279    public Stack<TDaxFunction> getDaxFunctionStack() {
280        if (daxFunctionStack == null){
281            daxFunctionStack = new Stack<TDaxFunction>();
282        }
283        return daxFunctionStack;
284    }
285
286    private TObjectName labelName;
287
288    public void setLabelName(TObjectName lName) {
289        labelName = lName;
290        if (labelName != null){
291            //labelName.setObjectType(TObjectName.ttobjLabelName);
292            labelName.setDbObjectType(EDbObjectType.label);
293        }
294    }
295
296    /**
297     *
298     * @return label name used in plsql statement.
299     */
300    public TObjectName getLabelName() {
301
302        return labelName;
303    }
304
305
306    private TObjectName endlabelName;
307
308    public void setEndlabelName(TObjectName endlabelName) {
309        this.endlabelName = endlabelName;
310    }
311
312    public TObjectName getEndlabelName() {
313
314        return endlabelName;
315    }
316
317    /**
318     * Type of this statement.
319     */
320    public ESqlStatementType sqlstatementtype;
321    /**
322     * Source tokens included in this statement. only source tokens available when this is a top level statement, otherwise, there is no source token in this statement.
323     * Please check {@link gudusoft.gsqlparser.nodes.TParseTreeNode#getStartToken()}, and {@link gudusoft.gsqlparser.nodes.TParseTreeNode#getEndToken()} of this statement. 
324     */
325    public TSourceTokenList sourcetokenlist;
326
327    public TSourceTokenList getTokenList() {
328        return sourcetokenlist;
329    }
330    /**
331     * Parser used to parse this statement.
332     */
333    public TCustomParser parser;
334    /**
335     * PLSQL parser used to parse this statement.
336     */
337    public TCustomParser plsqlparser;
338    /**
339     * Tag used by parser internally.
340     */
341    public int dummytag;
342
343    /**
344     * target table in the delete/insert/update/create table statement.
345     * @see #joins
346     * @see TSelectSqlStatement
347     * @see TDeleteSqlStatement
348     * @see TUpdateSqlStatement
349     * @see TCreateTableSqlStatement
350     * @see gudusoft.gsqlparser.stmt.TMergeSqlStatement
351     */
352    public TTable getTargetTable() {
353        return targetTable;
354    }
355
356    public void setTargetTable(TTable targetTable) {
357        setNewSubNode(this.targetTable,targetTable,getAnchorNode());
358        this.targetTable = targetTable;
359    }
360
361    private TTable targetTable ;
362
363    /**
364     * joins represents table sources in the from clause. All structure information was reserved.
365     * <p>SQL 1:
366     * <p><blockquote><pre>select f from t1</pre></blockquote>
367     * <p>size of joins will be 1, t1 can be fetch via joins.getJoin(0).getTable()
368     * <p>
369     * <p>SQL 2:
370     * <p><blockquote><pre>select f from t1,t2</pre></blockquote>
371     * <p>size of joins will be 2,
372     * <p>t1 can be fetch via joins.getJoin(0).getTable()
373     * <p>t2 can be fetch via joins.getJoin(1).getTable()
374     * <p>
375     * <p>SQL 3:
376     * <p><blockquote><pre>select f from t1 join t2 on t1.f1 = t2.f1</pre></blockquote>
377     * <p>size of joins will be 1,
378     * <p>t1 information can be fetch via joins.getJoin(0).getTable()
379     * <p>In order to access t2, we need to introduce a new  class {@link TJoinItem} which includes all information about t2 and join condition.
380     * <p>There is a property named joinItems of {@link TJoin} which is type of {@link TJoinItemList} that includes a list of {@link TJoinItem}.
381     * <p>this property can be access via {@link gudusoft.gsqlparser.nodes.TJoin#getJoinItems()}.
382     * <p>Now, t2 can be fetch via  joins.getJoin(0).getJoinItems().getJoinItem(0).getTable()
383     * <p>
384     * <p>SQL 4:
385     * <p><blockquote><pre>select f from t1 join t2 on t1.f1 = t2.f1 join t3 on t1.f1 = t3.f1</pre></blockquote>
386     * <p>size of joins will be 1,
387     * <p>t1 can be fetch via joins.getJoin(0).getTable()
388     * <p>t2 can be fetch via joins.getJoin(0).getJoinItems().getJoinItem(0).getTable()
389     * <p>t3 can be fetch via joins.getJoin(0).getJoinItems().getJoinItem(1).getTable()
390     *
391     * @see #tables
392     */
393    public TJoinList joins;
394
395    /**
396     * Provides a quick way to access all tables involved in this SQL statement.
397     * <p>It stores all tables in a flat way while {@link #joins} stores all tables in a hierarchical structure.
398     * <p>joins only represents tables in from clause of select/delete statement, and tables in update/insert statement.
399     * <p>{@link #tables} includes all tables in all types of SQL statements  such as tables involved in a create table or create trigger statements.
400     */
401    public TTableList tables;
402
403    public TJoinList getJoins() {
404        return joins;
405    }
406
407    public TTableList getTables() {
408        return tables;
409    }
410
411    /**
412     * Saves all first level sub statements.
413     * <p>By iterating statements recursively, you can fetch all included statements in an easy way.
414     * <p><blockquote><pre>
415     * select f1+(select f2 from t2) from t1
416     * where f2 &gt; all (select f3 from t3 where f4 = (select f5 from t4))</pre>
417     * </blockquote>
418     * <p> Statements included in above SQL was save in a hierarchical way like this:
419     * <ul>
420     * <li>(select f2 from t2)</li>
421     * <li>(select f3 from t3 where f4 = (select f5 from t4))
422     *     <ul>
423     *      <li>(select f5 from t4)</li>
424     *     </ul>
425     * </li>
426     * </ul>
427     * <p>If this statement is a create procedure/function statement, then all declaration statements and statements in
428     * procedure body can also be fetched quickly by iterating this property recursively.
429     *
430     *
431     */
432    public TStatementList getStatements() {
433        if (statements == null){
434            statements = new TStatementList();
435        }
436        return statements;
437    }
438
439    private TStatementList statements;
440
441    public void setCteList(TCTEList cteList) {
442        setNewSubNode(this.cteList,cteList,getAnchorNode());
443        this.cteList = cteList;
444    }
445
446    /**
447     * Multiple common table expressions {@link TCTE} can be specified following the single WITH keyword.
448     *<p> Each common table expression specified can also be referenced by name in the FROM clause of subsequent common table expressions.
449     *
450     * <p>Used in select, delete, update statement.
451     * @return  List of common table expression.
452     */
453
454    public TCTEList getCteList() {
455
456        return cteList;
457    }
458
459    private TCTEList cteList = null;
460
461    public void setResultColumnList(TResultColumnList resultColumnList) {
462        setNewSubNode(this.resultColumnList,resultColumnList,getAnchorNode());
463        this.resultColumnList = resultColumnList;
464    }
465
466    /**
467     * In select statement, this method returns Items in select_list.
468     * Can be *, expr, and name.*
469     * <br><br>
470     * In update statement, this method returns assignments in set clause.
471     *
472     * @return select list of select statement or assignments of update statement.
473     */
474    public TResultColumnList getResultColumnList() {
475
476        return resultColumnList;
477    }
478
479    private TResultColumnList resultColumnList = null;
480
481    private TWhereClause whereClause = null;
482    private TTopClause topClause = null;
483    private TOutputClause outputClause = null;
484    private TReturningClause returningClause = null;
485
486    public void setReturningClause(TReturningClause returningClause) {
487        setNewSubNode(this.returningClause,returningClause,getAnchorNode());
488        this.returningClause = returningClause;
489    }
490
491    /**
492     * @return {@link TReturningClause returning clause.}
493     */
494
495    public TReturningClause getReturningClause() {
496
497        return returningClause;
498    }
499
500    public void setOutputClause(TOutputClause outputClause) {
501        setNewSubNode(this.outputClause,outputClause,getAnchorNode());
502        this.outputClause = outputClause;
503    }
504
505    /**
506     * @return output clause.
507     */
508
509    public TOutputClause getOutputClause() {
510
511        return outputClause;
512    }
513
514    public void setTopClause(TTopClause topClause) {
515        setNewSubNode(this.topClause,topClause,getAnchorNode());
516        this.topClause = topClause;
517    }
518
519    /**
520     * @return {@link TTopClause top clause.}
521     */
522    public TTopClause getTopClause() {
523        return topClause;
524    }
525
526    public void setWhereClause(TWhereClause newWhereClause){
527        setNewSubNode(this.whereClause ,newWhereClause,getAnchorNode());
528        this.whereClause = newWhereClause;
529    }
530
531
532    /**
533     * @deprecated As of 2.0.9.0, use {@link #setWhereClause(TWhereClause)} instead
534     * Or, use {@link TWhereClause#setText(String)}
535     *
536     * @param condition
537     * @return
538     */
539    public  TWhereClause addWhereClause(String condition){
540           return this.whereClause;
541    }
542
543    /**
544     * restrict the rows selected to those that satisfy one or more conditions.
545     * used in select, delete, update statement.
546     * @return {@link TWhereClause where clause.}
547     */
548    public TWhereClause getWhereClause() {
549        return whereClause;
550    }
551
552    public void setAlreadyAddToParent(boolean alreadyAddToParent) {
553        this.alreadyAddToParent = alreadyAddToParent;
554    }
555
556    private boolean alreadyAddToParent = false;
557
558    private boolean ableToIncludeCTE(ESqlStatementType sst){
559       return ((sst == ESqlStatementType.sstselect)
560               ||(sst == ESqlStatementType.sstupdate)
561               ||(sst == ESqlStatementType.sstinsert)
562               ||(sst == ESqlStatementType.sstdelete)
563               );
564    }
565
566    private TCTEList cteListInAllLevels = new TCTEList();
567
568    protected  TCTEList searchCTEList(Boolean stopAtFirstFinding){
569        cteListInAllLevels.clear();
570        if (cteList != null ) {
571            cteListInAllLevels.addAll(cteList);
572            if (stopAtFirstFinding) return cteListInAllLevels;
573        }
574
575        TCustomSqlStatement lcParent = this.parentStmt;
576        while (lcParent != null){
577            if (!ableToIncludeCTE(lcParent.sqlstatementtype)) break;
578
579            if (lcParent.cteList != null) {
580                cteListInAllLevels.addAll(lcParent.cteList);
581                if (stopAtFirstFinding)  break;
582            }
583            lcParent = lcParent.parentStmt;
584        }
585        return cteListInAllLevels;
586    }
587
588
589//    protected  TCTEList searchCTEList(){
590//       TCTEList ret = null;
591//       if (cteList != null ) {return cteList;}
592//       TCustomSqlStatement lcParent = this.parentStmt;
593//       while (lcParent != null){
594//           if (!ableToIncludeCTE(lcParent.sqlstatementtype)) break;
595//           ret = lcParent.cteList;
596//           if (ret != null) break;
597//           lcParent = lcParent.parentStmt;
598//       }
599//        return ret;
600//    }
601
602    public TCustomSqlStatement getParentStmt() {
603        return parentStmt;
604    }
605
606    public TParseTreeNode getParentObjectName(){
607        TParseTreeNode result = super.getParentObjectName();
608        if (result != null) return result;
609        return getParentStmt();
610    }
611
612    public void setParentStmt(TCustomSqlStatement parentStmt) {
613        if (!alreadyAddToParent){
614            this.parentStmt = parentStmt;
615            if (this.parentStmt != null){
616                parentStmt.getStatements().add(this);
617                alreadyAddToParent = true;
618            }
619        }
620    }
621
622    public void setParentStmtToNull() {
623        this.parentStmt = null;
624    }
625
626    private TCustomSqlStatement ancestorStmt = null;
627
628    public TCustomSqlStatement getAncestorStmt() {
629        TCustomSqlStatement lcRet = this;
630        while (lcRet.getParentStmt() != null){
631            lcRet = lcRet.getParentStmt();
632        }
633        return lcRet;
634    }
635
636    /**
637     * parent statement of this statement if any
638     */
639    private TCustomSqlStatement parentStmt = null;
640
641    /**
642     * Original Parse tree node from parser
643     */
644    public TParseTreeNode rootNode;
645
646    private Stack symbolTable = null;
647
648    /**
649     *
650     * @deprecated since ver 2.5.3.5, please use {@link TStmtScope} instead
651     */
652    public Stack getSymbolTable() {
653        if (symbolTable == null){
654            symbolTable = new Stack();
655        }
656        return symbolTable;
657    }
658
659    TSourceToken semicolonended;
660    boolean isctequery;
661    private ArrayList <TSyntaxError> syntaxErrors;
662
663    public ArrayList<TSyntaxError> getSyntaxErrors() {
664        return syntaxErrors;
665    }
666
667    public String getErrormessage(){
668
669        String s="",hint="Syntax error";
670        TSyntaxError t;
671        for (int i= 0; i< syntaxErrors.size(); i++)
672        {
673            t = (TSyntaxError) syntaxErrors.get(i);
674            if (t.hint.length() > 0) hint = t.hint;
675            s= s+hint+"("+t.errorno+") near: "+t.tokentext;
676            s=s+"("+t.lineNo;
677            s=s+","+t.columnNo +")";
678            //s=s+" expected tokentext:"+t.hint;
679
680            // break;//get only one message, remove this one and uncomment next line to get all error messages
681            if (i !=  syntaxErrors.size() - 1)
682                s = s +TBaseType.linebreak;
683        }
684
685        return s;
686    }
687
688    public ArrayList<TSyntaxError> getSyntaxHints() {
689        return syntaxHints;
690    }
691
692    private ArrayList <TSyntaxError> syntaxHints;
693
694    protected boolean isparsed;
695    TSourceToken _semicolon;
696
697    /**
698     * Number of syntax errors for this statement.
699     * @return 0 means no syntax error.
700     */
701    public int getErrorCount() {
702        return syntaxErrors.size();
703    }
704
705    
706    public TCustomSqlStatement(EDbVendor dbvendor){
707        super();
708        this.dbvendor = dbvendor;
709        sqlstatementtype = ESqlStatementType.sstunknown;
710        dummytag = 0;
711        sourcetokenlist = new TSourceTokenList();
712        syntaxErrors = new ArrayList<TSyntaxError>(4);
713        syntaxHints = new ArrayList<TSyntaxError>(4);
714        tables = new TTableList();
715        joins = new TJoinList();
716        indexColumns = new TPTNodeList<TColumnWithSortOrder>();
717     }
718
719    /**
720     * Log error messages if syntax errors found while parsing this statement.
721     * @param se syntax error structure.
722     * @return  type of error
723     */
724    public EActionOnParseError parseerrormessagehandle(TSyntaxError se){
725        if (se.errortype == EErrorType.sphint){
726            this.getAncestorStmt().syntaxHints.add(se);
727        }else
728            this.getAncestorStmt().syntaxErrors.add(se);
729        return EActionOnParseError.aopcontinue;
730    }
731
732    public int parsestatement(TCustomSqlStatement pparentsql,boolean isparsetreeavailable){
733        return parsestatement(pparentsql,isparsetreeavailable,false);
734    }
735
736    /**
737     * Parse this statement.
738     * @param pparentsql
739     * @param isparsetreeavailable
740     * @return parse result, zero means no syntax error found.
741     */
742    public int parsestatement(TCustomSqlStatement pparentsql,boolean isparsetreeavailable, boolean onlyNeedRawParseTree){
743        int ret = 0;
744        isparsed = false;
745        if (!isparsetreeavailable){
746           ret = checksyntax(pparentsql);
747        }
748        if (ret == 0)
749        {
750            isparsed = true;
751            if (!onlyNeedRawParseTree){
752                ret = doParseStatement(pparentsql);
753            }
754        }else if (dbvendor == EDbVendor.dbvsybase){
755            if ((this.rootNode != null)&&
756                    ((sqlstatementtype == ESqlStatementType.sstmssqlcreateprocedure)
757                     ||(sqlstatementtype == ESqlStatementType.sstmssqlcreatefunction)
758                     ||(sqlstatementtype == ESqlStatementType.sstcreatetrigger)
759                    )){
760                if (!onlyNeedRawParseTree){
761                    doParseStatement(pparentsql);
762                }
763
764            }
765        }
766        return ret;
767    }
768
769    public boolean OracleStatementCanBeSeparatedByBeginEndPair(){
770        return  (
771
772                (this.sqlstatementtype == ESqlStatementType.sstplsql_createprocedure)
773                //|| (this.sqlstatementtype == ESqlStatementType.sst_block_with_label)
774                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createfunction)
775                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createpackage)
776                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtype_placeholder)
777                ||(this.sqlstatementtype == ESqlStatementType.sstoraclecreatepackagebody)
778                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtrigger)
779//                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtypebody)
780//                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_tabletypedef)
781                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_varraytypedef)
782                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createprocedure)
783                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_execimmestmt)
784                ||(this.sqlstatementtype == ESqlStatementType.sstoraclecreatelibrary)
785                );
786    }
787
788    public boolean VerticaStatementCanBeSeparatedByBeginEndPair(){
789        return  (
790
791                        (this.sqlstatementtype == ESqlStatementType.sstcreatefunction)
792        );
793    }
794
795    public boolean isnzplsql(){
796        return  (
797                (this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
798        );
799    }
800
801    public boolean ispgplsql(){
802        return (this instanceof TCommonBlock)
803                ||(this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
804                ||(this.sqlstatementtype == ESqlStatementType.sstcreatefunction)
805                ||(this.sqlstatementtype == ESqlStatementType.sstDoExecuteBlock)
806                ;
807    }
808
809    public boolean isGaussDBStoredProcedure(){
810        return (this instanceof TCommonBlock)
811                ||(this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
812                ||(this.sqlstatementtype == ESqlStatementType.sstcreatefunction)
813                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createpackage)
814                ||(this.sqlstatementtype == ESqlStatementType.sstoraclecreatepackagebody)
815                ||(this.sqlstatementtype == ESqlStatementType.sstDoExecuteBlock)
816                ;
817    }
818
819    public boolean isdatabricksplsql(){
820        return (this instanceof TCommonBlock)
821                ;
822    }
823
824    public boolean isgreeplumplsql(){
825        return (this instanceof TCommonBlock)
826                ||(this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
827                ||(this.sqlstatementtype == ESqlStatementType.sstcreatefunction)
828                ||(this.sqlstatementtype == ESqlStatementType.sstDoExecuteBlock)
829                ;
830    }
831
832    public boolean isathenaplsql(){
833        return (this instanceof TCommonBlock)
834                ;
835    }
836
837    public boolean isprestoplsql(){
838        return (this instanceof TCommonBlock)
839                ;
840    }
841
842    public boolean issnowflakeplsql(){
843        return ((this instanceof TCommonBlock)
844                ||(this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
845        );
846    }
847
848    public boolean isBigQueryplsql(){
849        return ((this instanceof TCommonBlock)
850                ||(this.sqlstatementtype == ESqlStatementType.sstcreateprocedure)
851        );
852    }
853
854    public boolean isverticaplsql(){
855        return  (
856                        (this.sqlstatementtype == ESqlStatementType.sstcreatefunction)
857        );
858    }
859
860    public boolean isoracleplsql(){
861        return  (
862                (this.sqlstatementtype == ESqlStatementType.sst_plsql_block)
863                ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createprocedure)
864                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createfunction)
865                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createpackage)
866                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtype_placeholder)
867                        ||(this.sqlstatementtype == ESqlStatementType.sstoraclecreatepackagebody)
868                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtrigger)
869                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createtypebody)
870                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_tabletypedef)
871                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_varraytypedef)
872                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_createprocedure)
873                        ||(this.sqlstatementtype == ESqlStatementType.sstplsql_execimmestmt)
874                        ||(this.sqlstatementtype == ESqlStatementType.sstoraclecreatelibrary)
875                );
876    }
877
878    int checksyntax(TCustomSqlStatement psql){
879        return dochecksyntax(psql);
880    }
881
882    protected int dochecksyntax(TCustomSqlStatement psql){
883        int ret = -1;
884        clear();
885        if (sourcetokenlist.size() == 0) return ret;
886
887//        TCustomParser lcparser;
888//        lcparser = new TLzParserOracleSql(sourcetokenlist);
889//        lcparser.sql = this;
890//        ret = lcparser.yyparse();
891
892
893        if ((this.dbvendor == EDbVendor.dbvoracle)&&(this.isoracleplsql()&&(plsqlparser!=null))
894//                || ((this.dbvendor == EDbVendor.dbvgaussdb) // gaussdb 中用 oracle plsql 写的存储过程,用 oracle plsql parser 来解析
895//                        &&(
896//                            ((this instanceof TCreateFunctionStmt)&&(((TCreateFunctionStmt)this).isGaussDBSpInOracle()))
897//                            ||((this instanceof TCreateProcedureStmt)&&(((TCreateProcedureStmt)this).isGaussDBSpInOracle()))
898//                            ||(this instanceof TPlsqlCreatePackage)
899//                          )
900//                )
901        ){
902            plsqlparser.sql = this;
903//            if (this.dbvendor == EDbVendor.dbvgaussdb){
904//                // 原来用 gaussDB lexer tokenize 的 token 需要用 Oracle lexer 重新 tokenize 一边
905//                String sqlText="";
906//                for(int k = 0;k<sourcetokenlist.size();k++){
907//                    sqlText = sqlText + sourcetokenlist.get(k).toString();
908//                }
909//                // TODO, need to use singleton pattern to get a single instance of Oracle parser.
910//                TGSqlParser sqlParser = new TGSqlParser(EDbVendor.dbvoracle);
911//                // keep coordinate of the origin query
912//                long originalLineNo = sourcetokenlist.get(0).lineNo;
913//                long originalColumnNo = sourcetokenlist.get(0).columnNo;
914//                sqlParser.sqltext = TBaseType.stringBlock((int) originalLineNo - 1,(int) originalColumnNo - 1)+ sqlText;;
915//
916//                int r = sqlParser.getrawsqlstatements();
917//                sourcetokenlist.clear();
918//                for(int k=0;k<sqlParser.sourcetokenlist.size();k++){
919//                    sourcetokenlist.add(sqlParser.sourcetokenlist.get(k));
920//                }
921//            }
922
923            plsqlparser.sourcetokenlist = sourcetokenlist;
924
925            if ((this instanceof TCommonStoredProcedureSqlStatement)
926                &&((TCommonStoredProcedureSqlStatement)this).isWrapped()){
927                // don't parse wrapped oracle plsql
928                ret = 0;
929                this.rootNode = this;
930            }else {
931                ret = plsqlparser.yyparse();
932                this.rootNode = plsqlparser.rootNode;
933            }
934        }
935        else{
936            if ((this.sqlstatementtype == ESqlStatementType.sstExplain)&&(dbvendor != EDbVendor.dbvhana)){
937                    // EXPLAIN PLAN ... FOR statement; only parse token after FOR keyword
938                    boolean isFoundStopToken = false;
939
940                    for(int k=0;k<sourcetokenlist.size();k++){
941                        TSourceToken st = sourcetokenlist.get(k);
942                        switch (dbvendor){
943                            case dbvoracle:
944                                if (st.tokencode == TBaseType.rrw_for) {
945                                    st.tokencode = TBaseType.sqlpluscmd;
946                                    isFoundStopToken = true;
947                                }
948                                break;
949                            case dbvredshift:
950                                if (st.tokencode == TBaseType.rrw_explain){
951                                    st.tokencode = TBaseType.sqlpluscmd;
952                                    TSourceToken nextst = st.nextSolidToken();
953                                    if (nextst.tokencode == TBaseType.rrw_redshift_verbose){
954                                        nextst.tokencode = TBaseType.sqlpluscmd;
955                                        //System.out.println("Found verbose after explain");
956                                    }
957                                    isFoundStopToken = true;
958                                }
959                                break;
960                            case dbvvertica:
961                                if ((st.tokencode == TBaseType.rrw_select)
962                                        ||(st.tokencode == TBaseType.rrw_insert)
963                                        ||(st.tokencode == TBaseType.rrw_update)
964                                        ||(st.tokencode == TBaseType.rrw_merge)
965                                )
966                                {
967                                    isFoundStopToken = true;
968                                }
969                                break;
970                            case dbvmysql:
971                            case dbvsparksql:
972                            case dbvdatabricks:
973                            case dbvpostgresql:
974                                if ((st.tokencode == TBaseType.rrw_select)
975                                        ||(st.tokencode == TBaseType.rrw_insert)
976                                        ||(st.tokencode == TBaseType.rrw_update)
977                                        ||(st.tokencode == TBaseType.rrw_delete)
978                                        ||(st.tokencode == TBaseType.rrw_replace)
979                                        ||(st.tokencode == '(')
980                                )
981                                {
982                                    isFoundStopToken = true;
983                                }
984                                break;
985                            case dbvcouchbase:
986                                if (st.tokencode == TBaseType.rrw_explain){
987                                    st.tokencode = TBaseType.sqlpluscmd;
988                                    isFoundStopToken = true;
989                                }
990                                break;
991                            case dbvpresto:
992                            case dbvathena:
993                            case dbvnetezza:
994                                if ((st.tokencode == TBaseType.rrw_select)
995                                        ||(st.tokencode == TBaseType.rrw_insert)
996                                        ||(st.tokencode == TBaseType.rrw_update)
997                                        ||(st.tokencode == TBaseType.rrw_delete)
998                                )
999                                {
1000                                    isFoundStopToken = true;
1001                                }
1002                                break;
1003                            case dbvteradata:
1004                                if ((st.tokencode == TBaseType.rrw_select)
1005                                        ||(st.tokencode == TBaseType.rrw_insert)
1006                                        ||(st.tokencode == TBaseType.rrw_update)
1007                                        ||(st.tokencode == TBaseType.rrw_delete)
1008                                        ||(st.tokencode == TBaseType.rrw_teradata_collect)
1009                                )
1010                                {
1011                                    isFoundStopToken = true;
1012                                }
1013                                break;
1014                        }//switch
1015
1016                        if (isFoundStopToken) break;
1017                        st.tokencode = TBaseType.sqlpluscmd;
1018                    }
1019            }else if (this.sqlstatementtype == ESqlStatementType.sstProfile){
1020                for(int k=0;k<sourcetokenlist.size();k++) {
1021                    TSourceToken st = sourcetokenlist.get(k);
1022                    if (dbvendor == EDbVendor.dbvvertica){
1023                        if ((st.tokencode == TBaseType.rrw_select)
1024                                ||(st.tokencode == TBaseType.rrw_insert)
1025                                ||(st.tokencode == TBaseType.rrw_update)
1026                                ||(st.tokencode == TBaseType.rrw_merge)
1027                                )
1028                        {
1029                            break;
1030                        }
1031                    }
1032                    st.tokencode = TBaseType.sqlpluscmd;
1033                }
1034            }else if (this.sqlstatementtype == ESqlStatementType.sstprepare){
1035                if ((dbvendor == EDbVendor.dbvcouchbase)||(dbvendor == EDbVendor.dbvpresto)||(dbvendor == EDbVendor.dbvathena)){
1036                    int keywordCount = 0;
1037                    for(int k=0;k<sourcetokenlist.size();k++) {
1038                        TSourceToken st = sourcetokenlist.get(k);
1039                            if (st.tokencode == TBaseType.rrw_prepare)
1040                            {
1041                                keywordCount++;
1042                            }else if ((st.tokentype == ETokenType.ttkeyword)
1043                                    &&(st.tokencode != TBaseType.rrw_from)
1044                                    &&(st.tokencode != TBaseType.rrw_as)){
1045                                keywordCount++;
1046                                if (keywordCount > 1) break;
1047                            }
1048                        st.tokencode = TBaseType.sqlpluscmd;
1049                    }
1050                }
1051            }
1052
1053            if (parser == null){
1054                // statement such as select/insert and etc  inside plsql
1055                if (psql != null){
1056                    parser = psql.getTopStatement().parser;
1057                    this.setParentStmt(psql);
1058                }
1059                // parser =  new TParserOracleSql(null);
1060                //parser.lexer = new TLexerOracle();
1061                //parser.lexer.delimiterchar = '/';
1062            }
1063            parser.sql = this;
1064            parser.sourcetokenlist = sourcetokenlist;
1065            ret = parser.yyparse();
1066            this.rootNode = parser.rootNode;
1067        }
1068
1069        if (ret == 0){
1070            ret = syntaxErrors.size();
1071        }
1072       // if (rootNode == null) {
1073       if (rootNode == null) {
1074            ret = TBaseType.MSG_ERROR_NO_ROOT_NODE;
1075            // todo , uncomment next line when all sql statements in .y file was processed
1076             parseerrormessagehandle( new TSyntaxError("no root node",0,0,"no_root_node",EErrorType.sperror,TBaseType.MSG_ERROR_NO_ROOT_NODE,this,-1));
1077        }
1078        return ret;
1079    }
1080
1081    public void clearError(){
1082        syntaxErrors.clear();
1083        syntaxHints.clear();
1084    }
1085
1086    void clear(){
1087        syntaxErrors.clear();
1088        syntaxHints.clear();
1089// todo all subclass should add super()       
1090    }
1091
1092    public void setStmtScope(TStmtScope stmtScope) {
1093        this.stmtScope = stmtScope;
1094    }
1095
1096    public TStmtScope getStmtScope() {
1097        return stmtScope;
1098    }
1099
1100    /**
1101     * Original SQL fragment of this statement.
1102     * @return   Original statement text.
1103     */
1104
1105    /*
1106    public String toString(){
1107       StringBuffer sb = new StringBuffer("");
1108       for(int i=0; i<sourcetokenlist.size();i++){
1109          sb.append(sourcetokenlist.get(i).toString());  
1110        }
1111       return sb.toString();
1112    }
1113    */
1114    protected TStmtScope stmtScope = null;
1115    void buildsql(){}
1116    public int doParseStatement(TCustomSqlStatement psql){
1117        if (psql != null){
1118            this.setParentStmt(psql);
1119            this.setFrameStack(psql.getFrameStack());
1120            stmtScope = new TStmtScope(psql.stmtScope,this);
1121            // psql.statements.add(this);
1122        }else{
1123            stmtScope = new TStmtScope(this);
1124        }
1125
1126        if ((this.getStartToken() == null)&&(rootNode != null)){
1127            this.setStartToken(rootNode.getStartToken());
1128        }
1129        if ((this.getEndToken() == null)&&(rootNode != null)){
1130            this.setEndToken(rootNode.getEndToken());
1131        }
1132
1133        if(this.getGsqlparser() == null){
1134            if (rootNode != null){
1135                this.setGsqlparser(rootNode.getGsqlparser());
1136            }
1137        }
1138        return 0;
1139    }
1140
1141    void addtokentolist(TSourceToken st){
1142       st.stmt = this;
1143       sourcetokenlist.add(st);
1144    }
1145
1146    public TTable analyzeTablename(TObjectName tableName){
1147        TTable lcTable = new TTable();
1148        lcTable.setTableType(ETableSource.objectname);
1149        lcTable.setStartToken(tableName.getStartToken());
1150        lcTable.setEndToken(tableName.getEndToken());
1151        lcTable.setGsqlparser(this.getGsqlparser());
1152        lcTable.setTableName(tableName);
1153
1154        tables.addTable(lcTable);
1155        return lcTable;
1156    }
1157
1158    protected boolean isTableACTE(TTable pTable){
1159        boolean lcResult = false;
1160        TCTEList cteList1 = getCteList();
1161        if (cteList1 == null){
1162            TCustomSqlStatement lcStmt = getParentStmt();
1163            while (lcStmt != null){
1164                if (lcStmt.getCteList() != null){
1165                    cteList1 = lcStmt.getCteList();
1166                    break;
1167                }else {
1168                    lcStmt = lcStmt.getParentStmt();
1169                }
1170            }
1171        }
1172        if (cteList1 == null) return  false;
1173       // TCTE lcCTE = cteList1.cteNames.get(TBaseType.getTextWithoutQuoted(pTable.toString()).toUpperCase());
1174        if (pTable.toString() == null) return false;
1175
1176        int searchPos = pTable.getStartToken().posinlist;
1177        if (this.getCteIncludeThisStmt() != null){
1178            searchPos = this.getCteIncludeThisStmt().getStartToken().posinlist;
1179        }
1180        TCTE lcCTE = cteList1.searchCTEByName(TBaseType.getTextWithoutQuoted(pTable.toString()).toUpperCase(),searchPos);
1181        if ( lcCTE != null ){
1182            if (pTable.setCTE(lcCTE)){
1183                pTable.setCTEName(true);
1184                lcResult = true;
1185            }
1186        }
1187//        for (int i=0;i<cteList1.size();i++){
1188//            lcCTE = cteList1.getCTE(i);
1189//            if (TBaseType.getTextWithoutQuoted(lcCTE.getTableName().toString()).equalsIgnoreCase(TBaseType.getTextWithoutQuoted(pTable.toString()))){
1190//                pTable.setCTEName(true);
1191//                pTable.setCTE(lcCTE);
1192//                lcResult = true;
1193//                break;
1194//            }
1195//        }
1196
1197        return lcResult;
1198
1199    }
1200
1201    public TTable findTable(ETableEffectType[] tableEffectTypes){
1202        TTable lcResult = null;
1203        for(int i=0;i<tables.size();i++){
1204            for(int j=0;j<tableEffectTypes.length;j++){
1205                if (tables.getTable(i).getEffectType() == tableEffectTypes[j]){
1206                    lcResult = tables.getTable(i);
1207                    return  lcResult;
1208                }
1209            }
1210        }
1211        return  lcResult;
1212    }
1213    public void addToTables(TTable pTable){
1214        tables.addTable(pTable);
1215        if (isTableACTE(pTable)) return;
1216
1217        if (pTable.getTableName() == null) return;
1218        if (pTable.getTableName().getTableToken() == null) return;
1219        if ((pTable.getTableName().getTableString().toString().equalsIgnoreCase("inserted"))||(pTable.getTableName().getTableString().toString().equalsIgnoreCase("deleted"))){
1220           if ((getAncestorStmt().sqlstatementtype == ESqlStatementType.sstcreatetrigger)
1221               ||(getAncestorStmt().sqlstatementtype == ESqlStatementType.sstmssqlaltertrigger)){
1222               //pTable.setLinkTable(true);
1223               ETableEffectType[] effectTypes = new ETableEffectType[]{
1224                       ETableEffectType.tetTriggerOn,ETableEffectType.tetTriggerInsert,ETableEffectType.tetTriggerDelete,ETableEffectType.tetTriggerUpdate,ETableEffectType.tetTriggerInsteadOf
1225               };
1226               pTable.setLinkTable(getAncestorStmt().findTable(effectTypes));
1227           }
1228        }
1229
1230    }
1231
1232    public TJoin analyzeTableOrJoin(TFromTable pfromTable){
1233        TFromTable lcFromTable = pfromTable;
1234        TJoin lcJoin;
1235        TTable lcTable;
1236
1237        if (lcFromTable.getFromtableType() != ETableSource.join){
1238            lcJoin = new TJoin();
1239            lcTable = analyzeFromTable(lcFromTable,true);
1240            lcTable.setEffectType(ETableEffectType.tetSelect);
1241            lcJoin.setTable(lcTable);
1242            lcJoin.setStartToken(lcJoin.getTable().getStartToken());
1243            lcJoin.setEndToken(lcJoin.getTable().getEndToken());
1244            lcJoin.setGsqlparser(getGsqlparser());
1245            this.fromSourceTable = lcTable;
1246            this.getRelations().add(lcTable);
1247        }else{
1248            this.fromSourceJoin = lcFromTable.getJoinExpr();
1249
1250            this.fromSourceTable = new TTable();
1251            this.fromSourceTable.setTableType(ETableSource.join);
1252            this.fromSourceTable.setAliasClause(lcFromTable.getJoinExpr().getAliasClause());
1253            this.fromSourceTable.setStartToken(lcFromTable.getStartToken());
1254            this.fromSourceTable.setEndToken(lcFromTable.getEndToken());
1255            this.fromSourceTable.setGsqlparser(lcFromTable.getGsqlparser());
1256            this.fromSourceTable.setJoinExpr(this.fromSourceJoin);
1257            this.getRelations().add(this.fromSourceTable);
1258
1259            lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true);
1260            lcJoin.doParse(this, ESqlClause.join);
1261
1262            if (lcFromTable.getLateralViewList() != null){
1263                for(TLateralView lateralView:lcFromTable.getLateralViewList()){
1264                    TTable t = lateralView.createATable(this);
1265                    addToTables(t);
1266                    this.relations.add(t);
1267                }
1268            }
1269        }
1270
1271        return lcJoin;
1272    }
1273
1274    public TTable analyzeFromTable(TFromTable pfromTable, Boolean addToTableList){
1275        return analyzeFromTable(pfromTable,addToTableList,ESqlClause.unknown);
1276    }
1277
1278    public TTable analyzeFromTable(TFromTable pfromTable, Boolean addToTableList, ESqlClause pLocation){
1279        TTable lcTable = new TTable();
1280        lcTable.setTableType(pfromTable.getFromtableType());
1281        lcTable.setAliasClause(pfromTable.getAliasClause());
1282        lcTable.setStartToken(pfromTable.getStartToken());
1283        lcTable.setEndToken(pfromTable.getEndToken());
1284        lcTable.setGsqlparser(pfromTable.getGsqlparser());
1285        lcTable.setTableHintList(pfromTable.getTableHintList());
1286        lcTable.setTableSample(pfromTable.getTableSample());
1287        lcTable.setLateralViewList(pfromTable.getLateralViewList());
1288        lcTable.setTableProperties(pfromTable.getTableProperties());
1289        lcTable.setPivotedTable(pfromTable.getPivotedTable());
1290        lcTable.setParenthesisCount(pfromTable.getParenthesisCount());
1291        lcTable.setParenthesisAfterAliasCount(pfromTable.getParenthesisAfterAliasCount());
1292        lcTable.setTableKeyword(pfromTable.isTableKeyword());
1293        lcTable.setOnlyKeyword(pfromTable.isOnlyKeyword());
1294        lcTable.setFlashback(pfromTable.getFlashback());
1295        lcTable.setPxGranule(pfromTable.getPxGranule());
1296        lcTable.setTimeTravelClause(pfromTable.getTimeTravelClause());
1297        //lcTable.setPartitionClause(pfromTable.getPartitionClause());
1298
1299        if(getFrameStack().firstElement() != null){
1300            TFrame stackFrame = getFrameStack().firstElement();
1301            TGlobalScope globalScope = (TGlobalScope)stackFrame.getScope();
1302            lcTable.setSqlEnv(globalScope.getSqlEnv());
1303        }
1304
1305       switch(lcTable.getTableType()){
1306           case objectname:{
1307              // tables.addTableByTableRefernce(pfromTable.getTableObjectName());
1308               boolean insertedInTrigger = false;
1309               if (getTopStatement().sqlstatementtype == ESqlStatementType.sstcreatetrigger){
1310                  insertedInTrigger = (pfromTable.getTableObjectName().toString().compareToIgnoreCase("inserted")==0);
1311               }
1312
1313               if (insertedInTrigger){
1314                   // change table name from inserted to onTable name in create trigger 
1315                 lcTable.setTableName(((TCreateTriggerStmt)getTopStatement()).getOnTable().getTableName());
1316                 //lcTable.setLinkTable(true);
1317                 lcTable.setLinkTable(((TCreateTriggerStmt)getTopStatement()).getOnTable());
1318               }else{
1319                    lcTable.setTableName(pfromTable.getTableObjectName());
1320                   lcTable.getTableName().setSqlEnv(getSqlEnv());
1321
1322//                   if (getSqlEnv().getDefaultCatalogName() != null){
1323//                       if (lcTable.getTableName().getDatabaseToken() == null){
1324//                           lcTable.getTableName().setDatabaseToken(new TSourceToken(getSqlEnv().getDefaultCatalogName()),true);
1325//                       }
1326//                   }
1327
1328//                   if ((lcTable.getTableName().getSchemaToken() == null)&&(TSQLEnv.supportSchema(this.dbvendor))){
1329//                       // let find schema name for this table in env
1330//                       TSQLTable t = getSqlEnv().searchTable(".."+lcTable.getFullName());
1331//                       if (t != null){
1332//                           TSQLSchema s = t.getSchema();
1333//                           if (s != null){
1334//                               lcTable.getTableName().setSchemaToken(new TSourceToken(s.getName()),true);
1335//                           }
1336//                       }
1337//                   }
1338
1339               }
1340               // let's check is it cte name or ordinary table name
1341               TCTEList lcCteList = searchCTEList(false);
1342               TCTE lcCte = null;
1343               if (lcCteList != null){
1344                 for(int i=0;i<lcCteList.size();i++){
1345                    lcCte = lcCteList.getCTE(i);
1346                    if (lcCte.getTableName().toString().compareToIgnoreCase(TBaseType.getTextWithoutQuoted(lcTable.getTableName().toString()))==0){
1347                        // this is cte name
1348                        if (lcTable.setCTE(lcCte)){
1349                            lcTable.setCTEName(true);
1350                            lcTable.setCteColomnReferences(lcCte.getColumnList());
1351                            break;
1352                        }
1353                    }
1354                 }
1355               }
1356
1357               break;
1358           }
1359           case tableExpr:{
1360               ESqlClause location =  ESqlClause.tableExpr; //ESqlClause.resultColumn;
1361               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1362                   // change location here
1363               }
1364               lcTable.setTableExpr(pfromTable.getTableExpr());
1365               lcTable.getTableExpr().doParse(this,location);
1366               // teradata: SELECT table1.* FROM table(strtok_split_to_table(1, 'dm-calcite-raven/td/bq', '-') RETURNS (outkey integer, tokennum integer, token varchar(20)) ) as table1;
1367               // RETURNS (outkey integer, tokennum integer, token varchar(20))
1368               lcTable.setColumnDefinitions(pfromTable.getColumnDefinitions());
1369               break;
1370           }
1371           case subquery:{
1372//               if (pfromTable.getSubquerynode().isHiveFromQuery()){
1373//                   THiveFromQuery fromQuery  = new THiveFromQuery(dbvendor);
1374//                   lcTable.setHiveFromQuery(fromQuery);
1375//                   fromQuery.rootNode = pfromTable.getSubquerynode();
1376//                   fromQuery.setStartToken(pfromTable.getSubquerynode());
1377//                   fromQuery.setEndToken(pfromTable.getSubquerynode());
1378//                   fromQuery.setLabelName(this.labelName);
1379//                   fromQuery.doParseStatement(this);
1380//               }else{
1381//                   lcTable.subquery = new TSelectSqlStatement(dbvendor);
1382//                   lcTable.subquery.rootNode = pfromTable.getSubquerynode();
1383//                   lcTable.subquery.setLocation(ESqlClause.elTable);
1384//                   //lcTable.subquery.resultColumnList = ((TSelectSqlNode)lcTable.subquery.rootNode).getResultColumnList();
1385//                   lcTable.subquery.doParseStatement(this);
1386//               }
1387
1388               lcTable.subquery = new TSelectSqlStatement(dbvendor);
1389               lcTable.subquery.rootNode = pfromTable.getSubquerynode();
1390               if (pLocation == ESqlClause.unknown){
1391                   lcTable.subquery.setLocation(ESqlClause.elTable);
1392               }else{
1393                   lcTable.subquery.setLocation(pLocation);
1394               }
1395               //lcTable.subquery.resultColumnList = ((TSelectSqlNode)lcTable.subquery.rootNode).getResultColumnList();
1396               lcTable.subquery.doParseStatement(this);
1397
1398               break;
1399           }
1400           case function:{
1401               ESqlClause location = ESqlClause.tableFunction;// resultColumn;
1402               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1403                   // change location here
1404               }
1405               lcTable.setFuncCall(pfromTable.getFuncCall());
1406               lcTable.getFuncCall().doParse(this,location);
1407               break;
1408           }
1409           case containsTable:{
1410               ESqlClause location = ESqlClause.containsTable;//resultColumn;
1411               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1412                   // change location here
1413               }
1414               lcTable.setContainsTable(pfromTable.getContainsTable());
1415               lcTable.getContainsTable().doParse(this,location);
1416               break;
1417           }
1418
1419           case openrowset:{
1420               ESqlClause location = ESqlClause.openrowset;//resultColumn;
1421               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1422                   // change location here
1423               }
1424               lcTable.setOpenRowSet(pfromTable.getOpenRowSet());
1425               lcTable.getOpenRowSet().doParse(this,location);
1426               break;
1427           }
1428
1429           case openxml:{
1430               ESqlClause location = ESqlClause.openxml;//resultColumn;
1431               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1432                   // change location here
1433               }
1434               lcTable.setOpenXML(pfromTable.getOpenXML());
1435               lcTable.getOpenXML().doParse(this,location);
1436               break;
1437           }
1438
1439           case opendatasource:{
1440               ESqlClause location = ESqlClause.opendatasource;//resultColumn;
1441               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1442                   // change location here
1443               }
1444               lcTable.setOpenDatasource(pfromTable.getOpenDatasource());
1445               lcTable.getOpenDatasource().doParse(this,location);
1446               break;
1447           }
1448
1449           case openquery:{
1450               ESqlClause location = ESqlClause.openquery;//resultColumn;
1451               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1452                   // change location here
1453               }
1454               lcTable.setOpenquery(pfromTable.getOpenQuery());
1455               lcTable.getOpenquery().doParse(this,location);
1456               lcTable.setSubquery(lcTable.getOpenquery().getSubquery());
1457               break;
1458           }
1459
1460           case datachangeTable:{
1461               ESqlClause location = ESqlClause.datachangeTable;//resultColumn;
1462               if (sqlstatementtype == ESqlStatementType.sstinsert ){
1463                   // change location here
1464               }
1465               lcTable.setDatachangeTable(pfromTable.getDatachangeTable());
1466               lcTable.getDatachangeTable().doParse(this,location);
1467               break;
1468           }
1469           case rowList:{
1470               ESqlClause location = ESqlClause.rowList;//resultColumn;
1471               lcTable.setValueClause(pfromTable.getValueClause());
1472               lcTable.getValueClause().doParse(this,location);
1473               break;
1474           }
1475           case pivoted_table:{
1476               ESqlClause location = ESqlClause.pivoted_table;//resultColumn;
1477               lcTable.getPivotedTable().doParse(this,location);
1478               addToTableList = false;
1479               targetTable = lcTable;
1480               break;
1481           }
1482           case xmltable:{
1483               ESqlClause location = ESqlClause.xmltable;//resultColumn;
1484               lcTable.setXmlTable(pfromTable.getXmlTable());
1485               lcTable.getXmlTable().doParse(this,location);
1486               break;
1487           }
1488
1489           case informixOuter:{
1490               ESqlClause location = ESqlClause.outerTable;//resultColumn;
1491               lcTable.setOuterClause(pfromTable.getOuterClause());
1492               lcTable.getOuterClause().doParse(this,location);
1493               break;
1494           }
1495
1496           case table_ref_list:{
1497               lcTable.setFromTableList(pfromTable.getFromTableList());
1498               break;
1499           }
1500//           case hiveFromQuery:{
1501//               THiveFromQuery fromQuery = new THiveFromQuery(EDbVendor.dbvhive);
1502//               fromQuery.rootNode = pfromTable.getFromQuerySqlNode();
1503//               fromQuery.doParseStatement(this);
1504//               lcTable.setHiveFromQuery(fromQuery);
1505//               break;
1506//           }
1507           case output_merge:{
1508               TMergeSqlStatement outputMerge = new TMergeSqlStatement(EDbVendor.dbvmssql);
1509               outputMerge.rootNode = pfromTable.getMergeSqlNode();
1510               outputMerge.doParseStatement(this);
1511               lcTable.setOutputMerge(outputMerge);
1512               break;
1513           }
1514           case td_unpivot:{
1515               pfromTable.getTdUnpivot().doParse(this,ESqlClause.tdUnPivot);
1516               lcTable.setTdUnpivot(pfromTable.getTdUnpivot());
1517               break;
1518           }
1519           case unnest:{
1520               pfromTable.getUnnestClause().doParse(this,ESqlClause.elTable);
1521               lcTable.setUnnestClause(pfromTable.getUnnestClause());
1522               if (lcTable.getAliasClause() != null){
1523                   if (lcTable.getAliasClause().getColumns() != null){
1524                       for(TObjectName pColumn:lcTable.getAliasClause().getColumns()){
1525                           lcTable.getLinkedColumns().addObjectName(pColumn);
1526                           pColumn.setSourceTable(lcTable);
1527                       }
1528                   }else if (lcTable.getAliasClause().getAliasName() != null){
1529//                       SELECT *
1530//                               FROM UNNEST(['foo', 'bar', 'baz', 'qux', 'corge', 'garply', 'waldo', 'fred']) AS element
1531//                       WITH OFFSET AS offset
1532
1533                       // add element as column of unnest table.
1534                       TObjectName newColumn = TObjectName.createObjectName(this.dbvendor,EDbObjectType.column,lcTable.getAliasClause().getAliasName().getStartToken());
1535                       lcTable.getLinkedColumns().addObjectName(newColumn);
1536                       newColumn.setSourceTable(lcTable);
1537                   }
1538               }
1539
1540               if (lcTable.getUnnestClause().getWithOffset() != null){
1541                   if (lcTable.getUnnestClause().getWithOffsetAlais() != null){
1542                       // with offset as offsetAlias
1543                       TAliasClause aliasClause = lcTable.getUnnestClause().getWithOffsetAlais();
1544                       if (aliasClause.getAliasName() != null){
1545                           TObjectName newColumn = TObjectName.createObjectName(this.dbvendor,EDbObjectType.column,aliasClause.getAliasName().getStartToken());
1546                           lcTable.getLinkedColumns().addObjectName(newColumn);
1547                           newColumn.setSourceTable(lcTable);
1548                       }
1549                   }else{
1550                       // with offset
1551                       TObjectName newColumn = TObjectName.createObjectName(this.dbvendor,EDbObjectType.column,new TSourceToken("offset"));
1552                       lcTable.getLinkedColumns().addObjectName(newColumn);
1553                       newColumn.setSourceTable(lcTable);
1554                   }
1555               }
1556
1557               // link columns in the select list to unnest()
1558               // select emp_id,name,state,city,zipcode from `absolute-runner-302907.gudu_sqlflow.ADDRESS_NESTED`, UNNEST(address)
1559               if (lcTable.getUnnestClause().getDerivedColumnList() != null){
1560                   TObjectNameList derivedColumns = lcTable.getUnnestClause().getDerivedColumnList();
1561                   for(int i=0;i<derivedColumns.size();i++){
1562                       //System.out.println(derivedColumns.getObjectName(i).toString());
1563                       lcTable.getLinkedColumns().addObjectName(derivedColumns.getObjectName(i));
1564                   }
1565               }
1566
1567               break;
1568           }
1569           case jsonTable:{
1570               ESqlClause location = ESqlClause.jsonTable;//resultColumn;
1571               lcTable.setJsonTable(pfromTable.getJsonTable());
1572               lcTable.getJsonTable().doParse(this,location);
1573               break;
1574           }
1575           case externalTable:
1576               lcTable.setTableName(pfromTable.getTableObjectName());
1577               lcTable.setColumnDefinitions(pfromTable.getColumnDefinitions());
1578               lcTable.getColumnDefinitions().doParse(this,pLocation);
1579               lcTable.setTableType(ETableSource.externalTable); // tableType is reset in setTableName() method, so we reset it here
1580               break;
1581           case caseJoin:
1582               lcTable.setCaseJoin(pfromTable.getCaseJoin());
1583               lcTable.getCaseJoin().doParse(this,pLocation);
1584               break;
1585           case stageReference:
1586               lcTable.setStageReference(pfromTable.getStageReference());
1587               lcTable.getStageReference().doParse(this,pLocation);
1588
1589               lcTable.setTableName(lcTable.getStageReference().getStageName());
1590               lcTable.setTableType(ETableSource.stageReference);
1591               lcTable.getTableName().setSqlEnv(getSqlEnv());
1592
1593               break;
1594
1595      }//switch
1596
1597//        if (pfromTable.getPivotClause() != null){
1598//            lcTable.setPivotClause(pfromTable.getPivotClause());
1599//            lcTable.getPivotClause().doParse(this,ESqlClause.resultColumn);
1600//        }
1601
1602        lcTable.setPartitionExtensionClause(pfromTable.getPartitionExtensionClause());
1603
1604        //tables.addTable(lcTable);
1605        if (addToTableList) {
1606            addToTables(lcTable);
1607        }
1608
1609        if (lcTable.getTableHintList() != null){
1610            for(int i=0;i<lcTable.getTableHintList().size();i++){
1611                TTableHint hint = lcTable.getTableHintList().getElement(i);
1612                hint.setOwnerTable(lcTable);
1613                hint.doParse(this,ESqlClause.tableHint);
1614            }
1615        }
1616
1617        if (lcTable.getLateralViewList() != null){
1618            for(TLateralView lateralView:lcTable.getLateralViewList()){
1619                TTable t = lateralView.createATable(this);
1620                addToTables(t);
1621                this.relations.add(t);
1622            }
1623        }
1624
1625        if (lcTable.getAliasClause() != null){
1626            if (lcTable.getAliasClause().toString().equalsIgnoreCase("and")){
1627                // end keyword can't be alias name
1628                TSourceToken st1 = lcTable.getAliasClause().getStartToken();
1629                TSyntaxError err = new TSyntaxError(st1.toString()
1630                        ,st1.lineNo,st1.columnNo
1631                        ,String.format("AND keyword can't be table alias")
1632                        ,EErrorType.sperror
1633                        ,TBaseType.MSG_ERROR_AND_KEYWORD_CANT_USED_AS_TABLE_ALIAS
1634                        ,this,st1.posinlist);
1635                this.parseerrormessagehandle( err);
1636
1637            }
1638        }
1639
1640        return lcTable;
1641    }
1642
1643   public TJoin analyzeJoin(TJoinExpr pJoinExpr,TJoin pJoin,Boolean isSub){
1644        TJoin retval = pJoin;
1645        TJoinItem lcJoinItem = null ;
1646
1647        if (pJoinExpr == null) {return retval;}
1648
1649        if (pJoinExpr.getJointype() == EJoinType.nested)
1650        {
1651            if (isSub)
1652            {
1653                if (retval == null) {  // top level, left side is a join
1654                  retval = new TJoin();
1655                  retval.setStartToken(pJoinExpr.getStartToken());
1656                  retval.setEndToken(pJoinExpr.getEndToken());
1657                }
1658
1659                pJoinExpr.setJointype(pJoinExpr.original_jontype);
1660                retval.setJoin(analyzeJoin(pJoinExpr,null,true));
1661                //retval =analyzeJoin(pJoinExpr,null,true);
1662                retval.setKind(TBaseType.join_source_join);
1663                retval.getJoin().setAliasClause(pJoinExpr.getAliasClause());
1664                retval.getJoin().setWithParen(true);
1665                retval.getJoin().setNestedParen(pJoinExpr.getNestedParen());
1666            }
1667           else
1668            {
1669                if (retval == null)
1670                {
1671                    retval = new TJoin();
1672                    retval.setStartToken(pJoinExpr.getStartToken());
1673                    retval.setEndToken(pJoinExpr.getEndToken());
1674                    retval.setGsqlparser(this.getGsqlparser());
1675                }
1676                else
1677                {
1678                }
1679                pJoinExpr.setJointype(pJoinExpr.original_jontype);
1680                retval = analyzeJoin(pJoinExpr,retval,false);
1681                //retval.setJoin(analyzeJoin(pJoinExpr,retval,false));
1682                //retval = analyzeJoin(pJoinExpr,retval,false);
1683                //retval.setKind(TBaseType.join_source_join);
1684                //retval.setKind(TBaseType.join_source_table);
1685                //retval.setAliasClause(pJoinExpr.getAliasClause());
1686                retval.setAliasClause(pJoinExpr.getAliasClause());
1687                retval.setWithParen(true);
1688                retval.setNestedParen(pJoinExpr.getNestedParen());
1689            }
1690            return retval;
1691        }
1692
1693        if (pJoinExpr.getLeftOperand().getFromtableType() != ETableSource.join){
1694            if (retval == null) {
1695              retval = new TJoin();
1696              retval.setStartToken(pJoinExpr.getStartToken());
1697              retval.setEndToken(pJoinExpr.getEndToken());
1698              retval.setGsqlparser(this.getGsqlparser());
1699
1700              //  retval.setStartToken(pJoinExpr.getLeftOperand().getStartToken());
1701              //  retval.setEndToken(pJoinExpr.getLeftOperand().getEndToken());
1702            }
1703            TTable lcTable = analyzeFromTable(pJoinExpr.getLeftOperand(),true,ESqlClause.join);
1704            lcTable.setEffectType(ETableEffectType.tetSelect);
1705            retval.setTable(lcTable);
1706            //retval.joinTable.OwnerJoin = result;
1707            retval.setKind(TBaseType.join_source_table);
1708            pJoinExpr.setLeftTable(lcTable);
1709        }else{
1710            TJoinExpr lcJoinItemJoinExpr = pJoinExpr.getLeftOperand().getJoinExpr();
1711            //if (lcJoinItemJoinExpr.getJointype() == TBaseType.join_nested){
1712            //    lcJoinItemJoinExpr.setJointype(lcJoinItemJoinExpr.original_jontype);
1713            //}
1714
1715            if (retval != null) {
1716              retval = analyzeJoin(lcJoinItemJoinExpr,retval,true);
1717            } else {
1718              retval = analyzeJoin(lcJoinItemJoinExpr,retval,isSub);
1719            }
1720            retval.setStartToken(lcJoinItemJoinExpr.getStartToken());
1721            retval.setEndToken(lcJoinItemJoinExpr.getEndToken());
1722
1723
1724            TTable lcTable = new TTable();
1725            lcTable.setTableType(pJoinExpr.getLeftOperand().getFromtableType());
1726            lcTable.setAliasClause(lcJoinItemJoinExpr.getAliasClause());
1727            lcTable.setStartToken(lcJoinItemJoinExpr.getStartToken());
1728            lcTable.setEndToken(lcJoinItemJoinExpr.getEndToken());
1729            pJoinExpr.setLeftTable(lcTable);
1730            lcTable.setJoinExpr(lcJoinItemJoinExpr);
1731        }
1732
1733        if (pJoinExpr.getRightOperand().getFromtableType() != ETableSource.join){
1734            if (retval != null)
1735            {
1736                lcJoinItem = new TJoinItem();
1737                TTable lcTable = analyzeFromTable(pJoinExpr.getRightOperand(),true,ESqlClause.join);
1738                lcTable.setEffectType(ETableEffectType.tetSelect);
1739                lcJoinItem.setTable(lcTable);
1740                lcJoinItem.setStartToken(lcJoinItem.getTable().getStartToken());
1741                lcJoinItem.setEndToken(lcJoinItem.getTable().getEndToken());
1742               // lcJoinItem.JoinItemTable.OwnerJoinItem := lcJoinItem;
1743                lcJoinItem.setKind(TBaseType.join_source_table);
1744                retval.getJoinItems().addJoinItem(lcJoinItem);
1745                pJoinExpr.setRightTable(lcTable);
1746            }
1747        }else{
1748            if (retval != null)
1749            {
1750                lcJoinItem = new TJoinItem();
1751                lcJoinItem.setKind(TBaseType.join_source_join);
1752                TJoinExpr lcJoinItemJoinExpr = pJoinExpr.getRightOperand().getJoinExpr();
1753                //if (lcJoinItemJoinExpr.getJointype() == TBaseType.join_nested){
1754                //    lcJoinItemJoinExpr.setJointype(lcJoinItemJoinExpr.original_jontype);
1755                //}
1756                lcJoinItem.setJoin(analyzeJoin(pJoinExpr.getRightOperand().getJoinExpr(),null,false));
1757                lcJoinItem.getJoin().setAliasClause(lcJoinItemJoinExpr.getAliasClause());
1758                lcJoinItem.setStartToken(lcJoinItem.getJoin().getStartToken());
1759                lcJoinItem.setEndToken(lcJoinItem.getJoin().getEndToken());
1760                retval.getJoinItems().addJoinItem(lcJoinItem);
1761
1762                TTable lcTable = new TTable();
1763                lcTable.setTableType(pJoinExpr.getRightOperand().getFromtableType());
1764                lcTable.setAliasClause(lcJoinItemJoinExpr.getAliasClause());
1765                lcTable.setStartToken(lcJoinItemJoinExpr.getStartToken());
1766                lcTable.setEndToken(lcJoinItemJoinExpr.getEndToken());
1767                pJoinExpr.setRightTable(lcTable);
1768                lcTable.setJoinExpr(lcJoinItemJoinExpr);
1769            }
1770        }
1771
1772        if (lcJoinItem == null) return retval;
1773
1774        lcJoinItem.setJoinType(pJoinExpr.getJointype());
1775        lcJoinItem.setUsingColumns(pJoinExpr.usingColumns);
1776        if ((lcJoinItem.getUsingColumns() != null) && (tables.size()>1)){
1777            TObjectName crf ;
1778            for (int i=0;i<lcJoinItem.getUsingColumns().size();i++){
1779                crf = lcJoinItem.getUsingColumns().getObjectName(i);
1780                // link this column to last 2 tables
1781                tables.getTable(tables.size()-1).getObjectNameReferences().addObjectName(crf);
1782                tables.getTable(tables.size()-2).getObjectNameReferences().addObjectName(crf);
1783
1784                tables.getTable(tables.size()-1).getLinkedColumns().addObjectName(crf);
1785                crf.setSourceTable(tables.getTable(tables.size()-1));
1786                tables.getTable(tables.size()-2).getLinkedColumns().addObjectName(crf);
1787                crf.setSourceTable(tables.getTable(tables.size()-2));
1788
1789            }
1790            lcJoinItem.setEndToken(lcJoinItem.getUsingColumns().getEndToken());
1791        }
1792        lcJoinItem.setOnCondition(pJoinExpr.onCondition);
1793        if (lcJoinItem.getOnCondition() != null)
1794        {
1795            lcJoinItem.getOnCondition().doParse(this,ESqlClause.joinCondition);
1796            lcJoinItem.setEndToken(lcJoinItem.getOnCondition().getEndToken());
1797        }
1798
1799
1800        return retval;
1801    }
1802
1803    public boolean locateVariableOrParameter(TObjectName cr){
1804        return locateVariableOrParameter(cr,false);
1805    }
1806    public boolean locateVariableOrParameter(TObjectName cr, boolean checkVariableDeclaredInProcedure){
1807      boolean ret =  false;
1808      if (cr.getDbObjectType() == EDbObjectType.variable) return true;
1809      if (cr.toString().equalsIgnoreCase("*")) return  false;
1810      //search variable in framestack
1811
1812      TVariable symbolVariable = null;
1813
1814      if (cr.getTableToken() != null){
1815          // record_variable.column
1816          symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),cr.getTableToken().toString());
1817          if (symbolVariable != null){
1818              cr.getTableToken().setDbObjectType(EDbObjectType.variable);
1819              //TTable sourceTable = new TTable(new TObjectName(EDbObjectType.table,symbolVariable.getVariableName().getStartToken()));
1820              TTable sourceTable = new TTable(TObjectName.createObjectName (this.dbvendor, EDbObjectType.variable,symbolVariable.getVariableName().getStartToken()));
1821              sourceTable.getLinkedColumns().addObjectName(cr);
1822              cr.setSourceTable(sourceTable);
1823             // symbolVariable.getVariableName().getReferencedObjects().addObjectName(cr);
1824             // System.out.println("find variable:"+cr.toString());
1825              cr.setResolveStatus(TBaseType.RESOLVED_AND_FOUND); // set resolve status to resolved,避免在 TAttributeResolver 中关联到其他 table
1826              return true;
1827          }
1828
1829      }else{
1830          // variable
1831          symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),cr.toString());
1832          if (symbolVariable != null){
1833              cr.setDbObjectType(EDbObjectType.variable);
1834              symbolVariable.getVariableName().getReferencedObjects().addObjectName(cr);
1835              return true;
1836          }
1837      }
1838
1839        // check parameters in plsql only, may add support for sql server later.
1840      if(! ((dbvendor == EDbVendor.dbvoracle)||(dbvendor == EDbVendor.dbvmysql))) return false;
1841      if (cr.getObjectType() == TObjectName.ttobjVariable) return true;
1842
1843        Stack symbolTable = this.getTopStatement().getSymbolTable();
1844        TSymbolTableItem item = null;
1845        TObjectName objName = null;
1846        TObjectName qualifiedName = null; // function/procedure name or label name of plsql block
1847        for (int i = symbolTable.size()-1;i>=0;i--){
1848            item = (TSymbolTableItem)symbolTable.get(i);
1849            if (item.getData() instanceof TParameterDeclaration){
1850                objName = ((TParameterDeclaration)item.getData()).getParameterName();
1851            }else if (item.getData() instanceof TVarDeclStmt){
1852                objName = ((TVarDeclStmt)item.getData()).getElementName();
1853            }else  if (item.getData() instanceof TObjectName){
1854                objName = (TObjectName)item.getData();
1855            }
1856
1857            if (objName == null) continue;
1858
1859            if (cr.toString().compareToIgnoreCase(objName.toString()) == 0){
1860                ret = true;
1861                if (checkVariableDeclaredInProcedure) break; // return true if variable declared in procedure
1862                for(int j=0;i<tables.size();i++){
1863                    TTable lcTable = tables.getTable(j);
1864                    if (lcTable.isBaseTable()){
1865                        if (fireOnMetaDatabaseTableColumn(
1866                                             lcTable.getPrefixServer()
1867                                            ,lcTable.getPrefixDatabase()
1868                                            ,lcTable.getPrefixSchema()
1869                                            ,lcTable.getName()
1870                                            ,cr.getColumnNameOnly())){
1871                            ret = false;
1872                            break;
1873                        }
1874                    }
1875                }
1876
1877                if (ret)  break;
1878            }else if (cr.toString().indexOf(".")>0){
1879                // qualified object reference, compare it with procedure/function/block label prefixed
1880                if (item.getStmt() instanceof TPlsqlCreateFunction){
1881                   qualifiedName = ((TPlsqlCreateFunction)item.getStmt()).getFunctionName();
1882                }else if (item.getStmt() instanceof TPlsqlCreateProcedure){
1883                   qualifiedName = ((TPlsqlCreateProcedure)item.getStmt()).getProcedureName();
1884                }else if (item.getStmt() instanceof TCommonBlock){
1885                   qualifiedName = ((TCommonBlock)item.getStmt()).getLabelName();
1886                }
1887
1888                if (qualifiedName != null){
1889                    if (cr.toString().compareToIgnoreCase(qualifiedName.toString()+'.'+objName.toString()) == 0){
1890                        ret = true;
1891                    }
1892                }
1893
1894                if (ret ) break;
1895            }
1896
1897        }
1898          if (ret){
1899              //add this parameter or variable reference to original parameter/variable
1900                  objName.getReferencedObjects().addObjectName(cr);
1901                  cr.setObjectType(TObjectName.ttobjVariable);
1902          }
1903          return ret;
1904    }
1905
1906    TCTE findCTEByName(String cteName){
1907        TCTEList lcCteList = searchCTEList(false);
1908        TCTE lcCte = null;
1909        if (lcCteList != null){
1910          for(int i=0;i<lcCteList.size();i++){
1911             if (lcCteList.getCTE(i).getTableName().toString().compareToIgnoreCase(cteName)==0){
1912                 lcCte = lcCteList.getCTE(i);
1913                 break;
1914             }
1915          }
1916        }
1917     return lcCte;
1918    }
1919
1920    /**
1921     * @deprecated since 2.3.8.2, use {@link TTable#getExpandedStarColumns()} instead.
1922     *
1923     * @param lcTable
1924     * @return
1925     */
1926    public ArrayList<String> getColumnsInTable(TTable lcTable){
1927        if (lcTable.isCTEName()){
1928            ArrayList<String> columns = new ArrayList<>();
1929            if (lcTable.getCteColomnReferences()!=null){
1930                for(TObjectName n:lcTable.getCteColomnReferences()){
1931                    columns.add(n.toString());
1932                }
1933            }else if (lcTable.getCTE().getSubquery() != null && lcTable.getCTE().getSubquery().getResultColumnList() != null){
1934                for(TResultColumn resultColumn:lcTable.getCTE().getSubquery().getResultColumnList()){
1935                    columns.add(resultColumn.getDisplayName());
1936                }
1937            }
1938            return columns;
1939        }else{
1940            return getColumnsInTable(
1941                    lcTable.getPrefixServer()
1942                    ,lcTable.getPrefixDatabase()
1943                    ,lcTable.getPrefixSchema()
1944                    ,lcTable.getName()
1945            );
1946        }
1947    }
1948
1949
1950    /**
1951     * @deprecated since 2.3.8.2, use {@link TTable#getExpandedStarColumns()} instead.
1952     *
1953     * @param pServer
1954     * @param pDatabase
1955     * @param pSchema
1956     * @param pTable
1957     * @return
1958     */
1959    public ArrayList<String> getColumnsInTable(String pServer,String pDatabase,String pSchema,String pTable){
1960        TFrame stackFrame = getFrameStack().firstElement();
1961        TGlobalScope globalScope = (TGlobalScope)stackFrame.getScope();
1962
1963        if (globalScope.getSqlEnv() != null){
1964            return globalScope.getSqlEnv().getColumnsInTable(pDatabase+"."+pSchema+"."+pTable,false);
1965        }else{
1966            return  null;
1967        }
1968    }
1969
1970
1971    public boolean fireOnMetaDatabaseTableColumn(String pServer,String pDatabase,String pSchema,String pTable,String pColumn){
1972//        boolean lcResult = false;
1973//        if (this.getGsqlparser().getMetaDatabase() != null){
1974//            lcResult = this.getGsqlparser().getMetaDatabase().checkColumn(pServer,pDatabase,pSchema,pTable,pColumn);
1975//        }
1976
1977        TFrame stackFrame = getFrameStack().firstElement();
1978        TGlobalScope globalScope = (TGlobalScope)stackFrame.getScope();
1979
1980        if (globalScope.getSqlEnv() != null){
1981           // System.out.println(globalScope.getSqlEnv().toString());
1982
1983            return globalScope.getSqlEnv().columnInTable(pDatabase+"."+pSchema+"."+pTable,pColumn);
1984        }else{
1985            return  false;
1986        }
1987
1988//        return lcResult;
1989    }
1990
1991    public TTable getFirstPhysicalTable(){
1992        TTable ret = null;
1993        if (tables.size() == 0) return null;
1994        for(int i=0;i<tables.size();i++){
1995            if (tables.getTable(i).isBaseTable()) {
1996                ret = tables.getTable(i);
1997                break;
1998            }
1999        }
2000        return ret;
2001    }
2002    private TObjectNameList orphanColumns = null;
2003
2004    public TObjectNameList getOrphanColumns() {
2005        if (orphanColumns == null) orphanColumns = new TObjectNameList();
2006        return orphanColumns;
2007    }
2008
2009    protected boolean linkToFirstTable(TObjectName pColumn,int pCandidateTableCnt){
2010        boolean lcResult = false;
2011        if ((dbvendor == EDbVendor.dbvteradata)&&(pColumn.isQualified())&&(pColumn.getTableToken().getDbObjectType() != EDbObjectType.subquery_alias)){
2012            // update table1 set col = 'value' where table1.id = table2.id2
2013            boolean isFoundLinkedTable = false;
2014            TCustomSqlStatement lcSql = this;
2015            while (lcSql != null){
2016                int i = 0;
2017                i = lcSql.tables.searchTableByNameOrAlias(pColumn.getTableToken().toString());
2018                isFoundLinkedTable = ( i != -1);
2019                if (isFoundLinkedTable) {
2020                    if (tables.getTable(i).getEffectType() == ETableEffectType.tetImplicitLateralDerivedTable ){
2021                        // 如果不查重table,会导致 employee.first_name 中的 employee 被第二次加到 tables 中
2022//                        DELETE FROM foodmart.trimmed_employee ACT
2023//                        WHERE ACT.employee_id = employee.employee_id
2024//                        AND  employee.first_name = 'Walter'
2025//                        AND  trimmed_salary.employee_id = -1
2026
2027                        TTable newTable = tables.getTable(i);
2028                        newTable.getLinkedColumns().addObjectName(pColumn);
2029                        pColumn.setSourceTable(newTable);
2030                        pColumn.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
2031                    }
2032                    break;
2033                }
2034                lcSql = lcSql.getParentStmt();
2035            }
2036            if (!isFoundLinkedTable){
2037                TTable newTable = null;
2038                if (pColumn.getDatabaseToken() == null){
2039
2040                    //newTable = new TTable(new TObjectName(EDbObjectType.table,pColumn.getTableToken()));
2041                    newTable = new TTable(TObjectName.createObjectName (this.dbvendor, EDbObjectType.table,pColumn.getTableToken()));
2042                    newTable.setStartToken(pColumn.getTableToken());
2043                    newTable.setEndToken(pColumn.getTableToken());
2044                }else{
2045
2046                    //newTable = new TTable(new TObjectName(EDbObjectType.table,pColumn.getSchemaToken(), pColumn.getTableToken()));
2047                    newTable = new TTable(TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,pColumn.getDatabaseToken(), pColumn.getTableToken()));
2048                    newTable.setStartToken(pColumn.getSchemaToken());
2049                    newTable.setEndToken(pColumn.getTableToken());
2050                }
2051
2052                newTable.setTableType(ETableSource.objectname);
2053                newTable.setEffectType(ETableEffectType.tetImplicitLateralDerivedTable);
2054                newTable.getLinkedColumns().addObjectName(pColumn);
2055                pColumn.setSourceTable(newTable);
2056                pColumn.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
2057                this.addToTables(newTable);
2058
2059                // 2024 年
2060                // 不能加入到 relations 中,否则会导致 下面 SQL 中 star column 同时链接到 SPCOMM.L_FIXED_RATE_PLAN_REF, ipshare_ofccplv.cprof_d_period_dates_ref
2061                // 从而导致 本来不该有的歧义产生
2062
2063                // UPDATE b_rate_plan
2064                //FROM
2065                //(
2066                //SELECT * FROM SPCOMM.L_FIXED_RATE_PLAN_REF
2067                //WHERE rate_plan_ref_eff_dt<= ipshare_ofccplv.cprof_d_period_dates_ref.PERIOD
2068                //) AS ref
2069                //SET accs_fee = REF.accs_fee,
2070                //SVC_TYPE = REF.prod_grp_lvl_1,
2071                //rate_plan_lvl3 = REF.rate_plan_lvl_3,
2072                //prod_grp_lvl3 = REF.prod_grp_lvl_2
2073                //WHERE b_rate_plan.svc_type IS NULL
2074
2075                // 2025/2/25, v3.0.4.8
2076                // 需要加入到 relations 中,新的 gudusoft.gsqlparser.resolver package 中的算法会处理这种情况
2077                // teradata 的隐式横向派生表不能加入到关系解析器中
2078                // this.getRelations().add(newTable);
2079            }
2080            return true;
2081        }
2082        if (pColumn.getCandidateTables().size() == 1){
2083            TTable table = pColumn.getCandidateTables().getTable(0);
2084            table.getLinkedColumns().addObjectName(pColumn);
2085            pColumn.setSourceTable(table);
2086            lcResult = true;
2087        }
2088        else if ((tables.size() == 1) || (pCandidateTableCnt == 1)){
2089            TTable table = tables.getTable(0);
2090
2091            if(table.getTableType() == ETableSource.function){
2092                //lcResult = linkToFunctionTable(table, pColumn);
2093                int iRet = table.getFuncCall().isColumnInThisTableFunction(this.getSqlEnv(),this.dbvendor,pColumn);
2094                if ( iRet == TBaseType.COLUMN_IN_TABEL_FUNCTION_YES){
2095                    lcResult = true;
2096                    table.getLinkedColumns().addObjectName(pColumn);
2097                    pColumn.setSourceTable(table);
2098                    lcResult = true;
2099                }else if ( iRet == TBaseType.COLUMN_IN_TABEL_FUNCTION_NO){
2100                    lcResult = false;
2101                }else{
2102                    table.getLinkedColumns().addObjectName(pColumn);
2103                    pColumn.setSourceTable(table);
2104                    lcResult = true;
2105                }
2106            }else if(table.getTableType() == ETableSource.subquery){
2107                if (! table.getSubquery().searchColumnInResultSet(pColumn,(tables.size()==1))){
2108                    getOrphanColumns().addObjectName(pColumn);
2109                    pColumn.setOrphanColumn(true);
2110                    TSourceToken st = pColumn.getStartToken();
2111                    if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
2112                        TBaseType.log(String.format("Add orphan column <%s> to statement in old algorithm in subquery %s",pColumn.toString(),table.getAliasName()),TLog.WARNING,table);
2113                    }
2114                    this.parseerrormessagehandle(new TSyntaxError(st.astext, st.lineNo, st.columnNo
2115                            ,"find orphan column", EErrorType.sphint
2116                            , TBaseType.MSG_HINT_FIND_ORPHAN_COLUMN,this,st.posinlist,pColumn));
2117                }
2118            }
2119            else{
2120                table.getLinkedColumns().addObjectName(pColumn);
2121                pColumn.setSourceTable(table);
2122                lcResult = true;
2123                if ((dbvendor == EDbVendor.dbvbigquery)&&(pCandidateTableCnt == 0) && (pColumn.isQualified())){
2124                    // bigquery struct column used in query
2125//                    create view test as (SELECT rollNo,
2126//                            info.name as n1,
2127//                    info2.name as n2,
2128//                            info.age from my_first_dataset.student_records);
2129
2130                    pColumn.columnToProperty();
2131                }
2132            }
2133        }else if (tables.size() > 1){
2134            // if there is only a table without table alias, then, link to this table
2135            boolean foundOnlyOneTable = false;
2136            TTable tableWithoutAlias = null;
2137            for(TTable table:tables){
2138                if (table.isCTEName()) continue; // CTE 即便没有 指定alias,也不作为考虑对象
2139                if (table.getAliasClause() == null){
2140                    tableWithoutAlias = table;
2141                    if (foundOnlyOneTable){
2142                        foundOnlyOneTable = false;
2143                        break;
2144                    }else{
2145                        foundOnlyOneTable = true;
2146                    }
2147                }
2148            }
2149
2150            if (foundOnlyOneTable){
2151                tableWithoutAlias.getLinkedColumns().addObjectName(pColumn);
2152                pColumn.setSourceTable(tableWithoutAlias);
2153                lcResult = true;
2154            }else{
2155                getOrphanColumns().addObjectName(pColumn);
2156                pColumn.setOrphanColumn(true);
2157                TSourceToken st = pColumn.getStartToken();
2158                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
2159                    TBaseType.log(String.format("Add orphan column <%s> to statement in old algorithm ",pColumn.toString()),TLog.WARNING,this);
2160                }
2161
2162                this.parseerrormessagehandle(new TSyntaxError(st.astext, st.lineNo, st.columnNo
2163                        ,"find orphan column", EErrorType.sphint
2164                        , TBaseType.MSG_HINT_FIND_ORPHAN_COLUMN,this,st.posinlist,pColumn));
2165            }
2166
2167        }
2168        return  lcResult;
2169    }
2170
2171    private boolean linkToFunctionTable(TTable table, TObjectName pColumn) {
2172        if(table.getTableName().toString().toUpperCase().equals("STRING_SPLIT")){
2173            if(pColumn.getColumnNameOnly().toUpperCase().equals("VALUE")){
2174                table.getLinkedColumns().addObjectName(pColumn);
2175                pColumn.setSourceTable(table);
2176                return true;
2177            }
2178            else return false;
2179        }
2180        else {
2181            table.getLinkedColumns().addObjectName(pColumn);
2182            pColumn.setSourceTable(table);
2183            return true;
2184        }
2185    }
2186
2187    boolean isSQLServerInsertedDelete(TObjectName pColumn){
2188        if (((pColumn.toString().toUpperCase().startsWith("INSERTED"))
2189                ||(pColumn.toString().toUpperCase().startsWith("DELETED")))
2190                //&&(plocation == ESqlClause.output)
2191                &&(targetTable != null)){
2192            targetTable.getObjectNameReferences().addObjectName(pColumn);
2193            pColumn.setSourceTable(targetTable);
2194            return true;
2195        }else
2196        {
2197            return false;
2198        }
2199    }
2200
2201    boolean isOracleNewOldTable(TObjectName pColumn){
2202        boolean ret = false;
2203        if (dbvendor != EDbVendor.dbvoracle) return false;
2204        if (!(pColumn.isQualified())) return false;
2205        if ((pColumn.getTableString().equalsIgnoreCase(":new"))
2206            ||(pColumn.getTableString().equalsIgnoreCase(":old"))){
2207            if (getAncestorStmt().tables != null){
2208                if (getAncestorStmt().tables.size() > 0){
2209                    getAncestorStmt().tables.getTable(0).getLinkedColumns().addObjectName(pColumn);
2210                    pColumn.setSourceTable(getAncestorStmt().tables.getTable(0));
2211                    ret = true;
2212                }
2213            }
2214        }
2215
2216        return ret;
2217    }
2218
2219    public boolean searchDaxVariableInStack(TObjectName pName){
2220        boolean ret = false;
2221        if (getVariableStack().size() == 0) return false;
2222        if (pName.getDbObjectType() == EDbObjectType.column) return false;
2223        for(int i=0;i<variableStack.size();i++){
2224            if (pName.toString().equalsIgnoreCase(((TObjectName) variableStack.get(i)).toString())){
2225                ret = true;
2226                break;
2227            }
2228        }
2229        return ret;
2230    }
2231
2232    boolean linkColumnToTableDax(TObjectName pColumn, ESqlClause pLocation){
2233        boolean lcResult = true ;
2234        TDaxFunction daxFunction = null;
2235        if (searchDaxVariableInStack(pColumn)) return false;
2236        if (getDaxFunctionStack().size() > 0){
2237            daxFunction = daxFunctionStack.peek();
2238        }
2239
2240        if (pColumn.getTableToken() != null){
2241            //TTable sourceTable = new TTable(new TObjectName(EDbObjectType.table,pColumn.getTableToken()));
2242            TTable sourceTable = new TTable(TObjectName.createObjectName (this.dbvendor,EDbObjectType.table,pColumn.getTableToken()));
2243            sourceTable.getLinkedColumns().addObjectName(pColumn);
2244            addToTables(sourceTable);
2245            if ((daxFunction != null) && (daxFunction.getDefaultTable() == null)){
2246                daxFunction.setDefaultTable(sourceTable);
2247            }
2248        }else{
2249            if ((daxFunction != null) &&(daxFunction.getDefaultTable() != null)){
2250                daxFunction.getDefaultTable().getLinkedColumns().addObjectName(pColumn);
2251            }else{
2252                ((TDaxStmt)this).getDefaultTable().getLinkedColumns().addObjectName(pColumn);
2253            }
2254        }
2255        return  lcResult;
2256    }
2257
2258    public boolean linkColumnToTable(TObjectName pColumn, ESqlClause pLocation){
2259        boolean lcResult = false,isContinue = false;
2260        int candidateTableCnt = 0;
2261        if (dbvendor == EDbVendor.dbvdax){
2262            return linkColumnToTableDax(pColumn,pLocation);
2263        }
2264
2265        if (pColumn.getSourceTable() != null) {
2266            lcResult = true;
2267            return lcResult;
2268        }
2269
2270        if (pColumn.getResolveStatus() == TBaseType.RESOLVE_DELAY_TO_COLUMN_RESOLVER) return true;
2271
2272        pColumn.setLocation(pLocation);
2273
2274        if (! pColumn.isValidColumnName(dbvendor)) {
2275            if (pColumn.isReservedKeyword()){
2276                if (
2277                        ((pColumn.getStartToken().tokencode != TBaseType.rrw_mysql_true)&&(!(pColumn.getStartToken().toString().equalsIgnoreCase("true"))))
2278                        &&((pColumn.getStartToken().tokencode != TBaseType.rrw_mysql_false)&&(!(pColumn.getStartToken().toString().equalsIgnoreCase("false"))))
2279                        &&(pColumn.getStartToken().tokencode != TBaseType.rrw_mysql_default)
2280                   ) {
2281                        boolean mysqlBuiltFunction = false;
2282                        if (dbvendor == EDbVendor.dbvmysql){
2283                            mysqlBuiltFunction = functionChecker.isBuiltInFunction(pColumn.toString(),EDbVendor.dbvmysql,"6.0");
2284                        }
2285                        if (!mysqlBuiltFunction){
2286                            TSourceToken st1 = pColumn.getStartToken();
2287                            TSyntaxError err = new TSyntaxError(st1.toString()
2288                                    , st1.lineNo, st1.columnNo
2289                                    , String.format("Reserved keyword can't be column name")
2290                                    , EErrorType.sperror
2291                                    , TBaseType.MSG_ERROR_RESERVED_KEYWORD_CANT_USED_AS_COLUMN_NAME
2292                            ,this,st1.posinlist);
2293                            this.parseerrormessagehandle(err);
2294                        }
2295                }
2296            }
2297            return false;
2298        }
2299
2300        if (isOracleNewOldTable(pColumn)) return true;
2301        if (isSQLServerInsertedDelete(pColumn)) return true;
2302
2303        // oracle insert all statement,
2304        // WHEN id <= 3 THEN INTO dest_tab1 VALUES(id, description1)
2305        // column in values clause must be in the subquery of insert all statement
2306        if (pColumn.getLocation() == ESqlClause.insertValues){
2307            if (this instanceof TInsertSqlStatement){
2308                TInsertSqlStatement insertSqlStatement = (TInsertSqlStatement)this;
2309                if (insertSqlStatement.isInsertAll()){
2310                   // if (pColumn.getStartToken().tokencode == TBaseType.rrw_snowflake_default) return true;
2311                    lcResult = insertSqlStatement.getSubQuery().searchColumnInResultSet(pColumn, true);
2312                }
2313            }
2314
2315            if (lcResult) return true;
2316
2317            // value in values clause maybe parameter of the procedure/function parameter
2318            lcResult = locateVariableOrParameter(pColumn,true);
2319            if (lcResult) return true;
2320        }
2321
2322        for(int i=0;i<tables.size();i++){
2323            TTable lcTable = tables.getTable(i);
2324            if (lcTable.getEffectType() == ETableEffectType.tetSelectInto) continue;
2325            if (lcTable.getEffectType() == ETableEffectType.tetImplicitLateralDerivedTable) continue;
2326
2327            if (pColumn.isQualified()){
2328                lcResult = pColumn.resolveWithThisTable(lcTable);
2329                if ((lcResult) && (lcTable.getTableType() == ETableSource.subquery)){
2330                    pColumn.getTableToken().setDbObjectType(EDbObjectType.subquery_alias);
2331
2332                    int lcPos = lcTable.searchColumnInAlias(pColumn);
2333                    lcResult = lcPos>=0;
2334                    if (lcResult){
2335                        // 在 alias 中找到 source column, 还需要对应到 subquery select 中的 select list
2336                        // sql 见 https://e.gitee.com/gudusoft/projects/151613/tasks/list?issue=I8JR0W#note_23051633
2337                        if ((lcTable.getSubquery() != null)&&(lcTable.getSubquery().getResultColumnList() != null)){
2338                            pColumn.setSourceColumn(lcTable.getSubquery().getResultColumnList().getResultColumn(lcPos));
2339                        }
2340                    }else{
2341                        lcResult =  lcTable.getSubquery().searchColumnInResultSet(pColumn,true);
2342                    }
2343               //     lcTable.getSubquery().searchColumnInResultSet(pColumn,true);
2344
2345                }else if ((lcResult) && (lcTable.isCTEName())){
2346                    lcTable.getCTE().searchColumnInResultSet(this,lcTable,pColumn,true);
2347                }else if ((lcResult) && (lcTable.getTableType() == ETableSource.openquery)&&(lcTable.getSubquery() != null)){
2348                    pColumn.getTableToken().setDbObjectType(EDbObjectType.subquery_alias);
2349                    lcTable.getSubquery().searchColumnInResultSet(pColumn,true);
2350//                }else if ((lcResult) && (lcTable.getTableType() == ETableSource.unnest)&&(lcTable.getUnnestClause() != null)){
2351//                    pColumn.getTableToken().setDbObjectType(EDbObjectType.subquery_alias);
2352//                    lcTable.getSubquery().searchColumnInResultSet(pColumn,true);
2353                }
2354                if (lcResult&&pColumn.toString().endsWith("*")){
2355                    pColumn.getSourceTableList().add(lcTable);
2356//                    ArrayList<String> lcColumns = getColumnsInTable(lcTable);
2357//                    if (lcColumns != null){
2358//                        pColumn.getColumnsLinkedToStarColumn().addAll(lcColumns);
2359//                    }
2360                }
2361            }else {
2362              // column not qualified
2363
2364                // check if this is the column alias in current select list.
2365                if((!lcResult)&& ((!pColumn.isQualified()) && (this instanceof TSelectSqlStatement)&&(getResultColumnList() !=null))
2366                        && (TBaseType.isSupportLateralColumn(dbvendor))
2367                ){
2368                    for(int j=0;j<getResultColumnList().size();j++){
2369                        TResultColumn lcField = getResultColumnList().getResultColumn(j);
2370                        lcResult = lcField.isMatchedUsingAlias(pColumn);
2371                        if (
2372                                 (!TSQLEnv.isAliasReferenceForbidden[this.dbvendor.ordinal()])&&
2373                                ((lcResult)&&(pColumn.getStartToken().posinlist > lcField.getAliasClause().getStartToken().posinlist))){
2374                            pColumn.setSourceColumn(lcField);
2375                            lcField.getTargetColumns().addObjectName(pColumn);
2376                            pColumn.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_COLUMN_ALIAS_IN_OLD_ALGORITHM);
2377                            break;
2378                        }else{
2379                            lcResult = false;
2380                        }
2381                    }
2382
2383                    if (lcResult) return true;
2384                }
2385
2386                if (pColumn.getColumnNameOnly().equalsIgnoreCase("*")){
2387                    lcResult = true;
2388                    isContinue = true; // in order to match next table in the from clause
2389                    pColumn.getSourceTableList().add(lcTable);
2390//                    ArrayList<String> lcColumns = getColumnsInTable(lcTable);
2391//                    if (lcColumns != null){
2392//                        pColumn.getColumnsLinkedToStarColumn().addAll(lcColumns);
2393//                    }
2394                }else if (lcTable.isBaseTable()){
2395                    lcResult = fireOnMetaDatabaseTableColumn(
2396                                         lcTable.getPrefixServer()
2397                                        ,lcTable.getPrefixDatabase()
2398                                        ,lcTable.getPrefixSchema()
2399                                        ,lcTable.getName()
2400                                        ,pColumn.getColumnNameOnly());
2401                    if (! lcResult) {
2402                        candidateTableCnt++;
2403                        pColumn.getCandidateTables().addTable(lcTable);
2404                    }
2405
2406                }else if ((lcTable.getTableType() == ETableSource.subquery)
2407                            ||((lcTable.getTableType() == ETableSource.openquery)&&(lcTable.getSubquery() != null))){
2408
2409                    lcResult = lcTable.searchColumnInAlias(pColumn)>=0;
2410                    if (!lcResult){
2411                        lcResult = lcTable.getSubquery().searchColumnInResultSet(pColumn,(tables.size() == 1)
2412                                &&(pColumn.getCandidateTables().size() == 0));
2413                        if (! lcResult) {
2414                            candidateTableCnt++;
2415                            pColumn.getCandidateTables().addTable(lcTable);
2416                        }
2417                    }
2418
2419
2420//                    if (lcTable.isIncludeColumnAlias()){
2421//                       // System.out.println("subquery with alias:"+lcTable.getAliasClause().toString()+", skip search:"+pColumn.toString());
2422//
2423//                    }else{
2424//                        lcResult = lcTable.getSubquery().searchColumnInResultSet(pColumn,(tables.size() == 1)&&(pColumn.getCandidateTables().size() == 0));
2425//                        if (! lcResult) candidateTableCnt++;
2426//                    }
2427                }else  if (lcTable.isCTEName()){
2428                    lcResult = lcTable.getCTE().searchColumnInResultSet(this,lcTable,pColumn,tables.size() == 1);
2429                    if (! lcResult) {
2430                        candidateTableCnt++;
2431                        pColumn.getCandidateTables().addTable(lcTable);
2432                    }
2433                }else if (lcTable.getTableType() == ETableSource.function){
2434                    //  search in this table function
2435                        if(tables.size() == 1){
2436                                lcResult = ( lcTable.getFuncCall().isColumnInThisTableFunction(this.getSqlEnv(),this.dbvendor,pColumn)
2437                                != TBaseType.COLUMN_IN_TABEL_FUNCTION_NO);
2438                        }
2439                        else{
2440                                lcResult = ( lcTable.getFuncCall().isColumnInThisTableFunction(this.getSqlEnv(),this.dbvendor,pColumn)
2441                                                                        == TBaseType.COLUMN_IN_TABEL_FUNCTION_YES);
2442                        }
2443                }else if (lcTable.getTableType() == ETableSource.tableExpr 
2444                                && lcTable.getTableExpr().getExpressionType() == EExpressionType.function_t
2445                                && lcTable.getTableExpr().getFunctionCall() != null){
2446                    //  search in this table function
2447                    lcResult = ( lcTable.getTableExpr().getFunctionCall().isColumnInThisTableFunction(this.getSqlEnv(),this.dbvendor,pColumn)
2448                                                                        == TBaseType.COLUMN_IN_TABEL_FUNCTION_YES);
2449                }else if (lcTable.getTableType() == ETableSource.pivoted_table){
2450                    lcResult = fireOnMetaDatabaseTableColumn(
2451                            lcTable.getPrefixServer()
2452                            ,lcTable.getPrefixDatabase()
2453                            ,lcTable.getPrefixSchema()
2454                            ,lcTable.getName()
2455                            ,pColumn.getColumnNameOnly());
2456                }else if (lcTable.getTableType() == ETableSource.unnest){
2457                    for(TObjectName objectName:lcTable.getLinkedColumns()){
2458                        if (objectName.toString().equalsIgnoreCase(pColumn.toString())){
2459                            lcResult = true;
2460                            break;
2461                        }
2462                    }
2463
2464                    if (!lcResult){
2465                        if (lcTable.getAliasClause() == null){
2466                            // this unnest() clause generate column with default name: "value"
2467                            if (pColumn.toString().equalsIgnoreCase("value")){
2468                                lcResult = true;
2469                            }
2470                        }else{
2471                        }
2472                    }
2473                }//unnest
2474            }
2475
2476            if (lcResult) {
2477                lcTable.getLinkedColumns().addObjectName(pColumn);
2478                pColumn.setSourceTable(lcTable);
2479               // pColumn.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
2480                if (!isContinue) break;
2481            }
2482        }
2483
2484        // check variable after metadata checking
2485        if (locateVariableOrParameter(pColumn)) return false;
2486
2487        // check if this is the column alias in current select list.
2488//        if((!lcResult)&& ((!pColumn.isPrefixed()) && (this instanceof TSelectSqlStatement)&&(getResultColumnList() !=null))){
2489//            for(int j=0;j<getResultColumnList().size();j++){
2490//                TResultColumn lcField = getResultColumnList().getResultColumn(j);
2491//                lcResult = lcField.isMatchedUsingAlias(pColumn);
2492//                if ((lcResult)&&(pColumn.getStartToken().posinlist > lcField.getAliasClause().getStartToken().posinlist)){
2493//                    pColumn.setSourceColumn(lcField);
2494//                    lcField.getTargetColumns().addObjectName(pColumn);
2495//                    break;
2496//                }else{
2497//                    lcResult = false;
2498//                }
2499//            }
2500//        }
2501
2502        if (lcResult) return true;
2503
2504        boolean isSearchUpLevel = (this.parentStmt != null);
2505
2506        if ((isSearchUpLevel) && (sqlstatementtype == ESqlStatementType.sstselect)){
2507            isSearchUpLevel = (pColumn.isQualified()
2508                                || (
2509//                                        (((TSelectSqlStatement)(this)).getLocation() != ESqlClause.elTable) &&
2510                                         (! ((TSelectSqlStatement)(this)).isQueryOfCTE())
2511                                    )
2512                               )
2513                            && (parentStmt.sqlstatementtype != ESqlStatementType.sstinsert)
2514                            && (!((pColumn.getLocation() == ESqlClause.selectList)&&(((TSelectSqlStatement)(this)).getLocation() == ESqlClause.join)))
2515                            && ((((TSelectSqlStatement)(this)).getLocation() != ESqlClause.pivot_in))
2516                            && (!((parentStmt.sqlstatementtype == ESqlStatementType.sstcreatetable)))
2517                            && (!((parentStmt.sqlstatementtype == ESqlStatementType.sstcreateview)))
2518//                            && (!((pColumn.getLocation() == ESqlClause.selectList)&&(parentStmt.sqlstatementtype == ESqlStatementType.sstcreatetable)))
2519//                            && (!((pColumn.getLocation() == ESqlClause.selectList)&&(parentStmt.sqlstatementtype == ESqlStatementType.sstcreateview)))
2520                            && (! ((pColumn.getLocation() == ESqlClause.selectList)
2521                                    &&(candidateTableCnt == 1) && (this instanceof TSelectSqlStatement)
2522                                    && (((TSelectSqlStatement)(this)).getLocation() == ESqlClause.elTable)
2523                                    ) ) // ref:mantis: #2628
2524                           // && ( ((TSelectSqlStatement)(this.parentStmt)).getSetOperatorType() == ESetOperatorType.none)
2525            ;
2526
2527            if (isSearchUpLevel){
2528                isSearchUpLevel = !((!pColumn.isQualified())&&(((TSelectSqlStatement) this).getLocation() == ESqlClause.where));
2529            }
2530        }
2531
2532        if (isSearchUpLevel&&(pColumn.isContinueToSearch())){ // only search one level up, c:\prg\gsp_sqlfiles\TestCases\java\oracle\dbobject\berger_sqltest_04.sql
2533            boolean increaseLevel = true;
2534            if (parentStmt instanceof TSelectSqlStatement){
2535                if( ((TSelectSqlStatement)parentStmt).getSetOperatorType() != ESetOperatorType.none){
2536                   increaseLevel = false;
2537                }
2538            }
2539            if (increaseLevel){
2540                pColumn.searchLevel++;
2541            }
2542
2543            lcResult = parentStmt.linkColumnToTable(pColumn,pLocation);
2544
2545            if (increaseLevel){
2546                pColumn.searchLevel--;
2547            }
2548        }
2549
2550        if ((! lcResult) && (pColumn.searchLevel == 0)) {
2551            if (this.sqlstatementtype == ESqlStatementType.sstselect){
2552                if( ((TSelectSqlStatement)this).getSetOperatorType() == ESetOperatorType.none){
2553                    //                    USING _spVV0 (INTEGER)
2554                    //                            INSERT INTO table3
2555                    //                    SELECT :_spVV0,x. *,m.col3
2556                    //                    from ((           select table1.col1, (table1.col1 + table5.col2) c from table1
2557                    //                            union all select col3,col4 from table2) x
2558                    //                    cross join (select id from table2) m )
2559
2560                    // table5 in the above sql only link to the nearest level sql, but not to up-level which is union all
2561
2562                    linkToFirstTable(pColumn,candidateTableCnt);
2563                }
2564            }else{
2565                linkToFirstTable(pColumn,candidateTableCnt);
2566            }
2567        }
2568
2569        return lcResult;
2570    }
2571
2572
2573    /**
2574     *
2575     * @deprecated As of v1.6.0.1, use  {@link #linkColumnToTable} instead
2576     */
2577    public void linkColumnReferenceToTable(TObjectName cr, ESqlClause plocation){
2578        // this is the column name, link it to table
2579        if (cr == null) return;
2580        cr.setLocation(plocation);
2581        if (cr.getObjectType() == TObjectName.ttobjVariable) return;
2582        if (cr.getObjectType() == TObjectName.ttobjColumnAlias) return;
2583        if (this.dbvendor == EDbVendor.dbvsybase){
2584            TSourceToken pt = cr.getPartToken();
2585            if ( pt != null){
2586                if (pt.tokentype == ETokenType.ttdqstring){
2587                //"0123", quoted string start with a number can't a column
2588                    if ((pt.toString().charAt(1) >= '0')
2589                        &&(pt.toString().charAt(1) <= '9')){
2590                        return;
2591                    }else if (pt.toString().length() == 2){
2592                        //"", empty
2593                        return;
2594                    }else if (pt.toString().substring(1,pt.toString().length()-1).trim().length() == 0){
2595                        //"  "
2596                        return;
2597                    }
2598                }
2599            }
2600        }
2601
2602
2603        if (cr.getPartToken() != null){
2604            if (cr.getPartToken().tokentype == ETokenType.ttkeyword){
2605                boolean reservedKeyword = false;
2606                switch (dbvendor){
2607                    case dbvmssql:
2608                        //reservedKeyword = ! this.getGsqlparser().getFlexer().canBeColumnName(cr.getPartToken().tokencode);
2609                        reservedKeyword = ! TLexerMssql.canBeColumnName(cr.getPartToken().tokencode);
2610                        break;
2611                    case dbvsybase:
2612                        reservedKeyword = keywordChecker.isKeyword(cr.getPartToken().toString(), EDbVendor.dbvsybase, "15.7", true);
2613                        break;
2614                    default:
2615                        break;
2616                }
2617                if (reservedKeyword) return;
2618            }
2619        }
2620
2621        // let's check is this columnreference is variable or parameter of plsql function/procedure
2622      //  if (locateVariableOrParameter(cr)) return;
2623
2624//        if ((cr.getPartToken() != null)&&((dbvendor == EDbVendor.dbvmssql)||(dbvendor == EDbVendor.dbvsybase))){
2625//            if ((cr.getPartToken().tokentype == ETokenType.ttkeyword)&&(!(this.getGsqlparser().getFlexer().canBeColumnName(cr.getPartToken().tokencode)))){
2626//                // keyword can't be column name:
2627//                //select * From dbo.table Where DATEDIFF(day, create_date, expiry_date) < 14
2628//               return;
2629//            }
2630//        }
2631
2632        if ((cr.toString().startsWith("@")))
2633//            if ((cr.toString().endsWith("*"))||(cr.toString().startsWith("@")))
2634        {
2635            cr.setObjectType(TObjectName.ttobjNotAObject);
2636            return;
2637        }
2638
2639        if (dbvendor == EDbVendor.dbvoracle){
2640            if ( //(cr.toString().compareToIgnoreCase ("rowid") == 0)||
2641                    (cr.toString().compareToIgnoreCase ("sysdate") == 0)
2642            || (cr.toString().compareToIgnoreCase ("nextval") == 0)
2643            || (cr.toString().compareToIgnoreCase ("rownum") == 0)
2644            || (cr.toString().compareToIgnoreCase ("level") == 0)
2645                    ){
2646                cr.setObjectType(TObjectName.ttobjNotAObject);
2647                if (cr.getDbObjectType() == EDbObjectType.unknown){
2648                    cr.setDbObjectType(EDbObjectType.notAColumn);
2649                }
2650                return;
2651            }
2652        }
2653
2654        if (((cr.toString().toUpperCase().startsWith("INSERTED"))||(cr.toString().toUpperCase().startsWith("DELETED")))&&(plocation == ESqlClause.output)&&(targetTable != null)){
2655            targetTable.getObjectNameReferences().addObjectName(cr);
2656            return;
2657        }
2658
2659        if ( ((cr.toString().toUpperCase().startsWith(":NEW"))
2660              ||(cr.toString().toUpperCase().startsWith(":OLD")))
2661             &&(this.getTopStatement() instanceof TPlsqlCreateTrigger)
2662             &&(dbvendor == EDbVendor.dbvoracle)){
2663             this.getTopStatement().tables.getTable(0).getObjectNameReferences().addObjectName(cr);
2664            return;
2665        }
2666
2667
2668
2669        int ret = this.tables.checkColumnReferenceInTables(cr);
2670         if (ret >= 0) {
2671             TTable lcTable = this.tables.getTable(ret);
2672             if (lcTable.isBaseTable()){
2673                lcTable.getObjectNameReferences().addObjectName(cr);
2674             }else if (lcTable.isCTEName()){
2675                //WITH temp
2676                //     AS (SELECT *
2677                //         FROM   sysibm.systables),
2678                //     temp1
2679                //     AS (SELECT *
2680                //         FROM   sysibm.syscolumns)
2681                //SELECT *
2682                //FROM   temp A
2683                //       INNER JOIN temp1 B
2684                //               ON A.creator = B.tbcreator
2685                //                  AND A.name = B.tbname
2686                 TCTE lccte = findCTEByName(lcTable.toString());
2687                 if (lccte != null){
2688                     TObjectName objectName = new TObjectName();
2689                     objectName.init(cr.getPartToken());
2690                     if (lccte.getSubquery() != null){
2691                         lccte.getSubquery().linkColumnReferenceToTable(objectName,plocation);
2692                     }
2693                 }
2694             }else if (lcTable.getTableType() == ETableSource.subquery){
2695                // link s2t1a1 to  subselect2table1 via s2
2696                //select
2697                //       s2.s2t1a1
2698                //from
2699                //    (
2700                //       select s2t1.*
2701                //          from subselect2table1 s2t1
2702                //    ) s2
2703               TSelectSqlStatement subquery = lcTable.getSubquery();
2704
2705                 if(((subquery.getValueClause() == null))&&(!subquery.isCombinedQuery())&&(subquery.getResultColumnList() != null)&&(subquery.getResultColumnList().size() == 1)){
2706                     TResultColumn lcColumn = subquery.getResultColumnList().getResultColumn(0);
2707                     if (lcColumn.toString().endsWith("*")){
2708                        boolean isfound = false;
2709
2710                        for(int i=0;i<subquery.tables.size();i++){
2711                            if (subquery.tables.getTable(i).getTableType() == ETableSource.subquery) continue;
2712                            String columnStr = null;
2713                            if (cr.getPartToken() != null){
2714                                //cr.getObjectType() is not ttObjColumn, so we can't use
2715                                // getColumnToken, this is a bug, need to check it later.
2716                                columnStr = cr.getPartToken().toString();
2717                            }
2718                            if (this.fireOnMetaDatabaseTableColumn(
2719                                    subquery.tables.getTable(i).getTableName().getServerString(),
2720                                    subquery.tables.getTable(i).getTableName().getDatabaseString(),
2721                                    subquery.tables.getTable(i).getTableName().getSchemaString(),
2722                                    subquery.tables.getTable(i).getName(),columnStr)){
2723                                subquery.tables.getTable(i).getObjectNameReferences().addObjectName(cr);
2724                                isfound = true;
2725                                break;
2726                            }
2727                        }
2728
2729
2730
2731                         if (!isfound)
2732                         {
2733                             if(subquery.tables.size() > 1){
2734                                 cr.setTableDetermined(false);
2735                             }
2736                           for(int i=0;i<subquery.tables.size();i++){
2737                             subquery.tables.getTable(i).getObjectNameReferences().addObjectName(cr);
2738                           }
2739                         }
2740
2741                     } // "*"
2742                 }
2743             }
2744         }else if (ret == -2){
2745           // no qualifier before column, check is this column of a cte, if not,set it to non-cte table
2746           boolean isfound = false;
2747             for (int i=0;i<this.tables.size();i++){
2748                 if ((this.tables.getTable(i).isCTEName()) &&(this.tables.getTable(i).getCteColomnReferences() != null)){
2749                     if (this.tables.getTable(i).getCteColomnReferences().searchColumnReference(cr) >= 0){
2750                        this.tables.getTable(i).getObjectNameReferences().addObjectName(cr);
2751                         isfound = true;
2752                         break;
2753                     }
2754                 }
2755             }
2756
2757           // no qualifier before column, but we still need to check uplevel table like this:
2758            //SELECT
2759            //       col1 ,
2760            //
2761            //           (    SELECT col2
2762            //                FROM tab1
2763            //                WHERE col2 = col1      )
2764            //   FROM tab2
2765           // we need to link col1 to tab2 in up level, but not to tab1
2766            if ((!isfound) &&(
2767                            (cr.getLocation() != ESqlClause.resultColumn)
2768                          &&(cr.getLocation() != ESqlClause.insertColumn)
2769                                    &&(cr.getLocation() != ESqlClause.mergeInsert)
2770                                    &&(cr.getLocation() != ESqlClause.selectList)
2771            ) ){  // code #111
2772                TCustomSqlStatement lcParent = null;
2773                lcParent = this.getParentStmt();
2774               while ( lcParent != null) {
2775                   TTable lcTable;
2776                 //ret = lcParent.tables.checkColumnReferenceInTables(cr);
2777                   if (lcParent.sqlstatementtype != ESqlStatementType.sstselect) {
2778                       break;
2779                   }
2780                   for (int i=0;i<lcParent.tables.size();i++){
2781                       lcTable = lcParent.tables.getTable(i);
2782                       if (lcTable.getTableType() == ETableSource.objectname) {
2783                           for(int k = 0; k< lcTable.getObjectNameReferences().size();k++){
2784                               if (lcTable.getObjectNameReferences().getObjectName(k).isTableDetermined()){
2785                                   if (cr.toString().equalsIgnoreCase(lcTable.getObjectNameReferences().getObjectName(k).toString())){
2786                                      isfound = true;
2787                                       break;
2788                                   }
2789                               }
2790                           }
2791                       if (isfound) break;
2792                       }
2793                   }
2794
2795                 if (isfound){
2796                     break;
2797                 }else{
2798                     lcParent = lcParent.getParentStmt();
2799                 }
2800               } // while
2801
2802             } // end of code #111
2803
2804            if (!isfound){
2805                isfound = checkNonQualifiedColumnReferenceInSubQueryOfUplevelStmt(cr
2806                        , ((plocation == ESqlClause.resultColumn)
2807                            ||(plocation == ESqlClause.insertColumn)
2808                                ||(plocation == ESqlClause.mergeInsert)
2809                                ||(plocation == ESqlClause.selectList)
2810                        )
2811                );
2812            }
2813
2814             if ((!isfound)&&(this.tables.size() > 0)){
2815                 int candidate = 0, firstCandidate = -1;
2816                 // add this column reference to first non-cte( or cte with column list is null) and non-subquery table
2817                 for (int i=0;i<this.tables.size();i++){
2818                     // no qualified column can't belong to a table with alias, that column must be qualified if it's belong to a table with alias
2819                     //if (this.tables.getTable(i).aliasClause != null) continue;
2820                     if (
2821                             (
2822                                     (!this.tables.getTable(i).isCTEName())
2823                                ||((this.tables.getTable(i).isCTEName())&&(this.tables.getTable(i).getCteColomnReferences() == null))
2824                             )&&((this.tables.getTable(i).getTableType() != ETableSource.subquery))
2825                     )
2826                     {
2827                         candidate++;
2828                         if (firstCandidate == -1) firstCandidate = i;
2829                         if (this.fireOnMetaDatabaseTableColumn(
2830                                    this.tables.getTable(i).getTableName().getServerString(),
2831                                    this.tables.getTable(i).getTableName().getDatabaseString(),
2832                                    this.tables.getTable(i).getTableName().getSchemaString(),
2833                                    this.tables.getTable(i).getName(),cr.toString())){
2834                                this.tables.getTable(i).getObjectNameReferences().addObjectName(cr);
2835                                isfound = true;
2836                                break;
2837                            }
2838                         else{
2839                             this.tables.getTable(i).getObjectNameReferences().addObjectName(cr);
2840                             if (this.tables.size() > 1){
2841                                 cr.setTableDetermined(false);
2842                             }
2843                             isfound = true;
2844                             break;
2845                         }
2846                     }
2847                  }
2848                 if ((!isfound) && (candidate == 1)){
2849                     this.tables.getTable(firstCandidate).getObjectNameReferences().addObjectName(cr);
2850                 }
2851             }
2852         }else if (ret == -1){
2853             TCustomSqlStatement lcParent = null;
2854             lcParent = this.getParentStmt();
2855            while ( lcParent != null) {
2856              ret = lcParent.tables.checkColumnReferenceInTables(cr);
2857              if (ret >= 0){
2858               lcParent.tables.getTable(ret).getObjectNameReferences().addObjectName(cr);
2859               break;
2860              }else{
2861                  lcParent = lcParent.getParentStmt();
2862              }
2863            } // while
2864         } //-1
2865
2866    }
2867
2868    /**
2869     * Found out is a non qualified column is a column in uplevel subquery table like this:
2870     * take ma_parkey for example: ma_parkey is not a physical column
2871     * 
2872        SELECT c_mandant
2873             , CASE WHEN EXISTS (SELECT 1
2874                                   FROM CDS_H_GRUPPE  GRP1
2875                                  WHERE GRP1.c_mandant = c_mandant
2876                                    AND GRP1.parkey1       = ma_parkey)
2877                      THEN 1
2878                  ELSE NULL
2879               END MA_ME
2880          FROM (SELECT c_mandant
2881                     , CASE WHEN funktionscode = 'U'
2882                              THEN parkey1
2883                          ELSE parkey2
2884                       END MA_PARKEY
2885                  FROM
2886                       CDS_H_GRUPPE
2887               )
2888     */
2889    public boolean checkNonQualifiedColumnReferenceInSubQueryOfUplevelStmt(TObjectName crf,boolean sameLevelOnly){
2890        boolean ret = false;
2891
2892        TCustomSqlStatement lcParent = null;
2893        lcParent = this;//getParentStmt();
2894       while ( lcParent != null) {
2895           TTable lcTable;
2896             for (int i=0;i<lcParent.tables.size();i++){
2897                 lcTable = lcParent.tables.getTable(i);
2898
2899                 if ((lcTable.getTableType() != ETableSource.subquery)) {continue;}
2900
2901                 ret = isColumnNameInSelectList(crf.toString(),lcTable.subquery);
2902                if (ret) {break;}
2903
2904             }
2905          if (ret) {break;}
2906           else{
2907              if (sameLevelOnly){
2908                  lcParent = null;
2909              }else{
2910                lcParent = lcParent.getParentStmt();
2911              }
2912          }
2913       } // while
2914
2915        return ret;
2916    }
2917
2918    private boolean isColumnNameInSelectList(String pColumn, TSelectSqlStatement pSelect){
2919        boolean ret = false;
2920        TResultColumn lcColumn;
2921        if (pSelect.isCombinedQuery()){
2922            ret = isColumnNameInSelectList(pColumn,pSelect.getLeftStmt());
2923            if (!ret){
2924                ret = isColumnNameInSelectList(pColumn,pSelect.getRightStmt());
2925            }
2926        }else{
2927            if (pSelect.getResultColumnList() != null){ //if it's a db2 value row, then pSelect.getResultColumnList() will be null 
2928                for(int j=0;j<pSelect.getResultColumnList().size();j++){
2929                   lcColumn = pSelect.getResultColumnList().getResultColumn(j);
2930                   if (lcColumn.getAliasClause() != null){
2931                       ret = pColumn.equalsIgnoreCase(lcColumn.getAliasClause().toString());
2932                   }
2933                   if (ret)  break;
2934                   ret = pColumn.equalsIgnoreCase(lcColumn.getExpr().toString());
2935                   if (ret)  break;
2936                }
2937            }
2938        }
2939        return ret;
2940    }
2941
2942    public TCustomSqlStatement getTopStatement(){
2943        TCustomSqlStatement ret = this;
2944        while (ret.getParentStmt() != null){
2945            ret = ret.getParentStmt();
2946        }
2947        return ret;
2948    }
2949
2950
2951//    public String toScript(){
2952//        if (!isChanged()){
2953//            return this.toString();
2954//        }
2955//        return super.toScript();
2956//    }
2957
2958}
2959
2960class constantVisitor extends TParseTreeVisitor {
2961    private boolean inWhere = false,inExprList = false;
2962    public void preVisit(TWhereClause node){
2963        inWhere = true;
2964    }
2965
2966    public void postVisit(TWhereClause node){
2967        inWhere = false;
2968    }
2969
2970    public void preVisit(TExpression node){
2971        if (inWhere){
2972            switch (node.getExpressionType()){
2973                case list_t:
2974                    inExprList = true;
2975                    boolean isNumber = true;
2976                    if (node.getExprList().size() > 0){
2977                        // check the type of the constant in the expr list
2978                        TExpression expr = node.getExprList().getExpression(0);
2979                        if (expr.getExpressionType() == EExpressionType.simple_constant_t){
2980                            if (expr.getConstantOperand().getLiteralType() == ELiteralType.etString){
2981                                isNumber = false;
2982                            }
2983                        }
2984                    }
2985
2986                    TSourceToken lcStartToken = node.getStartToken();
2987                    TSourceToken lcEndToken = node.getEndToken();
2988                    int tokenPos = 0;
2989                    if ((lcEndToken != null) && (lcStartToken != null)){
2990                        TSourceToken lcCurrentToken = lcStartToken;
2991                        while (lcCurrentToken != null){
2992
2993                            if (lcCurrentToken.equals(lcEndToken)){
2994                                break;
2995                            }else{
2996
2997                                if (tokenPos == 1){
2998                                    if (isNumber){
2999                                        lcCurrentToken.setTextWithBackup("999");
3000                                    }else{
3001                                        lcCurrentToken.setTextWithBackup("'placeholder_str'");
3002                                    }
3003                                }else if (tokenPos > 1){
3004                                    lcCurrentToken.tokenstatus = ETokenStatus.tsdeleted;
3005                                }
3006
3007                                lcCurrentToken = lcCurrentToken.getNextTokenInChain();
3008                                tokenPos++;
3009                            }
3010                        }
3011                    }
3012
3013                    break;
3014            }
3015        } // where
3016    }
3017
3018    public void postVisit(TExpression node){
3019        if (inWhere){
3020            switch (node.getExpressionType()){
3021                case list_t:
3022                    inExprList = false;
3023                    break;
3024            }
3025        }
3026    }
3027
3028    public void preVisit(TConstant node){
3029        if (inWhere&&(!inExprList)){
3030            switch (node.getLiteralType()){
3031                case etNumber:
3032                case etFloat:
3033                    node.getStartToken().setTextWithBackup("999");
3034                    break;
3035                case etString:
3036                    node.getStartToken().setTextWithBackup("'placeholder_str'");
3037                    break;
3038            }
3039        }
3040    }
3041
3042    public void preVisit(TFunctionCall node){
3043        if (TBaseType.as_canonical_f_decrypt_replace_password){
3044            int i = TBaseType.searchCryptFunction(node.getFunctionName().toString());
3045
3046            if (i>0){ // find this function
3047                if (node.getArgs().size() >= i){
3048                    TExpression secondArg = node.getArgs().getExpression(i-1);
3049                    if (secondArg.getExpressionType() == EExpressionType.simple_constant_t){
3050                        TConstant constant = secondArg.getConstantOperand();
3051                        constant.getValueToken().setTextWithBackup("'***'");
3052                        //System.out.println(node.toString()+":"+constant.toString());
3053                    }else if (secondArg.getExpressionType() == EExpressionType.simple_object_name_t){
3054                        TObjectName objectName = secondArg.getObjectOperand();
3055                        objectName.getStartToken().setTextWithBackup("'***'");
3056                        //System.out.println(node.toString()+":"+constant.toString());
3057                    }
3058                }
3059            }
3060
3061        }
3062    }
3063
3064    void processConstant(TConstant node){
3065        switch (node.getLiteralType()){
3066            case etNumber:
3067            case etFloat:
3068                node.getStartToken().setTextWithBackup("999");
3069                break;
3070            case etString:
3071                node.getStartToken().setTextWithBackup("'placeholder_str'");
3072                break;
3073        }
3074    }
3075
3076}