001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.nodes.couchbase.TUpdateFor;
005import gudusoft.gsqlparser.nodes.teradata.TDataConversion;
006import gudusoft.gsqlparser.nodes.teradata.TDataConversionItem;
007import gudusoft.gsqlparser.sqlenv.IdentifierService;
008import gudusoft.gsqlparser.sqlenv.TSQLEnv;
009
010import java.util.ArrayList;
011
012import gudusoft.gsqlparser.util.SQLUtil;
013
014import static gudusoft.gsqlparser.sqlenv.ESQLDataObjectType.dotColumn;
015
016/**
017* This class represents select_list item in select statement, lets you specify the columns you want to retrieve from the table.
018 *<p>Syntax:
019 * <blockquote><pre>
020 * query_name|[schema.]{table|view|materialized_view}|expr [ [AS] alias]</pre>
021 * </blockquote>
022 *
023 * 
024 *<p>or, set column values in update_set_clause.
025 *<p>Syntax:
026 *<p><blockquote>column = expr|(subquery) </blockquote>
027 *
028 * <p>or, values clause in insert statement was represented by {@link TResultColumnList}.
029 *<p>Syntax:
030 *<p><blockquote><pre>(expr,expr) </pre></blockquote>
031 *
032*/
033public class TResultColumn extends TNodeWithAliasClause implements Comparable{
034
035
036    // sparksql: select explode(str_to_map(regexp_replace(regexp_replace(regexp_replace(lower(t.input), '', ''), '',''), '', ''), '', '')) as (`key`, `value`) from B t1
037    // select t.a1, t.a2, stack(2, 'T', t.a1, t.a2, t.a3/t.a4, t.a5/t.a6,   'T+0', t.a7, t.a8, t.a9/t.a10, t.a11/t.a12) as (b1, b2, b3, b4, b5)  from db1.table1 t
038    // explode and stack functions are used to convert array or map into rows and create new column names
039    private ArrayList<TObjectName> aliasNameList = null;
040
041    public ArrayList<TObjectName> getAliasNameList() {
042        if (aliasNameList == null) {
043            aliasNameList = new ArrayList<>();
044        }
045        return aliasNameList;
046    }
047
048    private ArrayList<TObjectName> attributesFromUpLevelReferenceToStarColumn;
049
050    /**
051     * 这个属性只对 star column 有效。用来存放在 up level 中找到的关联到本 star column 的 column,
052     * 主要用来把来自 up level 的这些 column 继续和 本层 from clause 中的 table 关联起来,
053     * 以解决 up level column 来自低层哪个 table 的问题
054     *
055     * 实现代码见:TStarColumnPushDownResolver.preVisit(TSelectSqlStatement stmt),
056     * TAttributeNode.addAttributeRefToThisNode(TObjectName objectName)
057     *
058     * @return
059     */
060    public ArrayList<TObjectName> getAttributesFromUpLevelReferenceToStarColumn() {
061        if (attributesFromUpLevelReferenceToStarColumn == null){
062            attributesFromUpLevelReferenceToStarColumn = new ArrayList<>();
063        }
064        return attributesFromUpLevelReferenceToStarColumn;
065    }
066
067    private String aliasName;
068
069    public void setAliasName(String aliasName) {
070        this.aliasName = aliasName;
071    }
072
073    public String getAliasName() {
074        return aliasName;
075    }
076
077    private ArrayList<TReplaceExprAsIdentifier> exprAsIdentifiers;
078
079    /**
080     * BigQuery replace columns
081     * <br>
082     * SELECT * REPLACE (quantity/2 AS quantity)
083     *
084     * @return replace expr as identifier list
085     */
086    public ArrayList<TReplaceExprAsIdentifier> getExprAsIdentifiers() {
087        return exprAsIdentifiers;
088    }
089
090    /**
091     * Bigquery except columns
092     * SELECT COMMON.* EXCEPT (column1, column2) FROM dataset1.table1 COMMON;
093     *
094     * @return Bigquery except columns
095     */
096    public TObjectNameList getExceptColumnList() {
097        return exceptColumnList;
098    }
099
100    private TObjectNameList exceptColumnList;
101
102    /**
103     * BigQuery select * except(expr as identifier)
104     * @return
105     */
106    public ArrayList<TReplaceExprAsIdentifier> getReplaceExprAsIdentifiers() {
107        return replaceExprAsIdentifiers;
108    }
109
110    private  ArrayList<TReplaceExprAsIdentifier>  replaceExprAsIdentifiers;
111
112    private TQualifyClause qualifyClause;
113
114    public void setQualifyClause(TQualifyClause qualifyClause) {
115        this.qualifyClause = qualifyClause;
116    }
117
118    public TQualifyClause getQualifyClause() {
119
120        return qualifyClause;
121    }
122
123    public void setDataTypeConversionList(TPTNodeList<TExplicitDataTypeConversion> dataTypeConversionList) {
124        expr.setDataTypeConversionList(dataTypeConversionList);
125    }
126
127    private  TPTNodeList <TExplicitDataTypeConversion> dataTypeConversionList = null; // teradata
128
129    private TObjectNameList targetColumns = null;
130
131    public TObjectNameList getTargetColumns() {
132        if (targetColumns == null) targetColumns = new TObjectNameList();
133        return targetColumns;
134    }
135
136    public boolean isMatchedUsingAlias(TObjectName pColumn){
137        // No alias clause -> nothing to match; callers dereference getAliasClause()
138        // when this returns true (quote-stripping made "" match the empty no-alias string).
139        if (getAliasClause() == null) return false;
140        boolean lcResult = SQLUtil.sameName(this.dbvendor, dotColumn, pColumn.getColumnNameOnly(), getColumnAlias());
141        return lcResult;
142    }
143
144    public boolean isMatchedWithResultColumn(EDbVendor dbVendor, TObjectName pColumn){
145       // boolean lcResult = pColumn.getColumnNameOnly().equalsIgnoreCase(getColumnAlias());
146        //boolean lcResult = TSQLObject.compareTo(dbVendor, ESQLDataObjectType.dotColumn,pColumn.getColumnNameOnly(),getColumnAlias()) == 0;
147        boolean lcResult = TSQLEnv.compareIdentifier(dbVendor, dotColumn,pColumn.getColumnNameOnly(),getColumnAlias());
148        if ((getColumnAlias().length() > 0) && (!lcResult)){
149            return lcResult;
150        }
151        if (! lcResult) {
152            //lcResult = pColumn.getColumnNameOnly().equalsIgnoreCase(getColumnNameOnly());
153            //lcResult = TSQLObject.compareTo(dbVendor, ESQLDataObjectType.dotColumn,pColumn.getColumnNameOnly(),getColumnNameOnly()) == 0;
154            lcResult = TSQLEnv.compareIdentifier(dbVendor, dotColumn,pColumn.getColumnNameOnly(),getColumnNameOnly());
155        }
156
157        return lcResult;
158    }
159
160    public void TResultColumn(){
161
162    }
163
164    /**
165     * This is the display name shown in the output of select list
166     * @return display name
167     */
168    public String getDisplayName(){
169        if (getAliasClause() != null) return  getAliasClause().toString();
170        String result = "";
171        switch (expr.getExpressionType()){
172            case sqlserver_proprietary_column_alias_t:
173                if (expr.getRightOperand().getExpressionType() == EExpressionType.simple_object_name_t){
174                    result = expr.getRightOperand().getObjectOperand().getColumnNameOnly();
175                }
176                break;
177            case simple_object_name_t:
178                result = expr.getObjectOperand().getColumnNameOnly();
179                break;
180            default:
181                result = toString();
182                break;
183        }
184        return result;
185    }
186
187    public String getColumnAlias(){
188        if (getAliasClause() != null) return  getAliasClause().toString();
189        else return "";
190    }
191
192    public TObjectName getColumnFullname(){
193        TObjectName result = null;
194        switch (expr.getExpressionType()){
195            case sqlserver_proprietary_column_alias_t:
196                if (expr.getRightOperand().getExpressionType() == EExpressionType.simple_object_name_t){
197                    result = expr.getRightOperand().getObjectOperand();
198                }
199                break;
200            case simple_object_name_t:
201                result = expr.getObjectOperand();
202                break;
203            default:
204                break;
205        }
206        return result;
207    }
208
209    public String getColumnNameOnly(){
210        String result = "";
211        switch (expr.getExpressionType()){
212            case sqlserver_proprietary_column_alias_t:
213                if (expr.getRightOperand().getExpressionType() == EExpressionType.simple_object_name_t){
214                    result = expr.getRightOperand().getObjectOperand().getColumnNameOnly();
215                }
216                break;
217            case simple_object_name_t:
218                result = expr.getObjectOperand().getColumnNameOnly();
219                break;
220            case typecast_t:
221                result = expr.getLeftOperand().toString();
222                break;
223            default:
224                break;
225        }
226//        if (expr.getExpressionType() == EExpressionType.simple_object_name_t) return expr.getObjectOperand().getColumnNameOnly();
227//        else return "";
228
229        return result;
230    }
231
232    private TExpression expr = null;
233
234    public void setExpr(TExpression expr) {
235        this.expr = expr;
236    }
237
238    private  boolean placeHolder = false;
239
240    public void setPlaceHolder(boolean placeHolder) {
241        this.placeHolder = placeHolder;
242    }
243
244    /**
245     * this is true when  there is no column names specified for fields in teradata insert statement
246     * <p>
247     * INSERT INTO employee (10005, 'Orebo B',300,,,, 'Nov 17 1957','M',,,18,);
248     * @return
249     */
250    public boolean isPlaceHolder(){
251        return this.placeHolder;
252    }
253    /**
254     * column expression.
255     * If there is only column name in a select_list item, then, this expr is type of {@link TExpression#simpleObjectname},
256     * <p>Otherwise, it maybe a complex expr, you should check {@link TExpression#getExpressionType}.
257     * <p>for column values in update_set_clause, this expr is type of {@link TExpression#ASSIGNMENT}
258     * @return
259     */
260    public TExpression getExpr() {
261        return expr;
262    }
263
264
265    public void init(Object arg1)
266    {
267        if (arg1 instanceof TExpression){
268            expr = (TExpression)arg1;
269        }
270    }
271
272    public void init(Object arg1, Object arg2)
273    {
274        init(arg1);
275        if (arg2 instanceof TAliasClause) {
276            this.setAliasClause((TAliasClause) arg2);
277            if (((TAliasClause) arg2).getAliasName() != null) {
278                ((TAliasClause) arg2).getAliasName().setObjectType(TObjectName.ttobjColumnAlias);
279            }
280        }
281    }
282
283
284    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
285        if (this.isPlaceHolder()) return ;
286
287        if(psql.dbvendor == EDbVendor.dbvteradata){
288            boolean foundNamedDataAttribute = false;
289            if (expr.getDataConversions().size() > 0 ){
290                for(int i=0;i<expr.getDataConversions().size();i++){
291                    TDataConversion dataConversion = expr.getDataConversions().get(i);
292                    for(int j=0;j<dataConversion.getDataConversionItems().size();j++){
293                        TDataConversionItem dataConversionItem = dataConversion.getDataConversionItems().get(j);
294                        if (dataConversionItem.getDataConversionType() == TDataConversionItem.EDataConversionype.dataAttribute){
295                            TDatatypeAttribute datatypeAttribute = dataConversionItem.getDatatypeAttribute();
296                            if ((this.getAliasClause() == null) && (datatypeAttribute.getAttributeType() == EDataTypeAttribute.named_t)){
297                                TAliasClause aliasClause = new TAliasClause();
298
299                                aliasClause.init(datatypeAttribute.getNamedName());
300                                aliasClause.setStartToken(datatypeAttribute.getNamedName());
301                                aliasClause.setEndToken(datatypeAttribute.getNamedName());
302
303                                aliasClause.setTeradataNamedAlais(true);
304                                aliasClause.setAsToken(datatypeAttribute.getStartToken());
305                                this.setAliasClause(aliasClause);
306
307                                foundNamedDataAttribute = true;
308                                break;
309                            }
310                        }
311                    }
312                    if (foundNamedDataAttribute) break;
313                }
314            }
315
316//            if (expr.getDataTypeConversionList() != null){
317//                boolean namedAlias = false;
318//                TDatatypeAttribute datatypeAttribute = null;
319//                for(int i=0;i<expr.getDataTypeConversionList().size();i++){
320//                    TExplicitDataTypeConversion e = expr.getDataTypeConversionList().getElement(i);
321//                    if (e.getDataTypeAttributeList1() == null) continue;
322//                    for(int j=0;j<e.getDataTypeAttributeList1().size();j++){
323//                        datatypeAttribute = e.getDataTypeAttributeList1().getElement(j);
324//                        if (datatypeAttribute.getAttributeType() == EDataTypeAttribute.named_t){
325//                            break;
326//                        }else {
327//                            datatypeAttribute = null;
328//                        }
329//                    }
330//                    if (datatypeAttribute != null) break;
331//                }
332//
333//                if (datatypeAttribute != null){
334//                    if (datatypeAttribute.getAttributeType() == EDataTypeAttribute.named_t){
335//                        TAliasClause aliasClause = new TAliasClause();
336//                        if (datatypeAttribute.getValue_literal() != null){
337//                            aliasClause.init(datatypeAttribute.getValue_literal());
338//                            aliasClause.setStartToken(datatypeAttribute.getValue_literal().getStartToken());
339//                            aliasClause.setEndToken(datatypeAttribute.getValue_literal().getEndToken());
340//                        }else if (datatypeAttribute.getValue_identifier() != null){
341//                            aliasClause.init(datatypeAttribute.getValue_identifier());
342//                            aliasClause.setStartToken(datatypeAttribute.getValue_identifier());
343//                            aliasClause.setEndToken(datatypeAttribute.getValue_identifier());
344//                        }
345//                        aliasClause.setTeradataNamedAlais(true);
346//                        aliasClause.setAsToken(datatypeAttribute.getStartToken());
347//                        this.setAliasClause(aliasClause);
348//                        namedAlias = true;
349//                    }
350//                }
351//
352//                if(!namedAlias){
353//                    //expr.setEndToken(expr.getDataTypeConversion().getEndToken());
354//                }
355//
356//                //this.setEndToken(expr.getEndToken());
357//            }
358
359            // select col1 (DATE) from tab1
360//            if (expr.getExpressionType() == EExpressionType.function_t){
361//                TFunctionCall f = expr.getFunctionCall();
362//                if ((f.getArgs() != null)&&(f.getArgs().size() == 1)){
363//                    if (f.getArgs().getExpression(0).toString().equalsIgnoreCase("date")){
364//                        expr.setExpressionType(EExpressionType.simple_object_name_t);
365//                        f.getFunctionName().setDbObjectType(EDbObjectType.column);
366//                        f.getFunctionName().setPartToken(f.getFunctionName().getObjectToken());
367//                        f.getFunctionName().setObjectToken(null);
368//                        expr.setObjectOperand(f.getFunctionName());
369//                        expr.setStartToken(f.getFunctionName().getStartToken());
370//                        expr.setEndToken(f.getFunctionName().getEndToken());
371//                        //
372//                        TTypeName date1 = new TTypeName();
373//                        date1.init(EDataType.date_t.date_t);
374//                        date1.setStartToken(f.getArgs().getExpression(0).getStartToken());
375//                        date1.setEndToken(f.getArgs().getExpression(0).getEndToken());
376//                        TExplicitDataTypeConversion dtc = new TExplicitDataTypeConversion();
377//                        dtc.init(date1);
378//                        dtc.setStartToken(date1.getStartToken());
379//                        dtc.setEndToken(date1.getEndToken());
380//
381//                        TPTNodeList<TExplicitDataTypeConversion> dtcList = new TPTNodeList<TExplicitDataTypeConversion>();
382//                        dtcList.addNode(dtc);
383//                        expr.setDataTypeConversionList(dtcList);
384//                    }
385//                }
386//            }
387
388        }
389        // change plocation when resultcolumn is in update or insert
390        if (plocation == ESqlClause.set){
391            if (expr.getExpressionType() == EExpressionType.function_t){
392                /*
393                 *   UPDATE Cities
394                 *   SET Location.SetXY(23.5, 23.5)
395                 */
396                //expr.getFunctionCall().getFunctionName().parseColumnMethodName();
397                try{
398                    expr.getFunctionCall().getFunctionName().setObjectType(TObjectName.ttobjColumnMethod);
399                   // expr.getFunctionCall().getFunctionName().setDbObjectType(EDbObjectType.method);
400                }catch (Exception e){
401                    TSourceToken st = expr.getStartToken();
402                    psql.parseerrormessagehandle(new TSyntaxError(st.getAstext(), st.lineNo, st.columnNo
403                            ,"error function call in set clause", EErrorType.spfatalerror
404                            , TBaseType.MSG_ERROR_FUNCTION_IN_SET_CLAUSE
405                            ,psql,st.posinlist));
406                }
407                if( (expr.getFunctionCall().getFunctionName().getPartToken()!=null)&&(psql.getTargetTable()!=null)){
408                    TObjectName columName = TObjectName.createObjectName (psql.dbvendor, EDbObjectType.column,expr.getFunctionCall().getFunctionName().getPartToken());
409                    psql.getTargetTable().getLinkedColumns().addObjectName (columName);
410                    columName.setSourceTable(psql.getTargetTable());
411                    columName.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
412                }else{
413                     psql.linkColumnToTable(expr.getFunctionCall().getFunctionName(),plocation);
414                }
415
416                if (expr.getFunctionCall().getArgs() != null){
417                    for(int i=0;i<expr.getFunctionCall().getArgs().size();i++){
418                        expr.getFunctionCall().getArgs().doParse(psql,plocation);
419                    }
420                }
421              //  psql.linkColumnReferenceToTable( TGSqlParser.parseObjectName(psql.dbvendor, expr.getFunctionCall().getFunctionName().getPartToken().astext) ,plocation);
422            }else {
423                 if (expr.getLeftOperand().getExpressionType() == EExpressionType.simple_object_name_t){
424                     expr.getLeftOperand().getObjectOperand().setLocation(plocation);
425                     TTable lcTable = psql.tables.getTable(0);
426                     if (lcTable.isLinkTable()) lcTable = lcTable.getLinkTable();
427                     lcTable.getLinkedColumns().addObjectName(expr.getLeftOperand().getObjectOperand());
428                     expr.getLeftOperand().getObjectOperand().setSourceTable(lcTable);
429                     expr.getLeftOperand().getObjectOperand().setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
430                     lcTable.getObjectNameReferences().addObjectName(expr.getLeftOperand().getObjectOperand());
431                     expr.getRightOperand().doParse(psql,ESqlClause.setValue);
432                 }else {
433                     expr.doParse(psql,plocation);
434                 }
435            }
436            //psql.linkColumnToTable()
437        }else if (
438                (expr.getExpressionType() == EExpressionType.simple_comparison_t)
439                &&((psql.dbvendor == EDbVendor.dbvmssql)||(psql.dbvendor == EDbVendor.dbvsybase)||(psql.dbvendor == EDbVendor.dbvsybasease || psql.dbvendor == EDbVendor.dbvsqlanywhere || psql.dbvendor == EDbVendor.dbvsybaseiq))
440                &&(
441                        (plocation == ESqlClause.resultColumn)
442                        ||(plocation == ESqlClause.insertColumn)
443                                ||(plocation == ESqlClause.mergeInsert)
444                                ||(plocation == ESqlClause.selectList)
445                )
446
447            )
448        {
449            //@x in  select @x = id is not a alias
450            //The T-SQL "alias = expr" form only exists when the alias side is a
451            //simple identifier or a constant; any other left operand (e.g. a
452            //parenthesized or arithmetic expression) stays a plain comparison,
453            //otherwise an empty token-less alias clause would make
454            //getDisplayName() return null (mantis 4680).
455            if (
456                (expr.getComparisonOperator().toString().equalsIgnoreCase("="))
457                 &&((expr.getLeftOperand().getExpressionType() == EExpressionType.simple_object_name_t)
458                    ||(expr.getLeftOperand().getExpressionType() == EExpressionType.simple_constant_t))
459                 &&(!(expr.getLeftOperand().toString().startsWith("@")))
460                  ){
461                //expr.setExpressionType(TExpression.sqlserver_proprietary_column_alias);
462                expr.setExpressionType(EExpressionType.sqlserver_proprietary_column_alias_t);
463                TAliasClause aliasClause  = new TAliasClause();
464                if (expr.getLeftOperand().getExpressionType() == EExpressionType.simple_object_name_t){
465                    aliasClause.init(expr.getLeftOperand().getObjectOperand());
466                    aliasClause.setStartToken(expr.getLeftOperand().getStartToken());
467                    aliasClause.setEndToken(expr.getLeftOperand().getEndToken());
468                }else{
469                    aliasClause.init(expr.getLeftOperand().getConstantOperand());
470                    aliasClause.setStartToken(expr.getLeftOperand().getStartToken());
471                    aliasClause.setEndToken(expr.getLeftOperand().getEndToken());
472                }
473                setAliasClause(aliasClause);
474            }
475            expr.doParse(psql,plocation);
476        }else if((psql.dbvendor == EDbVendor.dbvpostgresql)
477                &&(expr.getExpressionType() == EExpressionType.simple_constant_t)
478                &&(plocation == ESqlClause.selectList)
479                &&(expr.getObjectOperand() != null)&&(expr.getExprAlias() != null)
480        ){// func_name Sconst /* generic type 'literal' syntax */
481            expr.setExpressionType(EExpressionType.simple_object_name_t);
482            setAliasClause(expr.getExprAlias());
483            getAliasClause().setStartToken(expr.getExprAlias().getStartToken());
484            getAliasClause().setEndToken(expr.getExprAlias().getEndToken());
485            expr.doParse(psql,plocation);
486        }else{
487            expr.doParse(psql,plocation);
488        }
489
490        if (qualifyClause != null){
491            qualifyClause.doParse(psql,plocation);
492        }
493
494//        if ((expr.getFieldList() != null) && (psql.dbvendor == EDbVendor.dbvbigquery)){
495//            // SELECT COMMON.* EXCEPT (column1, column2) FROM dataset1.table1 COMMON;
496//            this.exceptColumnList = expr.getFieldList();
497//            TTable table = psql.tables.getTable(0);
498//            if (table != null){
499//                for(int i=0;i<this.exceptColumnList.size();i++){
500//                    table.getLinkedColumns().addObjectName(this.exceptColumnList.getObjectName(i));
501//                    this.exceptColumnList.getObjectName(i).setSourceTable(table);
502//                }
503//            }
504//        }
505
506        if (expr.getExceptReplaceClause() != null){
507            // SELECT COMMON.* EXCEPT (column1, column2) FROM dataset1.table1 COMMON;
508            this.exceptColumnList = expr.getExceptReplaceClause().getColumnList();
509
510            // select * replace(expr as identifier)
511            this.replaceExprAsIdentifiers = expr.getExceptReplaceClause().getExprAsIdentifiers();
512
513            TTable table = psql.tables.getTable(0);
514            if (table != null){
515                if (this.exceptColumnList != null){
516                    for(int i=0;i<this.exceptColumnList.size();i++){
517                        table.getLinkedColumns().addObjectName(this.exceptColumnList.getObjectName(i));
518                        this.exceptColumnList.getObjectName(i).setSourceTable(table);
519                    }
520                }
521
522                if (replaceExprAsIdentifiers != null){
523                    for(int i=0;i<replaceExprAsIdentifiers.size();i++){
524                        TReplaceExprAsIdentifier replaceExprAsIdentifier = replaceExprAsIdentifiers.get(i);
525                        table.getLinkedColumns().addObjectName(replaceExprAsIdentifier.getIdentifier());
526                        replaceExprAsIdentifier.getIdentifier().setSourceTable(table);
527                    }
528                }
529            }
530
531        }
532    }
533
534
535    /**
536     *
537     * @return this is used to provide back compatibility of .NET version only. 
538     */
539    public TObjectName getFieldAttr() {
540        TObjectName ret = null;
541        if (expr.getExpressionType() == EExpressionType.simple_object_name_t){
542            ret = expr.getObjectOperand();
543        }
544        return ret;
545    }
546
547    public String getPrefixTable(){
548        if (getFieldAttr() == null) return "";
549        return getFieldAttr().getTableString();
550    }
551
552    public String getPrefixSchema(){
553        if (getFieldAttr() == null) return "";
554        return getFieldAttr().getSchemaString();
555    }
556
557    public String getPrefixDatabase(){
558        if (getFieldAttr() == null) return "";
559        return getFieldAttr().getDatabaseString();
560    }
561
562    public String getPrefixServer(){
563        if (getFieldAttr() == null) return "";
564        return getFieldAttr().getServerString();
565    }
566
567    public void accept(TParseTreeVisitor v){
568        v.preVisit(this);
569        v.postVisit(this);
570    }
571
572    public void acceptChildren(TParseTreeVisitor v){
573        v.preVisit(this);
574
575        if (!placeHolder)  getExpr().acceptChildren(v);
576        if (getAliasClause() != null){
577            getAliasClause().acceptChildren(v);
578        }
579
580        v.postVisit(this);
581    }
582
583    public void setTargetColumns(TObjectNameList targetColumns) {
584        this.targetColumns = targetColumns;
585    }
586
587    private TUpdateFor updateFor; //couchbase
588
589    public void setUpdateFor(TUpdateFor updateFor) {
590        this.updateFor = updateFor;
591    }
592
593    public TUpdateFor getUpdateFor() {
594
595        return updateFor;
596    }
597
598    /**
599     * Oracle 26c: OLD/NEW qualifier for RETURNING clause expressions.
600     * Indicates whether this result column in a RETURNING clause uses
601     * the OLD or NEW qualifier to capture pre-update or post-update values.
602     */
603    private EOldNewQualifier oldNewQualifier = EOldNewQualifier.none;
604
605    /**
606     * Sets the OLD/NEW qualifier for this RETURNING clause expression.
607     * @param oldNewQualifier the qualifier (OLD, NEW, or none)
608     */
609    public void setOldNewQualifier(EOldNewQualifier oldNewQualifier) {
610        this.oldNewQualifier = oldNewQualifier;
611    }
612
613    /**
614     * Gets the OLD/NEW qualifier for this RETURNING clause expression.
615     * @return the qualifier (OLD, NEW, or none for unqualified expressions)
616     */
617    public EOldNewQualifier getOldNewQualifier() {
618        return oldNewQualifier;
619    }
620
621    public int compareTo(Object o){
622        TResultColumn rc = (TResultColumn)o;
623        //getDisplayName() can be null for a malformed column whose nodes carry
624        //no boundary tokens (mantis 4680); order a name-less column first
625        //instead of throwing.
626        String thisKey = IdentifierService.normalizeStatic(this.dbvendor,dotColumn, this.getDisplayName());
627        String thatKey = IdentifierService.normalizeStatic(this.dbvendor,dotColumn,rc.getDisplayName());
628        if (thisKey == null) thisKey = "";
629        if (thatKey == null) thatKey = "";
630        return  thisKey.compareTo(thatKey);
631    }
632
633//    private int pos = -1;
634//
635//    public void setPos(int pos) {
636//        this.pos = pos;
637//    }
638//
639//    public int getPos() {
640//        return pos;
641//    }
642}