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

PreparedStatement.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): Nicolas Modrzyk, Jaco Swart.
00023  */
00024 
00025 package org.objectweb.cjdbc.driver;
00026 
00027 import java.io.ByteArrayInputStream;
00028 import java.io.ByteArrayOutputStream;
00029 import java.io.IOException;
00030 import java.io.InputStream;
00031 import java.io.ObjectInputStream;
00032 import java.io.ObjectOutputStream;
00033 import java.io.Serializable;
00034 import java.math.BigDecimal;
00035 import java.sql.Array;
00036 import java.sql.Date;
00037 import java.sql.ParameterMetaData;
00038 import java.sql.Ref;
00039 import java.sql.SQLException;
00040 import java.sql.Time;
00041 import java.sql.Timestamp;
00042 import java.sql.Types;
00043 import java.text.ParseException;
00044 import java.text.SimpleDateFormat;
00045 import java.util.ArrayList;
00046 
00047 import org.objectweb.cjdbc.common.sql.NotImplementedException;
00048 import org.objectweb.cjdbc.common.sql.filters.HexaBlobFilter;
00049 import org.objectweb.cjdbc.common.util.Strings;
00050 
00051 /**
00052  * A SQL Statement is pre-compiled and stored in a
00053  * <code>PreparedStatement</code> object. This object can then be used to
00054  * efficiently execute this statement multiple times.
00055  * <p>
00056  * <b>Note: </b> The setXXX methods for setting IN parameter values must specify
00057  * types that are compatible with the defined SQL type of the input parameter.
00058  * For instance, if the IN parameter has SQL type Integer, then setInt should be
00059  * used.
00060  * <p>
00061  * If arbitrary parameter type conversions are required, then the setObject
00062  * method should be used with a target SQL type.
00063  * <p>
00064  * For instance, this is just a dirty copy/paste from the PostgreSQL driver !
00065  * Implementation has to be completly checked and revised.
00066  * 
00067  * @see DriverResultSet
00068  * @see java.sql.PreparedStatement
00069  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00070  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00071  * @author <a href="mailto:marc.wick@monte-bre.ch">Marc Wick </a>
00072  * @author <a href="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
00073  * @version 1.0
00074  */
00075 public class PreparedStatement extends Statement
00076     implements
00077       java.sql.PreparedStatement
00078 {
00079   /** Tag for a byte parameter */
00080   public static final String BYTE_TAG        = "b|";
00081   /** Tag for a bytes (used for Blob) parameter */
00082   public static final String BYTES_TAG       = "B|";
00083   /** Tag for a BLOB (used for null Blob) parameter */
00084   public static final String BLOB_TAG        = "c|";
00085   /** Tag for a CLOB (used for null Clob) parameter */
00086   public static final String CLOB_TAG        = "C|";
00087   /** Tag for a boolean parameter */
00088   public static final String BOOLEAN_TAG     = "0|";
00089   /** Tag for a big decimal parameter */
00090   public static final String BIG_DECIMAL_TAG = "1|";
00091   /** Tag for a date parameter */
00092   public static final String DATE_TAG        = "d|";
00093   /** Tag for a double parameter */
00094   public static final String DOUBLE_TAG      = "D|";
00095   /** Tag for a float parameter */
00096   public static final String FLOAT_TAG       = "F|";
00097   /** Tag for a integer parameter */
00098   public static final String INTEGER_TAG     = "I|";
00099   /** Tag for a long parameter */
00100   public static final String LONG_TAG        = "L|";
00101   /** Tag for a setNull call */
00102   public static final String NULL_TAG        = "N|";
00103   /** Tag for an object parameter */
00104   public static final String OBJECT_TAG      = "O|";
00105   /** Tag for a short parameter */
00106   public static final String SHORT_TAG       = "s|";
00107   /** Tag for a string parameter */
00108   public static final String STRING_TAG      = "S|";
00109   /** Tag for a time parameter */
00110   public static final String TIME_TAG        = "t|";
00111   /** Tag for a timestamp parameter */
00112   public static final String TIMESTAMP_TAG   = "T|";
00113 
00114   protected String           sql;
00115   private String[]           templateStrings;
00116   private String[]           inStrings;
00117 
00118   // Some performance caches
00119   private StringBuffer       sbuf            = new StringBuffer();
00120 
00121   /**
00122    * Constructor. Splits the SQL statement into segments - separated by the
00123    * arguments. When we rebuild the thing with the arguments, we can substitute
00124    * the args and join the whole thing together.
00125    * 
00126    * @param connection the instanatiating connection
00127    * @param sqlStatement the SQL statement with ? for IN markers
00128    * @exception SQLException if something bad occurs
00129    */
00130   public PreparedStatement(Connection connection, String sqlStatement)
00131       throws SQLException
00132   {
00133     super(connection);
00134 
00135     ArrayList v = new ArrayList();
00136     int lastParmEnd = 0;
00137 
00138     // The following two boolean switches are used to make sure we're not
00139     // counting "?" in either strings or metadata strings. For instance the
00140     // following query:
00141     //    select '?' "A ? value" from dual
00142     // doesn't have any parameters.
00143 
00144     boolean inString = false;
00145     boolean inMetaString = false;
00146 
00147     this.sql = sqlStatement.trim();
00148     this.connection = connection;
00149     for (int i = 0; i < sql.length(); ++i)
00150     {
00151       if (sql.charAt(i) == '\'')
00152         inString = !inString;
00153       if (sql.charAt(i) == '"')
00154         inMetaString = !inMetaString;
00155       if ((sql.charAt(i) == '?') && (!(inString || inMetaString)))
00156       {
00157         v.add(sql.substring(lastParmEnd, i));
00158         lastParmEnd = i + 1;
00159       }
00160     }
00161     v.add(sql.substring(lastParmEnd, sql.length()));
00162 
00163     int size = v.size();
00164     templateStrings = new String[size];
00165     inStrings = new String[size - 1];
00166     clearParameters();
00167 
00168     for (int i = 0; i < size; ++i)
00169       templateStrings[i] = (String) v.get(i);
00170   }
00171 
00172   /**
00173    * Release objects for garbage collection and call Statement.close().
00174    * 
00175    * @throws SQLException if an error occurs
00176    */
00177   public void close() throws SQLException
00178   {
00179     sql = null;
00180     templateStrings = null;
00181     inStrings = null;
00182 
00183     super.close();
00184   }
00185 
00186   /**
00187    * A Prepared SQL query is executed and its <code>ResultSet</code> is
00188    * returned.
00189    * 
00190    * @return a <code>ResultSet</code> that contains the data produced by the *
00191    *         query - never <code>null</code>.
00192    * @exception SQLException if a database access error occurs
00193    */
00194   public java.sql.ResultSet executeQuery() throws SQLException
00195   {
00196     return super.executeQuery(sql, compileQuery()); // in Statement class
00197   }
00198 
00199   /**
00200    * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
00201    * statements that return nothing such as SQL DDL statements can be executed.
00202    * 
00203    * @return either the row count for <code>INSERT</code>,
00204    *         <code>UPDATE</code> or <code>DELETE</code>; or 0 for SQL
00205    *         statements that return nothing.
00206    * @exception SQLException if a database access error occurs
00207    */
00208   public int executeUpdate() throws SQLException
00209   {
00210     return super.executeUpdateWithSkeleton(sql, compileQuery());
00211     // in Statement class
00212   }
00213 
00214   /**
00215    * Helper - this compiles the SQL query from the various parameters This is
00216    * identical to toString() except it throws an exception if a parameter is
00217    * unused.
00218    * 
00219    * @return the compiled query
00220    * @throws SQLException if an error occurs
00221    */
00222   protected synchronized String compileQuery() throws SQLException
00223   {
00224     sbuf.setLength(0);
00225     int i;
00226 
00227     for (i = 0; i < inStrings.length; ++i)
00228     {
00229       if (inStrings[i] == null)
00230         throw new SQLException("Parameter " + (i + 1) + " is incorrect");
00231       sbuf.append(templateStrings[i]).append(inStrings[i]);
00232     }
00233     sbuf.append(templateStrings[inStrings.length]);
00234     return sbuf.toString();
00235   }
00236 
00237   /**
00238    * Escape the input string. <br>
00239    * <char>' </char> is replaced by <char>\' </char> <br>
00240    * <char>\ </char> is replaced by <char>\\' </char> <br>
00241    * if connection.escapeProcessing is set to true, surround the new string with
00242    * <char>\' </char>
00243    * 
00244    * @param x the string to process
00245    * @return escaped string
00246    */
00247   protected String doEscapeProcessing(String x)
00248   {
00249     // use the shared buffer object. Should never clash but this
00250     // makes us thread safe!
00251     synchronized (sbuf)
00252     {
00253       sbuf.setLength(0);
00254       int i;
00255       sbuf.append(connection.getEscapeChar());
00256       for (i = 0; i < x.length(); ++i)
00257       {
00258         char c = x.charAt(i);
00259         if ((c == '\'' && connection.isEscapeSingleQuote())
00260             || (c == '\\' && connection.isEscapeBackslash()))
00261           sbuf.append(c);
00262         sbuf.append(c);
00263       }
00264       sbuf.append(connection.getEscapeChar());
00265     }
00266     return sbuf.toString();
00267   }
00268 
00269   /**
00270    * Sets a parameter to SQL NULL.
00271    * <p>
00272    * <b>Note: </b> you must specify the parameters SQL type but we ignore it.
00273    * 
00274    * @param parameterIndex the first parameter is 1, etc...
00275    * @param sqlType the SQL type code defined in java.sql.Types
00276    * @exception SQLException if a database access error occurs
00277    */
00278   public void setNull(int parameterIndex, int sqlType) throws SQLException
00279   {
00280     if (connection.isDriverProcessed())
00281       set(parameterIndex, "null");
00282     else
00283       setWithTag(parameterIndex, NULL_TAG, String.valueOf(sqlType));
00284   }
00285 
00286   /**
00287    * Sets a parameter to a Java boolean value. The driver converts this to a SQL
00288    * BIT value when it sends it to the database.
00289    * 
00290    * @param parameterIndex the first parameter is 1...
00291    * @param x the parameter value
00292    * @exception SQLException if a database access error occurs
00293    */
00294   public void setBoolean(int parameterIndex, boolean x) throws SQLException
00295   {
00296     if (connection.isDriverProcessed())
00297     {
00298       set(parameterIndex, x
00299           ? connection.getPreparedStatementBooleanTrue()
00300           : connection.getPreparedStatementBooleanFalse());
00301     }
00302     else
00303     {
00304       setWithTag(parameterIndex, BOOLEAN_TAG, String.valueOf(x));
00305     }
00306   }
00307 
00308   /**
00309    * Sets a parameter to a Java byte value.
00310    * 
00311    * @param parameterIndex the first parameter is 1...
00312    * @param x the parameter value
00313    * @exception SQLException if a database access error occurs
00314    */
00315   public void setByte(int parameterIndex, byte x) throws SQLException
00316   {
00317     if (connection.isDriverProcessed())
00318     {
00319       set(parameterIndex, Integer.toString(x));
00320     }
00321     else
00322     {
00323       setWithTag(parameterIndex, BYTE_TAG, Integer.toString(x));
00324     }
00325   }
00326 
00327   /**
00328    * Sets a parameter to a Java short value. The driver converts this to a SQL
00329    * SMALLINT value when it sends it to the database.
00330    * 
00331    * @param parameterIndex the first parameter is 1...
00332    * @param x the parameter value
00333    * @exception SQLException if a database access error occurs
00334    */
00335   public void setShort(int parameterIndex, short x) throws SQLException
00336   {
00337     if (connection.isDriverProcessed())
00338     {
00339       set(parameterIndex, Integer.toString(x));
00340     }
00341     else
00342     {
00343       setWithTag(parameterIndex, SHORT_TAG, Integer.toString(x));
00344     }
00345   }
00346 
00347   /**
00348    * Sets a parameter to a Java int value. The driver converts this to a SQL
00349    * INTEGER value when it sends it to the database.
00350    * 
00351    * @param parameterIndex the first parameter is 1...
00352    * @param x the parameter value
00353    * @exception SQLException if a database access error occurs
00354    */
00355   public void setInt(int parameterIndex, int x) throws SQLException
00356   {
00357     if (connection.isDriverProcessed())
00358     {
00359       set(parameterIndex, Integer.toString(x));
00360     }
00361     else
00362     {
00363       setWithTag(parameterIndex, INTEGER_TAG, Integer.toString(x));
00364     }
00365   }
00366 
00367   /**
00368    * Sets a parameter to a Java long value. The driver converts this to a SQL
00369    * BIGINT value when it sends it to the database.
00370    * 
00371    * @param parameterIndex the first parameter is 1...
00372    * @param x the parameter value
00373    * @exception SQLException if a database access error occurs
00374    */
00375   public void setLong(int parameterIndex, long x) throws SQLException
00376   {
00377     if (connection.isDriverProcessed())
00378     {
00379       set(parameterIndex, Long.toString(x));
00380     }
00381     else
00382     {
00383       setWithTag(parameterIndex, LONG_TAG, Long.toString(x));
00384     }
00385   }
00386 
00387   /**
00388    * Sets a parameter to a Java float value. The driver converts this to a SQL
00389    * FLOAT value when it sends it to the database.
00390    * 
00391    * @param parameterIndex the first parameter is 1...
00392    * @param x the parameter value
00393    * @exception SQLException if a database access error occurs
00394    */
00395   public void setFloat(int parameterIndex, float x) throws SQLException
00396   {
00397     if (connection.isDriverProcessed())
00398     {
00399       set(parameterIndex, Float.toString(x));
00400     }
00401     else
00402     {
00403       setWithTag(parameterIndex, FLOAT_TAG, Float.toString(x));
00404     }
00405   }
00406 
00407   /**
00408    * Sets a parameter to a Java double value. The driver converts this to a SQL
00409    * DOUBLE value when it sends it to the database.
00410    * 
00411    * @param parameterIndex the first parameter is 1...
00412    * @param x the parameter value
00413    * @exception SQLException if a database access error occurs
00414    */
00415   public void setDouble(int parameterIndex, double x) throws SQLException
00416   {
00417     if (connection.isDriverProcessed())
00418     {
00419       set(parameterIndex, Double.toString(x));
00420     }
00421     else
00422     {
00423       setWithTag(parameterIndex, DOUBLE_TAG, Double.toString(x));
00424     }
00425   }
00426 
00427   /**
00428    * Sets a parameter to a java.lang.BigDecimal value. The driver converts this
00429    * to a SQL NUMERIC value when it sends it to the database.
00430    * 
00431    * @param parameterIndex the first parameter is 1...
00432    * @param x the parameter value
00433    * @exception SQLException if a database access error occurs
00434    */
00435   public void setBigDecimal(int parameterIndex, BigDecimal x)
00436       throws SQLException
00437   {
00438     if (connection.isDriverProcessed())
00439     {
00440       if (x == null)
00441         setNull(parameterIndex, Types.DECIMAL);
00442       else
00443         set(parameterIndex, x.toString());
00444     }
00445     else
00446     {
00447       if (x == null)
00448         setWithTag(parameterIndex, BIG_DECIMAL_TAG, NULL_TAG);
00449       else
00450         setWithTag(parameterIndex, BIG_DECIMAL_TAG, x.toString());
00451     }
00452   }
00453 
00454   /**
00455    * Sets a parameter to a Java String value. The driver converts this to a SQL
00456    * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
00457    * the driver's limits on VARCHARs) when it sends it to the database.
00458    * 
00459    * @param parameterIndex the first parameter is 1...
00460    * @param x the parameter value
00461    * @exception SQLException if a database access error occurs
00462    */
00463   public void setString(int parameterIndex, String x) throws SQLException
00464   {
00465     if (connection.isDriverProcessed())
00466     {
00467       if (x == null)
00468         // if the passed string is null, then set this column to null
00469         setNull(parameterIndex, Types.VARCHAR);
00470       else
00471       {
00472         if (escapeProcessing
00473             && (connection.isEscapeBackslash() || connection
00474                 .isEscapeSingleQuote()))
00475           set(parameterIndex, doEscapeProcessing(x));
00476         else
00477           // No escape processing
00478           set(parameterIndex, x);
00479       }
00480     }
00481     else
00482     {
00483       if (x == null)
00484         setWithTag(parameterIndex, STRING_TAG, NULL_TAG);
00485       else
00486         // No escape processing is needed for queries not being parsed into
00487         // statements.
00488         setWithTag(parameterIndex, STRING_TAG, x);
00489     }
00490   }
00491 
00492   /**
00493    * Sets a parameter to a Java array of bytes. The driver converts this to a
00494    * SQL VARBINARY or LONGVARBINARY (depending on the argument's size relative
00495    * to the driver's limits on VARBINARYs) when it sends it to the database.
00496    * <p>
00497    * Implementation note: with org.postgresql, this creates a large object, and
00498    * stores the objects oid in this column.
00499    * 
00500    * @param parameterIndex the first parameter is 1...
00501    * @param x the parameter value
00502    * @exception SQLException if a database access error occurs
00503    */
00504   public void setBytes(int parameterIndex, byte x[]) throws SQLException
00505   {
00506     String blob;
00507     try
00508     {
00509       synchronized (sbuf)
00510       {
00511         if (connection.isDriverProcessed())
00512         {
00513           blob = connection.getBlobFilter().encode(x);
00514           sbuf.setLength(0);
00515           sbuf.append(connection.escapeChar);
00516           sbuf.append(blob);
00517           sbuf.append(connection.escapeChar);
00518           set(parameterIndex, sbuf.toString());
00519         }
00520         else
00521         {
00522           blob = new HexaBlobFilter().encode(x);
00523           setWithTag(parameterIndex, BYTES_TAG, blob);
00524         }
00525       }
00526     }
00527     catch (OutOfMemoryError oome)
00528     {
00529       blob = null;
00530       sbuf = null;
00531       System.gc();
00532       throw new SQLException("Out of memory");
00533     }
00534   }
00535 
00536   /**
00537    * Sets a parameter to a java.sql.Date value. The driver converts this to a
00538    * SQL DATE value when it sends it to the database.
00539    * 
00540    * @param parameterIndex the first parameter is 1...
00541    * @param x the parameter value
00542    * @exception SQLException if a database access error occurs
00543    */
00544   public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
00545   {
00546     if (connection.isDriverProcessed())
00547     {
00548       if (x == null)
00549         setNull(parameterIndex, Types.DATE);
00550       else
00551         set(parameterIndex, "'" + new java.sql.Date(x.getTime()).toString()
00552             + "'");
00553     }
00554     else
00555     {
00556       if (x == null)
00557         setWithTag(parameterIndex, DATE_TAG, NULL_TAG);
00558       else
00559         setWithTag(parameterIndex, DATE_TAG, new java.sql.Date(x.getTime())
00560             .toString());
00561     }
00562   }
00563 
00564   /**
00565    * Sets a parameter to a <code>java.sql.Time</code> value. The driver
00566    * converts this to a SQL TIME value when it sends it to the database.
00567    * 
00568    * @param parameterIndex the first parameter is 1...));
00569    * @param x the parameter value
00570    * @exception SQLException if a database access error occurs
00571    */
00572   public void setTime(int parameterIndex, Time x) throws SQLException
00573   {
00574     if (connection.isDriverProcessed())
00575     {
00576       if (x == null)
00577         setNull(parameterIndex, Types.TIME);
00578       else
00579         set(parameterIndex, "{t '" + x.toString() + "'}");
00580     }
00581     else
00582     {
00583       if (x == null)
00584         setWithTag(parameterIndex, TIME_TAG, NULL_TAG);
00585       else
00586         setWithTag(parameterIndex, TIME_TAG, x.toString());
00587     }
00588   }
00589 
00590   /**
00591    * Sets a parameter to a <code>java.sql.Timestamp</code> value. The driver
00592    * converts this to a SQL TIMESTAMP value when it sends it to the database.
00593    * 
00594    * @param parameterIndex the first parameter is 1...
00595    * @param x the parameter value
00596    * @exception SQLException if a database access error occurs
00597    */
00598   public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
00599   {
00600     if (connection.isDriverProcessed())
00601     {
00602       if (x == null)
00603         setNull(parameterIndex, Types.TIMESTAMP);
00604       else
00605       {
00606         // Be careful don't use instanceof here since it would match derived
00607         // classes.
00608         if (x.getClass().equals(Timestamp.class))
00609           set(parameterIndex, "'" + x.toString() + "'");
00610         else
00611           set(parameterIndex, "'" + new Timestamp(x.getTime()).toString() + "'");
00612       }
00613     }
00614     else
00615     {
00616       if (x == null)
00617         setWithTag(parameterIndex, TIMESTAMP_TAG, NULL_TAG);
00618       else
00619       {
00620         if (x.getClass().equals(Timestamp.class))
00621           setWithTag(parameterIndex, TIMESTAMP_TAG, x.toString());
00622         else
00623           setWithTag(parameterIndex, TIMESTAMP_TAG, new Timestamp(x.getTime())
00624               .toString());
00625       }
00626     }
00627   }
00628 
00629   /**
00630    * When a very large ASCII value is input to a LONGVARCHAR parameter, it may
00631    * be more practical to send it via a java.io.InputStream. JDBC will read the
00632    * data from the stream as needed, until it reaches end-of-file. The JDBC
00633    * driver will do any necessary conversion from ASCII to the database char
00634    * format.
00635    * <p>
00636    * <b>Note: </b> this stream object can either be a standard Java stream
00637    * object or your own subclass that implements the standard interface.
00638    * 
00639    * @param parameterIndex the first parameter is 1...
00640    * @param x the parameter value
00641    * @param length the number of bytes in the stream
00642    * @exception SQLException if a database access error occurs
00643    */
00644   public void setAsciiStream(int parameterIndex, InputStream x, int length)
00645       throws SQLException
00646   {
00647     setBinaryStream(parameterIndex, x, length);
00648   }
00649 
00650   /**
00651    * When a very large Unicode value is input to a LONGVARCHAR parameter, it may
00652    * be more practical to send it via a java.io.InputStream. JDBC will read the
00653    * data from the stream as needed, until it reaches end-of-file. The JDBC
00654    * driver will do any necessary conversion from UNICODE to the database char
00655    * format.
00656    * <p>** DEPRECIATED IN JDBC 2 **
00657    * <p>
00658    * <b>Note: </b> this stream object can either be a standard Java stream
00659    * object or your own subclass that implements the standard interface.
00660    * 
00661    * @param parameterIndex the first parameter is 1...
00662    * @param x the parameter value
00663    * @param length the parameter length
00664    * @exception SQLException if a database access error occurs
00665    * @deprecated
00666    */
00667   public void setUnicodeStream(int parameterIndex, InputStream x, int length)
00668       throws SQLException
00669   {
00670     setBinaryStream(parameterIndex, x, length);
00671   }
00672 
00673   /**
00674    * When a very large binary value is input to a LONGVARBINARY parameter, it
00675    * may be more practical to send it via a java.io.InputStream. JDBC will read
00676    * the data from the stream as needed, until it reaches end-of-file.
00677    * <p>
00678    * <b>Note: </b> This stream object can either be a standard Java stream
00679    * object or your own subclass that implements the standard interface.
00680    * 
00681    * @param parameterIndex the first parameter is 1...
00682    * @param x the parameter value
00683    * @param length the parameter length
00684    * @exception SQLException if a database access error occurs
00685    */
00686   public void setBinaryStream(int parameterIndex, InputStream x, int length)
00687       throws SQLException
00688   {
00689     byte[] data = new byte[length];
00690     try
00691     {
00692       x.read(data, 0, length);
00693     }
00694     catch (Exception ioe)
00695     {
00696       throw new SQLException("Problem with streaming of data");
00697     }
00698     setBytes(parameterIndex, data);
00699   }
00700 
00701   /**
00702    * In general, parameter values remain in force for repeated used of a
00703    * <code>Statement</code>. Setting a parameter value automatically clears
00704    * its previous value. However, in coms cases, it is useful to immediately
00705    * release the resources used by the current parameter values; this can be
00706    * done by calling <code>clearParameters()</code>.
00707    * 
00708    * @exception SQLException if a database access error occurs
00709    */
00710   public void clearParameters() throws SQLException
00711   {
00712     int i;
00713 
00714     for (i = 0; i < inStrings.length; i++)
00715       inStrings[i] = null;
00716   }
00717 
00718   /**
00719    * Sets the value of a parameter using an object; use the
00720    * <code>java.lang</code> equivalent objects for integral values.
00721    * <p>
00722    * The given Java object will be converted to the targetSqlType before being
00723    * sent to the database.
00724    * <p>
00725    * Note that this method may be used to pass database-specific abstract data
00726    * types. This is done by using a Driver-specific Java type and using a
00727    * <code>targetSqlType</code> of <code>java.sql.Types.OTHER</code>.
00728    * 
00729    * @param parameterIndex the first parameter is 1...
00730    * @param x the object containing the input parameter value
00731    * @param targetSqlType The SQL type to be send to the database
00732    * @param scale for <code>java.sql.Types.DECIMAL</code> or
00733    *          <code>java.sql.Types.NUMERIC</code> types this is the number of
00734    *          digits after the decimal. For all other types this value will be
00735    *          ignored.
00736    * @exception SQLException if a database access error occurs
00737    */
00738   public void setObject(int parameterIndex, Object x, int targetSqlType,
00739       int scale) throws SQLException
00740   {
00741     if (x == null)
00742     {
00743       setNull(parameterIndex, targetSqlType);
00744     }
00745     else
00746     {
00747       switch (targetSqlType)
00748       {
00749         case Types.TINYINT :
00750         case Types.SMALLINT :
00751         case Types.INTEGER :
00752           setInt(parameterIndex, ((Number) x).intValue());
00753           break;
00754         case Types.BIGINT :
00755           setLong(parameterIndex, ((Number) x).longValue());
00756           break;
00757         case Types.REAL :
00758         case Types.FLOAT :
00759         case Types.DOUBLE :
00760         case Types.DECIMAL :
00761         case Types.NUMERIC :
00762           // Cast to Number is not necessary
00763           if (connection.isDriverProcessed())
00764             set(parameterIndex, x.toString());
00765           else
00766             setWithTag(parameterIndex, STRING_TAG, x.toString());
00767           break;
00768         case Types.BIT :
00769         case Types.BOOLEAN :
00770           setBoolean(parameterIndex, ((Boolean) x).booleanValue());
00771           break;
00772         case Types.CHAR :
00773         case Types.VARCHAR :
00774         case Types.LONGVARCHAR :
00775           setString(parameterIndex, (String) x);
00776           break;
00777         case Types.BINARY :
00778         case Types.VARBINARY :
00779         case Types.LONGVARBINARY :
00780           setBytes(parameterIndex, (byte[]) x);
00781           break;
00782         case Types.DATE :
00783           setDate(parameterIndex, (java.sql.Date) x);
00784           break;
00785         case Types.TIME :
00786           setTime(parameterIndex, (Time) x);
00787           break;
00788         case Types.TIMESTAMP :
00789           setTimestamp(parameterIndex, (Timestamp) x);
00790           break;
00791         case Types.BLOB :
00792           setBlob(parameterIndex, (Blob) x);
00793           break;
00794         case Types.DATALINK :
00795           setURL(parameterIndex, (java.net.URL) x);
00796           break;
00797         case Types.JAVA_OBJECT :
00798         case Types.OTHER :
00799           setObject(parameterIndex, x);
00800           break;
00801         default :
00802           throw new SQLException("Unsupported type value");
00803       }
00804     }
00805   }
00806 
00807   /**
00808    * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int)
00809    */
00810   public void setObject(int parameterIndex, Object x, int targetSqlType)
00811       throws SQLException
00812   {
00813     setObject(parameterIndex, x, targetSqlType, 0);
00814   }
00815 
00816   /**
00817    * This stores an Object into a parameter.
00818    * 
00819    * @param parameterIndex the first parameter is 1...
00820    * @param x the object to set
00821    * @exception SQLException if a database access error occurs
00822    */
00823   public void setObject(int parameterIndex, Object x) throws SQLException
00824   {
00825     if (x == null)
00826     {
00827       if (connection.isDriverProcessed())
00828         setNull(parameterIndex, Types.JAVA_OBJECT);
00829       else
00830         setWithTag(parameterIndex, OBJECT_TAG, NULL_TAG);
00831     }
00832     else
00833     {
00834       if (x instanceof String)
00835         setString(parameterIndex, (String) x);
00836       else if (x instanceof BigDecimal)
00837         setBigDecimal(parameterIndex, (BigDecimal) x);
00838       else if (x instanceof Short)
00839         setShort(parameterIndex, ((Short) x).shortValue());
00840       else if (x instanceof Integer)
00841         setInt(parameterIndex, ((Integer) x).intValue());
00842       else if (x instanceof Long)
00843         setLong(parameterIndex, ((Long) x).longValue());
00844       else if (x instanceof Float)
00845         setFloat(parameterIndex, ((Float) x).floatValue());
00846       else if (x instanceof Double)
00847         setDouble(parameterIndex, ((Double) x).doubleValue());
00848       else if (x instanceof byte[])
00849         setBytes(parameterIndex, (byte[]) x);
00850       else if (x instanceof java.sql.Date)
00851         setDate(parameterIndex, (java.sql.Date) x);
00852       else if (x instanceof Time)
00853         setTime(parameterIndex, (Time) x);
00854       else if (x instanceof Timestamp)
00855         setTimestamp(parameterIndex, (Timestamp) x);
00856       else if (x instanceof Boolean)
00857         setBoolean(parameterIndex, ((Boolean) x).booleanValue());
00858       else if (x instanceof Blob)
00859         setBlob(parameterIndex, (Blob) x);
00860       else if (x instanceof java.net.URL)
00861         setURL(parameterIndex, (java.net.URL) x);
00862       else if (x instanceof Serializable)
00863       {
00864         ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
00865         try
00866         {
00867           // Serialize object to byte array
00868           ObjectOutputStream objectOutputStream = new ObjectOutputStream(
00869               byteOutputStream);
00870           objectOutputStream.writeObject(x);
00871           objectOutputStream.flush();
00872           objectOutputStream.close();
00873           if (connection.isDriverProcessed())
00874             setBytes(parameterIndex, byteOutputStream.toByteArray());
00875           else
00876             synchronized (sbuf)
00877             {
00878               sbuf.setLength(0);
00879               sbuf.append(byteOutputStream);
00880               setWithTag(parameterIndex, OBJECT_TAG, sbuf.toString());
00881             }
00882         }
00883         catch (IOException e)
00884         {
00885           throw new SQLException("Failed to serialize object: " + e);
00886         }
00887       }
00888       else
00889         throw new SQLException("Objects of type " + x.getClass()
00890             + " are not supported.");
00891     }
00892   }
00893 
00894   /**
00895    * Some prepared statements return multiple results; the execute method
00896    * handles these complex statements as well as the simpler form of statements
00897    * handled by <code>executeQuery()</code> and <code>executeUpdate()</code>.
00898    * 
00899    * @return <code>true</code> if the next result is a
00900    *         <code>ResultSet<code>; <code>false<code> if it is an update count
00901    * or there are no more results
00902    * @exception SQLException if a database access error occurs
00903    */
00904   public boolean execute() throws SQLException
00905   {
00906     int start = 0;
00907     try
00908     {
00909       // Ignore any leading parenthesis
00910       while (sql.charAt(start) == '(')
00911         start++;
00912     }
00913     catch (IndexOutOfBoundsException e)
00914     {
00915       // Probably a buggy request, let it go through and let thefollowing code
00916       // to report an accurate error if any.
00917       start = 0;
00918     }
00919 
00920     if (sql.regionMatches(true, start, "select", 0, 6)
00921         || (sql.regionMatches(true, start, "{call", 0, 5)))
00922     {
00923       result = executeQuery(sql, compileQuery());
00924       return true;
00925     }
00926     else
00927     {
00928       updateCount = executeUpdateWithSkeleton(sql, compileQuery());
00929       return false;
00930     }
00931   }
00932 
00933   /**
00934    * Returns the SQL statement with the current template values substituted.
00935    * <p>
00936    * <b>Note: </b>: This is identical to <code>compileQuery()</code> except
00937    * instead of throwing SQLException if a parameter is <code>null</code>, it
00938    * places ? instead.
00939    * 
00940    * @return the SQL statement
00941    */
00942   public String toString()
00943   {
00944     synchronized (sbuf)
00945     {
00946       sbuf.setLength(0);
00947       int i;
00948 
00949       for (i = 0; i < inStrings.length; ++i)
00950       {
00951         if (inStrings[i] == null)
00952           sbuf.append('?');
00953         else
00954           sbuf.append(templateStrings[i]);
00955         sbuf.append(inStrings[i]);
00956       }
00957       sbuf.append(templateStrings[inStrings.length]);
00958       return sbuf.toString();
00959     }
00960   }
00961 
00962   // ** JDBC 2 Extensions **
00963 
00964   /**
00965    * This parses the query and adds it to the current batch
00966    * 
00967    * @throws SQLException if an error occurs
00968    */
00969   public void addBatch() throws SQLException
00970   {
00971     super.addBatch(compileQuery());
00972   }
00973 
00974   /**
00975    * Returns the <code>MetaData</code> for the last <code>ResultSet</code>
00976    * returned.
00977    * 
00978    * @return The ResultSet Metadata
00979    * @throws SQLException if an error occurs
00980    */
00981   public java.sql.ResultSetMetaData getMetaData() throws SQLException
00982   {
00983     java.sql.ResultSet rs = getResultSet();
00984     if (rs != null)
00985       return rs.getMetaData();
00986 
00987     // Does anyone really know what this method does?
00988     return null;
00989   }
00990 
00991   /**
00992    * @see java.sql.PreparedStatement#setArray(int, java.sql.Array)
00993    */
00994   public void setArray(int i, Array x) throws SQLException
00995   {
00996     throw new NotImplementedException("setArray()");
00997   }
00998 
00999   /**
01000    * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob)
01001    */
01002   public void setBlob(int i, java.sql.Blob x) throws SQLException
01003   {
01004     if (x == null)
01005     {
01006       if (connection.isDriverProcessed())
01007         setNull(i, Types.BLOB);
01008       else
01009         setWithTag(i, BLOB_TAG, NULL_TAG);
01010       return;
01011     }
01012 
01013     if (connection.isDriverProcessed())
01014       setBinaryStream(i, x.getBinaryStream(), (int) x.length());
01015     else
01016     {
01017       byte[] data = new byte[(int) x.length()];
01018       InputStream binStream = x.getBinaryStream();
01019       try
01020       {
01021         binStream.read(data, 0, (int) x.length());
01022       }
01023       catch (Exception ioe)
01024       {
01025         throw new SQLException("Problem with data streaming");
01026       }
01027       try
01028       {
01029         synchronized (sbuf)
01030         {
01031           sbuf.setLength(0);
01032           sbuf.append(new HexaBlobFilter().encode(data));
01033           setWithTag(i, BLOB_TAG, sbuf.toString());
01034         }
01035       }
01036       catch (OutOfMemoryError oome)
01037       {
01038         sbuf = null;
01039         System.gc();
01040         throw new SQLException("Out of memory");
01041       }
01042 
01043     }
01044   }
01045 
01046   /**
01047    * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader,
01048    *      int)
01049    */
01050   public void setCharacterStream(int i, java.io.Reader x, int length)
01051       throws SQLException
01052   {
01053     char[] data = new char[length];
01054     try
01055     {
01056       x.read(data, 0, length);
01057     }
01058     catch (Exception ioe)
01059     {
01060       throw new SQLException("Problem with streaming of data");
01061     }
01062     setString(i, new String(data));
01063   }
01064 
01065   /**
01066    * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob)
01067    */
01068   public void setClob(int i, java.sql.Clob x) throws SQLException
01069   {
01070     if (x == null)
01071     {
01072       if (connection.isDriverProcessed())
01073         setNull(i, Types.CLOB);
01074       else
01075         setWithTag(i, CLOB_TAG, NULL_TAG);
01076       return;
01077     }
01078     if (connection.isDriverProcessed())
01079       setString(i, x.getSubString(0, (int) x.length()));
01080     else
01081       setWithTag(i, CLOB_TAG, x.getSubString(0, (int) x.length()));
01082   }
01083 
01084   /**
01085    * @see java.sql.PreparedStatement#setNull(int, int, java.lang.String)
01086    */
01087   public void setNull(int i, int t, String s) throws SQLException
01088   {
01089     setNull(i, t);
01090   }
01091 
01092   /**
01093    * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref)
01094    */
01095   public void setRef(int i, Ref x) throws SQLException
01096   {
01097     throw new NotImplementedException("setRef()");
01098   }
01099 
01100   /**
01101    * @see java.sql.PreparedStatement#setDate(int, java.sql.Date,
01102    *      java.util.Calendar)
01103    */
01104   public void setDate(int i, java.sql.Date d, java.util.Calendar cal)
01105       throws SQLException
01106   {
01107     if (d == null)
01108     {
01109       if (connection.isDriverProcessed())
01110         setNull(i, Types.DATE);
01111       else
01112         setWithTag(i, DATE_TAG, NULL_TAG);
01113       return;
01114     }
01115     else
01116     {
01117       if (cal == null)
01118         setDate(i, d);
01119       else
01120       {
01121         cal.setTime(d);
01122         setDate(i, new java.sql.Date(cal.getTime().getTime()));
01123       }
01124     }
01125   }
01126 
01127   /**
01128    * @see java.sql.PreparedStatement#setTime(int, java.sql.Time,
01129    *      java.util.Calendar)
01130    */
01131   public void setTime(int i, Time t, java.util.Calendar cal)
01132       throws SQLException
01133   {
01134     if (t == null)
01135     {
01136       if (connection.isDriverProcessed())
01137         setNull(i, Types.TIME);
01138       else
01139         setWithTag(i, TIME_TAG, NULL_TAG);
01140       return;
01141     }
01142     else
01143     {
01144       if (cal == null)
01145         setTime(i, t);
01146       else
01147       {
01148         cal.setTime(t);
01149         setTime(i, new java.sql.Time(cal.getTime().getTime()));
01150       }
01151     }
01152   }
01153 
01154   /**
01155    * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp,
01156    *      java.util.Calendar)
01157    */
01158   public void setTimestamp(int i, Timestamp t, java.util.Calendar cal)
01159       throws SQLException
01160   {
01161     if (t == null)
01162     {
01163       if (connection.isDriverProcessed())
01164         setNull(i, Types.TIMESTAMP);
01165       else
01166         setWithTag(i, TIMESTAMP_TAG, NULL_TAG);
01167       return;
01168     }
01169     else
01170     {
01171       if (cal == null)
01172         setTimestamp(i, t);
01173       else
01174       {
01175         cal.setTime(t);
01176         setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
01177       }
01178     }
01179   }
01180 
01181   //------------------------- JDBC 3.0 -----------------------------------
01182 
01183   /**
01184    * Sets the designated parameter to the given <code>java.net.URL</code>
01185    * value. The driver converts this to an SQL <code>DATALINK</code> value
01186    * when it sends it to the database.
01187    * 
01188    * @param parameterIndex the first parameter is 1, the second is 2, ...
01189    * @param x the <code>java.net.URL</code> object to be set
01190    * @exception SQLException if a database access error occurs
01191    * @since JDK 1.4
01192    */
01193   public void setURL(int parameterIndex, java.net.URL x) throws SQLException
01194   {
01195     throw new NotImplementedException("setURL");
01196   }
01197 
01198   /**
01199    * Retrieves the number, types and properties of this
01200    * <code>PreparedStatement</code> object's parameters.
01201    * 
01202    * @return a <code>ParameterMetaData</code> object that contains information
01203    *         about the number, types and properties of this
01204    *         <code>PreparedStatement</code> object's parameters
01205    * @exception SQLException if a database access error occurs
01206    * @see ParameterMetaData
01207    * @since JDK 1.4
01208    */
01209   public ParameterMetaData getParameterMetaData() throws SQLException
01210   {
01211     throw new NotImplementedException("getParameterMetaData");
01212   }
01213 
01214   // **************************************************************
01215   //     END OF PUBLIC INTERFACE
01216   // **************************************************************
01217 
01218   /**
01219    * There are a lot of setXXX classes which all basically do the same thing. We
01220    * need a method which actually does the set for us.
01221    * 
01222    * @param paramIndex the index into the inString
01223    * @param s a string to be stored
01224    * @exception SQLException if something goes wrong
01225    */
01226   private void set(int paramIndex, String s) throws SQLException
01227   {
01228     if (paramIndex < 1 || paramIndex > inStrings.length)
01229       throw new SQLException("Parameter index out of range.");
01230     inStrings[paramIndex - 1] = s;
01231   }
01232 
01233   /**
01234    * calls set with tags for driverProcessed=false
01235    * 
01236    * @param paramIndex the index into the inString
01237    * @param tag the tag
01238    * @param s a string to be stored
01239    * @exception SQLException if something goes wrong
01240    */
01241   private void setWithTag(int paramIndex, String tag, String s)
01242       throws SQLException
01243   {
01244 
01245     if (!connection.isDriverProcessed() && NULL_TAG.equals(s))
01246     {
01247       //TODO : properly escape null tag
01248       // we throw an exception as values equal to the null_tag would be
01249       // converted into null
01250       throw new SQLException("driverProcessed=false does not support value "
01251           + NULL_TAG);
01252     }
01253 
01254     set(paramIndex, Connection.START_PARAM_TAG
01255         + tag
01256         + Strings.replace(s, Connection.TAG_MARKER,
01257             Connection.TAG_MARKER_ESCAPE) + Connection.END_PARAM_TAG);
01258   }
01259 
01260   /**
01261    * Set the auto generated key flag defined in Statement
01262    * 
01263    * @param autoGeneratedKeys usually
01264    *          <code>Statement.RETURN_GENERATED_KEYS</code>
01265    * @see Connection#prepareStatement(String, int)
01266    */
01267   protected void setGeneratedKeysFlag(int autoGeneratedKeys)
01268   {
01269     generatedKeysFlag = autoGeneratedKeys;
01270   }
01271 
01272   /**
01273    * Set a PreparedStatement by calling the appropriate setXXX methods on the
01274    * request skeleton.
01275    * 
01276    * @param sql sql statement with parameters to replace
01277    * @param ps the preparedStatement to set
01278    * @throws SQLException if an error occurs
01279    */
01280   public static void setPreparedStatement(String sql,
01281       java.sql.PreparedStatement ps) throws SQLException
01282   {
01283     int i = 0;
01284     int currentParameter = 0;
01285 
01286     // Set all parameters
01287     while ((i = sql.indexOf(Connection.START_PARAM_TAG, i)) > -1)
01288     {
01289       currentParameter++;
01290 
01291       int typeStart = i + Connection.START_PARAM_TAG.length();
01292 
01293       // Here we assume that all tags have the same length as the boolean tag.
01294       String tag = sql.substring(typeStart, typeStart + BOOLEAN_TAG.length());
01295       String value = sql.substring(typeStart + BOOLEAN_TAG.length(), sql
01296           .indexOf(Connection.END_PARAM_TAG, i));
01297       value = Strings.replace(value, Connection.TAG_MARKER_ESCAPE,
01298           Connection.TAG_MARKER);
01299 
01300       // Test tags in alphabetical order (to make the code easier to read)
01301       if (tag.equals(BIG_DECIMAL_TAG))
01302       {
01303         if (value.equals(NULL_TAG))
01304           ps.setBigDecimal(currentParameter, null);
01305         else
01306         {
01307           BigDecimal t = new BigDecimal(value);
01308           ps.setBigDecimal(currentParameter, t);
01309         }
01310       }
01311       else if (tag.equals(BOOLEAN_TAG))
01312         ps.setBoolean(currentParameter, Boolean.valueOf(value).booleanValue());
01313       else if (tag.equals(BYTE_TAG))
01314       {
01315         byte t = new Integer(value).byteValue();
01316         ps.setByte(currentParameter, t);
01317       }
01318       else if (tag.equals(BYTES_TAG))
01319       {
01320         byte[] t = new HexaBlobFilter().decode(value);
01321         ps.setBytes(currentParameter, t);
01322       }
01323       else if (tag.equals(BLOB_TAG))
01324       {
01325         if (value.equals(NULL_TAG))
01326           ps.setBlob(currentParameter, null);
01327         else
01328         {
01329           Blob b = new Blob(new HexaBlobFilter().decode(value));
01330           ps.setBlob(currentParameter, b);
01331         }
01332       }
01333       else if (tag.equals(CLOB_TAG))
01334       {
01335         if (value.equals(NULL_TAG))
01336           ps.setClob(currentParameter, null);
01337         else
01338         {
01339           Clob c = new Clob(value);
01340           ps.setClob(currentParameter, c);
01341         }
01342       }
01343       else if (tag.equals(DATE_TAG))
01344       {
01345         if (value.equals(NULL_TAG))
01346           ps.setDate(currentParameter, null);
01347         else
01348           try
01349           {
01350             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
01351             Date t = new Date(sdf.parse(value).getTime());
01352             ps.setDate(currentParameter, t);
01353           }
01354           catch (ParseException p)
01355           {
01356             ps.setDate(currentParameter, null);
01357             throw new SQLException("Couldn't format date!!!");
01358           }
01359       }
01360       else if (tag.equals(DOUBLE_TAG))
01361         ps.setDouble(currentParameter, Double.valueOf(value).doubleValue());
01362       else if (tag.equals(FLOAT_TAG))
01363         ps.setFloat(currentParameter, Float.valueOf(value).floatValue());
01364       else if (tag.equals(INTEGER_TAG))
01365         ps.setInt(currentParameter, Integer.valueOf(value).intValue());
01366       else if (tag.equals(LONG_TAG))
01367         ps.setLong(currentParameter, Long.valueOf(value).longValue());
01368       else if (tag.equals(NULL_TAG))
01369         ps.setNull(currentParameter, Integer.valueOf(value).intValue());
01370       else if (tag.equals(OBJECT_TAG))
01371       {
01372         if (value.equals(NULL_TAG))
01373           ps.setObject(currentParameter, null);
01374         else
01375         {
01376           try
01377           {
01378             ObjectInputStream in = new ObjectInputStream(
01379                 new ByteArrayInputStream(value.getBytes()));
01380             ps.setObject(currentParameter, in.readObject());
01381             in.close();
01382           }
01383           catch (Exception e)
01384           {
01385             throw new SQLException("Failed to rebuild object from stream " + e);
01386           }
01387         }
01388       }
01389       else if (tag.equals(SHORT_TAG))
01390       {
01391         short t = new Integer(value).shortValue();
01392         ps.setShort(currentParameter, t);
01393       }
01394       else if (tag.equals(STRING_TAG))
01395       {
01396         if (value.equals(NULL_TAG))
01397           ps.setString(currentParameter, null);
01398         else
01399           ps.setString(currentParameter, value);
01400       }
01401       else if (tag.equals(TIME_TAG))
01402       {
01403         if (value.equals(NULL_TAG))
01404           ps.setTime(currentParameter, null);
01405         else
01406           try
01407           {
01408             SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
01409             Time t = new Time(sdf.parse(value).getTime());
01410             ps.setTime(currentParameter, t);
01411           }
01412           catch (ParseException p)
01413           {
01414             ps.setTime(currentParameter, null);
01415             throw new SQLException("Couldn't format time!!!");
01416           }
01417       }
01418       else if (tag.equals(TIMESTAMP_TAG))
01419       {
01420         if (value.equals(NULL_TAG))
01421           ps.setTimestamp(currentParameter, null);
01422         else
01423           try
01424           {
01425             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
01426             Timestamp t = new Timestamp(sdf.parse(value).getTime());
01427             ps.setTimestamp(currentParameter, t);
01428           }
01429           catch (ParseException p)
01430           {
01431             ps.setTimestamp(currentParameter, null);
01432             throw new SQLException("Couldn't format timestamp!!!");
01433           }
01434       }
01435       else
01436       {
01437         // invalid parameter, we want to be able to store strings like
01438         // <?xml version="1.0" encoding="ISO-8859-1"?>
01439         currentParameter--;
01440       }
01441       i = typeStart;
01442     }
01443   }
01444 
01445 }

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