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        this.condition.doParse(this, ESqlClause.joinCondition);
217
218        if (mergeSqlNode.getColumnList() != null){
219            this.columnList = mergeSqlNode.getColumnList();
220            TObjectName crf ;
221            for (int i=0;i< mergeSqlNode.getColumnList().size();i++){
222                crf =mergeSqlNode.getColumnList().getObjectName(i);
223                // link this column to last 2 tables
224                crf.setLocation(ESqlClause.mergeInsert);
225                getTargetTable().getObjectNameReferences().addObjectName(crf);
226                getTargetTable().getLinkedColumns().addObjectName(crf);
227                crf.setSourceTable(getTargetTable());
228                crf.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM);
229            }
230
231            //insertNode.getColumnList().doParse(this,TBaseType.insertColumnClause);
232        }
233
234        this.whenClauses = mergeSqlNode.getWhenClauses();
235        if (this.whenClauses != null){
236            this.whenClauses.doParse(this,ESqlClause.unknown);
237        }
238
239        limitClause = mergeSqlNode.getLimitClause();
240        if (limitClause != null){
241            limitClause.doParse(this,ESqlClause.unknown);
242        }
243        returningClause = mergeSqlNode.getReturningClause();
244        if (returningClause != null){
245            returningClause.doParse(this,ESqlClause.unknown);
246        }
247
248        if (mergeSqlNode.getOutputClause() != null){
249            mergeSqlNode.getOutputClause().doParse(this,ESqlClause.output);
250            this.setOutputClause(mergeSqlNode.getOutputClause());
251        }
252
253        this.optionClause = mergeSqlNode.getOptionClause();
254
255        errorLoggingClause = mergeSqlNode.getErrorLoggingClause();
256       // tables.addTable(this.getTargetTable());
257
258        return 0;
259    }
260
261    public void accept(TParseTreeVisitor v){
262        v.preVisit(this);
263        v.postVisit(this);
264    }
265
266    public void acceptChildren(TParseTreeVisitor v){
267        v.preVisit(this);
268        this.getTargetTable().acceptChildren(v);
269        usingTable.acceptChildren(v);
270        condition.acceptChildren(v);
271        if (columnList != null) columnList.acceptChildren(v);
272        if (whenClauses != null) whenClauses.acceptChildren(v);
273        if (getOutputClause() != null) getOutputClause().acceptChildren(v);
274        if (errorLoggingClause != null) errorLoggingClause.acceptChildren(v);
275        v.postVisit(this);
276    }
277
278    public void setErrorLoggingClause(TErrorLoggingClause errorLoggingClause) {
279        this.errorLoggingClause = errorLoggingClause;
280    }
281
282    public void setOptionClause(TOptionClause optionClause) {
283        this.optionClause = optionClause;
284    }
285
286    public void setMatchedSearchCondition(TExpression matchedSearchCondition) {
287        this.matchedSearchCondition = matchedSearchCondition;
288    }
289
290    public void setNotMatchedSearchCondition(TExpression notMatchedSearchCondition) {
291        this.notMatchedSearchCondition = notMatchedSearchCondition;
292    }
293
294    public void setColumnList(TObjectNameList columnList) {
295        this.columnList = columnList;
296    }
297
298    public void setUsingTable(TTable usingTable) {
299        this.usingTable = usingTable;
300    }
301
302    public void setCondition(TExpression condition) {
303        this.condition = condition;
304    }
305
306    public void setUpdateClause(TMergeUpdateClause updateClause) {
307        this.updateClause = updateClause;
308    }
309
310    public void setInsertClause(TMergeInsertClause insertClause) {
311        this.insertClause = insertClause;
312    }
313
314    public void setWhenClauses(TPTNodeList<TMergeWhenClause> whenClauses) {
315        this.whenClauses = whenClauses;
316    }
317
318    private TLimitClause limitClause;
319
320    public void setLimitClause(TLimitClause limitClause) {
321        this.limitClause = limitClause;
322    }
323
324    /**
325     * Couchbase, limit clause.
326     * @return Couchbase, limit clause.
327     */
328    public TLimitClause getLimitClause() {
329
330        return limitClause;
331    }
332
333    private TReturningClause returningClause;
334
335    public void setReturningClause(TReturningClause returningClause) {
336        this.returningClause = returningClause;
337    }
338
339    /**
340     * Couchbase, returning clause.
341     * @return Couchbase, returning clause.
342     */
343    public TReturningClause getReturningClause() {
344
345        return returningClause;
346    }
347}