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

AbstractRequest.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 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): Julie Marguerite, Mathieu Peltier.
00023  */
00024 
00025 package org.objectweb.cjdbc.common.sql;
00026 
00027 import java.io.Serializable;
00028 import java.sql.SQLException;
00029 
00030 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema;
00031 
00032 /**
00033  * An <code>AbstractRequest</code> defines the skeleton of an SQL request.
00034  * 
00035  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00036  * @author <a href="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
00037  * @author <a href="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
00038  * @version 1.0
00039  */
00040 public abstract class AbstractRequest implements Serializable
00041 {
00042   /** Request unique id (set by the controller). */
00043   protected transient long id;
00044 
00045   /** SQL query (should be set in constructor). */
00046   protected String         sqlQuery;
00047 
00048   /** SQL query skeleton as it appears in PreparedStatements. */
00049   protected String         sqlSkeleton      = null;
00050 
00051   /**
00052    * Login used to issue this request (must be set by the
00053    * VirtualDatabaseWorkerThread).
00054    */
00055   protected String         login;
00056 
00057   /** Whether this request is cacheable or not. */
00058   protected int            cacheable;
00059 
00060   /** Whether the SQL content has been parsed or not. */
00061   protected boolean        isParsed;
00062 
00063   /**
00064    * Maximum number of rows in the ResultSet.
00065    * 
00066    * @see java.sql.Statement#setMaxRows(int)
00067    */
00068   protected int            maxRows;
00069 
00070   private int              fetchSize        = 0;
00071 
00072   //
00073   // Connection related parameters
00074   //
00075 
00076   /** True if the connection has been set to read-only */
00077   protected boolean        isReadOnly       = false;
00078 
00079   /**
00080    * Whether this request has been sent in <code>autocommit</code> mode or
00081    * not.
00082    */
00083   protected boolean        isAutoCommit;
00084 
00085   /**
00086    * Transaction identifier if this request belongs to a transaction. The value
00087    * is set by the VirtualDatabaseWorkerThread.
00088    */
00089   protected long           transactionId;
00090 
00091   /**
00092    * Timeout for this request in seconds, value 0 means no timeout (should be
00093    * set in constructor).
00094    */
00095   protected int            timeout;
00096 
00097   /**
00098    * Should the driver do escape processing before sending to the database? No
00099    * setter for this member, should be set in constructor.
00100    */
00101   protected boolean        escapeProcessing = true;
00102 
00103   /**
00104    * Should match System.getProperty("line.separator") on the driver side.
00105    * Required for parsing.
00106    */
00107   private String           lineSeparator    = null;
00108 
00109   /**
00110    * If set to true, the query is interpreted on the driver side, if false the
00111    * various parameters are encoded and passed as is to the database native
00112    * driver by the controller.
00113    */
00114   private boolean          driverProcessed  = true;
00115 
00116   /**
00117    * Default constructor Creates a new <code>AbstractRequest</code> object
00118    * 
00119    * @param sqlQuery the SQL query
00120    * @param escapeProcessing should the driver to escape processing before
00121    *          sending to the database ?
00122    * @param timeout an <code>int</code> value
00123    * @param lineSeparator the line separator used in the query
00124    */
00125   public AbstractRequest(String sqlQuery, boolean escapeProcessing,
00126       int timeout, String lineSeparator)
00127   {
00128     this.sqlQuery = sqlQuery;
00129     this.escapeProcessing = escapeProcessing;
00130     this.timeout = timeout;
00131     this.lineSeparator = lineSeparator;
00132   }
00133 
00134   /**
00135    * Returns <code>true</code> if this request is a read request (
00136    * <code>SELECT</code> requests for example perform a read).
00137    * 
00138    * @return <code>true</code> if this request is a read request
00139    */
00140   public abstract boolean isReadRequest();
00141 
00142   /**
00143    * Returns <code>true</code> if this request is a write request (
00144    * <code>INSERT</code> or <code>UPDATE</code> for example perform writes).
00145    * 
00146    * @return <code>true</code> if this requests is a write request
00147    */
00148   public abstract boolean isWriteRequest();
00149 
00150   /**
00151    * Returns <code>true</code> if the resulting operation on this request is
00152    * unknown (some non-standard command or stored procedure for example).
00153    * 
00154    * @return a <code>boolean</code> value
00155    */
00156   public abstract boolean isUnknownRequest();
00157 
00158   /**
00159    * Returns <code>true</code> if the request SQL content has been already
00160    * parsed.
00161    * 
00162    * @return a <code>boolean</code> value
00163    */
00164   public boolean isParsed()
00165   {
00166     return isParsed;
00167   }
00168 
00169   /**
00170    * Returns <code>true</code> if the connection is set to read-only
00171    * 
00172    * @return a <code>boolean</code> value
00173    */
00174   public boolean isReadOnly()
00175   {
00176     return isReadOnly;
00177   }
00178 
00179   /**
00180    * Sets the read-only mode for this request.
00181    * 
00182    * @param isReadOnly <code>true</code> if connection is read-only
00183    */
00184   public void setIsReadOnly(boolean isReadOnly)
00185   {
00186     this.isReadOnly = isReadOnly;
00187   }
00188 
00189   /**
00190    * Returns the cacheable status of this request. It can be:
00191    * {@link org.objectweb.cjdbc.common.sql.RequestType#CACHEABLE},
00192    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNCACHEABLE}or
00193    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNIQUE_CACHEABLE}
00194    * 
00195    * @return a <code>int</code> value
00196    */
00197   public int getCacheAbility()
00198   {
00199     return cacheable;
00200   }
00201 
00202   /**
00203    * Set the cacheable status of this request. It can be:
00204    * {@link org.objectweb.cjdbc.common.sql.RequestType#CACHEABLE},
00205    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNCACHEABLE}or
00206    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNIQUE_CACHEABLE}
00207    * 
00208    * @param cacheAbility a <code>int</code> value
00209    */
00210   public void setCacheAbility(int cacheAbility)
00211   {
00212     this.cacheable = cacheAbility;
00213   }
00214 
00215   /**
00216    * Returns <code>true</code> if the driver should escape processing before
00217    * sending to the database?
00218    * 
00219    * @return a <code>boolean</code> value
00220    */
00221   public boolean getEscapeProcessing()
00222   {
00223     return escapeProcessing;
00224   }
00225 
00226   /**
00227    * Returns the unique id of this request.
00228    * 
00229    * @return the request id
00230    */
00231   public long getId()
00232   {
00233     return id;
00234   }
00235 
00236   /**
00237    * Sets the unique id of this request.
00238    * 
00239    * @param id the id to set
00240    */
00241   public void setId(long id)
00242   {
00243     this.id = id;
00244   }
00245 
00246   /**
00247    * Returns <code>true</code> if the request should be executed in
00248    * <code>autocommit</code> mode.
00249    * 
00250    * @return a <code>boolean</code> value
00251    */
00252   public boolean isAutoCommit()
00253   {
00254     return isAutoCommit;
00255   }
00256 
00257   /**
00258    * Sets the autocommit mode for this request.
00259    * 
00260    * @param isAutoCommit <code>true</code> if <code>autocommit</code> should
00261    *          be used
00262    */
00263   public void setIsAutoCommit(boolean isAutoCommit)
00264   {
00265     this.isAutoCommit = isAutoCommit;
00266   }
00267 
00268   /**
00269    * Returns the login used to issue this request.
00270    * 
00271    * @return a <code>String</code> value
00272    */
00273   public String getLogin()
00274   {
00275     return login;
00276   }
00277 
00278   /**
00279    * Returns the lineSeparator value.
00280    * 
00281    * @return Returns the lineSeparator.
00282    */
00283   public String getLineSeparator()
00284   {
00285     return lineSeparator;
00286   }
00287 
00288   /**
00289    * Sets the lineSeparator value.
00290    * 
00291    * @param lineSeparator The lineSeparator to set.
00292    */
00293   public void setLineSeparator(String lineSeparator)
00294   {
00295     this.lineSeparator = lineSeparator;
00296   }
00297 
00298   /**
00299    * Sets the login to use to issue this request.
00300    * 
00301    * @param login a <code>String</code> value
00302    */
00303   public void setLogin(String login)
00304   {
00305     this.login = login;
00306   }
00307 
00308   /**
00309    * Gets the SQL code of this request.
00310    * 
00311    * @return the SQL query
00312    */
00313   public String getSQL()
00314   {
00315     return sqlQuery;
00316   }
00317 
00318   /**
00319    * Get a short form of this request if the SQL statement exceeds
00320    * nbOfCharacters.
00321    * 
00322    * @param nbOfCharacters number of characters to include in the short form.
00323    * @return the nbOfCharacters first characters of the SQL statement
00324    */
00325   public String getSQLShortForm(int nbOfCharacters)
00326   {
00327     if ((nbOfCharacters == 0) || (sqlQuery.length() < nbOfCharacters))
00328       return sqlQuery;
00329     else
00330       return sqlQuery.substring(0, nbOfCharacters) + "...";
00331   }
00332 
00333   /**
00334    * Get the maximum number of rows the ResultSet can contain.
00335    * 
00336    * @return maximum number of rows
00337    * @see java.sql.Statement#getMaxRows()
00338    */
00339   public int getMaxRows()
00340   {
00341     return maxRows;
00342   }
00343 
00344   /**
00345    * Set the maximum number of rows in the ResultSet.
00346    * 
00347    * @param rows maximum number of rows
00348    * @see java.sql.Statement#setMaxRows(int)
00349    */
00350   public void setMaxRows(int rows)
00351   {
00352     maxRows = rows;
00353   }
00354 
00355   /**
00356    * Set the SQL code of this request. Warning! The request parsing validity is
00357    * not checked. The caller has to recall
00358    * {@link #parse(DatabaseSchema, int, boolean)}if needed.
00359    * 
00360    * @param sql SQL statement
00361    */
00362   public void setSQL(String sql)
00363   {
00364     this.sqlQuery = sql;
00365   }
00366 
00367   /**
00368    * Gets the timeout for this request in seconds.
00369    * 
00370    * @return timeout in seconds (0 means no timeout)
00371    */
00372   public int getTimeout()
00373   {
00374     return timeout;
00375   }
00376 
00377   /**
00378    * Sets the new timeout in seconds for this request.
00379    * 
00380    * @param timeout an <code>int</code> value
00381    */
00382   public void setTimeout(int timeout)
00383   {
00384     this.timeout = timeout;
00385   }
00386 
00387   /**
00388    * Gets the identifier of the transaction if this request belongs to a
00389    * transaction, or -1 if this request does not belong to a transaction.
00390    * 
00391    * @return transaction identifier or -1
00392    */
00393   public long getTransactionId()
00394   {
00395     return transactionId;
00396   }
00397 
00398   /**
00399    * Sets the transaction identifier this request belongs to.
00400    * 
00401    * @param id transaction id
00402    */
00403   public void setTransactionId(long id)
00404   {
00405     transactionId = id;
00406   }
00407 
00408   /**
00409    * Two requests are equal if they have the same SQL code.
00410    * 
00411    * @param other an object
00412    * @return a <code>boolean</code> value
00413    */
00414   public boolean equals(Object other)
00415   {
00416     if (!(other instanceof AbstractRequest))
00417       return false;
00418 
00419     AbstractRequest r = (AbstractRequest) other;
00420     return sqlQuery.equals(r.getSQL())
00421         && (transactionId == r.getTransactionId());
00422   }
00423 
00424   /**
00425    * Parses the SQL request and extract the selected columns and tables given
00426    * the <code>DatabaseSchema</code> of the database targeted by this request.
00427    * <p>
00428    * An exception is thrown when the parsing fails. Warning, this method does
00429    * not check the validity of the request. In particular, invalid request could
00430    * be parsed without throwing an exception. However, valid SQL request should
00431    * never throw an exception.
00432    * 
00433    * @param schema a <code>DatabaseSchema</code> value
00434    * @param granularity parsing granularity as defined in
00435    *          <code>ParsingGranularities</code>
00436    * @param isCaseSensitive true if parsing must be case sensitive
00437    * @exception SQLException if the parsing fails
00438    */
00439   public abstract void parse(DatabaseSchema schema, int granularity,
00440       boolean isCaseSensitive) throws SQLException;
00441 
00442   /**
00443    * Clones the parsing of a request.
00444    * 
00445    * @param request the parsed request to clone
00446    */
00447   public abstract void cloneParsing(AbstractRequest request);
00448 
00449   /**
00450    * If the query has a skeleton defined, return the skeleton wth all carriage
00451    * returns replaces with spaces. If no SQL skeleton is defined, we perform the
00452    * same processing on the instanciated SQL statement.
00453    * 
00454    * @return statement with CR replaces by spaces
00455    */
00456   public String trimCarriageReturn()
00457   {
00458     if (sqlSkeleton != null)
00459       return trimCarriageReturn(sqlSkeleton);
00460     else
00461       return trimCarriageReturn(sqlQuery);
00462   }
00463 
00464   /**
00465    * Replaces any carriage returns by a space in a given <code>String</code>.
00466    * 
00467    * @param s the <code>String</code> to transform
00468    * @return the transformed <code>String</code>
00469    */
00470   private String trimCarriageReturn(String s)
00471   {
00472     int lineSeparatorLength = lineSeparator.length();
00473     int idx = s.indexOf(lineSeparator);
00474     if (idx == -1)
00475       return s;
00476     else
00477     {
00478       if (idx == 0) // carriage is the first character
00479         return trimCarriageReturn(s.substring(lineSeparatorLength));
00480       else if (idx == (s.length() - lineSeparatorLength)) // is the last
00481         // character
00482         return s.substring(0, s.length() - lineSeparatorLength);
00483       else
00484         // is somewhere in the string
00485         return s.substring(0, idx) + " "
00486             + trimCarriageReturn(s.substring(idx + lineSeparatorLength));
00487     }
00488   }
00489 
00490   /**
00491    * @return the SQL query skeleton given in a <code>PreparedStatement</code>.
00492    */
00493   public String getSqlSkeleton()
00494   {
00495     return sqlSkeleton;
00496   }
00497 
00498   /**
00499    * @param skel set the SQL query skeleton given in a
00500    *          <code>PreparedStatement</code>.
00501    */
00502   public void setSqlSkeleton(String skel)
00503   {
00504     sqlSkeleton = skel;
00505   }
00506 
00507   /**
00508    * Returns the driverProcessed value.
00509    * 
00510    * @return Returns the driverProcessed.
00511    */
00512   public boolean isDriverProcessed()
00513   {
00514     return driverProcessed;
00515   }
00516 
00517   /**
00518    * Sets the driverProcessed value.
00519    * 
00520    * @param driverProcessed The driverProcessed to set.
00521    */
00522   public void setDriverProcessed(boolean driverProcessed)
00523   {
00524     this.driverProcessed = driverProcessed;
00525   }
00526 
00527   /**
00528    * Sets the fetchSize value.
00529    * 
00530    * @param fetchSize The fetchSize to set.
00531    */
00532   public void setFetchSize(int fetchSize)
00533   {
00534     this.fetchSize = fetchSize;
00535   }
00536 
00537   /**
00538    * Returns the fetchSize value.
00539    * 
00540    * @return Returns the fetchSize.
00541    */
00542   public int getFetchSize()
00543   {
00544     return fetchSize;
00545   }
00546 
00547   /**
00548    * Displays some debugging information about this request.
00549    */
00550   public void debug()
00551   {
00552     System.out.println("Request: " + sqlQuery);
00553     System.out.print("Cacheable status: ");
00554     System.out.println(RequestType.getInformation(cacheable));
00555   }
00556 
00557 }

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