KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > driver > PreparedStatement


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
6  * Contact: sequoia@continuent.org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Initial developer(s): Emmanuel Cecchet.
21  * Contributor(s): Nicolas Modrzyk, Jaco Swart.
22  */

23
24 package org.continuent.sequoia.driver;
25
26 import java.io.ByteArrayOutputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.ObjectOutputStream JavaDoc;
30 import java.io.Serializable JavaDoc;
31 import java.math.BigDecimal JavaDoc;
32 import java.sql.Array JavaDoc;
33 import java.sql.BatchUpdateException JavaDoc;
34 import java.sql.Blob JavaDoc;
35 import java.sql.Date JavaDoc;
36 import java.sql.ParameterMetaData JavaDoc;
37 import java.sql.Ref JavaDoc;
38 import java.sql.SQLException JavaDoc;
39 import java.sql.Time JavaDoc;
40 import java.sql.Timestamp JavaDoc;
41 import java.sql.Types JavaDoc;
42 import java.util.LinkedList JavaDoc;
43 import java.util.Vector JavaDoc;
44
45 import org.continuent.sequoia.common.exceptions.NotImplementedException;
46 import org.continuent.sequoia.common.protocol.PreparedStatementSerializationConstants;
47 import org.continuent.sequoia.common.sql.filters.AbstractBlobFilter;
48 import org.continuent.sequoia.common.util.Strings;
49
50 /**
51  * A SQL Statement is pre-compiled and stored in a
52  * <code>PreparedStatement</code> object. This object can then be used to
53  * efficiently execute this statement multiple times.
54  * <p>
55  * <b>Note: </b> The setXXX methods for setting IN parameter values must specify
56  * types that are compatible with the defined SQL type of the input parameter.
57  * For instance, if the IN parameter has SQL type Integer, then setInt should be
58  * used.
59  * <p>
60  * If arbitrary parameter type conversions are required, then the setObject
61  * method should be used with a target SQL type.
62  * <p>
63  * In the old days, this was just a dirty copy/paste from the PostgreSQL driver.
64  * Some irrelevant comments are left-over here and there.
65  * <p>
66  * This class could maybe be splitted into DriverProcessedPreparedStatement and
67  * ProxyModeProcessedStatement
68  *
69  * @see DriverResultSet
70  * @see java.sql.PreparedStatement
71  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
72  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
73  * @author <a HREF="mailto:marc.wick@monte-bre.ch">Marc Wick </a>
74  * @author <a HREF="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
75  * @version 1.0
76  */

