1 23 24 package org.continuent.sequoia.controller.requests; 25 26 import java.io.Serializable ; 27 import java.sql.SQLException ; 28 import java.util.ArrayList ; 29 import java.util.HashMap ; 30 import java.util.StringTokenizer ; 31 import java.util.TreeSet ; 32 33 import org.continuent.sequoia.common.i18n.Translate; 34 import org.continuent.sequoia.controller.semantic.SemanticBehavior; 35 import org.continuent.sequoia.controller.sql.schema.DatabaseColumn; 36 import org.continuent.sequoia.controller.sql.schema.DatabaseSchema; 37 import org.continuent.sequoia.controller.sql.schema.DatabaseTable; 38 import org.continuent.sequoia.controller.sql.schema.TableColumn; 39 40 51 public class UpdateRequest extends AbstractWriteRequest implements Serializable 52 { 53 private static final long serialVersionUID = 1943340529813559587L; 54 55 56 protected transient boolean isUnique; 57 58 protected transient HashMap updatedValues = null; 59 60 75 public UpdateRequest(String sqlQuery, boolean escapeProcessing, int timeout, 76 String lineSeparator) 77 { 78 super(sqlQuery, escapeProcessing, timeout, lineSeparator, 79 RequestType.UPDATE); 80 } 81 82 85 public boolean altersAggregateList() 86 { 87 return false; 88 } 89 90 93 public boolean altersDatabaseCatalog() 94 { 95 return false; 96 } 97 98 101 public boolean altersDatabaseSchema() 102 { 103 return false; 104 } 105 106 109 public boolean altersMetadataCache() 110 { 111 return false; 112 } 113 114 117 public boolean altersQueryResultCache() 118 { 119 return true; 120 } 121 122 125 public boolean altersSomething() 126 { 127 return true; 128 } 129 130 133 public boolean altersStoredProcedureList() 134 { 135 return false; 136 } 137 138 141 public boolean altersUserDefinedTypes() 142 { 143 return false; 144 } 145 146 149 public boolean altersUsers() 150 { 151 return false; 152 } 153 154 157 public void cloneParsing(AbstractRequest request) 158 { 159 if (!request.isParsed()) 160 return; 161 cloneParsingCommons(request); 162 UpdateRequest updateRequest = (UpdateRequest) request; 163 cloneTableNameAndColumns(updateRequest); 164 updatedValues = updateRequest.getUpdatedValues(); 165 isParsed = true; 166 } 167 168 174 public HashMap getUpdatedValues() 175 { 176 return updatedValues; 177 } 178 179 185 public boolean isUnique() 186 { 187 return isUnique; 188 } 189 190 193 public boolean needsMacroProcessing() 194 { 195 return true; 196 } 197 198 215 public void parse(DatabaseSchema schema, int granularity, 216 boolean isCaseSensitive) throws SQLException 217 { 218 if (granularity == ParsingGranularities.NO_PARSING) 219 { 220 isParsed = true; 221 return; 222 } 223 224 try 225 { 226 String whereClause = null; 227 isUnique = true; 228 229 String originalSQL = this.trimCarriageReturnAndTabs(); 230 String sql = originalSQL.toLowerCase(); 231 232 sql = sql.substring(7).trim(); 234 235 int setIdx = sql.indexOf(" set "); 237 if (setIdx == -1) 238 throw new SQLException ( 239 "Unable to find the SET keyword in this UPDATE statement: '" 240 + sqlQueryOrTemplate + "'"); 241 242 int whereIdx = sql.indexOf(" where "); 243 if (whereIdx == -1) 244 whereIdx = sql.indexOf(")where "); 245 246 if (isCaseSensitive) 247 sql = originalSQL.substring(7).trim(); 248 249 if (whereIdx == -1) 250 { 251 whereIdx = sql.length(); 252 isUnique = false; 253 } 254 else 255 { 256 whereIdx++; 257 whereClause = sql.substring(whereIdx + 5); 260 sql = sql.substring(0, whereIdx + 1).trim(); 263 } 264 265 tableName = sql.substring(0, setIdx).trim(); 266 267 if (schema == null) 268 { 269 writeLockedTables = new TreeSet (); 270 writeLockedTables.add(tableName); 271 isParsed = true; 272 return; 273 } 274 275 DatabaseTable t = schema.getTable(tableName, isCaseSensitive); 277 if (t == null) 278 throw new SQLException ("Unknown table '" + tableName 279 + "' in this UPDATE statement: '" + sqlQueryOrTemplate + "'"); 280 else 281 tableName = t.getName(); 283 284 writeLockedTables = new TreeSet (); 286 writeLockedTables.add(tableName); 287 addDependingTables(schema, writeLockedTables); 288 289 if (granularity > ParsingGranularities.TABLE) 290 { 291 StringTokenizer columnTokens = new StringTokenizer (sql.substring( 294 setIdx + 5, whereIdx), ","); 295 columns = new ArrayList (); 297 DatabaseColumn col = null; 298 while (columnTokens.hasMoreTokens()) 299 { 300 String token = columnTokens.nextToken(); 301 int eq = token.indexOf("="); 302 if (eq == -1) 303 continue; 304 token = token.substring(0, eq).trim(); 305 col = t.getColumn(token, isCaseSensitive); 306 if (col == null) 307 { 308 tableName = null; 309 columns = null; 310 throw new SQLException ("Unknown column name '" + token 311 + "' in this UPDATE statement: '" + sqlQueryOrTemplate + "'"); 312 } 313 else 314 columns.add(new TableColumn(tableName, col.getName())); 315 } 316 } 317 318 isParsed = true; 319 if (!isUnique) 320 return; 321 else 322 isUnique = false; 323 324 if (granularity < ParsingGranularities.COLUMN_UNIQUE) 325 return; 326 327 updatedValues = new HashMap (columns.size()); 329 330 DatabaseColumn col = null; 334 ArrayList cols = t.getColumns(); 335 int size = cols.size(); 336 for (int j = 0; j < size; j++) 337 { 338 col = (DatabaseColumn) cols.get(j); 339 String colName = col.getName(); 340 int matchIdx = whereClause.indexOf(colName); 343 while (matchIdx > 0) 344 { 345 char beforePattern = whereClause.charAt(matchIdx - 1); 347 if (((beforePattern >= 'a') && (beforePattern <= 'z')) 348 || ((beforePattern >= 'A') && (beforePattern <= 'Z')) 349 || (beforePattern == '_')) 350 matchIdx = whereClause.indexOf(colName, matchIdx + 1); 351 else 352 { isUnique = col.isUnique(); 354 if (!isUnique) 355 return; 356 int eq = whereClause.indexOf("=", matchIdx); 359 if ((eq == -1) 360 || (whereClause.substring(matchIdx + colName.length(), eq) 361 .trim().length() > 0)) 362 { 363 isUnique = false; 364 return; 365 } 366 do 367 { 368 eq++; } 370 while (whereClause.charAt(eq) == ' '); 371 372 char startChar = whereClause.charAt(eq); 374 int end; 375 if ((startChar == '\'') || (startChar == '"')) 376 { 377 eq++; 378 do 379 { end = whereClause.indexOf(startChar, eq); 381 } 382 while (whereClause.charAt(end - 1) == '\\'); 383 } 384 else 385 { 386 end = whereClause.indexOf(",", eq); 388 if (end == -1) 389 end = whereClause.length(); 390 } 391 pkValue = whereClause.substring(eq, end); 392 393 matchIdx = whereClause.indexOf(colName, matchIdx + 1); 394 } 395 } 396 } 397 398 cacheable = RequestType.UNIQUE_CACHEABLE; 399 400 sql = originalSQL.substring(7).substring(0, whereIdx).trim(); 402 if (!isCaseSensitive) 403 sql = sql.toLowerCase(); 404 int set = sql.toLowerCase().indexOf("set"); 405 sql = sql.substring(set + 3).trim(); 406 407 for (int j = 0; j < cols.size(); j++) 408 { 409 col = (DatabaseColumn) cols.get(j); 410 String colName = (isCaseSensitive) ? col.getName() : col.getName() 413 .toLowerCase(); 414 int matchIdx = sql.indexOf(colName); 415 416 while (matchIdx >= 0) 417 { 418 char afterPattern = sql.charAt(matchIdx + colName.length()); 419 if ((afterPattern != '=') && (afterPattern != ' ')) 420 { 421 matchIdx = sql.indexOf(colName, matchIdx + colName.length()); 422 continue; 423 } 424 425 char beforePattern = Character.CONTROL; 427 try 428 { 429 beforePattern = sql.charAt(matchIdx - 1); 430 } 431 catch (RuntimeException e) 432 { 433 } 435 if (((beforePattern >= 'a') && (beforePattern <= 'z')) || (beforePattern == '_')) 439 matchIdx = sql.indexOf(colName, matchIdx + 1); 440 else 441 { int eq = sql.indexOf("=", matchIdx); 443 do 444 { 445 eq++; } 447 while (sql.charAt(eq) == ' '); 448 449 char startChar = sql.charAt(eq); 451 int end; 452 if ((startChar == '\'') || (startChar == '"')) 453 { 454 eq++; 455 do 456 { end = sql.indexOf(startChar, eq); 458 } 459 while (sql.charAt(end - 1) == '\\'); 460 } 461 else 462 { 463 end = sql.indexOf(",", eq); 465 if (end == -1) 466 end = sql.length(); 467 } 468 updatedValues.put(col.getName(), sql.substring(eq, end).trim()); 469 break; 470 } 471 } 472 } 473 } 474 finally 475 { 476 if (isParsed) 477 { 478 setSemantic(new SemanticBehavior(null, writeLockedTables, null, 479 altersDatabaseSchema(), altersMetadataCache(), 480 altersQueryResultCache(), altersUsers(), isReadOnly, 481 needsMacroProcessing(), SemanticBehavior.SERIALIZABLE_ORDER, 482 requiresConnectionPoolFlush 483 ? SemanticBehavior.FLUSH_ALL_USERS 484 : SemanticBehavior.FLUSH_NONE)); 485 } 486 } 487 } 488 489 494 public boolean returnsResultSet() 495 { 496 return false; 497 } 498 499 502 public String getParsingResultsAsString() 503 { 504 StringBuffer sb = new StringBuffer (super.getParsingResultsAsString()); 505 sb.append(Translate.get("request.update.unique", isUnique)); 506 if (updatedValues != null && updatedValues.size() > 0) 507 { 508 sb.append(Translate.get("request.update.values")); 509 for (int i = 0; i < updatedValues.size(); i++) 510 { 511 sb 512 .append(Translate.get("request.update.value", new String []{ 513 updatedValues.keySet().toArray()[i].toString(), 514 updatedValues.get(updatedValues.keySet().toArray()[i]) 515 .toString()})); 516 } 517 } 518 sb.append(Translate.get("request.alters", 519 new String []{String.valueOf(altersAggregateList()), 520 String.valueOf(altersDatabaseCatalog()), 521 String.valueOf(altersDatabaseSchema()), 522 String.valueOf(altersMetadataCache()), 523 String.valueOf(altersQueryResultCache()), 524 String.valueOf(altersSomething()), 525 String.valueOf(altersStoredProcedureList()), 526 String.valueOf(altersUserDefinedTypes()), 527 String.valueOf(altersUsers())})); 528 return sb.toString(); 529 } 530 531 534 public void debug() 535 { 536 super.debug(); 537 if (tableName != null) 538 System.out.println("Updated table: " + tableName); 539 else 540 System.out.println("No information about updated table"); 541 542 if (columns != null) 543 { 544 System.out.println("Updated columns:"); 545 for (int i = 0; i < columns.size(); i++) 546 System.out.println(" " 547 + ((TableColumn) columns.get(i)).getColumnName()); 548 } 549 else 550 System.out.println("No information about updated columns"); 551 552 System.out.println("Unique update: " + isUnique); 553 554 System.out.println(""); 555 } 556 } | Popular Tags |