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