001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.nodes.*;
005import gudusoft.gsqlparser.nodes.mssql.TOptionClause;
006import gudusoft.gsqlparser.nodes.oracle.TErrorLoggingClause;
007
008/**
009 * Merge SQL statement.
010 * <br>
011 * <br>{@link #getTargetTable()} returns the target table.
012 * <br>{@link #getUsingTable()} returns the source table in the using clause.
013 * <br>{@link #getCondition()} returns the merge search condition.
014 * <br>{@link #getWhenClauses()} returns when MATCHED/NOT MATCHED clauses.
015 *
016 * <pre>
017 *     merge into target_table [column_list]
018 *     using source_table|subquery
019 *     on merge_search_condition
020 *     [when matched [and search_conditions ] then update set {col_name = expression} | delete]
021 *     [when not matched [and search_conditions ] then insert [(column_list)] values (value_list)]
022 *  </pre>
023 *
024 *  <p> call {@link #getTargetTable()} to return a value for target_table.
025 *  <p> column_list can be fetched from {@link #getColumnList()} if any.
026 *  <p> source_table in using clause can be fetched via {@link #getUsingTable()},
027 *  subquery treated as a table as well.
028 *  <p>  call {@link #getCondition()} to return merge_search_condition.
029 *  <p> when [not] matched clause is available by calling {@link #getWhenClauses()}
030 *  which is a list of type {@link TMergeWhenClause}.
031 *
032 * @see TMergeWhenClause
033 * @see TMergeUpdateClause
034 * @see TMergeDeleteClause
035 * @see TMergeInsertClause
036 */
037public class TMergeSqlStatement extends TCustomSqlStatement {
038
039    private TErrorLoggingClause errorLoggingClause;
040
041    /**
042     * Oracle error logging clause.
043     * @return Oracle error logging clause.
044     */
045    public TErrorLoggingClause getErrorLoggingClause() {
046        return errorLoggingClause;
047    }
048
049    private TOptionClause optionClause;
050
051    /**
052     * sql server option clause
053     * @return option clause
054     *
055     * @see gudusoft.gsqlparser.nodes.mssql.TOptionClause
056     */
057    public TOptionClause getOptionClause() {
058        return optionClause;
059    }
060
061    public TMergeSqlStatement(EDbVendor dbvendor) {
062        super(dbvendor);
063        sqlstatementtype = ESqlStatementType.sstmerge;
064    }
065
066    void buildsql() {
067    }
068
069    void clear() {
070    }
071
072    String getasprettytext() {
073        return "";
074    }
075
076    void iterate(TVisitorAbs pvisitor) {
077    }
078
079    private TExpression matchedSearchCondition = null;
080    private TExpression notMatchedSearchCondition = null;
081    private TObjectNameList columnList = null;
082
083    /**
084     * Columns in target table.
085     * @return Columns in target table.
086     */
087    public TObjectNameList getColumnList() {
088        return columnList;
089    }
090
091    /**
092     * This method is not used, use {@link #getCondition()} instead.
093     * @return not used
094     */
095    public TExpression getMatchedSearchCondition() {
096        return matchedSearchCondition;
097    }
098
099    /**
100     * This method is not used, use {@link #getCondition()} instead.
101     * @return not used
102     */
103    public TExpression getNotMatchedSearchCondition() {
104        return notMatchedSearchCondition;
105    }
106
107    private TTable usingTable;
108
109    /**
110     * Source table in the using clause.
111     * @return Source table in the using clause.
112     */
113    public TTable getUsingTable() {
114        return usingTable;
115    }
116
117    private TExpression condition;
118
119    /**
120     * merge search condition.
121     * @return merge search condition.
122     */
123    public TExpression getCondition() {
124        return condition;
125    }
126
127
128    private TMergeUpdateClause updateClause;
129    private TMergeInsertClause insertClause;
130
131    /**
132     * This method is not used, use {@link #getWhenClauses()} instead.
133     * @return
134     */
135    public TMergeUpdateClause getUpdateClause() {
136        return updateClause;
137    }
138
139    /**
140     * This method is not used, use {@link #getWhenClauses()} instead.
141     * @return
142     */
143    public TMergeInsertClause getInsertClause() {
144        return insertClause;
145    }
146
147    private TPTNodeList <TMergeWhenClause> whenClauses;
148
149    /**
150     * when matched/not matched clauses.
151     * @return when matched/not matched clauses.
152     */
153    public TPTNodeList<TMergeWhenClause> getWhenClauses() {
154        return whenClauses;
155    }
156
157    public int doParseStatement(TCustomSqlStatement psql) {
158        if (rootNode == null) return -1;
159        TMergeSqlNode mergeSqlNode = (TMergeSqlNode)rootNode;
160        super.doParseStatement(psql);
161
162        if (mergeSqlNode.cteList != null){
163            this.setCteList( mergeSqlNode.cteList);
164            this.getCteList().doParse(this, ESqlClause.cte);
165        }
166
167        TTable lcTable;
168        lcTable = analyzeFromTable(mergeSqlNode.getTargetTable(),true);
169        lcTable.setEffectType(ETableEffectType.tetMerge);
170        setTargetTable(lcTable);
171        this.getRelations().add(lcTable);
172
173        //tables.addTable(this.getTargetTable());
174//        TFromTable lcFromTable = mergeSqlNode.getUsingTable();
175//        TJoin lcJoin;
176//        if (lcFromTable.getFromtableType() != ETableSource.join){
177//            lcJoin = new TJoin();
178//            lcTable = analyzeFromTable(lcFromTable,true);
179//            lcTable.setEffectType(ETableEffectType.tetSelect);
180//            lcJoin.setTable(lcTable);
181//            lcJoin.setStartToken(lcJoin.getTable().getStartToken());
182//            lcJoin.setEndToken(lcJoin.getTable().getEndToken());
183//            lcJoin.setGsqlparser(getGsqlparser());
184//            this.fromSourceTable = lcTable;
185//            this.getRelations().add(lcTable);
186//        }else{
187//            this.fromSourceJoin = lcFromTable.getJoinExpr();
188//
189//            this.fromSourceTable = new TTable();
190//            this.fromSourceTable.setTableType(ETableSource.join);
191//            this.fromSourceTable.setAliasClause(lcFromTable.getJoinExpr().getAliasClause());
192//            this.fromSourceTable.setStartToken(lcFromTable.getStartToken());
193//            this.fromSourceTable.setEndToken(lcFromTable.getEndToken());
194//            this.fromSourceTable.setGsqlparser(lcFromTable.getGsqlparser());
195//            this.fromSourceTable.setJoinExpr(this.fromSourceJoin);
196//            this.getRelations().add(this.fromSourceTable);
197//
198//            lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true);
199//            lcJoin.doParse(this, ESqlClause.join);
200//
201//            if (lcFromTable.getLateralViewList() != null){
202//                for(TLateralView lateralView:lcFromTable.getLateralViewList()){
203//                    addToTables(lateralView.createATable(this));
204//                }
205//            }
206//        }
207
208        analyzeTableOrJoin(mergeSqlNode.getUsingTable());
209        this.usingTable = this.fromSourceTable;//analyzeFromTable(mergeSqlNode.getUsingTable(),true);
210        //usingTable.setEffectType(ETableEffectType.tetSelect);
211        this.getRelations().add(usingTable);
212
213        //tables.addTable(this.usingTable);
214
215        this.condition = mergeSqlNode.getCondition();
216        if (this.condition != null) {
217            this.condition.doParse(this, ESqlClause.joinCondition);
218        }
219
220        if (mergeSqlNode.getColumnList() != null){
221            this.columnList = mergeSqlNode.getColumnList();
222            TObjectName crf ;
223            for (int i=0;i< mergeSqlNode.getColumnList().size();i++){
224                crf =mergeSqlNode.getColumnList().getObjectName(i);
225                // link this column to last 2 tables
226                crf.setLocation(ESqlClause.mergeInsert);
227                getTargetTable().getObjectNameReferences().addObjectName(crf);
228                getTargetTable().getLinkedColumns().addObjectName(crf);
229                crf.setSourceTable(getTargetTable());
230                crf.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
231            }
232
233            //insertNode.getColumnList().doParse(this,TBaseType.insertColumnClause);
234        }
235
236        this.whenClauses = mergeSqlNode.getWhenClauses();
237        if (this.whenClauses != null){
238            this.whenClauses.doParse(this,ESqlClause.unknown);
239        }
240
241        limitClause = mergeSqlNode.getLimitClause();
242        if (limitClause != null){
243            limitClause.doParse(this,ESqlClause.unknown);
244        }
245        returningClause = mergeSqlNode.getReturningClause();
246        if (returningClause != null){
247            returningClause.doParse(this,ESqlClause.unknown);
248        }
249
250        if (mergeSqlNode.getOutputClause() != null){
251            mergeSqlNode.getOutputClause().doParse(this,ESqlClause.output);
252            this.setOutputClause(mergeSqlNode.getOutputClause());
253        }
254
255        this.optionClause = mergeSqlNode.getOptionClause();
256
257        errorLoggingClause = mergeSqlNode.getErrorLoggingClause();
258       // tables.addTable(this.getTargetTable());
259
260        return 0;
261    }
262
263    public void accept(TParseTreeVisitor v){
264        v.preVisit(this);
265        v.postVisit(this);
266    }
267
268    public void acceptChildren(TParseTreeVisitor v){
269        v.preVisit(this);
270        this.getTargetTable().acceptChildren(v);
271        usingTable.acceptChildren(v);
272        condition.acceptChildren(v);
273        if (columnList != null) columnList.acceptChildren(v);
274        if (whenClauses != null) whenClauses.acceptChildren(v);
275        if (getOutputClause() != null) getOutputClause().acceptChildren(v);
276        if (errorLoggingClause != null) errorLoggingClause.acceptChildren(v);
277        v.postVisit(this);
278    }
279
280    public void setErrorLoggingClause(TErrorLoggingClause errorLoggingClause) {
281        this.errorLoggingClause = errorLoggingClause;
282    }
283
284    public void setOptionClause(TOptionClause optionClause) {
285        this.optionClause = optionClause;
286    }
287
288    public void setMatchedSearchCondition(TExpression matchedSearchCondition) {
289        this.matchedSearchCondition = matchedSearchCondition;
290    }
291
292    public void setNotMatchedSearchCondition(TExpression notMatchedSearchCondition) {
293        this.notMatchedSearchCondition = notMatchedSearchCondition;
294    }
295
296    public void setColumnList(TObjectNameList columnList) {
297        this.columnList = columnList;
298    }
299
300    public void setUsingTable(TTable usingTable) {
301        this.usingTable = usingTable;
302    }
303
304    public void setCondition(TExpression condition) {
305        this.condition = condition;
306    }
307
308    public void setUpdateClause(TMergeUpdateClause updateClause) {
309        this.updateClause = updateClause;
310    }
311
312    public void setInsertClause(TMergeInsertClause insertClause) {
313        this.insertClause = insertClause;
314    }
315
316    public void setWhenClauses(TPTNodeList<TMergeWhenClause> whenClauses) {
317        this.whenClauses = whenClauses;
318    }
319
320    private TLimitClause limitClause;
321
322    public void setLimitClause(TLimitClause limitClause) {
323        this.limitClause = limitClause;
324    }
325
326    /**
327     * Couchbase, limit clause.
328     * @return Couchbase, limit clause.
329     */
330    public TLimitClause getLimitClause() {
331
332        return limitClause;
333    }
334
335    private TReturningClause returningClause;
336
337    public void setReturningClause(TReturningClause returningClause) {
338        this.returningClause = returningClause;
339    }
340
341    /**
342     * Couchbase, returning clause.
343     * @return Couchbase, returning clause.
344     */
345    public TReturningClause getReturningClause() {
346
347        return returningClause;
348    }
349}