77 public class PreparedStatement extends Statement
78     implements
79       java.sql.PreparedStatement JavaDoc
80 {
81   /** Original, untouched request (only trimmed) */
82   protected String JavaDoc sql;
83   /** IN parameters, ready to be inlined in the request */
84   private String JavaDoc[] inStrings;
85
86   // Some performance caches
87
protected StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
88
89   /**
90    * Constructor. Counts the number of question mark placeholders to size the
91    * parameters array.
92    *
93    * @param connection the instantiating connection
94    * @param sqlStatement the SQL statement with ? for IN markers
95    * @param driver the Driver used to create connections
96    */

97   PreparedStatement(Connection connection, String JavaDoc sqlStatement, Driver driver)
98   {
99     super(connection, driver);
100
101     // The following two boolean switches are used to make sure we're not
102
// counting "?" in either strings or metadata strings. For instance the
103
// following query:
104
// select '?' "A ? value" from dual
105
// doesn't have any parameters.
106

107     boolean inString = false;
108     boolean inMetaString = false;
109     int nbParam = 0;
110
111     this.sql = sqlStatement.trim();
112     this.connection = connection;
113
114     // Count how many parameters have to be set
115
for (int i = 0; i < sql.length(); ++i)
116     {
117       if (sql.charAt(i) == '\'')
118         if (i > 0 && sql.charAt(i - 1) != '\\')
119           inString = !inString;
120       if (sql.charAt(i) == '"')
121         if (i > 0 && sql.charAt(i - 1) != '\\')
122           inMetaString = !inMetaString;
123       if ((sql.charAt(i) == '?') && (!(inString || inMetaString)))
124         nbParam++;
125     }
126
127     inStrings = new String JavaDoc[nbParam];
128
129     if (connection.isAlwaysGettingGeneratedKeys())
130       generatedKeysFlag = RETURN_GENERATED_KEYS;
131   }
132
133   /**
134    * @see PreparedStatement#PreparedStatement(Connection, String, Driver)
135    */

136   PreparedStatement(Connection connection, String JavaDoc sqlStatement, Driver driver,
137       int autoGeneratedKeysArg)
138   {
139     this(connection, sqlStatement, driver);
140     if (!connection.isAlwaysGettingGeneratedKeys())
141       generatedKeysFlag = autoGeneratedKeysArg;
142   }
143
144   /**
145    * Release objects for garbage collection and call Statement.close().
146    *
147    * @throws SQLException if an error occurs
148    */

149   public void close() throws SQLException JavaDoc
150   {
151     sql = null;
152     inStrings = null;
153
154     super.close();
155   }
156
157   /**
158    * A Prepared SQL query is executed and its <code>ResultSet</code> is
159    * returned.
160    *
161    * @return a <code>ResultSet</code> that contains the data produced by the *
162    * query - never <code>null</code>.
163    * @exception SQLException if a database access error occurs
164    */

165   public java.sql.ResultSet JavaDoc executeQuery() throws SQLException JavaDoc
166   {
167     // in Statement class
168
return super.executeQuery(sql, compileParameters(false));
169   }
170
171   /**
172    * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
173    * statements that return nothing such as SQL DDL statements can be executed.
174    *
175    * @return either the row count for <code>INSERT</code>,
176    * <code>UPDATE</code> or <code>DELETE</code>; or 0 for SQL
177    * statements that return nothing.
178    * @exception SQLException if a database access error occurs
179    */

180   public int executeUpdate() throws SQLException JavaDoc
181   {
182     // in Statement class
183
return super.executeUpdateWithSkeleton(sql, compileParameters(false));
184   }
185
186   /**
187    * Helper - this compiles the SQL query, inlining the parameters in the
188    * request String. This is identical to <code>this.toString()</code> except
189    * it throws an exception if a parameter was not set.
190    *
191    * @param fillEmptyParametersWithCSParamTag true if called from a
192    * CallableStatement
193    * @return the compiled query
194    * @throws SQLException if an error occurs
195    */

196   protected synchronized String JavaDoc compileParameters(
197       boolean fillEmptyParametersWithCSParamTag) throws SQLException JavaDoc
198   {
199     if (inStrings.length == 0)
200     {
201       return "";
202     }
203
204     sbuf.setLength(0);
205     for (int i = 0; i < inStrings.length; ++i)
206     {
207       if (inStrings[i] == null)
208       {
209         if (!fillEmptyParametersWithCSParamTag)
210           throw new SQLException JavaDoc("Parameter " + (i + 1) + " is not set");
211         setParameterWithTag(i + 1,
212             PreparedStatementSerializationConstants.CS_PARAM_TAG, "");
213       }
214       sbuf.append(inStrings[i]);
215     }
216     return sbuf.toString();
217   }
218
219   /**
220    * Escape the input string. <br>
221    * <char>' </char> is replaced by <char>\' </char> <br>
222    * <char>\ </char> is replaced by <char>\\ </char> <br>
223    * if connection.escapeProcessing is set to true, surround the new string with
224    * <char>\' </char>
225    *
226    * @param x the string to process
227    * @return escaped string
228    */

229   protected String JavaDoc doEscapeProcessing(String JavaDoc x)
230   {
231     // use the shared buffer object. Should never clash but this
232
// makes us thread safe!
233
synchronized (sbuf)
234     {
235       sbuf.setLength(0);
236       int i;
237       sbuf.append(connection.getEscapeChar());
238       for (i = 0; i < x.length(); ++i)
239       {
240         char c = x.charAt(i);
241         if ((c == '\'' && connection.isEscapeSingleQuote())
242             || (c == '\\' && connection.isEscapeBackslash()))
243           sbuf.append(c);
244         sbuf.append(c);
245       }
246       sbuf.append(connection.getEscapeChar());
247     }
248     return sbuf.toString();
249   }
250
251   /**
252    * Sets a parameter to SQL NULL.
253    *
254    * @param parameterIndex the first parameter is 1, etc...
255    * @param sqlType the SQL type code defined in java.sql.Types
256    * @exception SQLException if a database access error occurs
257    */

258   public void setNull(int parameterIndex, int sqlType) throws SQLException JavaDoc
259   {
260     // NULL_VALUE is (confusingly) also used as the "NULL_TAG" to proxy
261
// the setNull() call
262
setParameterWithTag(parameterIndex,
263         PreparedStatementSerializationConstants.NULL_VALUE, String
264             .valueOf(sqlType));
265   }
266
267   /**
268    * Sets a parameter to a Java boolean value. The driver converts this to a SQL
269    * BIT value when it sends it to the database.
270    *
271    * @param parameterIndex the first parameter is 1...
272    * @param x the parameter value
273    * @exception SQLException if a database access error occurs
274    */

275   public void setBoolean(int parameterIndex, boolean x) throws SQLException JavaDoc
276   {
277     setParameterWithTag(parameterIndex,
278         PreparedStatementSerializationConstants.BOOLEAN_TAG, String.valueOf(x));
279   }
280
281   /**
282    * Sets a parameter to a Java byte value.
283    *
284    * @param parameterIndex the first parameter is 1...
285    * @param x the parameter value
286    * @exception SQLException if a database access error occurs
287    */

288   public void setByte(int parameterIndex, byte x) throws SQLException JavaDoc
289   {
290     setParameterWithTag(parameterIndex,
291         PreparedStatementSerializationConstants.BYTE_TAG, Integer.toString(x));
292   }
293
294   /**
295    * Sets a parameter to a Java short value. The driver converts this to a SQL
296    * SMALLINT value when it sends it to the database.
297    *
298    * @param parameterIndex the first parameter is 1...
299    * @param x the parameter value
300    * @exception SQLException if a database access error occurs
301    */

302   public void setShort(int parameterIndex, short x) throws SQLException JavaDoc
303   {
304     setParameterWithTag(parameterIndex,
305         PreparedStatementSerializationConstants.SHORT_TAG, Integer.toString(x));
306   }
307
308   /**
309    * Sets a parameter to a Java int value. The driver converts this to a SQL
310    * INTEGER value when it sends it to the database.
311    *
312    * @param parameterIndex the first parameter is 1...
313    * @param x the parameter value
314    * @exception SQLException if a database access error occurs
315    */

316   public void setInt(int parameterIndex, int x) throws SQLException JavaDoc
317   {
318     setParameterWithTag(parameterIndex,
319         PreparedStatementSerializationConstants.INTEGER_TAG, Integer
320             .toString(x));
321   }
322
323   /**
324    * Sets a parameter to a Java long value. The driver converts this to a SQL
325    * BIGINT value when it sends it to the database.
326    *
327    * @param parameterIndex the first parameter is 1...
328    * @param x the parameter value
329    * @exception SQLException if a database access error occurs
330    */

331   public void setLong(int parameterIndex, long x) throws SQLException JavaDoc
332   {
333     setParameterWithTag(parameterIndex,
334         PreparedStatementSerializationConstants.LONG_TAG, Long.toString(x));
335   }
336
337   /**
338    * Sets a parameter to a Java float value. The driver converts this to a SQL
339    * FLOAT value when it sends it to the database.
340    *
341    * @param parameterIndex the first parameter is 1...
342    * @param x the parameter value
343    * @exception SQLException if a database access error occurs
344    */

345   public void setFloat(int parameterIndex, float x) throws SQLException JavaDoc
346   {
347     setParameterWithTag(parameterIndex,
348         PreparedStatementSerializationConstants.FLOAT_TAG, Float.toString(x));
349   }
350
351   /**
352    * Sets a parameter to a Java double value. The driver converts this to a SQL
353    * DOUBLE value when it sends it to the database.
354    *
355    * @param parameterIndex the first parameter is 1...
356    * @param x the parameter value
357    * @exception SQLException if a database access error occurs
358    */

359   public void setDouble(int parameterIndex, double x) throws SQLException JavaDoc
360   {
361     setParameterWithTag(parameterIndex,
362         PreparedStatementSerializationConstants.DOUBLE_TAG, Double.toString(x));
363   }
364
365   /**
366    * Sets a parameter to a java.lang.BigDecimal value. The driver converts this
367    * to a SQL NUMERIC value when it sends it to the database.
368    *
369    * @param parameterIndex the first parameter is 1...
370    * @param x the parameter value
371    * @exception SQLException if a database access error occurs
372    */

373   public void setBigDecimal(int parameterIndex, BigDecimal JavaDoc x)
374       throws SQLException JavaDoc
375   {
376     String JavaDoc serializedParam = (x == null ? null : x.toString());
377
378     setParameterWithTag(parameterIndex,
379         PreparedStatementSerializationConstants.BIG_DECIMAL_TAG,
380         serializedParam);
381   }
382
383   /**
384    * Sets a parameter to a Java String value. The driver converts this to a SQL
385    * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
386    * the driver's limits on VARCHARs) when it sends it to the database.
387    *
388    * @param parameterIndex the first parameter is 1...
389    * @param x the parameter value
390    * @exception SQLException if a database access error occurs
391    */

392   public void setString(int parameterIndex, String JavaDoc x) throws SQLException JavaDoc
393   {
394     if (PreparedStatementSerializationConstants.NULL_VALUE.equals(x))
395       // Someone is trying to set a String that matches our NULL tag, a real
396
// bad luck, use our special type NULL_STRING_TAG!
397
setParameterWithTag(parameterIndex,
398           PreparedStatementSerializationConstants.NULL_STRING_TAG, x);
399     else
400       setParameterWithTag(parameterIndex,
401           PreparedStatementSerializationConstants.STRING_TAG, x);
402   }
403
404   /**
405    * Sets a parameter to a Java array of bytes.
406    * <p>
407    *
408    * @param parameterIndex the first parameter is 1...
409    * @param x the parameter value
410    * @exception SQLException if a database access error occurs
411    */

412   public void setBytes(int parameterIndex, byte[] x) throws SQLException JavaDoc
413   {
414     try
415     {
416       /**
417        * Encoded only for request inlining. Decoded right away by the controller
418        * at static
419        * {@link #setPreparedStatement(String, java.sql.PreparedStatement)}
420        */

421       String JavaDoc encodedString = AbstractBlobFilter.getDefaultBlobFilter()
422           .encode(x);
423       setParameterWithTag(parameterIndex,
424           PreparedStatementSerializationConstants.BYTES_TAG, encodedString);
425     }
426     catch (OutOfMemoryError JavaDoc oome)
427     {
428       System.gc();
429       throw new SQLException JavaDoc("Out of memory while encoding bytes");
430     }
431   }
432
433   /**
434    * Sets a parameter to a java.sql.Date value. The driver converts this to a
435    * SQL DATE value when it sends it to the database.
436    *
437    * @param parameterIndex the first parameter is 1...
438    * @param x the parameter value
439    * @exception SQLException if a database access error occurs
440    */

441   public void setDate(int parameterIndex, java.sql.Date JavaDoc x) throws SQLException JavaDoc
442   {
443     String JavaDoc serializedParam = (x == null ? null : new java.sql.Date JavaDoc(x.getTime())
444         .toString());
445
446     setParameterWithTag(parameterIndex,
447         PreparedStatementSerializationConstants.DATE_TAG, serializedParam);
448   }
449
450   /**
451    * Sets a parameter to a <code>java.sql.Time</code> value. The driver
452    * converts this to a SQL TIME value when it sends it to the database.
453    *
454    * @param parameterIndex the first parameter is 1...));
455    * @param x the parameter value
456    * @exception SQLException if a database access error occurs
457    */

458   public void setTime(int parameterIndex, Time JavaDoc x) throws SQLException JavaDoc
459   {
460     String JavaDoc serializedParam = (x == null ? null : x.toString());
461
462     setParameterWithTag(parameterIndex,
463         PreparedStatementSerializationConstants.TIME_TAG, serializedParam);
464   }
465
466   /**
467    * Sets a parameter to a <code>java.sql.Timestamp</code> value. The driver
468    * converts this to a SQL TIMESTAMP value when it sends it to the database.
469    *
470    * @param parameterIndex the first parameter is 1...
471    * @param x the parameter value
472    * @exception SQLException if a database access error occurs
473    */

474   public void setTimestamp(int parameterIndex, Timestamp JavaDoc x) throws SQLException JavaDoc
475   {
476     if (x == null)
477       setParameterWithTag(parameterIndex,
478           PreparedStatementSerializationConstants.TIMESTAMP_TAG, null);
479     else
480     {
481       if (x.getClass().equals(Timestamp JavaDoc.class))
482         setParameterWithTag(parameterIndex,
483             PreparedStatementSerializationConstants.TIMESTAMP_TAG, x.toString());
484       else
485         setParameterWithTag(parameterIndex,
486             PreparedStatementSerializationConstants.TIMESTAMP_TAG,
487             new Timestamp JavaDoc(x.getTime()).toString());
488     }
489   }
490
491   /**
492    * When a very large ASCII value is input to a LONGVARCHAR parameter, it may
493    * be more practical to send it via a java.io.InputStream. JDBC will read the
494    * data from the stream as needed, until it reaches end-of-file. The JDBC
495    * driver will do any necessary conversion from ASCII to the database char
496    * format.
497    * <p>
498    * <b>Note: </b> this stream object can either be a standard Java stream
499    * object or your own subclass that implements the standard interface.
500    *
501    * @param parameterIndex the first parameter is 1...
502    * @param x the parameter value
503    * @param length the number of bytes in the stream
504    * @exception SQLException if a database access error occurs
505    */

506   public void setAsciiStream(int parameterIndex, InputStream JavaDoc x, int length)
507       throws SQLException JavaDoc
508   {
509     setBinaryStream(parameterIndex, x, length);
510   }
511
512   /**
513    * When a very large Unicode value is input to a LONGVARCHAR parameter, it may
514    * be more practical to send it via a java.io.InputStream. JDBC will read the
515    * data from the stream as needed, until it reaches end-of-file. The JDBC
516    * driver will do any necessary conversion from UNICODE to the database char
517    * format.
518    * <p>** DEPRECIATED IN JDBC 2 **
519    * <p>
520    * <b>Note: </b> this stream object can either be a standard Java stream
521    * object or your own subclass that implements the standard interface.
522    *
523    * @param parameterIndex the first parameter is 1...
524    * @param x the parameter value
525    * @param length the parameter length
526    * @exception SQLException if a database access error occurs
527    * @deprecated
528    */

529   public void setUnicodeStream(int parameterIndex, InputStream JavaDoc x, int length)
530       throws SQLException JavaDoc
531   {
532     setBinaryStream(parameterIndex, x, length);
533   }
534
535   /**
536    * Stores a binary stream into parameters array, using an intermediate byte[].
537    * When a very large binary value is input to a LONGVARBINARY parameter, it
538    * may be more practical to send it via a java.io.InputStream. JDBC will read
539    * the data from the stream as needed, until it reaches end-of-file. This
540    * should be more or less equivalent to setBytes(blob.getBytes()).
541    * <p>
542    * <b>Note: </b> This stream object can either be a standard Java stream
543    * object or your own subclass that implements the standard interface.
544    *
545    * @param parameterIndex the first parameter is 1...
546    * @param inStreamArg the parameter value
547    * @param length the parameter length
548    * @exception SQLException if a database access error occurs
549    * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream,
550    * int)
551    */

552   public void setBinaryStream(int parameterIndex, InputStream JavaDoc inStreamArg,
553       int length) throws SQLException JavaDoc
554   {
555     byte[] data = new byte[length];
556     try
557     {
558       inStreamArg.read(data, 0, length);
559     }
560     catch (Exception JavaDoc ioe)
561     {
562       throw new SQLException JavaDoc("Problem with streaming of data");
563     }
564     // TODO: optimize me and avoid the copy thanks to a new setBytesFromStream()
565
// setBytes does the blob filter encoding.
566
setBytes(parameterIndex, data);
567   }
568
569   /**
570    * In general, parameter values remain in force for repeated used of a
571    * <code>Statement</code>. Setting a parameter value automatically clears
572    * its previous value. However, in coms cases, it is useful to immediately
573    * release the resources used by the current parameter values; this can be
574    * done by calling <code>clearParameters()</code>.
575    *
576    * @exception SQLException if a database access error occurs
577    */

578   public void clearParameters() throws SQLException JavaDoc
579   {
580     int i;
581
582     for (i = 0; i < inStrings.length; i++)
583       inStrings[i] = null;
584   }
585
586   /**
587    * Sets the value of a parameter using an object; use the
588    * <code>java.lang</code> equivalent objects for integral values.
589    * <p>
590    * The given Java object will be converted to the targetSqlType before being
591    * sent to the database.
592    * <p>
593    * Note that this method may be used to pass database-specific abstract data
594    * types. This is done by using a Driver-specific Java type and using a
595    * <code>targetSqlType</code> of <code>java.sql.Types.OTHER</code>.
596    *
597    * @param parameterIndex the first parameter is 1...
598    * @param x the object containing the input parameter value
599    * @param targetSqlType The SQL type to be send to the database
600    * @param scale for <code>java.sql.Types.DECIMAL</code> or
601    * <code>java.sql.Types.NUMERIC</code> types this is the number of
602    * digits after the decimal. For all other types this value will be
603    * ignored.
604    * @exception SQLException if a database access error or an incompatible type
605    * match occurs
606    * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int, int)
607    */

608   public void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType,
609       int scale) throws SQLException JavaDoc
610   {
611     if (x == null)
612     {
613       setNull(parameterIndex, targetSqlType);
614       return;
615     }
616
617     try
618     {
619       boolean failed = false;
620       switch (targetSqlType)
621       {
622         /**
623          * Reference is table "Conversions Performed by setObject()..." in JDBC
624          * Reference Book (table 47.9.5 in 2nd edition, 50.5 in 3rd edition).
625          * Also available online in Sun's "JDBC Technology Guide: Getting
626          * Started", section "Mapping SQL and Java Types".
627          */

628
629         // Some drivers (at least postgresql > 8.1) don't accept setInt for tiny
630
// and small ints. We can safely use setShort instead. See bug
631
// SEQUOIA-543
632
// setShort().
633
case Types.TINYINT :
634         case Types.SMALLINT :
635           if (x instanceof Number JavaDoc)
636             setShort(parameterIndex, ((Number JavaDoc) x).shortValue());
637           else if (x instanceof Boolean JavaDoc)
638             setShort(parameterIndex, ((Boolean JavaDoc) x).booleanValue()
639                 ? (short) 1
640                 : (short) 0);
641           else if (x instanceof String JavaDoc)
642             setShort(parameterIndex, Short.parseShort((String JavaDoc) x));
643           else
644             failed = true;
645           break;
646         // setInt()
647
case Types.INTEGER :
648           if (x instanceof Number JavaDoc)
649             setInt(parameterIndex, ((Number JavaDoc) x).intValue());
650           else if (x instanceof Boolean JavaDoc)
651             setInt(parameterIndex, ((Boolean JavaDoc) x).booleanValue() ? 1 : 0);
652           else if (x instanceof String JavaDoc)
653             setInt(parameterIndex, Integer.parseInt((String JavaDoc) x));
654           else
655             failed = true;
656           break;
657         // setLong()
658
case Types.BIGINT :
659           if (x instanceof Number JavaDoc)
660             setLong(parameterIndex, ((Number JavaDoc) x).longValue());
661           else if (x instanceof String JavaDoc)
662             setLong(parameterIndex, Long.parseLong((String JavaDoc) x));
663           else if (x instanceof Boolean JavaDoc)
664             setLong(parameterIndex, ((Boolean JavaDoc) x).booleanValue() ? 1 : 0);
665           else
666             failed = true;
667           break;
668         // setDouble()
669
case Types.REAL :
670         case Types.FLOAT :
671         case Types.DOUBLE :
672           if (x instanceof Number JavaDoc)
673             setDouble(parameterIndex, ((Number JavaDoc) x).doubleValue());
674           else if (x instanceof String JavaDoc)
675             setDouble(parameterIndex, Double.parseDouble((String JavaDoc) x));
676           else if (x instanceof Boolean JavaDoc)
677             setDouble(parameterIndex, ((Boolean JavaDoc) x).booleanValue() ? 1 : 0);
678           else
679             failed = true;
680           break;
681         // setBigDecimal()
682
case Types.DECIMAL :
683         case Types.NUMERIC :
684           BigDecimal JavaDoc bd;
685           if (x instanceof Boolean JavaDoc)
686             bd = new BigDecimal JavaDoc(((Boolean JavaDoc) x).booleanValue() ? 1d : 0d);
687           else if (x instanceof Number JavaDoc)
688             bd = new BigDecimal JavaDoc(((Number JavaDoc) x).toString());
689           else if (x instanceof String JavaDoc)
690             bd = new BigDecimal JavaDoc((String JavaDoc) x);
691           else
692           {
693             failed = true;
694             break;
695           }
696           bd = bd.setScale(scale, BigDecimal.ROUND_HALF_UP);
697           setBigDecimal(parameterIndex, bd);
698           break;
699         // setBoolean()
700
case Types.BIT :
701         case Types.BOOLEAN :
702           if (x instanceof Number JavaDoc)
703             setBoolean(parameterIndex, 0 != ((Number JavaDoc) x).longValue());
704           else if (x instanceof Boolean JavaDoc)
705             setBoolean(parameterIndex, ((Boolean JavaDoc) x).booleanValue());
706           else if (x instanceof String JavaDoc)
707             setBoolean(parameterIndex, Boolean.valueOf((String JavaDoc) x)
708                 .booleanValue());
709           else
710             failed = true;
711           break;
712         // setString()
713
case Types.CHAR :
714         case Types.VARCHAR :
715         case Types.LONGVARCHAR :
716           setString(parameterIndex, x.toString());
717           break;
718         // setBytes(), setBlob(),...
719
case Types.BINARY :
720         case Types.VARBINARY :
721         case Types.LONGVARBINARY :
722           if (x instanceof byte[])
723             setBytes(parameterIndex, (byte[]) x);
724           else if (x instanceof Blob JavaDoc)
725             setBlob(parameterIndex, (Blob JavaDoc) x);
726           else if (x instanceof Serializable JavaDoc)
727             // Try it as an Object (serialized in bytes in setObject below)
728
setObject(parameterIndex, x);
729           else
730             failed = true;
731           break;
732         // setDate()
733
case Types.DATE :
734           if (x instanceof String JavaDoc)
735             setDate(parameterIndex, java.sql.Date.valueOf((String JavaDoc) x));
736           else if (x instanceof java.sql.Date JavaDoc)
737             setDate(parameterIndex, (java.sql.Date JavaDoc) x);
738           else if (x instanceof Timestamp JavaDoc)
739             setDate(parameterIndex,
740                 new java.sql.Date JavaDoc(((Timestamp JavaDoc) x).getTime()));
741           else
742             failed = true;
743           break;
744         // setTime()
745
case Types.TIME :
746           if (x instanceof String JavaDoc)
747             setTime(parameterIndex, Time.valueOf((String JavaDoc) x));
748           else if (x instanceof Time JavaDoc)
749             setTime(parameterIndex, (Time JavaDoc) x);
750           else if (x instanceof Timestamp JavaDoc)
751             setTime(parameterIndex, new Time JavaDoc(((Timestamp JavaDoc) x).getTime()));
752           else
753             failed = true;
754           break;
755         // setTimeStamp()
756
case Types.TIMESTAMP :
757           if (x instanceof String JavaDoc)
758             setTimestamp(parameterIndex, Timestamp.valueOf((String JavaDoc) x));
759           else if (x instanceof Date JavaDoc)
760             setTimestamp(parameterIndex, new Timestamp JavaDoc(((Date JavaDoc) x).getTime()));
761           else if (x instanceof Timestamp JavaDoc)
762             setTimestamp(parameterIndex, (Timestamp JavaDoc) x);
763           else
764             failed = true;
765           break;
766         // setBlob()
767
case Types.BLOB :
768           if (x instanceof Blob JavaDoc)
769             setBlob(parameterIndex, (Blob JavaDoc) x);
770           else
771             failed = true;
772           break;
773         // setURL()
774
case Types.DATALINK :
775           if (x instanceof java.net.URL JavaDoc)
776             setURL(parameterIndex, (java.net.URL JavaDoc) x);
777           else
778             setURL(parameterIndex, new java.net.URL JavaDoc(x.toString()));
779           break;
780         case Types.JAVA_OBJECT :
781         case Types.OTHER :
782           // let's ignore the unknown target type given.
783
setObject(parameterIndex, x);
784           break;
785         default :
786           throw new SQLException JavaDoc("Unsupported type value");
787       }
788       if (true == failed)
789         throw new IllegalArgumentException JavaDoc(
790             "Attempt to perform an illegal conversion");
791     }
792     catch (Exception JavaDoc e)
793     {
794       SQLException JavaDoc outE = new SQLException JavaDoc("Exception while converting type "
795           + x.getClass() + " to SQL type " + targetSqlType);
796       outE.initCause(e);
797       throw outE;
798     }
799   }
800
801   /**
802    * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int)
803    */

