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

InsertRequest.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2005 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet.
00022  * Contributor(s): Mathieu Peltier, Sara Bouchenak.
00023  */
00024 
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.StringTokenizer;
00031 
00032 import org.objectweb.cjdbc.common.sql.schema.DatabaseColumn;
00033 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema;
00034 import org.objectweb.cjdbc.common.sql.schema.DatabaseTable;
00035 import org.objectweb.cjdbc.common.sql.schema.TableColumn;
00036 
00037 /**
00038  * An <code>InsertRequest</code> is an SQL request of the following syntax:
00039  * 
00040  * <pre>
00041  *  INSERT INTO table-name [(column-name[,column-name]*)] {VALUES (constant|null[,constant|null]*)}|{SELECT query}
00042  * </pre>
00043  * <code>VALUES<code> are ignored.
00044  *   *
00045  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet</a>
00046  * @version 1.0
00047  */
00048 public class InsertRequest extends AbstractWriteRequest implements Serializable
00049 {
00050   /**
00051    * Creates a new <code>InsertRequest</code> instance. The caller must give
00052    * an SQL request, without any leading or trailing spaces and beginning with
00053    * 'insert into ' (it will not be checked).
00054    * <p>
00055    * If the syntax is incorrect an exception is thrown.
00056    * 
00057    * @param sqlQuery the SQL query
00058    * @param escapeProcessing should the driver to escape processing before
00059    *          sending to the database ?
00060    * @param timeout an <code>int</code> value
00061    * @param lineSeparator the line separator used in the query
00062    * @param schema a <code>DatabaseSchema</code> value
00063    * @param granularity parsing granularity as defined in
00064    *          <code>ParsingGranularities</code>
00065    * @param isCaseSensitive true if parsing is case sensitive
00066    * @exception SQLException if an error occurs
00067    */
00068   public InsertRequest(String sqlQuery, boolean escapeProcessing, int timeout,
00069       String lineSeparator, DatabaseSchema schema, int granularity,
00070       boolean isCaseSensitive) throws SQLException
00071   {
00072     this(sqlQuery, escapeProcessing, timeout, lineSeparator);
00073     parse(schema, granularity, isCaseSensitive);
00074   }
00075 
00076   /**
00077    * Creates a new <code>DropRequest</code> instance. The caller must give an
00078    * SQL request, without any leading or trailing spaces and beginning with
00079    * 'create table ' (it will not be checked).
00080    * <p>
00081    * The request is not parsed but it can be done later by a call to
00082    * {@link #parse(DatabaseSchema, int, boolean)}.
00083    * 
00084    * @param sqlQuery the SQL request
00085    * @param escapeProcessing should the driver to escape processing before
00086    *          sending to the database ?
00087    * @param timeout an <code>int</code> value
00088    * @param lineSeparator the line separator used in the query
00089    * @see #parse
00090    */
00091   public InsertRequest(String sqlQuery, boolean escapeProcessing, int timeout,
00092       String lineSeparator)
00093   {
00094     super(sqlQuery, escapeProcessing, timeout, lineSeparator);
00095     cacheable = RequestType.UNCACHEABLE;
00096     isParsed = false;
00097   }
00098 
00099   /**
00100    * Parse the query to know which table is affected. Also checks for the
00101    * columns if the parsing granularity requires it.
00102    * 
00103    * @see org.objectweb.cjdbc.common.sql.AbstractRequest#parse(org.objectweb.cjdbc.common.sql.schema.DatabaseSchema,
00104    *      int, boolean)
00105    */
00106   public void parse(DatabaseSchema schema, int granularity,
00107       boolean isCaseSensitive) throws SQLException
00108   {
00109     if (granularity == ParsingGranularities.NO_PARSING)
00110     {
00111       isParsed = true;
00112       return;
00113     }
00114 
00115     // Sanity check
00116     if (schema == null)
00117       throw new SQLException(
00118           "Unable to parse request with an undefined database schema");
00119 
00120     String originalSQL = this.trimCarriageReturn();
00121     String sql = originalSQL.toLowerCase();
00122 
00123     // Strip 'insert into '
00124     sql = sql.substring(7).trim().substring(5).trim();
00125 
00126     // Look for the VALUES or SELECT clause
00127     int endIdx = sql.indexOf(" values ");
00128     if (endIdx == -1)
00129     {
00130       endIdx = sql.indexOf(" values(");
00131       if (endIdx == -1)
00132       {
00133         endIdx = sql.indexOf("select ");
00134         if (endIdx == -1)
00135           throw new SQLException(
00136               "Unable to find the VALUES or SELECT keyword in this INSERT statement: '"
00137                   + sqlQuery + "'");
00138       }
00139     }
00140 
00141     if (isCaseSensitive)
00142     {
00143       int shift = originalSQL.length() - sql.length();
00144       sql = originalSQL.substring(shift, shift + endIdx).trim();
00145     }
00146     else
00147       sql = sql.substring(0, endIdx).trim();
00148 
00149     int openParenthesisIdx = sql.indexOf("(");
00150 
00151     // Get the table on which INSERT occurs
00152     String insertTable;
00153     if (openParenthesisIdx == -1)
00154       // Query like INSERT INTO table VALUES(...)
00155       insertTable = sql;
00156     else
00157       // Query of the form INSERT INTO table(column1, ...) VALUES(...)
00158       insertTable = sql.substring(0, openParenthesisIdx).trim();
00159 
00160     DatabaseTable t = schema.getTable(insertTable, isCaseSensitive);
00161     if (t == null)
00162       throw new SQLException("Unknown table '" + insertTable
00163           + "' in this INSERT statement: '" + sqlQuery + "'");
00164     else
00165       tableName = t.getName();
00166 
00167     if ((granularity == ParsingGranularities.COLUMN)
00168         || (granularity == ParsingGranularities.COLUMN_UNIQUE))
00169     {
00170       if (openParenthesisIdx != -1)
00171       {
00172         // Fetch the affected columns
00173         int closingParenthesisIdx = sql.indexOf(")");
00174         if ((closingParenthesisIdx == -1) || (closingParenthesisIdx > endIdx))
00175         {
00176           tableName = null;
00177           columns = null;
00178           throw new SQLException(
00179               "Syntax error in columns definition for this INSERT statement: '"
00180                   + sqlQuery + "'");
00181         }
00182 
00183         // Column names are separated by comas
00184         StringTokenizer columnTokens = new StringTokenizer(sql.substring(
00185             openParenthesisIdx + 1, closingParenthesisIdx), ",");
00186         columns = new ArrayList();
00187         DatabaseColumn col = null;
00188         while (columnTokens.hasMoreTokens())
00189         {
00190           String token = columnTokens.nextToken().trim();
00191           if ((col = t.getColumn(token)) == null)
00192           {
00193             tableName = null;
00194             columns = null;
00195             throw new SQLException("Unknown column name '" + token
00196                 + "' in this INSERT statement: '" + sqlQuery + "'");
00197           }
00198           else
00199           {
00200             columns.add(new TableColumn(tableName, col.getName()));
00201           }
00202         }
00203       }
00204       else
00205       {
00206         // All columns are affected
00207         columns = new ArrayList();
00208         ArrayList cols = t.getColumns();
00209         int size = cols.size();
00210         for (int j = 0; j < size; j++)
00211         {
00212           columns.add(new TableColumn(tableName, ((DatabaseColumn) cols.get(j))
00213               .getName()));
00214         }
00215       }
00216     }
00217 
00218     isParsed = true;
00219   }
00220 
00221   /**
00222    * @see AbstractRequest#cloneParsing(AbstractRequest)
00223    */
00224   public void cloneParsing(AbstractRequest request)
00225   {
00226     if (!request.isParsed())
00227       return;
00228     cloneTableNameAndColumns((AbstractWriteRequest) request);
00229     isParsed = true;
00230   }
00231 
00232   /**
00233    * @return <code>true</code>
00234    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isInsert()
00235    */
00236   public boolean isInsert()
00237   {
00238     return true;
00239   }
00240 
00241   /**
00242    * @return <code>false</code>
00243    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isUpdate()
00244    */
00245   public boolean isUpdate()
00246   {
00247     return false;
00248   }
00249 
00250   /**
00251    * @return <code>false</code>
00252    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isDelete()
00253    */
00254   public boolean isDelete()
00255   {
00256     return false;
00257   }
00258 
00259   /**
00260    * @return <code>false</code>
00261    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isCreate()
00262    */
00263   public boolean isCreate()
00264   {
00265     return false;
00266   }
00267 
00268   /**
00269    * @return <code>false</code>
00270    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isDrop()
00271    */
00272   public boolean isDrop()
00273   {
00274     return false;
00275   }
00276 
00277   /**
00278    * Displays some debugging information about this request.
00279    */
00280   public void debug()
00281   {
00282     super.debug();
00283     if (tableName != null)
00284       System.out.println("Inserted table: " + tableName);
00285     else
00286       System.out.println("No information about inserted table");
00287 
00288     if (columns != null)
00289     {
00290       System.out.println("Inserted columns:");
00291       for (int i = 0; i < columns.size(); i++)
00292         System.out.println("  "
00293             + ((TableColumn) columns.get(i)).getColumnName());
00294     }
00295     else
00296       System.out.println("No information about inserted columns");
00297 
00298     System.out.println("");
00299   }
00300 
00301   /**
00302    * @see org.objectweb.cjdbc.common.sql.AbstractWriteRequest#isAlter()
00303    */
00304   public boolean isAlter()
00305   {
00306     return false;
00307   }
00308 }

Generated on Mon Apr 11 22:01:32 2005 for C-JDBC by  doxygen 1.3.9.1