001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.nodes.couchbase.TObjectConstruct;
005import gudusoft.gsqlparser.nodes.couchbase.TPair;
006import gudusoft.gsqlparser.stmt.TMergeSqlStatement;
007
008
009/**
010 * insert clause in merge statement.
011 * <pre>
012 *     [when not matched [and search_conditions ] then insert [(column_list)] values (value_list)]
013 * </pre>
014 *
015 * <p> call {@link #getColumnList()} to return value for (column_list)
016 * <p> call {@link #getValuelist()} to return value for  (value_list)
017 *
018 * @see TMergeWhenClause
019 */
020
021public class TMergeInsertClause extends  TMergeActionClause {
022    private TExpression insertWhereClause;
023    private TObjectNameList columnList = null;
024    private TResultColumnList   valuelist;
025    private TObjectName rowTypeValue;
026
027    /**
028     * plsql row type record
029     */
030    public TObjectName getRowTypeValue() {
031        return rowTypeValue;
032    }
033
034    public TObjectNameList getColumnList() {
035        return columnList;
036
037    }
038
039    public TExpression getInsertWhereClause() {
040        return insertWhereClause;
041    }
042
043    public TResultColumnList getValuelist() {
044        return valuelist;
045    }
046
047    public void init(Object arg1) {
048        this.mergeActionType = EMergeActionType.insert;
049        insertValue = (TExpression)arg1;
050    }
051
052    public void init(Object arg1,Object arg2){
053        init(arg1);
054        insertWhereClause = (TExpression)arg2;
055    }
056
057    public void init(Object arg1,Object arg2,Object arg3){
058        // Teradata BNF rule in order to avoid conflicts, the column list is replaced by target list, we need to change it back to column list
059        if (arg1 != null){
060            if (arg1 instanceof TResultColumnList){
061                this.columnList = new TObjectNameList();
062                for(int i=0;i<((TResultColumnList)arg1).size();i++){
063                    TResultColumn rc = ((TResultColumnList)arg1).getResultColumn(i);
064                    this.columnList.addObjectName(rc.getExpr().getObjectOperand());
065                }
066            }else{
067                this.columnList = (TObjectNameList)arg1;
068            }
069        }
070
071
072        if (arg2 instanceof TResultColumnList){
073            this.valuelist = (TResultColumnList)arg2;
074            for(int i=0;i<valuelist.size();i++){
075                TResultColumn resultColumn = valuelist.getResultColumn(i);
076                if (resultColumn.getExpr() != null){
077                    TExpression expression = resultColumn.getExpr();
078                    if ((expression.getExpressionType() == EExpressionType.simple_comparison_t)&&(expression.getComparisonOperator().tokencode == '=')){
079                        expression.setExpressionType(EExpressionType.assignment_t);
080                    }
081                }
082            }
083        }
084        else if (arg2 instanceof TObjectName)
085            rowTypeValue = (TObjectName)arg2;
086        else if (arg2 instanceof TObjectNameList) {
087            // change to resultcolumnlist
088            valuelist = new TResultColumnList();
089            TObjectNameList onList = (TObjectNameList)arg2;
090            for(int i=0;i<onList.size();i++){
091                TResultColumn rc = new TResultColumn();
092                TExpression retval = new TExpression();
093                retval.init(EExpressionType.simple_object_name_t);
094                TObjectName objectName = onList.getObjectName(i);
095                objectName.setObjectType(TObjectName.ttobjColumn);
096                retval.setObjectOperand(objectName);
097                retval.setStartToken(objectName);
098                retval.setEndToken(objectName);
099                rc.init(retval);
100                valuelist.addResultColumn(rc);
101            }
102        }
103
104        if (arg3 != null){
105            this.insertWhereClause = (TExpression)arg3;
106        }
107    }
108
109    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
110
111        if (this.columnList != null){
112
113            TObjectName crf ;
114            for (int i=0;i< this.columnList.size();i++){
115                crf =this.columnList.getObjectName(i);
116                // link this column to the first tables
117                crf.setLocation(ESqlClause.insertColumn);
118                psql.getTargetTable().getObjectNameReferences().addObjectName(crf);
119                psql.getTargetTable().getLinkedColumns().addObjectName(crf);
120                crf.setSourceTable(psql.getTargetTable());
121                crf.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
122            }
123        }
124
125        if (this.valuelist != null){
126            for(int i=0;i<valuelist.size();i++){
127                TResultColumn resultColumn = valuelist.getResultColumn(i);
128                if (resultColumn.getExpr() != null){
129                    TExpression expression = resultColumn.getExpr();
130                    if (expression.getObjectOperand() != null){
131                        expression.getObjectOperand().setResolveStatus(TBaseType.RESOLVE_DELAY_TO_COLUMN_RESOLVER);
132                        // INSERT (id, name, joining_date) VALUES (id, TRIM(name), joining_date);
133                        // 上面 values clause 中的 column 关联到 using table 的逻辑放到  TAttributeResolver 中去实现
134                        // 除了关联 column 外,还可以实现 column push down 到 * column 及对应的 table
135                        // 增加了下面两个方法
136                        // public void preVisit(TMergeInsertClause node)
137                        // public void postVisit(TMergeInsertClause node)
138
139//                        TMergeSqlStatement mergeSqlStatement = (TMergeSqlStatement)psql;
140//                        mergeSqlStatement.getUsingTable().getLinkedColumns().addObjectName(expression.getObjectOperand());
141//                        expression.getObjectOperand().setSourceTable(mergeSqlStatement.getUsingTable());
142//                        expression.getObjectOperand().setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
143                    }
144                }
145            }
146            this.valuelist.doParse(psql,ESqlClause.insertValues);
147        }
148
149        if (this.insertValue != null){
150            if (this.insertValue.getExpressionType() == EExpressionType.objectConstruct_t){
151                // couchbase { "name": b.name, "title": b.title, "depts": b.depts, "empId": b.empId, "dob": b.dob }
152                TObjectConstruct objectConstruct = this.insertValue.getObjectConstruct();
153                TMergeSqlStatement mergeSqlStatement = (TMergeSqlStatement)psql;
154                for(int i=0;i<objectConstruct.getPairs().size();i++){
155                    TPair pair = objectConstruct.getPairs().getElement(i);
156                    if (pair.getKeyName() != null){
157                        if (pair.getKeyName().getExpressionType() == EExpressionType.simple_constant_t){
158                            TObjectName columnName = new TObjectName();
159                            TSourceToken newSt = new TSourceToken(pair.getKeyName().getConstantOperand().getValueToken().getTextWithoutQuoted());
160                            columnName.setPartToken(newSt);
161                            mergeSqlStatement.getTargetTable().getLinkedColumns().addObjectName(columnName);
162                            columnName.setSourceTable(mergeSqlStatement.getTargetTable());
163                            columnName.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
164                        }
165                    }
166                    pair.getKeyValue().doParse(psql,plocation);
167                }
168            }
169        }
170
171        if (this.insertWhereClause != null){
172            this.insertWhereClause.doParse(psql,ESqlClause.where);
173        }
174
175    }
176
177    public void accept(TParseTreeVisitor v){
178        v.preVisit(this);
179        v.postVisit(this);
180    }
181
182    public void acceptChildren(TParseTreeVisitor v){
183        v.preVisit(this);
184        if (this.columnList != null){
185            columnList.acceptChildren(v);
186        }
187
188        if (this.valuelist != null){
189            this.valuelist.acceptChildren(v);
190        }
191
192        if (this.insertWhereClause != null){
193            this.insertWhereClause.acceptChildren(v);
194        }
195        v.postVisit(this);
196    }
197
198    public void setInsertWhereClause(TExpression insertWhereClause) {
199        this.insertWhereClause = insertWhereClause;
200    }
201
202    public void setColumnList(TObjectNameList columnList) {
203        this.columnList = columnList;
204    }
205
206    public void setValuelist(TResultColumnList valuelist) {
207        this.valuelist = valuelist;
208    }
209
210    public void setRowTypeValue(TObjectName rowTypeValue) {
211        this.rowTypeValue = rowTypeValue;
212    }
213
214    private TExpression insertValue; //couchbase
215
216    public TExpression getInsertValue() {
217        return insertValue;
218    }
219}