804   public void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType)
805       throws SQLException JavaDoc
806   {
807     setObject(parameterIndex, x, targetSqlType, 0);
808   }
809
810   /**
811    * This stores an Object parameter into the parameters array.
812    *
813    * @param parameterIndex the first parameter is 1...
814    * @param x the object to set
815    * @exception SQLException if a database access error occurs
816    */

817   public void setObject(int parameterIndex, Object JavaDoc x) throws SQLException JavaDoc
818   {
819     if (x == null)
820     {
821       setParameterWithTag(parameterIndex,
822           PreparedStatementSerializationConstants.OBJECT_TAG, null);
823     }
824     else
825     { // This is an optimization, faster than going through
826
// the generic setObject() method and calling instanceof again.
827
// This has to be in the end equivalent to
828
// setObject(index, object, DEFAULT_targetSqlType, 0)
829
// where DEFAULT_targetSqlType is defined in table:
830
// "Java Object Type Mapped to JDBC Types".
831
// It's currently not exactly the same, since generic setObject()
832
// is not strict enough in its conversions. For instance
833
// setObject(target=Float) actually calls "setDouble()" -- MH.
834

835       if (x instanceof String JavaDoc)
836         setString(parameterIndex, (String JavaDoc) x);
837       else if (x instanceof BigDecimal JavaDoc)
838         setBigDecimal(parameterIndex, (BigDecimal JavaDoc) x);
839       else if (x instanceof Boolean JavaDoc)
840         setBoolean(parameterIndex, ((Boolean JavaDoc) x).booleanValue());
841       else if (x instanceof Short JavaDoc)
842         setShort(parameterIndex, ((Short JavaDoc) x).shortValue());
843       else if (x instanceof Integer JavaDoc)
844         setInt(parameterIndex, ((Integer JavaDoc) x).intValue());
845       else if (x instanceof Long JavaDoc)
846         setLong(parameterIndex, ((Long JavaDoc) x).longValue());
847       else if (x instanceof Float JavaDoc)
848         setFloat(parameterIndex, ((Float JavaDoc) x).floatValue());
849       else if (x instanceof Double JavaDoc)
850         setDouble(parameterIndex, ((Double JavaDoc) x).doubleValue());
851       else if (x instanceof byte[])
852         setBytes(parameterIndex, (byte[]) x);
853       else if (x instanceof java.sql.Date JavaDoc)
854         setDate(parameterIndex, (java.sql.Date JavaDoc) x);
855       else if (x instanceof Time JavaDoc)
856         setTime(parameterIndex, (Time JavaDoc) x);
857       else if (x instanceof Timestamp JavaDoc)
858         setTimestamp(parameterIndex, (Timestamp JavaDoc) x);
859       else if (x instanceof Blob JavaDoc)
860         setBlob(parameterIndex, (Blob JavaDoc) x);
861       else if (x instanceof java.net.URL JavaDoc)
862         setURL(parameterIndex, (java.net.URL JavaDoc) x);
863       else if (x instanceof Serializable JavaDoc)
864       {
865         ByteArrayOutputStream JavaDoc byteOutputStream = new ByteArrayOutputStream JavaDoc();
866         try
867         {
868           // Serialize object to byte array
869
ObjectOutputStream JavaDoc objectOutputStream = new ObjectOutputStream JavaDoc(
870               byteOutputStream);
871           objectOutputStream.writeObject(x);
872           objectOutputStream.close();
873           synchronized (this.sbuf)
874           {
875             this.sbuf.setLength(0);
876             /**
877              * Encoded only for request inlining. Decoded right away by the
878              * controller
879              */

880             this.sbuf.append(AbstractBlobFilter.getDefaultBlobFilter().encode(
881                 byteOutputStream.toByteArray()));
882             setParameterWithTag(parameterIndex,
883                 PreparedStatementSerializationConstants.OBJECT_TAG, this.sbuf
884                     .toString());
885           }
886         }
887         catch (IOException JavaDoc e)
888         {
889           throw new SQLException JavaDoc("Failed to serialize object: " + e);
890         }
891       }
892       else
893         throw new SQLException JavaDoc("Objects of type " + x.getClass()
894             + " are not supported.");
895     }
896   }
897
898   /**
899    * Some prepared statements return multiple results; the execute method
900    * handles these complex statements as well as the simpler form of statements
901    * handled by <code>executeQuery()</code> and <code>executeUpdate()</code>.
902    *
903    * @return <code>true</code> if the next result is a
904    * <code>ResultSet<code>; <code>false<code> if it is an update count
905    * or there are no more results
906    * @exception SQLException if a database access error occurs
907    */

