Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

org.objectweb.cjdbc.common.sql.UpdateRequest Class Reference

Inheritance diagram for org.objectweb.cjdbc.common.sql.UpdateRequest:

Inheritance graph
[legend]
Collaboration diagram for org.objectweb.cjdbc.common.sql.UpdateRequest:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 UpdateRequest (String sqlQuery, boolean escapeProcessing, int timeout, String lineSeparator, DatabaseSchema schema, int granularity, boolean isCaseSensitive) throws SQLException
 UpdateRequest (String sqlQuery, boolean escapeProcessing, int timeout, String lineSeparator)
void parse (DatabaseSchema schema, int granularity, boolean isCaseSensitive) throws SQLException
HashMap getUpdatedValues ()
void cloneParsing (AbstractRequest request)
boolean isInsert ()
boolean isUpdate ()
boolean isDelete ()
boolean isCreate ()
boolean isDrop ()
boolean isUnique ()
void debug ()
boolean isAlter ()

Detailed Description

An UpdateRequest is an SQL request with the following syntax:

   UPDATE table-name SET (column-name=expression[,column-name=expression]*) WHERE search-condition
 

Author:
Emmanuel Cecchet

Mathieu Peltier

Version:
1.0

Definition at line 49 of file UpdateRequest.java.


Constructor & Destructor Documentation

org.objectweb.cjdbc.common.sql.UpdateRequest.UpdateRequest String  sqlQuery,
boolean  escapeProcessing,
int  timeout,
String  lineSeparator,
DatabaseSchema  schema,
int  granularity,
boolean  isCaseSensitive
throws SQLException
 

Creates a new UpdateRequest instance. The caller must give an SQL request, without any leading or trailing spaces and beginning with 'update ' (it will not be checked).

If the syntax is incorrect an exception is thrown.

Parameters:
sqlQuery the SQL query
escapeProcessing should the driver to escape processing before sending to the database ?
timeout an int value
lineSeparator the line separator used in the query
schema a DatabaseSchema value
granularity parsing granularity as defined in ParsingGranularities
isCaseSensitive true if parsing is case sensitive
Exceptions:
SQLException if an error occurs

Definition at line 74 of file UpdateRequest.java.

References org.objectweb.cjdbc.common.sql.UpdateRequest.parse().

00077   {
00078     this(sqlQuery, escapeProcessing, timeout, lineSeparator);
00079     parse(schema, granularity, isCaseSensitive);
00080   }

org.objectweb.cjdbc.common.sql.UpdateRequest.UpdateRequest String  sqlQuery,
boolean  escapeProcessing,
int  timeout,
String  lineSeparator
 

Creates a new UpdateRequest instance. The caller must give an SQL request, without any leading or trailing spaces and beginning with 'update ' (it will not be checked).

The request is not parsed but it can be done later by a call to parse(DatabaseSchema, int, boolean).

Parameters:
sqlQuery the SQL query
escapeProcessing should the driver to escape processing before sending to the database ?
timeout an int value
lineSeparator the line separator used in the query
See also:
parse

Definition at line 97 of file UpdateRequest.java.

00099   {
00100     super(sqlQuery, escapeProcessing, timeout, lineSeparator);
00101     cacheable = RequestType.UNCACHEABLE;
00102     isParsed = false;
00103     isUnique = false;
00104   }


Member Function Documentation

void org.objectweb.cjdbc.common.sql.UpdateRequest.cloneParsing AbstractRequest  request  )  [virtual]
 

See also:
AbstractRequest.cloneParsing(AbstractRequest)

Implements org.objectweb.cjdbc.common.sql.AbstractRequest.

Definition at line 377 of file UpdateRequest.java.

References org.objectweb.cjdbc.common.sql.AbstractWriteRequest.cloneTableNameAndColumns(), and org.objectweb.cjdbc.common.sql.AbstractRequest.isParsed.

