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