908   public boolean execute() throws SQLException JavaDoc
909   {
910     if (this.generatedKeysFlag == RETURN_GENERATED_KEYS)
911     {
912       if (connection.isAlwaysGettingGeneratedKeys()
913           && !sql.toLowerCase().trim().startsWith("insert"))
914       {
915         return super.execute(sql, compileParameters(false));
916       }
917       int result = executeUpdate();
918       resultList = new LinkedList JavaDoc();
919       resultList.add(new Integer JavaDoc(result));
920       resultListIterator = resultList.iterator();
921       return getMoreResults();
922     }
923     return super.execute(sql, compileParameters(false));
924   }
925
926   /**
927    * Returns the SQL statement with the current template values substituted.
928    * <p>
929    * <b>Note: </b>: This is identical to <code>compileQuery()</code> except
930    * instead of throwing SQLException if a parameter is <code>null</code>, it
931    * places ? instead.
932    *
933    * @return the SQL statement
934    */

935   public String JavaDoc toString()
936   {
937     synchronized (sbuf)
938     {
939       sbuf.setLength(0);
940       sbuf.append(sql);
941       int i;
942
943       if (inStrings == null)
944         return sbuf.toString();
945
946       for (i = 0; i < inStrings.length; ++i)
947       {
948         if (inStrings[i] == null)
949           sbuf.append('?');
950         else
951           sbuf.append(inStrings[i]);
952       }
953       return sbuf.toString();
954     }
955   }
956
957   // ** JDBC 2 Extensions **
958

