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                     // SET tgt.objcol.attr: the head is the target's alias, not a schema (Mantis #4747)
428                     expr.getLeftOperand().getObjectOperand().columnToPropertyIfQualifiedByTable(lcTable);
429                     lcTable.getLinkedColumns().addObjectName(expr.getLeftOperand().getObjectOperand());
430                     expr.getLeftOperand().getObjectOperand().setSourceTable(lcTable);
431                     expr.getLeftOperand().getObjectOperand().setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
432                     lcTable.getObjectNameReferences().addObjectName(expr.getLeftOperand().getObjectOperand());
433                     expr.getRightOperand().doParse(psql,ESqlClause.setValue);
434                 }else {
435                     expr.doParse(psql,plocation);
436                 }
437            }
438            //psql.linkColumnToTable()
439        }else if (
440                (expr.getExpressionType() == EExpressionType.simple_comparison_t)
441                &&((psql.dbvendor == EDbVendor.dbvmssql)||(psql.dbvendor == EDbVendor.dbvsybase)||(psql.dbvendor == EDbVendor.dbvsybasease || psql.dbvendor == EDbVendor.dbvsqlanywhere || psql.dbvendor == EDbVendor.dbvsybaseiq))
442                &&(
443                        (plocation == ESqlClause.resultColumn)
444                        ||(plocation == ESqlClause.insertColumn)
445                                ||(plocation == ESqlClause.mergeInsert)
446                                ||(plocation == ESqlClause.selectList)
447                )
448
449            )
450        {
451            //@x in  select @x = id is not a alias
452            //The T-SQL "alias = expr" form only exists when the alias side is a
453            //simple identifier or a constant; any other left operand (e.g. a
454            //parenthesized or arithmetic expression) stays a plain comparison,
455            //otherwise an empty token-less alias clause would make
456            //getDisplayName() return null (mantis 4680).
457            if (
458                (expr.getComparisonOperator().toString().equalsIgnoreCase("="))
459                 &&((expr.getLeftOperand().getExpressionType() == EExpressionType.simple_object_name_t)
460                    ||(expr.getLeftOperand().getExpressionType() == EExpressionType.simple_constant_t))
461                 &&(!(expr.getLeftOperand().toString().startsWith("@")))
462                  ){
463                //expr.setExpressionType(TExpression.sqlserver_proprietary_column_alias);
464                expr.setExpressionType(EExpressionType.sqlserver_proprietary_column_alias_t);
465                TAliasClause aliasClause  = new TAliasClause();
466                if (expr.getLeftOperand().getExpressionType() == EExpressionType.simple_object_name_t){
467                    aliasClause.init(expr.getLeftOperand().getObjectOperand());
468                    aliasClause.setStartToken(expr.getLeftOperand().getStartToken());
469                    aliasClause.setEndToken(expr.getLeftOperand().getEndToken());
470                }else{
471                    aliasClause.init(expr.getLeftOperand().getConstantOperand());
472                    aliasClause.setStartToken(expr.getLeftOperand().getStartToken());
473                    aliasClause.setEndToken(expr.getLeftOperand().getEndToken());
474                }
475                setAliasClause(aliasClause);
476            }
477            expr.doParse(psql,plocation);
478        }else if((psql.dbvendor == EDbVendor.dbvpostgresql)
479                &&(expr.getExpressionType() == EExpressionType.simple_constant_t)
480                &&(plocation == ESqlClause.selectList)
481                &&(expr.getObjectOperand() != null)&&(expr.getExprAlias() != null)
482        ){// func_name Sconst /* generic type 'literal' syntax */
483            expr.setExpressionType(EExpressionType.simple_object_name_t);
484            setAliasClause(expr.getExprAlias());
485            getAliasClause().setStartToken(expr.getExprAlias().getStartToken());
486            getAliasClause().setEndToken(expr.getExprAlias().getEndToken());
487            expr.doParse(psql,plocation);
488        }else{
489            expr.doParse(psql,plocation);
490        }
491
492        if (qualifyClause != null){
493            qualifyClause.doParse(psql,plocation);
494        }
495
496//        if ((expr.getFieldList() != null) && (psql.dbvendor == EDbVendor.dbvbigquery)){
497//            // SELECT COMMON.* EXCEPT (column1, column2) FROM dataset1.table1 COMMON;
498//            this.exceptColumnList = expr.getFieldList();
499//            TTable table = psql.tables.getTable(0);
500//            if (table != null){
501//                for(int i=0;i<this.exceptColumnList.size();i++){
502//                    table.getLinkedColumns().addObjectName(this.exceptColumnList.getObjectName(i));
503//                    this.exceptColumnList.getObjectName(i).setSourceTable(table);
504//                }
505//            }
506//        }
507
508        if (expr.getExceptReplaceClause() != null){
509            // SELECT COMMON.* EXCEPT (column1, column2) FROM dataset1.table1 COMMON;
510            this.exceptColumnList = expr.getExceptReplaceClause().getColumnList();
511
512            // select * replace(expr as identifier)
513            this.replaceExprAsIdentifiers = expr.getExceptReplaceClause().getExprAsIdentifiers();
514
515            TTable table = psql.tables.getTable(0);
516            if (table != null){
517                if (this.exceptColumnList != null){
518                    for(int i=0;i<this.exceptColumnList.size();i++){
519                        table.getLinkedColumns().addObjectName(this.exceptColumnList.getObjectName(i));
520                        this.exceptColumnList.getObjectName(i).setSourceTable(table);
521                    }
522                }
523
524                if (replaceExprAsIdentifiers != null){
525                    for(int i=0;i<replaceExprAsIdentifiers.size();i++){
526                        TReplaceExprAsIdentifier replaceExprAsIdentifier = replaceExprAsIdentifiers.get(i);
527                        table.getLinkedColumns().addObjectName(replaceExprAsIdentifier.getIdentifier());
528                        replaceExprAsIdentifier.getIdentifier().setSourceTable(table);
529                    }
530                }
531            }
532
533        }
534    }
535
536
537    /**
538     *
539     * @return this is used to provide back compatibility of .NET version only. 
540     */
541    public TObjectName getFieldAttr() {
542        TObjectName ret = null;
543        if (expr.getExpressionType() == EExpressionType.simple_object_name_t){
544            ret = expr.getObjectOperand();
545        }
546        return ret;
547    }
548
549    public String getPrefixTable(){
550        if (getFieldAttr() == null) return "";
551        return getFieldAttr().getTableString();
552    }
553
554    public String getPrefixSchema(){
555        if (getFieldAttr() == null) return "";
556        return getFieldAttr().getSchemaString();
557    }
558
559    public String getPrefixDatabase(){
560        if (getFieldAttr() == null) return "";
561        return getFieldAttr().getDatabaseString();
562    }
563
564    public String getPrefixServer(){
565        if (getFieldAttr() == null) return "";
566        return getFieldAttr().getServerString();
567    }
568
569    public void accept(TParseTreeVisitor v){
570        v.preVisit(this);
571        v.postVisit(this);
572    }
573
574    public void acceptChildren(TParseTreeVisitor v){
575        v.preVisit(this);
576
577        if (!placeHolder)  getExpr().acceptChildren(v);
578        if (getAliasClause() != null){
579            getAliasClause().acceptChildren(v);
580        }
581
582        v.postVisit(this);
583    }
584
585    public void setTargetColumns(TObjectNameList targetColumns) {
586        this.targetColumns = targetColumns;
587    }
588
589    private TUpdateFor updateFor; //couchbase
590
591    public void setUpdateFor(TUpdateFor updateFor) {
592        this.updateFor = updateFor;
593    }
594
595    public TUpdateFor getUpdateFor() {
596
597        return updateFor;
598    }
599
600    /**
601     * Oracle 26c: OLD/NEW qualifier for RETURNING clause expressions.
602     * Indicates whether this result column in a RETURNING clause uses
603     * the OLD or NEW qualifier to capture pre-update or post-update values.
604     */
605    private EOldNewQualifier oldNewQualifier = EOldNewQualifier.none;
606
607    /**
608     * Sets the OLD/NEW qualifier for this RETURNING clause expression.
609     * @param oldNewQualifier the qualifier (OLD, NEW, or none)
610     */
611    public void setOldNewQualifier(EOldNewQualifier oldNewQualifier) {
612        this.oldNewQualifier = oldNewQualifier;
613    }
614
615    /**
616     * Gets the OLD/NEW qualifier for this RETURNING clause expression.
617     * @return the qualifier (OLD, NEW, or none for unqualified expressions)
618     */
619    public EOldNewQualifier getOldNewQualifier() {
620        return oldNewQualifier;
621    }
622
623    public int compareTo(Object o){
624        TResultColumn rc = (TResultColumn)o;
625        //getDisplayName() can be null for a malformed column whose nodes carry
626        //no boundary tokens (mantis 4680); order a name-less column first
627        //instead of throwing.
628        String thisKey = IdentifierService.normalizeStatic(this.dbvendor,dotColumn, this.getDisplayName());
629        String thatKey = IdentifierService.normalizeStatic(this.dbvendor,dotColumn,rc.getDisplayName());
630        if (thisKey == null) thisKey = "";
631        if (thatKey == null) thatKey = "";
632        return  thisKey.compareTo(thatKey);
633    }
634
635//    private int pos = -1;
636//
637//    public void setPos(int pos) {
638//        this.pos = pos;
639//    }
640//
641//    public int getPos() {
642//        return pos;
643//    }
644}