00378   {
00379     if (!request.isParsed())
00380       return;
00381     cloneTableNameAndColumns((AbstractWriteRequest) request);
00382     updatedValues = ((UpdateRequest) request).getUpdatedValues();
00383     isParsed = true;
00384   }

void org.objectweb.cjdbc.common.sql.UpdateRequest.debug  ) 
 

Displays some debugging information about this request.

Reimplemented from org.objectweb.cjdbc.common.sql.AbstractRequest.

Definition at line 445 of file UpdateRequest.java.

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   }

HashMap org.objectweb.cjdbc.common.sql.UpdateRequest.getUpdatedValues  ) 
 

What are the updated values in this request

Returns:
a hashtable of (colname,value) or null if parsing granularity has stop computation

Definition at line 369 of file UpdateRequest.java.

Referenced by org.objectweb.cjdbc.controller.cache.result.ResultCache.needInvalidate().

00370   {
00371     return updatedValues;
00372   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isAlter  )  [virtual]
 

See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isAlter()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 470 of file UpdateRequest.java.

00471   {
00472     return false;
00473   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isCreate  )  [virtual]
 

Returns:
false
See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isCreate()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 417 of file UpdateRequest.java.

00418   {
00419     return false;
00420   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isDelete  )  [virtual]
 

Returns:
false
See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isDelete()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 408 of file UpdateRequest.java.

00409   {
00410     return false;
00411   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isDrop  )  [virtual]
 

Returns:
false
See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isDrop()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 426 of file UpdateRequest.java.

00427   {
00428     return false;
00429   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isInsert  )  [virtual]
 

Returns:
false
See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isInsert()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 390 of file UpdateRequest.java.

00391   {
00392     return false;
00393   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isUnique  ) 
 

Returns true as this request updates a UNIQUE row.

Returns:
false

Definition at line 437 of file UpdateRequest.java.

00438   {
00439     return isUnique;
00440   }

boolean org.objectweb.cjdbc.common.sql.UpdateRequest.isUpdate  )  [virtual]
 

Returns:
true
See also:
org.objectweb.cjdbc.common.sql.AbstractWriteRequest.isUpdate()

Implements org.objectweb.cjdbc.common.sql.AbstractWriteRequest.

Definition at line 399 of file UpdateRequest.java.

00400   {
00401     return true;
00402   }

void org.objectweb.cjdbc.common.sql.UpdateRequest.parse DatabaseSchema  schema,
int  granularity,
boolean  isCaseSensitive
throws SQLException [virtual]
 

Parses the SQL request and extract the selected columns and tables given the DatabaseSchema of the database targeted by this request. Determines also if this query only deletes a single row, and the equivalent INSERT statement.

An exception is thrown when the parsing fails. Warning, this method does not check the validity of the request. In particular, invalid request could be parsed without throwing an exception. However, valid SQL request should never throw an exception.

Parameters:
schema a DatabaseSchema value
granularity parsing granularity as defined in ParsingGranularities
isCaseSensitive true if table name parsing is case sensitive
Exceptions:
SQLException if the parsing fails

Implements org.objectweb.cjdbc.common.sql.AbstractRequest.

Definition at line 123 of file UpdateRequest.java.

References org.objectweb.cjdbc.common.sql.schema.DatabaseTable.getColumn(), org.objectweb.cjdbc.common.sql.schema.DatabaseTable.getColumns(), org.objectweb.cjdbc.common.sql.schema.DatabaseColumn.getName(), org.objectweb.cjdbc.common.sql.schema.DatabaseTable.getName(), and org.objectweb.cjdbc.common.sql.schema.DatabaseColumn.isUnique.

Referenced by org.objectweb.cjdbc.common.sql.UpdateRequest.UpdateRequest().

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   }


The documentation for this class was generated from the following file:
Generated on Mon Apr 11 22:02:11 2005 for C-JDBC by  doxygen 1.3.9.1