959   /**
960    * This parses the query and adds it to the current batch
961    *
962    * @throws SQLException if an error occurs
963    */

964   public synchronized void addBatch() throws SQLException JavaDoc
965   {
966     if (batch == null)
967       batch = new Vector JavaDoc();
968     batch.addElement(new BatchElement(sql, compileParameters(false)));
969   }
970
971   /**
972    * Execute a batch of commands
973    *
974    * @return an array containing update count that corresponding to the commands
975    * that executed successfully
976    * @exception BatchUpdateException if an error occurs on one statement (the
977    * number of updated rows for the successfully executed
978    * statements can be found in
979    * BatchUpdateException.getUpdateCounts())
980    */

981   public int[] executeBatch() throws BatchUpdateException JavaDoc
982   {
983     if (batch == null || batch.isEmpty())
984       return new int[0];
985
986     int size = batch.size();
987     int[] nbsRowsUpdated = new int[size];
988     int i = 0;
989
990     try
991     {
992       for (i = 0; i < size; i++)
993       {
994         BatchElement be = (BatchElement) batch.elementAt(i);
995         nbsRowsUpdated[i] = this.executeUpdateWithSkeleton(be.getSqlTemplate(),
996             be.getParameters());
997       }
998       return nbsRowsUpdated;
999     }
1000    catch (SQLException JavaDoc e)
1001    {
1002      String JavaDoc message = "Batch failed for request " + i + ": "
1003          + ((BatchElement) batch.elementAt(i)).getSqlTemplate() + " (" + e
1004          + ")";
1005
1006      // shrink the returned array
1007
int[] updateCounts = new int[i];
1008      System.arraycopy(nbsRowsUpdated, 0, updateCounts, 0, i);
1009
1010      throw new BatchUpdateException JavaDoc(message, updateCounts);
1011    }
1012    finally
1013    {
1014      batch.removeAllElements();
1015    }
1016  }
1017
1018  /**
1019   * Returns the <code>MetaData</code> for the last <code>ResultSet</code>
1020   * returned.
1021   *
1022   * @return The ResultSet Metadata
1023   * @throws SQLException if an error occurs
1024   */

