001package gudusoft.gsqlparser.stmt; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.nodes.*; 005import gudusoft.gsqlparser.nodes.couchbase.TUseKeyIndex; 006import gudusoft.gsqlparser.nodes.mssql.TOptionClause; 007import gudusoft.gsqlparser.nodes.oracle.TErrorLoggingClause; 008 009import java.util.ArrayList; 010 011/** 012 * SQL update statement. 013 * <br> 014 * <br> {@link #getTargetTable} returns the target table, this table can also be fetched from the first element of {@link #tables}. 015 * <br> If there is a from clause in update statement, {@link #joins} returns all the tables in the from clause. 016 * <br> {@link #getResultColumnList()} returns assignment in set clause. 017 * 018 *<pre> 019 * UPDATE dbo.Table2 020 * SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB 021 * FROM dbo.Table2 022 * INNER JOIN dbo.Table1 023 * ON (dbo.Table2.ColA = dbo.Table1.ColA); 024 *</pre> 025 * Table: dbo.Table2 can be fetched from {@link #getTargetTable} or {@link #tables} 026 * <br>set clause: dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB, {@link #getResultColumnList} 027 * <br>from clause: dbo.Table2 inner join , {@link #joins} 028 * 029 * 030 * @see TCustomSqlStatement#cteList 031 * @see TCustomSqlStatement#topClause 032 * @see TCustomSqlStatement#targetTable 033 * @see TCustomSqlStatement#outputClause 034 * @see TCustomSqlStatement#joins 035 * @see TCustomSqlStatement#resultColumnList 036 * @see TCustomSqlStatement#whereClause 037 * @see TCustomSqlStatement#returningClause 038 */ 039 040public class TUpdateSqlStatement extends TCustomSqlStatement { 041 042 043 private TInsertSqlStatement insertSqlStatement = null; 044 045 /** 046 * Teradata, insert statement used after ELSE keyword 047 * @return insert statement used after ELSE keyword 048 */ 049 public TInsertSqlStatement getInsertSqlStatement() { 050 return insertSqlStatement; 051 } 052 053 private TErrorLoggingClause errorLoggingClause; 054 055 /** 056 * Oracle, error logging clause 057 * @return Oracle, error logging clause 058 */ 059 public TErrorLoggingClause getErrorLoggingClause() { 060 return errorLoggingClause; 061 } 062 063 private TOptionClause optionClause; 064 065 /** 066 * sql server option clause 067 * @return option clause 068 * 069 * @see gudusoft.gsqlparser.nodes.mssql.TOptionClause 070 */ 071 public TOptionClause getOptionClause() { 072 return optionClause; 073 } 074 075 private TSourceToken updateToken = null; 076 077 public void setUpdateToken(TSourceToken updateToken) { 078 this.updateToken = updateToken; 079 } 080 081 /** 082 * UPDATE keyword 083 * 084 * @return UPDATE keyword in update statement. 085 */ 086 public TSourceToken getUpdateToken() { 087 088 return updateToken; 089 } 090 091 private TJoinList referenceJoins = null; 092 093 /** 094 * @deprecated As of v1.9.7.2, use {@link #joins} instead. 095 * <br> 096 * <p> getReferenceJoins() represents: table_references 097 * @return table references in from clause 098 */ 099 public TJoinList getReferenceJoins() { 100 if (this.referenceJoins == null){ 101 this.referenceJoins = new TJoinList(); 102 } 103 return referenceJoins; 104 } 105 106 private TOrderBy orderByClause = null; 107 108 /** 109 * Couchbase, MySQL limit clause. 110 * @return Couchbase, MySQL limit clause. 111 */ 112 public TLimitClause getLimitClause() { 113 return limitClause; 114 } 115 116 /** 117 * Order by clause is not used. 118 * @return Order by clause 119 */ 120 public TOrderBy getOrderByClause() { 121 return orderByClause; 122 } 123 124 private TLimitClause limitClause = null; 125 126 public TUpdateSqlStatement(EDbVendor dbvendor) { 127 super(dbvendor); 128 sqlstatementtype = ESqlStatementType.sstupdate; 129 } 130 131 void buildsql() { 132 } 133 134 void clear() { 135 } 136 137 String getasprettytext() { 138 return ""; 139 } 140 141 void iterate(TVisitorAbs pvisitor) { 142 } 143 144 public int doParseStatement(TCustomSqlStatement psql) { 145 if (rootNode == null) return -1; 146 TUpdateSqlNode updateNode = (TUpdateSqlNode)rootNode; 147 148 if (this.sourcetokenlist.size() == 0){ 149 // subquery nested in other statements. 150 this.setStartToken(updateNode.getStartToken()); 151 this.setEndToken(updateNode.getEndToken()); 152 } 153 154 super.doParseStatement(psql); 155 this.updateToken = updateNode.getUpdateToken(); 156 157 if (updateNode.cteList != null){ 158 this.setCteList(updateNode.cteList); 159 this.getCteList().doParse(this, ESqlClause.cte); 160 } 161 162 if (updateNode.getTopClause() != null){ 163 updateNode.getTopClause().doParse(this,ESqlClause.top); 164 this.setTopClause(updateNode.getTopClause()); 165 } 166 167 if (updateNode.getSourceTableList() != null){ // update ... from source table list 168 TFromTable lcFromTable = null; 169 TJoin lcJoin = null; 170 171 for(int i=0; i<updateNode.getSourceTableList().size();i++){ 172 lcFromTable = updateNode.getSourceTableList().getFromTable(i); 173 if (lcFromTable.getFromtableType() != ETableSource.join){ 174 lcJoin = new TJoin(); 175 TTable lcTable = analyzeFromTable(lcFromTable,true); 176 lcTable.setEffectType(ETableEffectType.tetSelect); 177 lcJoin.setTable(lcTable); 178 this.getRelations().add(lcTable); 179 }else{ 180 this.fromSourceJoin = lcFromTable.getJoinExpr(); 181 182 this.fromSourceTable = new TTable(); 183 this.fromSourceTable.setTableType(ETableSource.join); 184 this.fromSourceTable.setAliasClause(lcFromTable.getJoinExpr().getAliasClause()); 185 this.fromSourceTable.setStartToken(lcFromTable.getStartToken()); 186 this.fromSourceTable.setEndToken(lcFromTable.getEndToken()); 187 this.fromSourceTable.setGsqlparser(lcFromTable.getGsqlparser()); 188 this.fromSourceTable.setJoinExpr(this.fromSourceJoin); 189 this.getRelations().add(this.fromSourceTable); 190 191 lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true); 192 lcJoin.doParse(this, ESqlClause.join); 193 } 194 joins.addJoin(lcJoin); 195 } 196 } 197 198 if (updateNode.getTargetTable().getFromtableType() != ETableSource.join ){ 199 // search in from clause to see if this is the table alias of table in from clause 200 boolean isTableAlias = false; 201 TTable lcLinkTable = null; 202 if (getJoins().size() > 0){ 203 for(int j=0;j<getJoins().size();j++){ 204 lcLinkTable = getJoins().getJoin(j).getTable(); 205 if (lcLinkTable != null){ 206 if (lcLinkTable.getAliasClause() != null){ 207 isTableAlias = updateNode.getTargetTable().toString().equalsIgnoreCase(lcLinkTable.getAliasName()); 208 if (isTableAlias) break; 209 } 210 } 211 } 212 } 213 TTable lcTable = analyzeFromTable(updateNode.getTargetTable(),false); 214 lcTable.setEffectType(ETableEffectType.tetUpdate); 215 if (isTableAlias){ 216 lcTable.setLinkTable(lcLinkTable); 217 setTargetTable(lcLinkTable); 218 }else{ 219 tables.insertElementAt(lcTable,0); 220 setTargetTable(lcTable); 221 this.getRelations().add(0,lcTable); // update table 需要放在 from table 前 222 } 223 //setTargetTable(lcTable); 224 }else{ 225 this.fromSourceJoin = updateNode.getTargetTable().getJoinExpr(); 226 227 this.fromSourceTable = new TTable(); 228 this.fromSourceTable.setTableType(ETableSource.join); 229 this.fromSourceTable.setAliasClause(updateNode.getTargetTable().getJoinExpr().getAliasClause()); 230 this.fromSourceTable.setStartToken(updateNode.getTargetTable().getJoinExpr().getStartToken()); 231 this.fromSourceTable.setEndToken(updateNode.getTargetTable().getJoinExpr().getEndToken()); 232 this.fromSourceTable.setGsqlparser(updateNode.getTargetTable().getJoinExpr().getGsqlparser()); 233 this.fromSourceTable.setJoinExpr(this.fromSourceJoin); 234 this.getRelations().add(0,this.fromSourceTable); // update table 需要放在 from table 前 235 236 TJoin lcJoin1 = analyzeJoin(updateNode.getTargetTable().getJoinExpr(),null,true); 237 lcJoin1.doParse(this, ESqlClause.join); 238 setTargetTable(lcJoin1.getTable()); 239 joins.addJoin(lcJoin1); 240 } 241 242 if (updateNode.getUseKeyIndex() != null){ 243 setUseKeyIndex(updateNode.getUseKeyIndex()); 244 getUseKeyIndex().doParse(this,ESqlClause.unknown); 245 } 246 247 if (updateNode.getOutputClause() != null){ 248 updateNode.getOutputClause().doParse(this,ESqlClause.output); 249 this.setOutputClause(updateNode.getOutputClause()); 250 } 251 252 setResultColumnList(updateNode.getResultColumnList()); 253 254 if (updateNode.getUnSetTerms() != null){ 255 setUnSetTerms(updateNode.getUnSetTerms()); 256 getUnSetTerms().doParse(this,ESqlClause.unSet); 257 } 258 259 260 if (updateNode.getReferenceTableList() != null){ 261 // Postgresql syntax: 262 // update table_name1 set f=1 263 // from table_references 264 TFromTable lcFromTable = null; 265 TJoin lcJoin = null; 266 267 for(int i=0; i<updateNode.getReferenceTableList().size();i++){ 268 lcFromTable = updateNode.getReferenceTableList().getFromTable(i); 269 if (lcFromTable.getFromtableType() != ETableSource.join){ 270 lcJoin = new TJoin(); 271 TTable lcTable = analyzeFromTable(lcFromTable,true); 272 lcTable.setEffectType(ETableEffectType.tetSelect); 273 lcJoin.setTable( lcTable); 274 this.getRelations().add(lcTable); 275 }else{ 276 this.fromSourceJoin = lcFromTable.getJoinExpr(); 277 278 this.fromSourceTable = new TTable(); 279 this.fromSourceTable.setTableType(ETableSource.join); 280 this.fromSourceTable.setAliasClause(lcFromTable.getJoinExpr().getAliasClause()); 281 this.fromSourceTable.setStartToken(lcFromTable.getJoinExpr().getStartToken()); 282 this.fromSourceTable.setEndToken(lcFromTable.getJoinExpr().getEndToken()); 283 this.fromSourceTable.setGsqlparser(lcFromTable.getJoinExpr().getGsqlparser()); 284 this.fromSourceTable.setJoinExpr(this.fromSourceJoin); 285 this.getRelations().add(this.fromSourceTable); 286 287 lcJoin = analyzeJoin(lcFromTable.getJoinExpr(),null,true); 288 lcJoin.doParse(this, ESqlClause.join); 289 } 290 // this.getReferenceJoins().addJoin(lcJoin); 291 joins.addJoin(lcJoin); 292 } 293 294 } 295 296 if (getResultColumnList() != null){ 297 getResultColumnList().doParse(this,ESqlClause.set); 298 } 299 300 if (updateNode.getOrderByClause() != null){ 301 setOrderByClause(updateNode.getOrderByClause()); 302 getOrderByClause().doParse(this,ESqlClause.orderby); 303 } 304 305 if (updateNode.getLimitClause() != null){ 306 setLimitClause(updateNode.getLimitClause()); 307 getLimitClause().doParse(this,ESqlClause.limit); 308 } 309 310 if (updateNode.getWhereCondition() != null){ 311 updateNode.getWhereCondition().doParse(this,ESqlClause.where); 312 this.setWhereClause(updateNode.getWhereCondition()); 313 } 314 315 if (updateNode.getReturningClause() != null){ 316 updateNode.getReturningClause().doParse(this,ESqlClause.returning); 317 this.setReturningClause(updateNode.getReturningClause()); 318 } 319 320 this.optionClause = updateNode.getOptionClause(); 321 322 errorLoggingClause = updateNode.getErrorLoggingClause(); 323 324 if (updateNode.getInsertSqlNode() != null){ 325 insertSqlStatement = new TInsertSqlStatement(this.dbvendor); 326 insertSqlStatement.rootNode = updateNode.getInsertSqlNode(); 327 insertSqlStatement.doParseStatement(this); 328 329 } 330 331 // remove table alias A from tables like this SQL: 332 // delete A 333 // from myTable A 334 // join otherTable B on A.Id=B.Id 335 int deletedTables[] = new int[this.tables.size()]; 336 TTable lcTable = null,lcTable2 = null; 337 for(int i=0;i<this.tables.size();i++){ 338 lcTable = this.tables.getTable(i); 339 if ((lcTable.getAliasClause() == null)&&(lcTable.isBaseTable())){ 340 for(int j=0;j<this.tables.size();j++){ 341 if (i == j) {continue;} 342 lcTable2 = this.tables.getTable(j); 343 if (lcTable2.getAliasClause() != null){ 344 if (lcTable2.getAliasClause().toString().compareToIgnoreCase(lcTable.toString()) == 0){ 345 deletedTables[i] = 1; 346 //lcTable.setLinkTable(true); 347 lcTable.setLinkTable(lcTable2); 348// for(int k=0;k<lcTable.getObjectNameReferences().size();k++){ 349// lcTable2.getObjectNameReferences().addObjectName(lcTable.getObjectNameReferences().getObjectName(k)); 350// //lcTable2.getLinkedColumns().addObjectName(lcTable.getObjectNameReferences().getObjectName(k)); 351// //lcTable.getObjectNameReferences().getObjectName(k).setSourceTable(lcTable2); 352// // System.out.println(lcTable.getObjectNameReferences().getAliasName(k).toString()); 353// } 354 } 355 } 356 357 } 358 } 359 } 360// for(int i = this.tables.size()-1;i>=0;i--){ 361// if (deletedTables[i] == 1){ 362// //this.tables.removeElementAt(i); 363// } 364// } 365 366 return 0; 367 } 368 369 public void accept(TParseTreeVisitor v){ 370 v.preVisit(this); 371 v.postVisit(this); 372 } 373 374 public void acceptChildren(TParseTreeVisitor v){ 375 v.preVisit(this); 376 377 if (this.getCteList() != null){ 378 this.getCteList().acceptChildren(v); 379 } 380 381 382 383 if (TBaseType.USE_JOINEXPR_INSTEAD_OF_JOIN){ 384 385 for(TTable table:getRelations()){ 386 table.acceptChildren(v); 387 } 388 389 }else{ 390 this.getTargetTable().acceptChildren(v); 391 if (this.joins.size() > 0){ 392 this.joins.acceptChildren(v); 393 } 394 } 395 396 if (this.getTopClause() != null){ 397 this.getTopClause().acceptChildren(v); 398 } 399 400 if (this.getOutputClause() != null){ 401 this.getOutputClause().acceptChildren(v); 402 } 403 404 if (this.getResultColumnList() != null){ 405 this.getResultColumnList().acceptChildren(v); 406 }else{ 407 TBaseType.log("set clause in update stmt is null",TLog.WARNING); 408 } 409 410 411 if (this.getWhereClause() != null){ 412 this.getWhereClause().acceptChildren(v); 413 } 414 415 if (this.getOrderByClause() != null){ 416 this.getOrderByClause().acceptChildren(v); 417 } 418 419 if (this.getLimitClause() != null){ 420 this.getLimitClause().acceptChildren(v); 421 } 422 423 if (this.getReturningClause() != null){ 424 this.getReturningClause().acceptChildren(v); 425 } 426 427 v.postVisit(this); 428 } 429 430 public void setErrorLoggingClause(TErrorLoggingClause errorLoggingClause) { 431 this.errorLoggingClause = errorLoggingClause; 432 } 433 434 public void setOptionClause(TOptionClause optionClause) { 435 this.optionClause = optionClause; 436 } 437 438 public void setReferenceJoins(TJoinList referenceJoins) { 439 this.referenceJoins = referenceJoins; 440 } 441 442 public void setOrderByClause(TOrderBy orderByClause) { 443 this.orderByClause = orderByClause; 444 } 445 446 public void setLimitClause(TLimitClause limitClause) { 447 this.limitClause = limitClause; 448 } 449 450 private TUseKeyIndex useKeyIndex;//couchbase 451 452 public void setUseKeyIndex(TUseKeyIndex useKeyIndex) { 453 this.useKeyIndex = useKeyIndex; 454 } 455 456 public TUseKeyIndex getUseKeyIndex() { 457 458 return useKeyIndex; 459 } 460 461 private TResultColumnList unSetTerms; //couchbase 462 463 public void setUnSetTerms(TResultColumnList unSetTerms) { 464 this.unSetTerms = unSetTerms; 465 } 466 467 /** 468 * Couchbase unset clause 469 * @return Couchbase unset clause 470 */ 471 public TResultColumnList getUnSetTerms() { 472 473 return unSetTerms; 474 } 475 476}