src/org/objectweb/cjdbc/common/sql/UpdateRequest.java

説明を見る。
00001 00025 package org.objectweb.cjdbc.common.sql; 00026 00027 import java.io.Serializable; 00028 import java.sql.SQLException; 00029 import java.util.ArrayList; 00030 import java.util.HashMap; 00031 import java.util.StringTokenizer; 00032 00033 import org.objectweb.cjdbc.common.sql.schema.DatabaseColumn; 00034 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema; 00035 import org.objectweb.cjdbc.common.sql.schema.DatabaseTable; 00036 import org.objectweb.cjdbc.common.sql.schema.TableColumn; 00037 00049 public class UpdateRequest extends AbstractWriteRequest implements Serializable 00050 { 00052 private transient boolean isUnique; 00053 00054 private transient HashMap updatedValues = null; 00055 00074 public UpdateRequest(String sqlQuery, boolean escapeProcessing, int timeout, 00075 String lineSeparator, DatabaseSchema schema, int granularity, 00076 boolean isCaseSensitive) throws SQLException 00077 { 00078 this(sqlQuery, escapeProcessing, timeout, lineSeparator); 00079 parse(schema, granularity, isCaseSensitive); 00080 } 00081 00097 public UpdateRequest(String sqlQuery, boolean escapeProcessing, int timeout, 00098 String lineSeparator) 00099 { 00100 super(sqlQuery, escapeProcessing, timeout, lineSeparator); 00101 cacheable = RequestType.UNCACHEABLE; 00102 isParsed = false; 00103 isUnique = false; 00104 } 00105 00123 public void parse(DatabaseSchema schema, int granularity, 00124 boolean isCaseSensitive) throws SQLException 00125 { 00126 if (granularity == ParsingGranularities.NO_PARSING) 00127 { 00128 isParsed = true; 00129 return; 00130 } 00131 00132 // Sanity check 00133 if (schema == null) 00134 throw new SQLException( 00135 "Unable to parse request with an undefined database schema"); 00136 00137 String whereClause = null; 00138 isUnique = true; 00139 00140 String originalSQL = this.trimCarriageReturn(); 00141 String sql = originalSQL.toLowerCase(); 00142 00143 // Strip 'update ' 00144 sql = sql.substring(7).trim(); 00145 00146 // Look for the SET or WHERE clause 00147 int setIdx = sql.indexOf("set "); 00148 int whereIdx = sql.indexOf("where "); 00149 if (setIdx == -1) 00150 throw new SQLException( 00151 "Unable to find the SET keyword in this UPDATE statement: '" 00152 + sqlQuery + "'"); 00153 00154 if (isCaseSensitive) 00155 sql = originalSQL.substring(7).trim(); 00156 00157 if (whereIdx == -1) 00158 { 00159 whereIdx = sql.length(); 00160 isUnique = false; 00161 } 00162 else 00163 { 00164 whereClause = sql.substring(whereIdx + 5); 00165 // 5 = "where".length(), do not trim or remove anything after 00166 // else the following code will no more work 00167 sql = sql.substring(0, whereIdx + 1).trim(); 00168 } 00169 00170 // Get the table on which UPDATE occurs 00171 DatabaseTable t = schema.getTable(sql.substring(0, setIdx).trim(), 00172 isCaseSensitive); 00173 if (t == null) 00174 throw new SQLException("Unknown table '" + tableName 00175 + "' in this UPDATE statement: '" + sqlQuery + "'"); 00176 else 00177 // Get the real name here (resolves case sentivity problems) 00178 tableName = t.getName(); 00179 00180 if (granularity > ParsingGranularities.TABLE) 00181 { 00182 // We have to get the affected columns 00183 // Column names are separated by comas and are before a '=' symbol 00184 StringTokenizer columnTokens = new StringTokenizer(sql.substring( 00185 setIdx + 4, whereIdx), ","); 00186 // 4=length("SET ") 00187 columns = new ArrayList(); 00188 DatabaseColumn col = null; 00189 while (columnTokens.hasMoreTokens()) 00190 { 00191 String token = columnTokens.nextToken(); 00192 int eq = token.indexOf("="); 00193 if (eq == -1) 00194 continue; 00195 token = token.substring(0, eq).trim(); 00196 col = t.getColumn(token, isCaseSensitive); 00197 if (col == null) 00198 { 00199 tableName = null; 00200 columns = null; 00201 throw new SQLException("Unknown column name '" + token 00202 + "' in this UPDATE statement: '" + sqlQuery + "'"); 00203 } 00204 else 00205 columns.add(new TableColumn(tableName, col.getName())); 00206 } 00207 } 00208 00209 isParsed = true; 00210 if (!isUnique) 00211 return; 00212 else 00213 isUnique = false; 00214 00215 if (granularity < ParsingGranularities.COLUMN_UNIQUE) 00216 return; 00217 00218 // Prepare hashtable for updated values 00219 updatedValues = new HashMap(columns.size()); 00220 00221 // Check whether this update affects a single row or not 00222 // Instead of parsing the clause, we use a brutal force technique 00223 // and we try to directly identify every column name of the table. 00224 DatabaseColumn col = null; 00225 ArrayList cols = t.getColumns(); 00226 int size = cols.size(); 00227 for (int j = 0; j < size; j++) 00228 { 00229 col = (DatabaseColumn) cols.get(j); 00230 String colName = col.getName(); 00231 // if pattern found and column not already in result, it's a dependency ! 00232 int matchIdx = whereClause.indexOf(colName); 00233 while (matchIdx > 0) 00234 { 00235 // Try to check that we got the full pattern and not a sub-pattern 00236 char beforePattern = whereClause.charAt(matchIdx - 1); 00237 if (((beforePattern >= 'a') && (beforePattern <= 'z')) 00238 || ((beforePattern >= 'A') && (beforePattern <= 'Z')) 00239 || (beforePattern == '_')) 00240 matchIdx = whereClause.indexOf(colName, matchIdx + 1); 00241 else 00242 { // Ok it's a good one, check if it is UNIQUE 00243 isUnique = col.isUnique(); 00244 if (!isUnique) 00245 return; 00246 // Check if this UNIQUE columns stands in the left part of an 00247 // equality 00248 int eq = whereClause.indexOf("=", matchIdx); 00249 if ((eq == -1) 00250 || (whereClause.substring(matchIdx + colName.length(), eq).trim() 00251 .length() > 0)) 00252 { 00253 isUnique = false; 00254 return; 00255 } 00256 do 00257 { 00258 eq++; // Skip spaces 00259 } 00260 while (whereClause.charAt(eq) == ' '); 00261 00262 // Check if we have "..." or '...' 00263 char startChar = whereClause.charAt(eq); 00264 int end; 00265 if ((startChar == '\'') || (startChar == '"')) 00266 { 00267 eq++; 00268 do 00269 { // Look for the end of the quote and take care of \' or \" 00270 end = whereClause.indexOf(startChar, eq); 00271 } 00272 while (whereClause.charAt(end - 1) == '\\'); 00273 } 00274 else 00275 { 00276 // It's a regular value just find the next comma 00277 end = whereClause.indexOf(",", eq); 00278 if (end == -1) 00279 end = whereClause.length(); 00280 } 00281 pkValue = whereClause.substring(eq, end); 00282 00283 matchIdx = whereClause.indexOf(colName, matchIdx + 1); 00284 } 00285 } 00286 } 00287 00288 cacheable = RequestType.UNIQUE_CACHEABLE; 00289 00290 // Now get the values for each updated field 00291 sql = originalSQL.substring(7).substring(0, whereIdx).trim(); 00292 if(!isCaseSensitive) 00293 sql.toLowerCase(); 00294 int set = sql.toLowerCase().indexOf("set"); 00295 sql = sql.substring(set+3).trim(); 00296 00297 for (int j = 0; j < cols.size(); j++) 00298 { 00299 col = (DatabaseColumn) cols.get(j); 00300 // if pattern found and column not already in result, it's a dependency ! 00301 String colName = (isCaseSensitive) ? col.getName() : col.getName().toLowerCase(); 00302 int matchIdx = sql.indexOf(colName); 00303 00304 while (matchIdx >= 0) 00305 { 00306 char afterPattern = sql.charAt(matchIdx + colName.length()); 00307 if ((afterPattern != '=') && (afterPattern != ' ')) 00308 { 00309 matchIdx = sql.indexOf(colName, matchIdx + colName.length()); 00310 continue; 00311 } 00312 00313 // Try to check that we got the full pattern and not a sub-pattern 00314 char beforePattern = Character.CONTROL; 00315 try 00316 { 00317 beforePattern = sql.charAt(matchIdx - 1); 00318 } 00319 catch (RuntimeException e) 00320 { 00321 // nothing 00322 } 00323 if (((beforePattern >= 'a') && (beforePattern <= 'z')) // Everything 00324 // should be 00325 // lowercase here 00326 || (beforePattern == '_')) 00327 matchIdx = sql.indexOf(colName, matchIdx + 1); 00328 else 00329 { // Ok, it's good, get the value on the right part of the equality 00330 int eq = sql.indexOf("=", matchIdx); 00331 do 00332 { 00333 eq++; // Skip spaces 00334 } 00335 while (sql.charAt(eq) == ' '); 00336 00337 // Check if we have "..." or '...' 00338 char startChar = sql.charAt(eq); 00339 int end; 00340 if ((startChar == '\'') || (startChar == '"')) 00341 { 00342 eq++; 00343 do 00344 { // Look for the end of the quote and take care of \' or \" 00345 end = sql.indexOf(startChar, eq); 00346 } 00347 while (sql.charAt(end - 1) == '\\'); 00348 } 00349 else 00350 { 00351 // It's a regular value just find the next comma 00352 end = sql.indexOf(",", eq); 00353 if (end == -1) 00354 end = sql.length(); 00355 } 00356 updatedValues.put(col.getName(), sql.substring(eq, end).trim()); 00357 break; 00358 } 00359 } 00360 } 00361 } 00362 00369 public HashMap getUpdatedValues() 00370 { 00371 return updatedValues; 00372 } 00373 00377 public void cloneParsing(AbstractRequest request) 00378 { 00379 if (!request.isParsed()) 00380 return; 00381 cloneTableNameAndColumns((AbstractWriteRequest) request); 00382 updatedValues = ((UpdateRequest) request).getUpdatedValues(); 00383 isParsed = true; 00384 } 00385 00390 public boolean isInsert() 00391 { 00392 return false; 00393 } 00394 00399 public boolean isUpdate() 00400 { 00401 return true; 00402 } 00403 00408 public boolean isDelete() 00409 { 00410 return false; 00411 } 00412 00417 public boolean isCreate() 00418 { 00419 return false; 00420 } 00421 00426 public boolean isDrop() 00427 { 00428 return false; 00429 } 00430 00437 public boolean isUnique() 00438 { 00439 return isUnique; 00440 } 00441 00445 public void debug() 00446 { 00447 super.debug(); 00448 if (tableName != null) 00449 System.out.println("Updated table: " + tableName); 00450 else 00451 System.out.println("No information about updated table"); 00452 00453 if (columns != null) 00454 { 00455 System.out.println("Updated columns:"); 00456 for (int i = 0; i < columns.size(); i++) 00457 System.out.println(" " 00458 + ((TableColumn) columns.get(i)).getColumnName()); 00459 } 00460 else 00461 System.out.println("No information about updated columns"); 00462 00463 System.out.println("Unique update: " + isUnique); 00464 00465 System.out.println(""); 00466 } 00470 public boolean isAlter() 00471 { 00472 return false; 00473 } 00474 }

CJDBCversion1.0.4に対してTue Oct 12 15:15:58 2004に生成されました。 doxygen 1.3.8