1025  public java.sql.ResultSetMetaData JavaDoc getMetaData() throws SQLException JavaDoc
1026  {
1027    java.sql.ResultSet JavaDoc rs = getResultSet();
1028    if (rs != null)
1029      return rs.getMetaData();
1030    else
1031      return connection.preparedStatementGetMetaData(sql);
1032  }
1033
1034  /**
1035   * @see java.sql.PreparedStatement#setArray(int, java.sql.Array)
1036   */

1037  public void setArray(int i, Array JavaDoc x) throws SQLException JavaDoc
1038  {
1039    throw new NotImplementedException("setArray()");
1040  }
1041
1042  /**
1043   * @see java.sql.PreparedStatement#setBlob(int, Blob)
1044   */

1045  public void setBlob(int paramIndex, Blob JavaDoc sqlBlobParam) throws SQLException JavaDoc
1046  {
1047    if (sqlBlobParam == null)
1048    {
1049      setParameterWithTag(paramIndex,
1050          PreparedStatementSerializationConstants.BLOB_TAG, null);
1051      return;
1052    }
1053
1054    // sqlBlobParam.getBytes() seems limited in size ?
1055
// So we use .getBinaryStream()
1056
InputStream JavaDoc blobBinStream = sqlBlobParam.getBinaryStream();
1057
1058    byte[] data = new byte[(int) sqlBlobParam.length()];
1059    try
1060    {
1061      blobBinStream.read(data, 0, (int) sqlBlobParam.length());
1062    }
1063    catch (Exception JavaDoc ioe)
1064    {
1065      throw new SQLException JavaDoc("Problem with data streaming");
1066    }
1067    try
1068    {
1069      synchronized (this.sbuf)
1070      {
1071        this.sbuf.setLength(0);
1072        /**
1073         * Encoded only for request inlining. Decoded right away by the
1074         * controller at static
1075         * {@link #setPreparedStatement(String, java.sql.PreparedStatement)}
1076         */

1077        this.sbuf
1078            .append(AbstractBlobFilter.getDefaultBlobFilter().encode(data));
1079        setParameterWithTag(paramIndex,
1080            PreparedStatementSerializationConstants.BLOB_TAG, this.sbuf
1081                .toString());
1082      }
1083    }
1084    catch (OutOfMemoryError JavaDoc oome)
1085    {
1086      this.sbuf = null;
1087      System.gc();
1088      throw new SQLException JavaDoc("Out of memory");
1089    }
1090  }
1091
1092  /**
1093   * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader,
1094   * int)
1095   */

