001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.compiler.TStmtScope;
005import gudusoft.gsqlparser.nodes.*;
006import gudusoft.gsqlparser.nodes.hana.TTimeTravel;
007import gudusoft.gsqlparser.nodes.hive.*;
008import gudusoft.gsqlparser.nodes.mssql.TOptionClause;
009import gudusoft.gsqlparser.nodes.THierarchical;
010import gudusoft.gsqlparser.nodes.teradata.TExpandOnClause;
011import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType;
012import gudusoft.gsqlparser.sqlenv.IdentifierService;
013import gudusoft.gsqlparser.sqlenv.TSQLEnv;
014import gudusoft.gsqlparser.sqlenv.TSQLTable;
015
016import java.util.ArrayList;
017import java.util.Collections;
018import java.util.TreeMap;
019
020
021/**
022 * Class {@link gudusoft.gsqlparser.stmt.TSelectSqlStatement } represents query specification, query expression and select statement.
023 * <br><br><b>query specification</b> including following clause:
024 * <ul>
025 *     <li>select list {@link #getResultColumnList}</li>
026 *     <li>from clause {@link #joins}</li>
027 *     <li>where clause {@link #getWhereClause}</li>
028 *     <li>group clause {@link #getGroupByClause}</li>
029 *     <li>having clause {@link #getGroupByClause}</li>
030 * </ul>
031 * In some databases, query specification also known as sub-select.
032 *
033 * <br><br><b>query expression</b> including all elements in query specification and following clause:
034 * <ul>
035 *     <li>order by clause {@link #getOrderbyClause}</li>
036 *     <li>offset clause {@link #getOffsetClause}</li>
037 *     <li>for clause</li>
038 * </ul>
039 * In some databases, query expression also known as full-select.
040 * <br>It is a component of the select-statement, the INSERT statement, and the CREATE VIEW statement.
041 * And a full-select that is enclosed in parentheses is sometimes called a sub-query.
042 *
043 * <br><br>select statement including all elements in query expression and following clause:
044 * <ul>
045 *     <li>compute clause {@link #getComputeClause}</li>
046 *     <li>for update clause {@link #getForUpdateClause}</li>
047 *     <li>optimizer hint</li>
048 *     <li>ctes {@link #getCteList}</li>
049 * </ul>
050 * Lots of clauses on this level are db vendors specific.
051 *
052
053 * <br><br>
054 * Use {@link #isCombinedQuery} to check whether UNION, EXCEPT and INTERSECT operators is used.
055 * If returns true, use {@link #getLeftStmt} and {@link #getRightStmt} to get query expression.
056 * You need to check {@link #isCombinedQuery} recursively, all clauses of {@link gudusoft.gsqlparser.stmt.TSelectSqlStatement}
057 * only available when this function returns false.
058 *
059 */
060
061public class TSelectSqlStatement extends TCustomSqlStatement {
062
063    // 如果是 combined query, 并且当前select 没有预先设定的 endToken, 则取最右边 query 的 endToken
064    public TSourceToken getEndToken() {
065        if (super.getEndToken() != null) return super.getEndToken();
066        if (this.isCombinedQuery()){
067            return this.getRightStmt().getEndToken();
068        }else{
069            return super.getEndToken();
070        }
071    }
072
073    public void setSubQueryInFromClauseCanUseParentSelectAsEnclosingScope(boolean subQueryInFromClauseCanUseParentSelectAsEnclosingScope) {
074        this.subQueryInFromClauseCanUseParentSelectAsEnclosingScope = subQueryInFromClauseCanUseParentSelectAsEnclosingScope;
075    }
076
077    public boolean isSubQueryInFromClauseCanUseParentSelectAsEnclosingScope() {
078        return subQueryInFromClauseCanUseParentSelectAsEnclosingScope;
079    }
080
081    private boolean subQueryInFromClauseCanUseParentSelectAsEnclosingScope = false;
082
083    boolean starColumnPushedDown = false;
084
085    public boolean isStarColumnPushedDown() {
086        return starColumnPushedDown;
087    }
088
089    public void setStarColumnPushedDown(boolean starColumnPushedDown) {
090        this.starColumnPushedDown = starColumnPushedDown;
091    }
092
093    // StarRocks pipe operator support
094    private TPTNodeList<TParseTreeNode> pipeOperators;
095    private boolean isPipeQuery = false;
096
097    // Oracle 12c WITH FUNCTION/PROCEDURE support - inline PL/SQL definitions
098    private TStatementListSqlNode withPlsqlItems;
099
100    /**
101     * Get the inline PL/SQL function/procedure definitions from WITH clause.
102     * Oracle 12c+ allows defining PL/SQL functions inline in the WITH clause:
103     * WITH FUNCTION f(x NUMBER) RETURN NUMBER IS BEGIN RETURN x*2; END;
104     * SELECT f(1) FROM dual
105     *
106     * @return list of inline function/procedure definitions, or null if none
107     */
108    public TStatementListSqlNode getWithPlsqlItems() {
109        return withPlsqlItems;
110    }
111
112    /**
113     * Set the inline PL/SQL function/procedure definitions.
114     * @param withPlsqlItems list of inline function/procedure definitions
115     */
116    public void setWithPlsqlItems(TStatementListSqlNode withPlsqlItems) {
117        this.withPlsqlItems = withPlsqlItems;
118    }
119
120    /**
121     * Get the list of pipe operators for StarRocks pipe query syntax.
122     * Pipe queries use the |> operator to chain operations:
123     * FROM table |> SELECT * |> WHERE cond |> ORDER BY col
124     *
125     * @return list of TPipeOperator nodes, or null if not a pipe query
126     */
127    public TPTNodeList<TParseTreeNode> getPipeOperators() {
128        return pipeOperators;
129    }
130
131    /**
132     * Set the pipe operators list.
133     * @param pipeOperators list of pipe operator nodes
134     */
135    public void setPipeOperators(TPTNodeList<TParseTreeNode> pipeOperators) {
136        this.pipeOperators = pipeOperators;
137    }
138
139    /**
140     * Check if this is a StarRocks pipe query.
141     * Pipe queries use the syntax: FROM table |> SELECT * |> WHERE ...
142     *
143     * @return true if this is a pipe query
144     */
145    public boolean isPipeQuery() {
146        return isPipeQuery;
147    }
148
149    /**
150     * Set whether this is a pipe query.
151     * @param isPipeQuery true if this is a pipe query
152     */
153    public void setIsPipeQuery(boolean isPipeQuery) {
154        this.isPipeQuery = isPipeQuery;
155    }
156
157    /**
158     * 在 sql script 中,和该 relation 关联的 attribute。
159     * select a from t;
160     * attribute a 就是 relation t 的 referenceAttribute, 如果没有 metadata and ddl,
161     * relation t 的 getAttributes() 应该可以推断出包含 a, 但 t 是否还包含其他的 attribute 就无从得知。
162     */
163
164    @Override
165    public ArrayList<TAttributeNode> getAttributes(){
166        if (this.getFromClause() == null) return null;
167
168        return this.getFromClause().getAttributes();
169
170//        relationAttributes.clear();
171//        for(TTable table:getRelations()){
172//            relationAttributes.addAll(table.getAttributes());
173//        }
174//
175//        if (relationAttributes.size() > 0){
176//            TBaseType.log ("relationAttributes.size() in select is :"+relationAttributes.size()
177//                    +", relation size: "+getRelations().size()
178//                    +", relation 0 type:"+getRelations().get(0).getTableType()
179//                    ,1);
180//            // System.out.println(this.toString());
181//        }
182//
183//        return relationAttributes;
184    }
185
186    ArrayList<TAttributeNode> relationAttributes = new ArrayList<>();
187
188//    private TExpression skipOffset;
189//    private TExpression firstMax;
190//    private TExpression limitMax;
191//
192//    public void setSkipOffset(TExpression skipOffset) {
193//        this.skipOffset = skipOffset;
194//    }
195//
196//    public void setFirstMax(TExpression firstMax) {
197//        this.firstMax = firstMax;
198//    }
199//
200//    public void setLimitMax(TExpression limitMax) {
201//        this.limitMax = limitMax;
202//    }
203//
204//    /**
205//     * Informix skip offset
206//     * @return skip offset
207//     */
208//    public TExpression getSkipOffset() {
209//
210//        return skipOffset;
211//    }
212//
213//    /**
214//     * Informix first Max
215//     * @return first Max
216//     */
217//    public TExpression getFirstMax() {
218//        return firstMax;
219//    }
220//
221//    /**
222//     * Informix limit max
223//     * @return limit max
224//     */
225//    public TExpression getLimitMax() {
226//        return limitMax;
227//    }
228
229    private ArrayList<TSelectSqlStatement> multiSelectStatements;
230
231    /**
232     * Hive, from ... select, select,...
233     * <br> Multiple select statement in Hive from query syntax
234     *
235     * @return Multiple select statement in Hive from query syntax
236     */
237    public ArrayList<TSelectSqlStatement> getMultiSelectStatements() {
238        if(multiSelectStatements == null){
239            multiSelectStatements = new ArrayList<>();
240        }
241        return multiSelectStatements;
242    }
243
244    private TClusterBy clusterBy;
245
246    public void setClusterBy(TClusterBy clusterBy) {
247        this.clusterBy = clusterBy;
248    }
249
250    public TClusterBy getClusterBy() {
251        return clusterBy;
252    }
253
254    private boolean isConsume;
255
256    public void setConsume(boolean consume) {
257        isConsume = consume;
258    }
259
260    public boolean isConsume() {
261        return isConsume;
262    }
263
264    private TStatementList hiveBodyList = null;
265
266    /**
267     * @deprecated since 2.6.3.5, please use {@link #getMultiSelectStatements()} to retrieve
268     * multimple select statement in Hive from query ... select, select, ...
269     *
270     * @return
271     */
272    public TStatementList getHiveBodyList() {
273        if (hiveBodyList == null)
274            hiveBodyList = new TStatementList();
275        return hiveBodyList;
276    }
277
278    public void setSelectModifiers(ArrayList<TSelectModifier> selectModifiers) {
279        this.selectModifiers = selectModifiers;
280    }
281
282    public ArrayList<TSelectModifier> getSelectModifiers() {
283        return selectModifiers;
284    }
285
286    private ArrayList<TSelectModifier> selectModifiers;
287
288
289    private TTimeTravel timeTravel; // hana
290    private THintClause hintClause; //hana
291
292    public void setTimeTravel(TTimeTravel timeTravel) {
293        setNewSubNode(this.timeTravel,timeTravel,getAnchorNode());
294        this.timeTravel = timeTravel;
295    }
296
297    public void setHintClause(THintClause hintClause) {
298        setNewSubNode(this.hintClause,hintClause,getAnchorNode());
299        this.hintClause = hintClause;
300    }
301
302
303    public TTimeTravel getTimeTravel() {
304
305        return timeTravel;
306    }
307
308    public THintClause getHintClause() {
309        return hintClause;
310    }
311
312    private int parenthesisCount = 0;
313    private int parenthesisCountBeforeOrder = 0;
314
315    public void setFetchFirstClause(TFetchFirstClause fetchFirstClause) {
316        setNewSubNode(this.fetchFirstClause,fetchFirstClause,getAnchorNode());
317        this.fetchFirstClause = fetchFirstClause;
318    }
319
320
321    public void setParenthesisCount(int parenthesisCount) {
322        this.parenthesisCount = parenthesisCount;
323    }
324
325    public void setParenthesisCountBeforeOrder(int parenthesisCountBeforeOrder) {
326        this.parenthesisCountBeforeOrder = parenthesisCountBeforeOrder;
327    }
328
329    public void setAll(boolean all) {
330        this.all = all;
331    }
332
333    public void setSetOperatorType(ESetOperatorType setOperatorType) {
334        this.setOperatorType = setOperatorType;
335    }
336
337    public void setWindowClause(TWindowClause windowClause) {
338        setNewSubNode(this.windowClause,windowClause,getAnchorNode());
339        this.windowClause = windowClause;
340    }
341
342    public void setLockingClauses(TPTNodeList<TLockingClause> lockingClauses) {
343        this.lockingClauses = lockingClauses;
344    }
345
346    public void setSelectDistinct(TSelectDistinct selectDistinct) {
347        setNewSubNode(this.selectDistinct,selectDistinct,getAnchorNode());
348        this.selectDistinct = selectDistinct;
349    }
350
351    public void setExpandOnClause(TExpandOnClause expandOnClause) {
352        setNewSubNode(this.expandOnClause,expandOnClause,getAnchorNode());
353        this.expandOnClause = expandOnClause;
354    }
355
356
357    public void setSetOperator(int setOperator) {
358        this.setOperator = setOperator;
359    }
360
361    public void setLeftStmt(TSelectSqlStatement leftStmt) {
362        this.leftStmt = leftStmt;
363    }
364
365    public void setRightStmt(TSelectSqlStatement rightStmt) {
366        this.rightStmt = rightStmt;
367    }
368
369    public void setValueClause(TValueClause valueClause) {
370        setNewSubNode(this.valueClause,valueClause,getAnchorNode());
371        this.valueClause = valueClause;
372    }
373
374    public void setOracleHint(String oracleHint) {
375        this.oracleHint = oracleHint;
376    }
377
378    public void setHiveHintClause(THiveHintClause hiveHintClause) {
379        setNewSubNode(this.hiveHintClause,hiveHintClause,getAnchorNode());
380        this.hiveHintClause = hiveHintClause;
381    }
382
383
384    public void setTransformClause(THiveTransformClause transformClause) {
385        setNewSubNode(this.transformClause,transformClause,getAnchorNode());
386        this.transformClause = transformClause;
387    }
388
389    public void setDistributeBy(TDistributeBy distributeBy) {
390        setNewSubNode(this.distributeBy,distributeBy,getAnchorNode());
391        this.distributeBy = distributeBy;
392    }
393
394
395    public void setIntoClause(TIntoClause intoClause) {
396        setNewSubNode(this.intoClause,intoClause,getAnchorNode());
397        this.intoClause = intoClause;
398    }
399
400    public void setOrderbyClause(TOrderBy newOrderbyClause) {
401        setNewSubNode(this.orderbyClause,newOrderbyClause,getAnchorNode());
402        this.orderbyClause = newOrderbyClause;
403    }
404
405//    public void setOrderbyClause(TOrderBy newOrderbyClause, TParseTreeNode anchorNode) {
406//        if (newOrderbyClause == null){
407//            //remove
408//            this.orderbyClause.removeTokens();
409//            this.orderbyClause = null;
410//        }else{
411//            if (this.orderbyClause != null){
412//                this.orderbyClause.replaceWithNewNode(newOrderbyClause);
413//            }else{
414//                doAppendNewNode(newOrderbyClause,anchorNode,false);
415//            }
416//            this.orderbyClause = newOrderbyClause;
417//        }
418//    }
419
420    public void setQualifyClause(TQualifyClause qualifyClause) {
421        setNewSubNode(this.qualifyClause,qualifyClause,getAnchorNode());
422        this.qualifyClause = qualifyClause;
423    }
424
425    public void setSampleClause(TSampleClause sampleClause) {
426        setNewSubNode(this.sampleClause,sampleClause,getAnchorNode());
427        this.sampleClause = sampleClause;
428    }
429
430    public void setTeradataWithClause(TTeradataWithClause teradataWithClause) {
431        setNewSubNode(this.teradataWithClause,teradataWithClause,getAnchorNode());
432        this.teradataWithClause = teradataWithClause;
433    }
434
435    public void setForUpdateClause(TForUpdate forUpdateClause) {
436        setNewSubNode(this.forUpdateClause,forUpdateClause,getAnchorNode());
437        this.forUpdateClause = forUpdateClause;
438    }
439
440
441    public void setComputeClause(TComputeClause computeClause) {
442        this.computeClause = computeClause;
443    }
444
445    public void setGroupByClause(TGroupBy groupByClause) {
446        setNewSubNode(this.groupByClause,groupByClause,getAnchorNode());
447        this.groupByClause = groupByClause;
448    }
449
450
451    public void setHierarchicalClause(THierarchical hierarchicalClause) {
452        setNewSubNode(this.hierarchicalClause,hierarchicalClause,getAnchorNode());
453        this.hierarchicalClause = hierarchicalClause;
454    }
455
456
457    public void setLimitClause(TLimitClause limitClause) {
458        setNewSubNode(this.limitClause,limitClause,getAnchorNode());
459        this.limitClause = limitClause;
460    }
461
462    public void setOffsetClause(TOffsetClause offsetClause) {
463        setNewSubNode(this.offsetClause,offsetClause,getAnchorNode());
464        this.offsetClause = offsetClause;
465    }
466
467    public void setOptionClause(TOptionClause optionClause) {
468        setNewSubNode(this.optionClause,optionClause,getAnchorNode());
469        this.optionClause = optionClause;
470    }
471
472    public void setIsolationClause(TIsolationClause isolationClause) {
473        setNewSubNode(this.isolationClause,isolationClause,getAnchorNode());
474        this.isolationClause = isolationClause;
475    }
476
477//    public void setHiveClusterBy(THiveClusterBy hiveClusterBy) {
478//        setNewSubNode(this.hiveClusterBy,hiveClusterBy,getAnchorNode());
479//        this.hiveClusterBy = hiveClusterBy;
480//    }
481
482
483    public void setSortBy(TSortBy sortBy) {
484        setNewSubNode(this.sortBy,sortBy,getAnchorNode());
485        this.sortBy = sortBy;
486    }
487
488    public void setIntoTableClause(TIntoTableClause intoTableClause) {
489        setNewSubNode(this.intoTableClause,intoTableClause,getAnchorNode());
490        this.intoTableClause = intoTableClause;
491    }
492
493    public int getParenthesisCountBeforeOrder() {
494        return parenthesisCountBeforeOrder;
495    }
496
497    public int getParenthesisCount() {
498        return parenthesisCount;
499    }
500
501    private boolean queryOfCTE;
502
503    public void setQueryOfCTE(boolean queryOfCTE) {
504        this.queryOfCTE = queryOfCTE;
505    }
506
507    public boolean isQueryOfCTE() {
508        return queryOfCTE;
509    }
510
511    /**
512     * Offset clause.
513     * <br>
514     * <pre>OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY;</pre>
515     * @return {@link TOffsetClause offset clause}
516     */
517    public TOffsetClause getOffsetClause() {
518        return offsetClause;
519    }
520
521    /**
522     * Fetch first/next clause
523     * <br>
524     * <pre>OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY;</pre>
525     * @return {@link TFetchFirstClause fetch first/next clause}
526     */
527    public TFetchFirstClause getFetchFirstClause() {
528
529        return fetchFirstClause;
530    }
531
532    private TFetchFirstClause fetchFirstClause;
533    private TOffsetClause offsetClause;
534
535    private TOptionClause optionClause;
536
537    /**
538     *
539     * @return {@link  TOptionClause sql server option clause}
540     *
541     * @see gudusoft.gsqlparser.nodes.mssql.TOptionClause
542     */
543    public TOptionClause getOptionClause() {
544        return optionClause;
545    }
546
547
548    /**
549     *
550     * @return {@link TIsolationClause isolation clause}
551     */
552    public TIsolationClause getIsolationClause() {
553        return isolationClause;
554    }
555
556    private TIsolationClause isolationClause;
557
558//     private THiveClusterBy hiveClusterBy;
559//
560//    /**
561//     *
562//     * @return {@link THiveClusterBy Hive cluster by clause}
563//     */
564//    public THiveClusterBy getHiveClusterBy() {
565//        return hiveClusterBy;
566//    }
567
568    private TSortBy sortBy;
569
570    /**
571     *
572     * @return {@link TSortBy Hive sort by clause}
573     */
574    public TSortBy getSortBy() {
575        return sortBy;
576    }
577
578    private TIntoTableClause intoTableClause;
579
580    /**
581     *
582     * @return {@link TIntoTableClause informix into table clause}
583     */
584    public TIntoTableClause getIntoTableClause() {
585        return intoTableClause;
586    }
587
588    public void setSelectToken(TSourceToken selectToken) {
589        this.selectToken = selectToken;
590    }
591
592    /**
593     *
594     * @return SELECT token of this query.
595     */
596    public TSourceToken getSelectToken() {
597        return selectToken;
598    }
599
600    private TSourceToken selectToken = null;
601    
602    public static final int SET_OPERATOR_NONE = 0;
603
604    public static final int setOperator_union = 1;
605    public static final int setOperator_unionall = 2;
606    public static final int SET_OPERATOR_UNIONDISTINCT = 9;
607
608    public static final int setOperator_intersect = 3;
609    public static final int setOperator_intersectall = 4;
610    public static final int SET_OPERATOR_INTERSECTDISTINCT = 10;
611
612    public static final int setOperator_minus = 5;
613    public static final int setOperator_minusall = 6;
614    public static final int SET_OPERATOR_MINUSDISTINCT = 11;
615
616    public static final int setOperator_except = 7;
617    public static final int setOperator_exceptall = 8;
618    public static final int SET_OPERATOR_EXCEPTDISTINCT = 11;
619
620    public boolean isAll() {
621        return all;
622    }
623
624    private boolean all = false;
625
626    public boolean isSetOpDistinct() {
627        return setOpDistinct;
628    }
629
630    private boolean setOpDistinct = false;
631    private ESetOperatorType setOperatorType = ESetOperatorType.none;
632
633    public ESetOperatorType getSetOperatorType() {
634        return setOperatorType;
635    }
636
637    private  TWindowClause  windowClause;
638
639    /**
640     *
641     * @return {@link TWindowClause window clause.}
642     */
643    public TWindowClause getWindowClause() {
644        return windowClause;
645    }
646
647    private TPTNodeList <TLockingClause> lockingClauses;
648
649    /**
650     *  PostgreSQL, for update of, for read only.
651     *  <br>
652     * @return list of {@link TLockingClause}
653     */
654    public TPTNodeList<TLockingClause> getLockingClauses() {
655        return lockingClauses;
656    }
657
658    /**
659     *
660     * @return {@link TSelectDistinct distinct clause}
661     */
662    public TSelectDistinct getSelectDistinct() {
663        return selectDistinct;
664    }
665
666    private TSelectDistinct selectDistinct = null;
667
668    /**
669     *
670     * @return {@link gudusoft.gsqlparser.nodes.TIntoClause into clause}
671     */
672    public TIntoClause getIntoClause() {
673        return intoClause;
674    }
675
676    private TIntoClause intoClause = null;
677
678
679    private TOrderBy orderbyClause;
680
681    /**
682     * @return {@link TOrderBy order by clause}
683     */
684    public TOrderBy getOrderbyClause() {
685        return orderbyClause;
686    }
687
688    public TSelectSqlStatement(EDbVendor dbvendor) {
689        super(dbvendor);
690        sqlstatementtype = ESqlStatementType.sstselect;
691    }
692
693    void buildsql() {
694    }
695
696    void clear() {
697    }
698
699    String getasprettytext() {
700        return "";
701    }
702
703    void iterate(TVisitorAbs pvisitor) {
704    }
705
706    /**
707     *
708     * @return {@link TQualifyClause teradata qualify clause}
709     */
710    public TQualifyClause getQualifyClause() {
711        return qualifyClause;
712    }
713
714    private TQualifyClause qualifyClause = null;
715    private TSampleClause sampleClause = null;
716    private TTeradataWithClause teradataWithClause = null;
717
718    /**
719     * @return {@link TTeradataWithClause Teradata with clause }
720     */
721    public TTeradataWithClause getTeradataWithClause() {
722        return teradataWithClause;
723    }
724
725    /**
726     *
727     * @return {@link gudusoft.gsqlparser.nodes.TSampleClause SQL Server sample clause}
728     */
729    public TSampleClause getSampleClause() {
730        return sampleClause;
731    }
732
733    /**
734     * @return {@link gudusoft.gsqlparser.nodes.TForUpdate for update clause}
735     */
736    public TForUpdate getForUpdateClause() {
737        return forUpdateClause;
738    }
739
740    private TForUpdate forUpdateClause;
741
742    /**
743     *
744     * @return {@link TComputeClause SQL Server compute clause}
745     */
746    public TComputeClause getComputeClause() {
747        return computeClause;
748    }
749
750    private TComputeClause computeClause = null;
751
752    /**
753     * @return  {@link TGroupBy group by clause and having clause}
754     */
755    public TGroupBy getGroupByClause() {
756        return groupByClause;
757    }
758
759    private TGroupBy groupByClause = null;
760
761
762    /**
763     * Oracle hierarchical_query_clause
764     * @return {@link gudusoft.gsqlparser.nodes.THierarchical Oracle hierarchical_query_clause}
765     */
766    public THierarchical getHierarchicalClause() {
767        return hierarchicalClause;
768    }
769
770    private THierarchical hierarchicalClause = null;
771
772    /**
773     * MySQL,PostgreSQL limit clause
774     * @return {@link TLimitClause MySQL,PostgreSQL limit clause}
775     */
776    public TLimitClause getLimitClause() {
777        return limitClause;
778    }
779
780    private TLimitClause limitClause = null;
781
782
783    private TExpandOnClause expandOnClause;
784
785    /**
786     *
787     * @return {@link TExpandOnClause Teradata expand on clause}
788     */
789    public TExpandOnClause getExpandOnClause() {
790        return expandOnClause;
791    }
792
793    /**
794     *
795     * The set operators UNION, EXCEPT, and INTERSECT correspond to the relational operators union, difference, and intersection.
796     * @return  set operator of this statement.If a set operator is not used, setOperator_none will be returned.
797     * otherwise, set operand can be fetched by using getLeftStmt() and getRightStmt().
798     *
799     * @deprecated As of v1.6.4.2, use {@link #getSetOperatorType()}  and {@link #isAll()} instead.
800     */
801    public int getSetOperator() {
802        return setOperator;
803    }
804
805    private int setOperator = 0;
806
807    /**
808     * Valid when {@link #getSetOperator} is not setOperator_none.
809     * @return left side query expression
810     */
811    public TSelectSqlStatement getLeftStmt() {
812        return leftStmt;
813    }
814
815    public TSelectSqlStatement getFarLeftStmt() {
816        TSelectSqlStatement current = leftStmt;
817        while (current.isCombinedQuery()) {
818            current = current.getLeftStmt();
819        }
820        return current;
821    }
822
823    /**
824     * Valid when {@link #getSetOperator} is not setOperator_none.
825     * @return right side query expression.
826     */
827    public TSelectSqlStatement getRightStmt() {
828        return rightStmt;
829    }
830
831    private TSelectSqlStatement leftStmt;
832    private TSelectSqlStatement rightStmt;
833
834    private TValueClause valueClause = null;
835
836    private String oracleHint;
837
838    private String hint;
839
840    private boolean isValueClause = false;
841
842    public boolean isValueClause() {
843        return isValueClause;
844    }
845
846    /**
847     * Hint for Oracle and MySQL
848     *
849     * @return hint string
850     */
851    public String getHint() {
852        return hint;
853    }
854
855    /**
856     * Hint for Oracle and MySQL
857     *
858     * @return  hint string.
859     */
860    /**
861     * @deprecated As of 2.0.4.5, replaced by {@link #getHint()}
862     */
863    public String getOracleHint() {
864        return oracleHint;
865    }
866
867    private THiveHintClause hiveHintClause;
868
869    /**
870     *
871     * @return {@link THiveHintClause Hive hint clause}
872     */
873    public THiveHintClause getHiveHintClause() {
874        return hiveHintClause;
875    }
876
877    private THiveTransformClause transformClause;
878
879    /**
880     *
881     * @return {@link THiveTransformClause Hive from clause}
882     */
883    public THiveTransformClause getTransformClause() {
884        return transformClause;
885    }
886
887    private TDistributeBy distributeBy;
888
889    /**
890     *
891     * @return {@link TDistributeBy Hive distribute by clause}
892     */
893    public TDistributeBy getDistributeBy() {
894        return distributeBy;
895    }
896
897    /**
898     * DB2 value clause
899     * @return {@link TValueClause DB2 value clause}
900     */
901    public TValueClause getValueClause() {
902        return valueClause;
903    }
904
905    public void setChildOfCombinedQuery(boolean childOfCombinedQuery) {
906        this.childOfCombinedQuery = childOfCombinedQuery;
907    }
908
909    public boolean isChildOfCombinedQuery() {
910
911        return childOfCombinedQuery;
912    }
913
914    private boolean childOfCombinedQuery = false;
915
916
917    @Override
918    public TreeMap<String,TResultColumn> getExpandedResultColumns() {
919        if (this.setOperatorType == ESetOperatorType.none){
920            return super.getExpandedResultColumns();
921        }else{
922            return this.getLeftStmt().getExpandedResultColumns();
923        }
924    }
925
926    private ArrayList<TSelectSqlStatement> flattenSelects = null;
927
928    public ArrayList<TSelectSqlStatement> getFlattenedSelects() {
929        if (!isCombinedQuery()) return null;
930        if (this.flattenSelects != null) return this.flattenSelects;
931
932        this.flattenSelects = new ArrayList<TSelectSqlStatement>();
933        this.flattenSelects.add(this.rightStmt);
934        doFlattenCombinedSelect(this.leftStmt,this.flattenSelects);
935
936        Collections.reverse(this.flattenSelects);
937        return flattenSelects;
938    }
939
940    void doFlattenCombinedSelect(TSelectSqlStatement select, ArrayList<TSelectSqlStatement> container){
941        TSelectSqlStatement current = select;
942        while (current.isCombinedQuery()){
943            container.add(current.getRightStmt());
944            current = current.getLeftStmt();
945        }
946        container.add(current);
947    }
948
949    /**
950     * This function is used internal. DON'T call it explicitly.
951     *
952     * @param psql input query.
953     * @return  zero means there is no syntax error detected.
954     */
955    public int doParseStatement(TCustomSqlStatement psql) {
956        if (rootNode == null) return -1;
957        TSelectSqlNode selectNode = (TSelectSqlNode)rootNode;
958
959        if (this.sourcetokenlist.size() == 0){
960            // subquery nested in other statements.
961            this.setStartToken(selectNode.getStartToken());
962            this.setEndToken(selectNode.getEndToken());
963        }
964
965        super.doParseStatement(psql);
966        this.selectToken = selectNode.getSelectToken();
967        parenthesisCount = selectNode.getParenthesisCount();
968        parenthesisCountBeforeOrder = selectNode.getParenthissisCountBeforeOrder();
969
970        setOperator = selectNode.getSetOperator();
971        initSetOperatorFields();
972
973        if(selectNode.isCombinedQuery()){
974            TCustomSqlStatement lcParentSql = psql;
975            if ((lcParentSql == null)||(!childOfCombinedQuery)){
976                lcParentSql = this;
977            }
978
979            if (selectNode.cteList != null){
980                this.setCteList(selectNode.cteList);
981                for(int i=0;i<getCteList().size();i++){
982                    getCteList().getCTE(i).doParse(this,ESqlClause.cte);
983                }
984            }
985
986            // Oracle 12c WITH FUNCTION/PROCEDURE support
987            if (selectNode.getWithPlsqlItems() != null){
988                this.setWithPlsqlItems(selectNode.getWithPlsqlItems());
989            }
990
991            // Iterative construction of the left-recursive UNION/INTERSECT/EXCEPT chain.
992            // This avoids StackOverflow for queries with many set operations (e.g., 2000+ UNION ALL).
993            // We collect the chain of combined query nodes, set up their properties top-down,
994            // then process leaf children and clauses from deepest to shallowest.
995
996            ArrayList<TSelectSqlStatement> stmtChain = new ArrayList<>();
997            ArrayList<TSelectSqlNode> nodeChain = new ArrayList<>();
998
999            stmtChain.add(this);
1000            nodeChain.add(selectNode);
1001
1002            TSelectSqlStatement currentStmt = this;
1003            TSelectSqlNode currentNode = selectNode;
1004
1005            // Walk down the left chain, creating intermediate TSelectSqlStatements
1006            while (currentNode.getLeftNode() != null && currentNode.getLeftNode().isCombinedQuery()) {
1007                TSelectSqlNode leftNode = currentNode.getLeftNode();
1008
1009                TSelectSqlStatement nextStmt = new TSelectSqlStatement(dbvendor);
1010                nextStmt.rootNode = leftNode;
1011                nextStmt.setChildOfCombinedQuery(true);
1012
1013                // Wire up parent's leftStmt
1014                currentStmt.leftStmt = nextStmt;
1015
1016                // Inline common setup (equivalent of super.doParseStatement + field init)
1017                if (nextStmt.sourcetokenlist.size() == 0) {
1018                    nextStmt.setStartToken(leftNode.getStartToken());
1019                    nextStmt.setEndToken(leftNode.getEndToken());
1020                }
1021                // Equivalent of TCustomSqlStatement.doParseStatement(lcParentSql)
1022                nextStmt.setParentStmt(lcParentSql);
1023                nextStmt.setFrameStack(lcParentSql.getFrameStack());
1024                lcParentSql.getStmtScope().incrementCurrentStmtIndex();
1025                nextStmt.setQueryId(String.format("%s#stmt_%d_%s",
1026                        lcParentSql.getQueryId(),
1027                        lcParentSql.getStmtScope().getCurrentStmtIndex(),
1028                        nextStmt.sqlstatementtype));
1029                nextStmt.setStmtScope(new TStmtScope(lcParentSql.getStmtScope(), nextStmt));
1030                if (nextStmt.getStartToken() == null && nextStmt.rootNode != null) {
1031                    nextStmt.setStartToken(nextStmt.rootNode.getStartToken());
1032                }
1033                if (nextStmt.getEndToken() == null && nextStmt.rootNode != null) {
1034                    nextStmt.setEndToken(nextStmt.rootNode.getEndToken());
1035                }
1036                if (nextStmt.getGsqlparser() == null && nextStmt.rootNode != null) {
1037                    nextStmt.setGsqlparser(nextStmt.rootNode.getGsqlparser());
1038                }
1039
1040                nextStmt.selectToken = leftNode.getSelectToken();
1041                nextStmt.parenthesisCount = leftNode.getParenthesisCount();
1042                nextStmt.parenthesisCountBeforeOrder = leftNode.getParenthissisCountBeforeOrder();
1043                nextStmt.setOperator = leftNode.getSetOperator();
1044                nextStmt.initSetOperatorFields();
1045
1046                stmtChain.add(nextStmt);
1047                nodeChain.add(leftNode);
1048
1049                currentStmt = nextStmt;
1050                currentNode = leftNode;
1051            }
1052
1053            // Create and process the leftmost leaf (non-combined SELECT)
1054            TSelectSqlStatement leftmostLeaf = new TSelectSqlStatement(dbvendor);
1055            leftmostLeaf.rootNode = currentNode.getLeftNode();
1056            leftmostLeaf.setChildOfCombinedQuery(true);
1057            currentStmt.leftStmt = leftmostLeaf;
1058            leftmostLeaf.doParseStatement(lcParentSql);
1059
1060            // Process right children and clauses from deepest to shallowest
1061            for (int i = stmtChain.size() - 1; i >= 0; i--) {
1062                TSelectSqlStatement stmt = stmtChain.get(i);
1063                TSelectSqlNode node = nodeChain.get(i);
1064
1065                // Create and process right child (always a leaf for left-recursive grammar)
1066                stmt.rightStmt = new TSelectSqlStatement(dbvendor);
1067                stmt.rightStmt.rootNode = node.getRightNode();
1068                stmt.rightStmt.setChildOfCombinedQuery(true);
1069                stmt.rightStmt.doParseStatement(lcParentSql);
1070
1071                // Handle clauses for this level
1072                if (node.getOrderbyClause() != null) {
1073                    node.getOrderbyClause().doParse(stmt, ESqlClause.orderby);
1074                    stmt.orderbyClause = node.getOrderbyClause();
1075                }
1076                stmt.limitClause = node.getLimitClause();
1077                if (node.getForupdateClause() != null) {
1078                    node.getForupdateClause().doParse(stmt, ESqlClause.forUpdate);
1079                    stmt.forUpdateClause = node.getForupdateClause();
1080                }
1081                if (node.getComputeClause() != null) {
1082                    node.getComputeClause().doParse(stmt, ESqlClause.compute);
1083                    stmt.computeClause = node.getComputeClause();
1084                }
1085                stmt.optionClause = node.getOptionClause();
1086                stmt.timeTravel = node.getTimeTravel();
1087                stmt.hintClause = node.getHintClause();
1088            }
1089
1090            return 0;
1091        }
1092
1093        if (selectNode.getValueClause() != null){
1094            this.valueClause = selectNode.getValueClause();
1095            this.valueClause.doParse(this,ESqlClause.selectValue);
1096            isValueClause = true;
1097            return 0;
1098        }
1099
1100        if (selectNode.getTransformClause() != null){
1101            this.transformClause = selectNode.getTransformClause();
1102            this.transformClause.doParse(this,ESqlClause.transformClause);
1103        }
1104
1105        if (selectNode.cteList != null){
1106            this.setCteList(selectNode.cteList);
1107            this.getCteList().doParse(this,ESqlClause.cte);
1108        }
1109
1110        // Oracle 12c WITH FUNCTION/PROCEDURE support
1111        if (selectNode.getWithPlsqlItems() != null){
1112            this.setWithPlsqlItems(selectNode.getWithPlsqlItems());
1113        }
1114
1115        if (selectNode.isHiveFromQuery()){
1116            if(selectNode.getSelectSqlNodes() != null){
1117                for(int i=1;i<selectNode.getSelectSqlNodes().size();i++){
1118                    //start from the second, the first select statement is represented by this class instance.
1119
1120                    TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive);
1121                    select.rootNode = selectNode.getSelectSqlNodes().get(i);
1122                    select.doParseStatement(this);
1123                    this.getMultiSelectStatements().add(select);
1124                }
1125            }
1126
1127            // Hive: from query insert...
1128//            if (selectNode.getFromTableList() != null){
1129//                TFromTable lcFromTable;
1130//                TJoin lcJoin;
1131//
1132//                for(int i=0; i<selectNode.getFromTableList().size();i++){
1133//                    lcFromTable = selectNode.getFromTableList().getFromTable(i);
1134//                    TTable lcTable = null;
1135//
1136//                    if (lcFromTable.getFromtableType() != ETableSource.join){
1137//                        lcJoin = new TJoin();
1138//                        lcTable = analyzeFromTable(lcFromTable,true);
1139//                        lcTable.setEffectType(ETableEffectType.tetSelect);
1140//                        lcJoin.setTable(lcTable);
1141//                        lcJoin.setStartToken(lcJoin.getTable().getStartToken());
1142//                        lcJoin.setEndToken(lcJoin.getTable().getEndToken());
1143//                        lcJoin.setGsqlparser(getGsqlparser());
1144//                    }else{
1145//                        lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true);
1146//                        lcJoin.doParse(this, ESqlClause.join);
1147//
1148//                        if (lcFromTable.getLateralViewList() != null){
1149//                            for(TLateralView lateralView:lcFromTable.getLateralViewList()){
1150//                                addToTables(lateralView.createATable(this));
1151//                            }
1152//                        }
1153//                    }
1154//
1155//                    joins.addJoin(lcJoin);
1156//                }
1157//            }
1158
1159
1160//            if (selectNode.getHiveBodyList() != null){
1161//                for(int i = 0; i<selectNode.getHiveBodyList().size();i++){
1162//                    TParseTreeNode node1 = selectNode.getHiveBodyList().get(i);
1163//                    switch (node1.getNodeType()){
1164//                        case TStatementSqlNode.select:
1165//                            TSelectSqlStatement select = new TSelectSqlStatement(EDbVendor.dbvhive);
1166//                            select.rootNode = node1;
1167//                            select.doParseStatement(this);
1168//                            this.getHiveBodyList().add(select);
1169//
1170//                            break;
1171//                        case TStatementSqlNode.insert:
1172//
1173//                            TInsertSqlStatement insert = new TInsertSqlStatement(EDbVendor.dbvhive);
1174//                            insert.rootNode = node1;
1175//                            insert.doParseStatement(this);
1176//                            this.getHiveBodyList().add(insert);
1177//                            break;
1178//                        default:
1179//                            break;
1180//                    }
1181//                }
1182//            }
1183           // return 0;
1184        }
1185
1186        // get oracle hint
1187        if((dbvendor == EDbVendor.dbvoracle)||(dbvendor == EDbVendor.dbvmysql)){
1188            TSourceToken lcnextst = this.selectToken.container.nextsolidtoken(this.selectToken.posinlist,1,true);
1189            while (lcnextst != null){
1190                if (!((lcnextst.tokentype == ETokenType.ttsimplecomment) || (lcnextst.tokentype == ETokenType.ttbracketedcomment))) break;
1191
1192                if (lcnextst.tokentype == ETokenType.ttbracketedcomment){
1193                    if (lcnextst.toString().startsWith("/*+")){
1194                       //lcnextst.setDbObjType(TObjectName.ttObjOracleHint);
1195                       lcnextst.setDbObjectType(EDbObjectType.oracleHint);
1196                       if (oracleHint == null){
1197                           oracleHint = lcnextst.toString();
1198                       }else {
1199                           oracleHint = oracleHint + " " + lcnextst.toString();
1200                       }
1201                    }
1202                }
1203
1204                if (lcnextst.tokentype == ETokenType.ttsimplecomment){
1205                    if (lcnextst.toString().startsWith("--+")){
1206                       //lcnextst.setDbObjType(TObjectName.ttObjOracleHint);
1207                        lcnextst.setDbObjectType(EDbObjectType.oracleHint);
1208                       if (oracleHint == null){
1209                           oracleHint = lcnextst.toString();
1210                       }else {
1211                           oracleHint = oracleHint + " " + lcnextst.toString();
1212                       }
1213                    }
1214                }
1215
1216                lcnextst = lcnextst.container.nextsolidtoken(lcnextst,1,true);
1217            }
1218
1219            hint = oracleHint;
1220        }
1221
1222        if (selectNode.getHiveHintClause() != null){
1223            hiveHintClause = selectNode.getHiveHintClause();
1224        }
1225
1226        isConsume = selectNode.isConsume();
1227
1228        if (selectNode.getTopClause() != null){
1229           selectNode.getTopClause().doParse(this,ESqlClause.top);
1230            this.setTopClause(selectNode.getTopClause()); 
1231        }
1232
1233 //       this.skipOffset = selectNode.getSkipOffset();
1234//        this.firstMax = selectNode.getFirstMax();
1235//        this.limitMax = selectNode.getLimitMax();
1236
1237        if (selectNode.getSelectDistinct() != null){
1238            this.selectDistinct = selectNode.getSelectDistinct(); 
1239        }
1240
1241        this.selectModifiers = selectNode.getSelectModifiers();
1242
1243        TFromTable lcFromTable = null;
1244        TJoin lcJoin = null;
1245
1246        if (selectNode.getFromTableList() != null){
1247            fromClause = new TFromClause(this.getRelations());
1248            fromClause.setStartToken(selectNode.getFromTableList().getStartToken());
1249            fromClause.setEndToken(selectNode.getFromTableList().getEndToken());
1250
1251            for(int i=0; i<selectNode.getFromTableList().size();i++){
1252                 lcFromTable = selectNode.getFromTableList().getFromTable(i);
1253                 lcJoin = analyzeTableOrJoin(lcFromTable);
1254                 joins.addJoin(lcJoin);
1255            }
1256        }
1257
1258        if (selectNode.getResultColumnList() != null){
1259            this.setResultColumnList(selectNode.getResultColumnList());
1260
1261//            if ((this.getResultColumnList().size() > 10)
1262//                    &&(this.getTables().size() == 1)
1263//                    &&(this.getTables().getTable(0).getTableType() == ETableSource.subquery)
1264//                    &&( this.getTables().getTable(0).getSubquery().getResultColumnList().size() == this.getResultColumnList().size() )
1265//            ){
1266//                TTable t0 = this.getTables().getTable(0);
1267//                ArrayList<TResultColumn> targetColumnArrayList = this.getResultColumnList().getSortedColumns();
1268//                ArrayList<TResultColumn> sourceColumnArrayList = t0.getSubquery().getResultColumnList().getSortedColumns();
1269//                int i=0;
1270//                for(TResultColumn rc:targetColumnArrayList){
1271//                    TObjectName targetColumn = rc.getExpr().getObjectOperand();
1272//                    TResultColumn sourceResultColumn = sourceColumnArrayList.get(i++);
1273//                    //TObjectName sourceColumn = sourceResultColumn.getExpr().getObjectOperand();
1274//                    if (targetColumn != null){
1275//                        //System.out.println(targetColumn+"\t->\t"+sourceResultColumn.getDisplayName());
1276//                        targetColumn.setSourceTable(t0);
1277//                        t0.getLinkedColumns().addObjectName(targetColumn);
1278//                        targetColumn.setSourceColumn(sourceResultColumn);
1279//                        sourceResultColumn.getTargetColumns().addObjectName(targetColumn);
1280//                    }
1281//                }
1282//            }
1283
1284            selectNode.getResultColumnList().doParse(this,ESqlClause.selectList);
1285
1286            for(int i=0;i<selectNode.getResultColumnList().size();i++){
1287                TResultColumn resultColumn = selectNode.getResultColumnList().getResultColumn(i);
1288                if (resultColumn.getExpr().toString().endsWith("*")){
1289                    //System.out.println(resultColumn.toString()+":"+resultColumn.getStartToken().lineNo+","+resultColumn.getStartToken().columnNo);
1290                    if (resultColumn.getExpr().toString().startsWith("*")){
1291                        // add all result columns in from tables
1292                        for(int j=0;j<getTables().size();j++){
1293                            if (getTables().getTable(j).getTableType() == ETableSource.subquery){
1294                                getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns());
1295                            }else{
1296                                // ToDo for real table
1297                            }
1298                            //System.out.println("\t"+getTables().getTable(j).toString()+",\t"+getTables().getTable(j).getTableType()+",\t"+getTables().getTable(j).isCTEName());
1299                        }
1300                        if (getTables().size() == 1){
1301                            resultColumn.getExpr().getObjectOperand().setSourceTable(getTables().getTable(0));
1302                        }
1303
1304                    }else{
1305                        for(int j=0;j<getTables().size();j++){
1306                            if (getTables().getTable(j).getAliasName().equalsIgnoreCase( resultColumn.toString().split("[.]")[0])){
1307                                if (getTables().getTable(j).getTableType() == ETableSource.subquery){
1308                                    getExpandedResultColumns().putAll(getTables().getTable(j).getSubquery().getExpandedResultColumns());
1309                                }else{
1310                                    // ToDo for real table
1311                                }
1312                                resultColumn.getExpr().getObjectOperand().setSourceTable(getTables().getTable(j));
1313                                break;
1314                            }
1315                        }
1316                    }
1317                }else{
1318                    getExpandedResultColumns().put(IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,resultColumn.getDisplayName()),resultColumn);
1319                }
1320            }
1321        }
1322
1323        if (selectNode.getIntoClause() != null){
1324            this.intoClause = selectNode.getIntoClause();
1325            this.intoClause.doParse(this,ESqlClause.selectInto);
1326        }
1327
1328
1329        if (selectNode.getWhereCondition() != null){
1330            selectNode.getWhereCondition().doParse(this,ESqlClause.where);
1331            this.setWhereClause( selectNode.getWhereCondition());
1332        }
1333
1334        if (selectNode.getHierarchicalClause() != null){
1335         selectNode.getHierarchicalClause().doParse(this,ESqlClause.hierarchical);
1336         this.hierarchicalClause = selectNode.getHierarchicalClause();
1337        }
1338
1339        if (selectNode.getGroupByClause() != null){
1340            selectNode.getGroupByClause().doParse(this,ESqlClause.groupby);
1341            this.groupByClause = selectNode.getGroupByClause(); 
1342        }
1343
1344        if (selectNode.getQualifyClause() != null){
1345            selectNode.getQualifyClause().doParse(this,ESqlClause.qualify);
1346            this.qualifyClause = selectNode.getQualifyClause(); 
1347        }
1348
1349        if (selectNode.getSampleClause() != null){
1350            selectNode.getSampleClause().doParse(this,ESqlClause.sample);
1351            this.sampleClause = selectNode.getSampleClause();
1352        }
1353
1354        if (selectNode.getExpandOnClause() != null){
1355            selectNode.getExpandOnClause().doParse(this,ESqlClause.expandOn);
1356            this.expandOnClause = selectNode.getExpandOnClause();
1357        }
1358
1359        if (selectNode.getWithClause() != null){
1360            selectNode.getWithClause().doParse(this,ESqlClause.teradataWith);
1361            this.teradataWithClause  = selectNode.getWithClause();
1362        }
1363
1364        if (selectNode.getOrderbyClause() != null){
1365            selectNode.getOrderbyClause().doParse(this,ESqlClause.orderby);
1366            this.orderbyClause = selectNode.getOrderbyClause(); 
1367        }
1368
1369        if (selectNode.getLockingClauses() != null){
1370           selectNode.getLockingClauses().doParse(this,ESqlClause.lockingClause);
1371            this.lockingClauses = selectNode.getLockingClauses();
1372        }
1373
1374        this.sortBy = selectNode.getSortBy();
1375        if (this.sortBy != null){
1376            this.sortBy.doParse(this,ESqlClause.sortby);
1377        }
1378
1379        this.clusterBy = selectNode.getClusterBy();
1380        if (this.clusterBy != null){
1381            this.clusterBy.doParse(this,ESqlClause.cluster);
1382        }
1383
1384        this.windowClause = selectNode.getWindowClause();
1385        if (this.windowClause != null){
1386            this.windowClause.doParse(this,ESqlClause.windowClause);
1387        }
1388        this.limitClause = selectNode.getLimitClause();
1389        if (this.limitClause != null){
1390            this.limitClause.doParse(this,ESqlClause.limit);
1391        }
1392
1393       if (selectNode.getForupdateClause() != null){
1394            selectNode.getForupdateClause().doParse(this,ESqlClause.forUpdate);
1395            this.forUpdateClause  = selectNode.getForupdateClause();
1396        }
1397
1398        if (selectNode.getComputeClause() != null){
1399            selectNode.getComputeClause().doParse(this,ESqlClause.compute);
1400            this.computeClause = selectNode.getComputeClause(); 
1401        }
1402
1403        this.intoTableClause = selectNode.getIntoTableClause();
1404
1405        if (selectNode.getDistributeBy() != null){
1406            this.distributeBy = selectNode.getDistributeBy();
1407            this.distributeBy.doParse(this,ESqlClause.distributeBy);
1408        }
1409
1410
1411        this.isolationClause = selectNode.getIsolationClause();
1412
1413        this.optionClause = selectNode.getOptionClause();
1414
1415        this.offsetClause = selectNode.getOffsetClause();
1416        this.fetchFirstClause = selectNode.getFetchFirstClause();
1417
1418        this.timeTravel = selectNode.getTimeTravel();
1419        this.hintClause = selectNode.getHintClause();
1420
1421        if (selectNode.getForXMLClause() != null){
1422            if (tables.size() > 0){
1423                tables.getTable(0).setForXMLClause(selectNode.getForXMLClause());
1424            }
1425        }
1426
1427        // StarRocks pipe operator support
1428        this.pipeOperators = selectNode.getPipeOperators();
1429        this.isPipeQuery = selectNode.isPipeQuery();
1430
1431        return 0;
1432    }
1433
1434    /**
1435     * Determine whether The UNION, EXCEPT and INTERSECT operators were used.
1436     * @return true if one of those operators were used.
1437     */
1438    public boolean isCombinedQuery(){
1439    // combine multiple queries using the set operators UNION, UNION ALL, INTERSECT, and MINUS.
1440        return (setOperator > 0);
1441    }
1442
1443    /**
1444     * Initialize setOperatorType, all, and setOpDistinct fields from setOperator value.
1445     * Used by doParseStatement's iterative combined query construction.
1446     */
1447    private void initSetOperatorFields() {
1448        switch (setOperator) {
1449            case SET_OPERATOR_NONE:
1450                setOperatorType = ESetOperatorType.none; all = false; break;
1451            case setOperator_union:
1452                setOperatorType = ESetOperatorType.union; all = false; break;
1453            case setOperator_unionall:
1454                setOperatorType = ESetOperatorType.union; all = true; break;
1455            case SET_OPERATOR_UNIONDISTINCT:
1456                setOperatorType = ESetOperatorType.union; setOpDistinct = true; break;
1457            case setOperator_intersect:
1458                setOperatorType = ESetOperatorType.intersect; all = false; break;
1459            case setOperator_intersectall:
1460                setOperatorType = ESetOperatorType.intersect; all = true; break;
1461            case setOperator_except:
1462                setOperatorType = ESetOperatorType.except; all = false; break;
1463            case setOperator_exceptall:
1464                setOperatorType = ESetOperatorType.except; all = true; break;
1465            case setOperator_minus:
1466                setOperatorType = ESetOperatorType.minus; all = false; break;
1467            case setOperator_minusall:
1468                setOperatorType = ESetOperatorType.minus; all = true; break;
1469            case SET_OPERATOR_INTERSECTDISTINCT:
1470                setOperatorType = ESetOperatorType.intersect; setOpDistinct = true; break;
1471            case SET_OPERATOR_EXCEPTDISTINCT:
1472                setOperatorType = ESetOperatorType.except; setOpDistinct = true; break;
1473        }
1474    }
1475
1476    public void accept(TParseTreeVisitor v)
1477    {
1478        v.preVisit(this);
1479        v.postVisit(this);
1480    }
1481
1482    /**
1483     * Accept visitor to visit this class.
1484     * @param v user defined visitor.
1485     */
1486    public void acceptChildren(TParseTreeVisitor v)
1487    {
1488
1489        if(this.isCombinedQuery()){
1490
1491            // Iterative traversal for combined queries to avoid StackOverflow
1492            // on deeply nested left-recursive UNION/INTERSECT/EXCEPT chains.
1493            // Collect the left-recursive chain of combined query nodes.
1494            ArrayList<TSelectSqlStatement> chain = new ArrayList<>();
1495            TSelectSqlStatement current = this;
1496            while (current.isCombinedQuery()) {
1497                chain.add(current);
1498                current = current.getLeftStmt();
1499            }
1500            // 'current' is now the leftmost leaf (non-combined SELECT)
1501
1502            // Phase 1: preVisit all combined nodes and their CTEs, from root to deepest
1503            for (int i = 0; i < chain.size(); i++) {
1504                TSelectSqlStatement node = chain.get(i);
1505                v.preVisit(node);
1506                if (node.getCteList() != null) {
1507                    node.getCteList().acceptChildren(v);
1508                }
1509            }
1510
1511            // Phase 2: Visit leftmost leaf SELECT
1512            current.acceptChildren(v);
1513
1514            // Phase 3: Visit right branches and postVisit, from deepest to root
1515            for (int i = chain.size() - 1; i >= 0; i--) {
1516                TSelectSqlStatement node = chain.get(i);
1517                node.getRightStmt().acceptChildren(v);
1518
1519                if (node.getOrderbyClause() != null) {
1520                    node.getOrderbyClause().acceptChildren(v);
1521                }
1522                if (node.getLimitClause() != null) {
1523                    node.getLimitClause().acceptChildren(v);
1524                }
1525                if (node.getForUpdateClause() != null) {
1526                    node.getForUpdateClause().acceptChildren(v);
1527                }
1528                if (node.getComputeClause() != null) {
1529                    node.getComputeClause().acceptChildren(v);
1530                }
1531                v.postVisit(node);
1532            }
1533
1534            return ;
1535        }
1536
1537        // System.out.println(this.toString().hashCode()+" "+ this.toString().substring(0,50));
1538
1539        v.preVisit(this);
1540
1541        if (this.getTransformClause() != null){
1542            this.getTransformClause().acceptChildren(v);
1543        }
1544
1545        if (this.getCteList() != null){
1546            this.getCteList().acceptChildren(v);
1547        }
1548
1549        if (TBaseType.USE_JOINEXPR_INSTEAD_OF_JOIN){
1550//            fromClause.acceptChildren(v);
1551            v.preVisit(fromClause);
1552            for(TTable table:getRelations()){
1553                table.acceptChildren(v);
1554            }
1555            v.postVisit(fromClause);
1556        }else{
1557            if (this.getJoins() != null){
1558                this.getJoins().acceptChildren(v);
1559            }
1560        }
1561
1562        if (this.getHiveHintClause() != null){
1563            this.getHiveHintClause().acceptChildren(v);
1564        }
1565
1566
1567        if (this.getTopClause() != null){
1568            this.getTopClause().acceptChildren(v);
1569        }
1570
1571        if (this.getSelectDistinct() != null){
1572            this.getSelectDistinct().acceptChildren(v);
1573        }
1574        
1575        if (this.getResultColumnList() != null){
1576            this.getResultColumnList().acceptChildren(v);
1577        }
1578
1579        if (this.getIntoClause() != null){
1580            this.getIntoClause().acceptChildren(v);
1581        }
1582
1583
1584        if (this.getWhereClause() != null){
1585            this.getWhereClause().acceptChildren(v);
1586        }
1587
1588        if (this.getHierarchicalClause() != null){
1589            this.getHierarchicalClause().acceptChildren(v);
1590        }
1591
1592        if (this.getGroupByClause() != null){
1593            this.getGroupByClause().acceptChildren(v);
1594        }
1595
1596        if (this.getQualifyClause() != null){
1597            this.getQualifyClause().acceptChildren(v);
1598        }
1599
1600        if (this.getSampleClause() != null){
1601            this.getSampleClause().acceptChildren(v);
1602        }
1603
1604        if (this.getExpandOnClause() != null){
1605            this.getExpandOnClause().acceptChildren(v);
1606        }
1607
1608        if (this.getTeradataWithClause() != null){
1609            this.getTeradataWithClause().acceptChildren(v);
1610        }
1611
1612        if (this.getOrderbyClause() != null){
1613            this.getOrderbyClause().acceptChildren(v);
1614        }
1615
1616        if (this.getLockingClauses() != null){
1617            this.getLockingClauses().acceptChildren(v);
1618        }
1619
1620        if (this.getSortBy() != null){
1621            this.getSortBy().acceptChildren(v);
1622        }
1623
1624        if (this.getClusterBy() != null){
1625            this.getClusterBy().acceptChildren(v);
1626        }
1627
1628        if (this.getWindowClause() != null){
1629            this.getWindowClause().acceptChildren(v);
1630        }
1631
1632        if (this.getLimitClause() != null){
1633            this.getLimitClause().acceptChildren(v);
1634        }
1635
1636        if (this.getForUpdateClause() != null){
1637            this.getForUpdateClause().acceptChildren(v);
1638        }
1639
1640        if (this.getComputeClause() != null){
1641            this.getComputeClause().acceptChildren(v);
1642        }
1643
1644        if (this.getIntoTableClause() != null){
1645            this.getIntoTableClause().acceptChildren(v);
1646        }
1647
1648        if (this.getDistributeBy() != null){
1649            this.getDistributeBy().acceptChildren(v);
1650        }
1651
1652        if (this.getIsolationClause() != null){
1653            this.getIsolationClause().acceptChildren(v);
1654        }
1655
1656        if (this.getOptionClause() != null){
1657            this.getOptionClause().acceptChildren(v);
1658        }
1659
1660        if (this.getOffsetClause() != null){
1661            this.getOffsetClause().acceptChildren(v);
1662        }
1663
1664        if (this.getFetchFirstClause() != null){
1665            this.getFetchFirstClause().acceptChildren(v);
1666        }
1667
1668        if (this.getTimeTravel() != null){
1669            this.getTimeTravel().acceptChildren(v);
1670        }
1671
1672        if (this.getHintClause() != null){
1673            this.getHintClause().acceptChildren(v);
1674        }
1675
1676        v.postVisit(this);
1677        return ;
1678
1679    };
1680
1681    /**
1682     *  Add an order by clause to this class.
1683     * @param orderByStr new order by string
1684     * @return added order by clause.
1685     */
1686    public  TOrderBy addOrderBy(String orderByStr){
1687        if (this.getOrderbyClause() != null){
1688            this.getOrderbyClause().addOrderByItem(orderByStr);
1689        }else{
1690
1691            TOrderBy orderBy = new TOrderBy();
1692            orderBy.setGsqlparser(this.getGsqlparser());
1693            orderBy.setString(" order by "+orderByStr);
1694            this.orderbyClause = orderBy;
1695            TSourceToken last_token = null;
1696            if (this.getGroupByClause() != null){
1697                last_token = this.getGroupByClause().getEndToken();
1698            }else if (this.getWhereClause() != null){
1699                last_token = this.getWhereClause().getEndToken();
1700            }else{
1701                last_token = joins.getEndToken();
1702            }
1703
1704            orderbyClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1);
1705
1706           for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){
1707               TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i);
1708               if (node instanceof TSelectSqlStatement)
1709               {
1710                   // change all end token of parse tree node except the last order by item
1711                   node.setEndToken(orderbyClause.getEndToken());
1712               }
1713           }
1714        }
1715
1716        return this.getOrderbyClause();
1717    }
1718
1719    /**
1720     *  this function is alias of addWhereClause
1721     * @param condition new condition
1722     * @return new where clause
1723     */
1724    public TWhereClause addCondition(String condition){
1725        return  addWhereClause(condition);
1726    }
1727
1728    public TWhereClause addConditionOR(String condition){
1729        return  addWhereClauseOR(condition);
1730    }
1731
1732    public  TWhereClause addWhereClause(String condition){
1733       return doAddWhereClause(condition,true);
1734    }
1735
1736    public  TWhereClause addWhereClauseOR(String condition){
1737       return doAddWhereClause(condition,false);
1738    }
1739
1740    protected  TWhereClause doAddWhereClause(String condition, boolean isAnd){
1741
1742        if (this.getWhereClause() != null){
1743                if (isAnd){
1744                    this.getWhereClause().getCondition().addANDCondition(condition);
1745                }else{
1746                    this.getWhereClause().getCondition().addORCondition(condition);
1747                }
1748
1749          }else{
1750             TWhereClause whereClause = new TWhereClause();
1751             whereClause.setGsqlparser(this.getGsqlparser());
1752             whereClause.setString(" where "+condition);
1753             this.setWhereClause(whereClause);
1754
1755            TSourceToken last_token = null;
1756            TJoin lastjoin = joins.getJoin(joins.size()-1);
1757            if (lastjoin.getJoinItems().size() > 0){
1758                TJoinItem lastitem = lastjoin.getJoinItems().getJoinItem(lastjoin.getJoinItems().size()-1);
1759                 last_token = lastitem.getEndToken();
1760            }else {
1761                last_token = joins.getEndToken();
1762            }
1763
1764             whereClause.addAllMyTokensToTokenList(last_token.container, last_token.posinlist+1);
1765
1766            for(int i=0;i<last_token.getNodesEndWithThisToken().size();i++){
1767                TParseTreeNode node = last_token.getNodesEndWithThisToken().get(i);
1768                if (!((node instanceof TJoinList)
1769                        ||(node instanceof TJoin)
1770                        ||(node instanceof TJoinItemList)
1771                        ||(node instanceof TJoinItem)
1772                        ))
1773                {
1774                    // change all end token of parse tree node except the last order by item
1775                    node.setEndToken(whereClause.getEndToken());
1776                }
1777            }
1778
1779          }
1780           return this.getWhereClause();
1781    }
1782
1783    private ArrayList<String> columnsInFromClause = null;
1784
1785
1786    @Override
1787    public TFromClause getFromClause() {
1788        // #todo , select union 类型的 sql 语句,需要穿透到低层的各个 子 select 语句,需要进一步完善
1789        TFromClause ret = super.getFromClause();
1790        if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){
1791            return   this.getRightStmt().getFromClause();
1792        }else{
1793            return  ret;
1794        }
1795    }
1796
1797    public TResultColumnList getResultColumnList(boolean useColumnsFromLeftmost) {
1798        TResultColumnList ret = super.getResultColumnList();
1799        if (ret != null) return ret;
1800
1801        if (isCombinedQuery()){
1802            if (useColumnsFromLeftmost) {
1803                return this.getFarLeftStmt().getResultColumnList();
1804            } else {
1805                return   this.getRightStmt().getResultColumnList();
1806            }
1807        }
1808        return ret;
1809
1810
1811//        if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){
1812//            return   this.getRightStmt().getResultColumnList();
1813//        }else{
1814//            return  ret;
1815//        }
1816    }
1817
1818    @Override
1819    public TResultColumnList getResultColumnList() {
1820        return getResultColumnList(false);
1821
1822//        TResultColumnList ret = super.getResultColumnList();
1823//        if ((ret == null)&&(isCombinedQuery()&&(this.getRightStmt()!=null))){
1824//            return   this.getRightStmt().getResultColumnList();
1825//        }else{
1826//            return  ret;
1827//        }
1828    }
1829
1830    public ArrayList<String> getColumnsInFromClause() {
1831        if (columnsInFromClause != null) return columnsInFromClause;
1832        columnsInFromClause = new ArrayList<String>();
1833        TTable lcTable;
1834        for(int j=0;j<tables.size();j++){
1835            lcTable = tables.getTable(j);
1836            switch (lcTable.getTableType()){
1837                case objectname:
1838                    break;
1839                case subquery:
1840                    TSelectSqlStatement subQuery = lcTable.getSubquery();
1841                                        if (subQuery.getResultColumnList() != null)
1842                                                for(int i=0;i<subQuery.getResultColumnList().size();i++){
1843                                                        TResultColumn resultColumn = subQuery.getResultColumnList().getResultColumn(i);
1844                                                        String aliasName = null;
1845                                                        if (resultColumn.getAliasClause() != null){
1846                                                                aliasName = resultColumn.getAliasClause().getAliasName().toString();
1847                                                        }else{
1848                                                                if (resultColumn.getExpr().getObjectOperand() != null){
1849                                                                        aliasName = resultColumn.getExpr().getObjectOperand().toString();
1850                                                                }
1851                                                        }
1852                                                        if (aliasName != null){
1853                                                                columnsInFromClause.add(TSQLEnv.getObjectName(aliasName));
1854                                                        }
1855                                                }
1856                    break;
1857            }
1858        }
1859        return columnsInFromClause;
1860    }
1861
1862    public void addColumnInSelectListToSQLEnv(TSQLTable sqlTable){
1863
1864        if (this.getValueClause() != null) return;
1865                
1866                if (this.getResultColumnList() != null)
1867                        for(int i=0;i<this.getResultColumnList().size();i++){
1868                                TResultColumn resultColumn = this.getResultColumnList().getResultColumn(i);
1869                                String aliasName = null;
1870                                if (resultColumn.getAliasClause() != null){
1871                                        aliasName = resultColumn.getAliasClause().getAliasName().toString();
1872                                }else{
1873                                        if (resultColumn.getExpr().getObjectOperand() != null){
1874                                                aliasName = resultColumn.getExpr().getObjectOperand().toString();
1875                                        }
1876                                }
1877                                if (aliasName != null){
1878                                        sqlTable.addColumn(TSQLEnv.getObjectName(aliasName));
1879                                }
1880                        }
1881    }
1882
1883    /**
1884     * search column in the select list
1885     *
1886     * Internal function, DON'T call it explicitly.
1887     * @param pColumn
1888     * @param pMustIn
1889     * @return true if found.
1890     */
1891    public boolean searchColumnInResultSet(TObjectName pColumn,boolean pMustIn){
1892        boolean lcResult = false;
1893        int candidateTableCnt = 0;
1894        int numOfColumnStar = 0;
1895        TResultColumn columnStar = null;
1896
1897
1898
1899        TResultColumn c = null;
1900        if ( (c=  this.getExpandedResultColumns().get(IdentifierService.normalizeStatic(this.dbvendor, ESQLDataObjectType.dotColumn,pColumn.getColumnNameOnly()))) != null)
1901        {
1902            //System.out.println("Found:"+pColumn.toString());
1903            pColumn.setSourceColumn(c);
1904            c.getTargetColumns().addObjectName(pColumn);
1905
1906            return true;
1907        }else{
1908           // System.out.println("NotCatch:"+pColumn.toString());
1909        }
1910
1911        if (isCombinedQuery()){
1912            boolean lcResult1;//,lcResult2;
1913            // search column in all select
1914            lcResult1 = getFarLeftStmt().searchColumnInResultSet(pColumn,pMustIn);
1915            if (!lcResult1)
1916            lcResult1 = rightStmt.searchColumnInResultSet(pColumn,pMustIn);
1917            return  lcResult1;
1918        }
1919
1920        if (getResultColumnList() == null) return  false;
1921
1922        if (pColumn.toString().endsWith("*")){
1923            // pColumn here is o1.*
1924            // select o1.*, o2.c1
1925            // from (select c123, c345 from some_table) o1, other_table o2
1926            pColumn.setColumnsLinkedToStar(this.getResultColumnList());
1927            return true;
1928        }
1929
1930        // search columns in select list, skip t.* but count it for later use
1931        for(int i=0;i<getResultColumnList().size();i++){
1932            TResultColumn lcField = getResultColumnList().getResultColumn(i);
1933            if (lcField.toString().endsWith("*")){
1934                numOfColumnStar++;
1935                columnStar = lcField;
1936                continue;
1937            }
1938            lcResult = lcField.isMatchedWithResultColumn(this.dbvendor, pColumn);
1939            if (lcResult){
1940                pColumn.setSourceColumn(lcField);
1941                lcField.getTargetColumns().addObjectName(pColumn);
1942                break;
1943            }
1944        }
1945
1946        if (lcResult) return true;
1947
1948//        // search in * column, including t.* and *
1949        for(int i=0;i<getResultColumnList().size();i++){
1950            TResultColumn lcField = getResultColumnList().getResultColumn(i);
1951            if (lcField.toString().endsWith("*")){
1952                // search column in t.*, have to check column in table t
1953                String prefixTableName = "";
1954                if (lcField.toString().endsWith(".*")){
1955                    String[] a = lcField.toString().split("[.]");
1956                    prefixTableName = a[a.length - 2];
1957                }
1958                for(int j=0;j<tables.size();j++){
1959                    lcResult = tables.getTable(j).searchColumn(this,prefixTableName,pColumn,false);
1960                    if (lcResult) {
1961//                        tables.getTable(j).getLinkedColumns().addObjectName(pColumn);
1962//                        pColumn.setSourceTable(tables.getTable(j));
1963                        pColumn.setSourceColumn(lcField);
1964                        lcField.getTargetColumns().addObjectName(pColumn);
1965                        break;
1966                    }
1967                }
1968            }else{
1969                continue;
1970            }
1971            if (lcResult) break;
1972        }
1973
1974        if (lcResult) return true;
1975
1976        if (pMustIn){
1977            if (tables.size() == 1){ // only a single table in from clause
1978                lcResult = true;
1979                boolean inStarColumn = false;
1980//                tables.getTable(0).getLinkedColumns().addObjectName(pColumn);
1981//                pColumn.setSourceTable(tables.getTable(0));
1982                for(int i=0;i<getResultColumnList().size();i++) {
1983                    TResultColumn lcField = getResultColumnList().getResultColumn(i);
1984                    if (lcField.toString().endsWith("*")) {
1985                        String prefixTableName = "";
1986                        if (lcField.toString().endsWith(".*")){
1987                            String[] a = lcField.toString().split("[.]");
1988                            prefixTableName = a[a.length - 2];
1989                        }
1990                        tables.getTable(0).searchColumn(this,prefixTableName,pColumn,true);
1991                        pColumn.setSourceColumn(lcField);
1992                        lcField.getTargetColumns().addObjectName(pColumn);
1993                        inStarColumn = true;
1994                        break;
1995                    }
1996                }
1997                if (!inStarColumn){
1998
1999                    if (!locateVariableOrParameter(pColumn)){
2000                        // check variable before raise error
2001
2002                        // raise
2003                        TSyntaxError err = new TSyntaxError(pColumn.getStartToken().toString()
2004                                ,pColumn.getStartToken().lineNo,pColumn.getStartToken().columnNo
2005                                ,String.format("Column %s is not found in subquery",pColumn.toString())
2006                                ,EErrorType.sphint ,TBaseType.MSG_ERROR_COLUMN_NOT_FOUND,this,pColumn.getStartToken().posinlist);
2007                        this.parseerrormessagehandle( err);
2008                    }
2009
2010                }
2011            }else if (numOfColumnStar == 1){// only a single * column in select list, but more than one table in from clause
2012
2013                pColumn.setSourceColumn(columnStar);
2014                columnStar.getTargetColumns().addObjectName(pColumn);
2015                if (columnStar.toString().endsWith(".*")){
2016                    lcResult = true;
2017                    String[] a = columnStar.toString().split("[.]");
2018                    String prefixTableName = a[a.length - 2];
2019                    for(int i=0;i<tables.size();i++){
2020                        if (tables.getTable(i).checkTableByName(prefixTableName)){
2021                            tables.getTable(i).searchColumn(this,prefixTableName,pColumn,true);
2022//                            tables.getTable(i).getLinkedColumns().addObjectName(pColumn);
2023//                            pColumn.setSourceTable(tables.getTable(i));
2024                            pColumn.setSourceColumn(columnStar);
2025                            columnStar.getTargetColumns().addObjectName(pColumn);
2026                            break;
2027                        }
2028                    }
2029                }else{
2030                    lcResult = false;
2031                    // * column, no table prefix, this column can only be in one of tables
2032                    for(int i=0;i<tables.size();i++){
2033                        lcResult = tables.getTable(i).searchColumn(this,"",pColumn,false);
2034                        //tables.getTable(i).getLinkedColumns().addObjectName(pColumn);
2035                        //pColumn.setSourceTable(tables.getTable(i));
2036                        pColumn.setSourceColumn(columnStar);
2037                        columnStar.getTargetColumns().addObjectName(pColumn);
2038                    }
2039                }
2040                if (!lcResult) {
2041                    lcResult = linkToFirstTable(pColumn,0);
2042                }
2043            }else{
2044                // multi tables in from clause and multi * column in select list.
2045                lcResult = linkToFirstTable(pColumn,0);
2046            }
2047        }
2048
2049        return lcResult;
2050
2051        //if (lcResult) return true;
2052
2053        // From now on, let's search in * column, there maybe more than one * column in the select list, such as t1.*, t2.*
2054//        TResultColumn resultColumn = getResultColumnList().getResultColumn(0);
2055//        if ((getResultColumnList().size() == 1) &&(resultColumn.toString().equalsIgnoreCase("*") )){
2056//            // search in * or t1.* in the select list
2057//            int tableCntInFromClause = 0;
2058//            TTable tableInFromClause = null;
2059//            for(int i=0;i<tables.size();i++){
2060//                TTable tn = tables.getTable(i);
2061//                if (tn.getEffectType() == ETableEffectType.tetTeradataReference) continue;
2062//                tableInFromClause = tn;
2063//                tableCntInFromClause++;
2064//            }
2065//            //if (tables.size() == 1){
2066//            if (tableCntInFromClause == 1){
2067//                    //TTable t0 = tables.getTable(0);
2068//                TTable t0 = tableInFromClause;
2069//
2070//                if (t0.isBaseTable()){
2071//                        lcResult = fireOnMetaDatabaseTableColumn(t0.getPrefixServer(),t0.getPrefixDatabase(),t0.getPrefixSchema(),t0.getName(),pColumn.getColumnNameOnly());
2072//                        if (! lcResult) candidateTableCnt++;
2073//                    }else{
2074//                        if (t0.getTableType() == ETableSource.subquery){
2075//                            if (t0.isIncludeColumnAlias()){
2076//                                lcResult = t0.searchColumnInAlias(pColumn);
2077//                            }else{
2078//                                lcResult = t0.getSubquery().searchColumnInResultSet(pColumn,pMustIn);
2079//                                if (! lcResult) candidateTableCnt++;
2080//                            }
2081//                        }else if (t0.isCTEName()){
2082//                            lcResult = t0.getCTE().searchColumnInResultSet(this,t0,pColumn,pMustIn);
2083//                            if (! lcResult) candidateTableCnt++;
2084//                        }
2085//                    }
2086//                    if (pMustIn) lcResult = true;
2087//                    if (lcResult){
2088//                        t0.getLinkedColumns().addObjectName(pColumn);
2089//                        pColumn.setSourceTable(t0);
2090//                        pColumn.setSourceColumn(resultColumn);
2091//                        resultColumn.getTargetColumns().addObjectName(pColumn);
2092//                    }
2093//            }else{ // more than one table
2094//                    candidateTableCnt = 0;
2095//                    for(int i=0;i<tables.size();i++){
2096//                        TTable tn = tables.getTable(i);
2097//                        if (tn.isBaseTable()){
2098//                            lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly());
2099//                            if (!lcResult) candidateTableCnt++;
2100//                        }else{
2101//                            if (tn.getTableType() == ETableSource.subquery){
2102//                                if (tn.isIncludeColumnAlias()){
2103//                                    lcResult = tn.searchColumnInAlias(pColumn);
2104//                                }else{
2105//                                    lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,false);
2106//                                    if (!lcResult) candidateTableCnt++;
2107//                                }
2108//                            }else if (tn.isCTEName()){
2109//                                lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,false);
2110//                                if (!lcResult) candidateTableCnt++;
2111//                            }
2112//                        }
2113//
2114//                        if (lcResult){
2115//                            tn.getLinkedColumns().addObjectName(pColumn);
2116//                            pColumn.setSourceTable(tn);
2117//                            pColumn.setSourceColumn(resultColumn);
2118//                            resultColumn.getTargetColumns().addObjectName(pColumn);
2119//                            break;
2120//                        }
2121//                    }
2122//                    if ((!lcResult) && (pMustIn)) linkToFirstTable(pColumn,candidateTableCnt);
2123//            }
2124//           // }
2125//        }
2126//
2127//        if (lcResult) return true;
2128//
2129//        // search t.*
2130//        //int starColumnPos = 0,
2131//        int numOfTableDotStar=0;
2132//        for (int i=0;i<getResultColumnList().size();i++){
2133//            if (getResultColumnList().getResultColumn(i).toString().endsWith(".*")){
2134//                numOfTableDotStar++;
2135//            }
2136//        }
2137//
2138//        TResultColumn rc = null;
2139//        TTable tn = null;
2140//        for (int i=0;i<getResultColumnList().size();i++){
2141//            if (!getResultColumnList().getResultColumn(i).toString().endsWith(".*")) continue;
2142//            rc = getResultColumnList().getResultColumn(i);
2143//          //  starColumnPos = i;
2144//
2145//            for (int j=0;j<tables.size();j++){
2146//                if (! tables.getTable(j).equalByName(rc.getPrefixTable())) continue;
2147//                tn = tables.getTable(j);
2148//
2149//                if (tn.isBaseTable()){
2150//                    lcResult = fireOnMetaDatabaseTableColumn(tn.getPrefixServer(),tn.getPrefixDatabase(),tn.getPrefixSchema(),tn.getName(),pColumn.getColumnNameOnly());
2151//                    if (!lcResult) candidateTableCnt++;
2152//                }else{
2153//                    if (tn.getTableType() == ETableSource.subquery){
2154//                        if (tn.isIncludeColumnAlias()){
2155//                            lcResult = tn.searchColumnInAlias(pColumn);
2156//                        }else{
2157//                            lcResult = tn.getSubquery().searchColumnInResultSet(pColumn,((pMustIn)&&(numOfTableDotStar == 1)));
2158//                            if (!lcResult) candidateTableCnt++;
2159//                        }
2160//                    }else if (tn.isCTEName()){
2161//                        lcResult = tn.getCTE().searchColumnInResultSet(this,tn,pColumn,((pMustIn)&&(numOfTableDotStar == 1)));
2162//                        if (!lcResult) candidateTableCnt++;
2163//                    }
2164//                }
2165//
2166//                if (lcResult){
2167//                    tn.getLinkedColumns().addObjectName(pColumn);
2168//                    pColumn.setSourceTable(tn);
2169//                    pColumn.setSourceColumn(rc);
2170//                    rc.getTargetColumns().addObjectName(pColumn);
2171//                    break;
2172//                }
2173//            }
2174//            if (lcResult) break;
2175//        }
2176//
2177//        if (lcResult) return true;
2178//
2179//        if ((pMustIn) && (numOfTableDotStar == 1) && (tn != null)){
2180//            tn.getLinkedColumns().addObjectName(pColumn);
2181//            pColumn.setSourceTable(tn);
2182//            pColumn.setSourceColumn(rc);
2183//            rc.getTargetColumns().addObjectName(pColumn);
2184//            lcResult = true;
2185//        }
2186//
2187//        if (lcResult) return true;
2188//
2189//        if ((pMustIn) && (numOfTableDotStar > 0)) lcResult = linkToFirstTable(pColumn,candidateTableCnt);
2190//
2191//        if ((pMustIn)&&(!lcResult)) try {
2192//            throw new Exception(" column must be found in the select list:"+pColumn.toString());
2193//        } catch (Exception e) {
2194//            e.printStackTrace();
2195//        }
2196//
2197//        return lcResult;
2198    }
2199
2200
2201}