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 unbindCteTarget(lcTable); 171 setTargetTable(lcTable); 172 this.getRelations().add(lcTable); 173 174 //tables.addTable(this.getTargetTable()); 175// TFromTable lcFromTable = mergeSqlNode.getUsingTable(); 176// TJoin lcJoin; 177// if (lcFromTable.getFromtableType() != ETableSource.join){ 178// lcJoin = new TJoin(); 179// lcTable = analyzeFromTable(lcFromTable,true); 180// lcTable.setEffectType(ETableEffectType.tetSelect); 181// lcJoin.setTable(lcTable); 182// lcJoin.setStartToken(lcJoin.getTable().getStartToken()); 183// lcJoin.setEndToken(lcJoin.getTable().getEndToken()); 184// lcJoin.setGsqlparser(getGsqlparser()); 185// this.fromSourceTable = lcTable; 186// this.getRelations().add(lcTable); 187// }else{ 188// this.fromSourceJoin = lcFromTable.getJoinExpr(); 189// 190// this.fromSourceTable = new TTable(); 191// this.fromSourceTable.setTableType(ETableSource.join); 192// this.fromSourceTable.setAliasClause(lcFromTable.getJoinExpr().getAliasClause()); 193// this.fromSourceTable.setStartToken(lcFromTable.getStartToken()); 194// this.fromSourceTable.setEndToken(lcFromTable.getEndToken()); 195// this.fromSourceTable.setGsqlparser(lcFromTable.getGsqlparser()); 196// this.fromSourceTable.setJoinExpr(this.fromSourceJoin); 197// this.getRelations().add(this.fromSourceTable); 198// 199// lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true); 200// lcJoin.doParse(this, ESqlClause.join); 201// 202// if (lcFromTable.getLateralViewList() != null){ 203// for(TLateralView lateralView:lcFromTable.getLateralViewList()){ 204// addToTables(lateralView.createATable(this)); 205// } 206// } 207// } 208 209 analyzeTableOrJoin(mergeSqlNode.getUsingTable()); 210 this.usingTable = this.fromSourceTable;//analyzeFromTable(mergeSqlNode.getUsingTable(),true); 211 //usingTable.setEffectType(ETableEffectType.tetSelect); 212 this.getRelations().add(usingTable); 213 214 //tables.addTable(this.usingTable); 215 216 this.condition = mergeSqlNode.getCondition(); 217 if (this.condition != null) { 218 this.condition.doParse(this, ESqlClause.joinCondition); 219 } 220 221 if (mergeSqlNode.getColumnList() != null){ 222 this.columnList = mergeSqlNode.getColumnList(); 223 TObjectName crf ; 224 for (int i=0;i< mergeSqlNode.getColumnList().size();i++){ 225 crf =mergeSqlNode.getColumnList().getObjectName(i); 226 // link this column to last 2 tables 227 crf.setLocation(ESqlClause.mergeInsert); 228 crf.columnToPropertyIfQualifiedByTable(getTargetTable()); // Mantis #4747 229 getTargetTable().getObjectNameReferences().addObjectName(crf); 230 getTargetTable().getLinkedColumns().addObjectName(crf); 231 crf.setSourceTable(getTargetTable()); 232 crf.setValidate_column_status(TBaseType.COLUMN_LINKED_TO_TABLE_IN_OLD_ALGORITHM); 233 } 234 235 //insertNode.getColumnList().doParse(this,TBaseType.insertColumnClause); 236 } 237 238 this.whenClauses = mergeSqlNode.getWhenClauses(); 239 if (this.whenClauses != null){ 240 this.whenClauses.doParse(this,ESqlClause.unknown); 241 } 242 243 limitClause = mergeSqlNode.getLimitClause(); 244 if (limitClause != null){ 245 limitClause.doParse(this,ESqlClause.unknown); 246 } 247 returningClause = mergeSqlNode.getReturningClause(); 248 if (returningClause != null){ 249 returningClause.doParse(this,ESqlClause.unknown); 250 } 251 252 if (mergeSqlNode.getOutputClause() != null){ 253 mergeSqlNode.getOutputClause().doParse(this,ESqlClause.output); 254 this.setOutputClause(mergeSqlNode.getOutputClause()); 255 } 256 257 this.optionClause = mergeSqlNode.getOptionClause(); 258 259 errorLoggingClause = mergeSqlNode.getErrorLoggingClause(); 260 // tables.addTable(this.getTargetTable()); 261 262 return 0; 263 } 264 265 public void accept(TParseTreeVisitor v){ 266 v.preVisit(this); 267 v.postVisit(this); 268 } 269 270 public void acceptChildren(TParseTreeVisitor v){ 271 v.preVisit(this); 272 // Walk the WITH clause first so TSQLResolver2's ScopeBuilder can 273 // build CTEScope before the USING / WHEN clauses are visited. 274 // Mirrors TSelectSqlStatement.acceptChildren ordering. 275 if (getCteList() != null) getCteList().acceptChildren(v); 276 if (getTargetTable() != null) getTargetTable().acceptChildren(v); 277 if (usingTable != null) usingTable.acceptChildren(v); 278 if (condition != null) condition.acceptChildren(v); 279 if (columnList != null) columnList.acceptChildren(v); 280 if (whenClauses != null) whenClauses.acceptChildren(v); 281 if (getOutputClause() != null) getOutputClause().acceptChildren(v); 282 if (errorLoggingClause != null) errorLoggingClause.acceptChildren(v); 283 v.postVisit(this); 284 } 285 286 public void setErrorLoggingClause(TErrorLoggingClause errorLoggingClause) { 287 this.errorLoggingClause = errorLoggingClause; 288 } 289 290 public void setOptionClause(TOptionClause optionClause) { 291 this.optionClause = optionClause; 292 } 293 294 public void setMatchedSearchCondition(TExpression matchedSearchCondition) { 295 this.matchedSearchCondition = matchedSearchCondition; 296 } 297 298 public void setNotMatchedSearchCondition(TExpression notMatchedSearchCondition) { 299 this.notMatchedSearchCondition = notMatchedSearchCondition; 300 } 301 302 public void setColumnList(TObjectNameList columnList) { 303 this.columnList = columnList; 304 } 305 306 public void setUsingTable(TTable usingTable) { 307 this.usingTable = usingTable; 308 } 309 310 public void setCondition(TExpression condition) { 311 this.condition = condition; 312 } 313 314 public void setUpdateClause(TMergeUpdateClause updateClause) { 315 this.updateClause = updateClause; 316 } 317 318 public void setInsertClause(TMergeInsertClause insertClause) { 319 this.insertClause = insertClause; 320 } 321 322 public void setWhenClauses(TPTNodeList<TMergeWhenClause> whenClauses) { 323 this.whenClauses = whenClauses; 324 } 325 326 private TLimitClause limitClause; 327 328 public void setLimitClause(TLimitClause limitClause) { 329 this.limitClause = limitClause; 330 } 331 332 /** 333 * Couchbase, limit clause. 334 * @return Couchbase, limit clause. 335 */ 336 public TLimitClause getLimitClause() { 337 338 return limitClause; 339 } 340 341 private TReturningClause returningClause; 342 343 public void setReturningClause(TReturningClause returningClause) { 344 this.returningClause = returningClause; 345 } 346 347 /** 348 * Couchbase, returning clause. 349 * @return Couchbase, returning clause. 350 */ 351 public TReturningClause getReturningClause() { 352 353 return returningClause; 354 } 355}