1096  public void setCharacterStream(int i, java.io.Reader JavaDoc x, int length)
1097      throws SQLException JavaDoc
1098  {
1099    char[] data = new char[length];
1100    try
1101    {
1102      x.read(data, 0, length);
1103    }
1104    catch (Exception JavaDoc ioe)
1105    {
1106      throw new SQLException JavaDoc("Problem with streaming of data");
1107    }
1108    setString(i, new String JavaDoc(data));
1109  }
1110
1111  /**
1112   * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob)
1113   */

1114  public void setClob(int i, java.sql.Clob JavaDoc clobArg) throws SQLException JavaDoc
1115  {
1116    String JavaDoc serializedParam = (clobArg == null ? null : clobArg.getSubString(0,
1117        (int) clobArg.length()));
1118
1119    setParameterWithTag(i, PreparedStatementSerializationConstants.CLOB_TAG,
1120        serializedParam);
1121  }
1122
1123  /**
1124   * @see java.sql.PreparedStatement#setNull(int, int, java.lang.String)
1125   */

1126  public void setNull(int i, int t, String JavaDoc s) throws SQLException JavaDoc
1127  {
1128    setNull(i, t);
1129  }
1130
1131  /**
1132   * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref)
1133   */

1134  public void setRef(int i, Ref JavaDoc x) throws SQLException JavaDoc
1135  {
1136    String JavaDoc serializedParam = (x == null ? null : x.toString());
1137
1138    setParameterWithTag(i, PreparedStatementSerializationConstants.REF_TAG,
1139        serializedParam);
1140  }
1141
1142  /**
1143   * @see java.sql.PreparedStatement#setDate(int, java.sql.Date,
1144   * java.util.Calendar)
1145   */

1146  public void setDate(int i, java.sql.Date JavaDoc d, java.util.Calendar JavaDoc cal)
1147      throws SQLException JavaDoc
1148  {
1149    if (d == null)
1150      setParameterWithTag(i, PreparedStatementSerializationConstants.DATE_TAG,
1151          null);
1152    else
1153    {
1154      if (cal == null)
1155        setDate(i, d);
1156      else
1157      {
1158        cal.setTime(d);
1159        setDate(i, new java.sql.Date JavaDoc(cal.getTime().getTime()));
1160      }
1161    }
1162  }
1163
1164  /**
1165   * @see java.sql.PreparedStatement#setTime(int, java.sql.Time,
1166   * java.util.Calendar)
1167   */

1168  public void setTime(int i, Time JavaDoc t, java.util.Calendar JavaDoc cal)
1169      throws SQLException JavaDoc
1170  {
1171    if (t == null)
1172      setParameterWithTag(i, PreparedStatementSerializationConstants.TIME_TAG,
1173          null);
1174    else
1175    {
1176      if (cal == null)
1177        setTime(i, t);
1178      else
1179      {
1180        cal.setTime(t);
1181        setTime(i, new java.sql.Time JavaDoc(cal.getTime().getTime()));
1182      }
1183    }
1184  }
1185
1186  /**
1187   * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp,
1188   * java.util.Calendar)
1189   */

1190  public void setTimestamp(int i, Timestamp JavaDoc t, java.util.Calendar JavaDoc cal)
1191      throws SQLException JavaDoc
1192  {
1193    if (t == null)
1194      setParameterWithTag(i,
1195          PreparedStatementSerializationConstants.TIMESTAMP_TAG, null);
1196    else
1197    {
1198      if (cal == null)
1199        setTimestamp(i, t);
1200      else
1201      {
1202        cal.setTime(t);
1203        setTimestamp(i, new java.sql.Timestamp JavaDoc(cal.getTime().getTime()));
1204      }
1205    }
1206  }
1207
1208  // ------------------------- JDBC 3.0 -----------------------------------
1209

1210  /**
1211   * Sets the designated parameter to the given <code>java.net.URL</code>
1212   * value. The driver converts this to an SQL <code>DATALINK</code> value
1213   * when it sends it to the database.
1214   *
1215   * @param parameterIndex the first parameter is 1, the second is 2, ...
1216   * @param x the <code>java.net.URL</code> object to be set
1217   * @exception SQLException if a database access error occurs
1218   * @since JDK 1.4
1219   */

1220  public void setURL(int parameterIndex, java.net.URL JavaDoc x) throws SQLException JavaDoc
1221  {
1222    String JavaDoc serializedParam = (x == null ? null : x.toString());
1223
1224    setParameterWithTag(parameterIndex,
1225        PreparedStatementSerializationConstants.URL_TAG, serializedParam);
1226  }
1227
1228  /**
1229   * Retrieves the number, types and properties of this
1230   * <code>PreparedStatement</code> object's parameters.
1231   *
1232   * @return a <code>ParameterMetaData</code> object that contains information
1233   * about the number, types and properties of this
1234   * <code>PreparedStatement</code> object's parameters
1235   * @exception SQLException if a database access error occurs
1236   * @see ParameterMetaData
1237   * @since JDK 1.4
1238   */

1239  public ParameterMetaData JavaDoc getParameterMetaData() throws SQLException JavaDoc
1240  {
1241    throw new NotImplementedException("getParameterMetaData");
1242  }
1243
1244  // **************************************************************
1245
// END OF PUBLIC INTERFACE
1246
// **************************************************************
1247

1248  /**
1249   * Stores a parameter into parameters String array. Called by most setXXX()
1250   * methods.
1251   *
1252   * @param paramIndex the index into the inString
1253   * @param s a string to be stored
1254   * @exception SQLException if something goes wrong
1255   */

1256  protected void setParameter(int paramIndex, String JavaDoc s) throws SQLException JavaDoc
1257  {
1258    if (paramIndex < 1 || paramIndex > inStrings.length)
1259      throw new SQLException JavaDoc("Parameter index out of range.");
1260    inStrings[paramIndex - 1] = s;
1261  }
1262
1263  /**
1264   * Return a stored parameter tag and value.
1265   *
1266   * @param paramIndex the index into the inString
1267   * @return a the parameter tag and the parameter value
1268   * @exception SQLException if something goes wrong
1269   */

1270  protected String JavaDoc[] getParameterTagAndValue(int paramIndex)
1271      throws SQLException JavaDoc
1272  {
1273    if (paramIndex < 1 || paramIndex > inStrings.length)
1274      throw new SQLException JavaDoc("Parameter index out of range.");
1275    int typeStart = PreparedStatementSerializationConstants.START_PARAM_TAG
1276        .length();
1277
1278    // Here we assume that all tags have the same length as the boolean tag.
1279
String JavaDoc tagString = inStrings[paramIndex - 1];
1280    String JavaDoc paramType = tagString.substring(typeStart, typeStart
1281        + PreparedStatementSerializationConstants.BOOLEAN_TAG.length());
1282    String JavaDoc paramValue = tagString.substring(typeStart
1283        + PreparedStatementSerializationConstants.BOOLEAN_TAG.length(),
1284        tagString
1285            .indexOf(PreparedStatementSerializationConstants.END_PARAM_TAG));
1286    paramValue = Strings.replace(paramValue,
1287        PreparedStatementSerializationConstants.TAG_MARKER_ESCAPE,
1288        PreparedStatementSerializationConstants.TAG_MARKER);
1289    return new String JavaDoc[]{paramType, paramValue};
1290  }
1291
1292  /**
1293   * Stores parameter and its type as a <em>quoted</em> String, so the
1294   * controller can decode them back.
1295   * <p>
1296   * We could avoid inlining the arguments and just tag them and send them apart
1297   * as an object list. But this would imply a couple of changes elsewhere,
1298   * among other: macro-handling, recoverylog,...
1299   *
1300   * @param paramIndex the index into the inString
1301   * @param typeTag type of the parameter
1302   * @param param the parameter string to be stored
1303   * @exception SQLException if something goes wrong
1304   */

1305  void setParameterWithTag(int paramIndex, String JavaDoc typeTag, String JavaDoc param)
1306      throws SQLException JavaDoc
1307  {
1308    if (isClosed())
1309      throw new SQLException JavaDoc("Unable to set a parameter on a closed statement");
1310
1311    /**
1312     * insert TAGS so the controller can parse and "unset" the request using
1313     * {@link #setPreparedStatement(String, java.sql.PreparedStatement)
1314     */

1315    if (param == null)
1316      param = PreparedStatementSerializationConstants.NULL_VALUE;
1317    else
1318      // escape the markers in argument data
1319
param = Strings.replace(param,
1320          PreparedStatementSerializationConstants.TAG_MARKER,
1321          PreparedStatementSerializationConstants.TAG_MARKER_ESCAPE);
1322
1323    setParameter(paramIndex,
1324        PreparedStatementSerializationConstants.START_PARAM_TAG + typeTag
1325            + param + PreparedStatementSerializationConstants.END_PARAM_TAG);
1326  }
1327
1328  /**
1329   * This class defines a BatchElement used for the batch update vector of
1330   * PreparedStatements to execute.
1331   *
1332   * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet
1333   * </a>
1334   * @version 1.0
1335   */

1336  protected class BatchElement
1337  {
1338    private String JavaDoc sqlTemplate;
1339    private String JavaDoc parameters;
1340
1341    /**
1342     * Creates a new <code>BatchElement</code> object
1343     *
1344     * @param sqlTemplate SQL query template (aka skeleton)
1345     * @param parameters prepared statement parameters
1346     */

1347    public BatchElement(String JavaDoc sqlTemplate, String JavaDoc parameters)
1348    {
1349      this.sqlTemplate = sqlTemplate;
1350      this.parameters = parameters;
1351    }
1352
1353    /**
1354     * Returns the compiledSql value.
1355     *
1356     * @return Returns the compiledSql.
1357     */

1358    public String JavaDoc getParameters()
1359    {
1360      return parameters;
1361    }
1362
1363    /**
1364     * Returns the sqlTemplate value.
1365     *
1366     * @return Returns the sqlTemplate.
1367     */

1368    public String JavaDoc getSqlTemplate()
1369    {
1370      return sqlTemplate;
1371    }
1372  }
1373}
1374
Popular Tags