KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > driver > PreparedStatement


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2005 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Nicolas Modrzyk, Jaco Swart.
23  */

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

82 public class PreparedStatement extends Statement
83     implements
84       java.sql.PreparedStatement JavaDoc
85 {
86   /** Could we use {@link java.sql.Types} instead ? */
87
88   /**
89    * All tags must have the same length
90    * {@link #setPreparedStatement(String, java.sql.PreparedStatement)}
91    */

92   /** Tag for a byte parameter */
93   public static final String JavaDoc BYTE_TAG = "b|";
94   /** Tag for a bytes (used for Blob) parameter */
95   public static final String JavaDoc BYTES_TAG = "B|";
96   /** Tag for a BLOB (used for null Blob) parameter */
97   public static final String JavaDoc BLOB_TAG = "c|";
98   /** Tag for a CLOB (used for null Clob) parameter */
99   public static final String JavaDoc CLOB_TAG = "C|";
100   /** Tag for a boolean parameter */
101   public static final String JavaDoc BOOLEAN_TAG = "0|";
102   /** Tag for a big decimal parameter */
103   public static final String JavaDoc BIG_DECIMAL_TAG = "1|";
104   /** Tag for a date parameter */
105   public static final String JavaDoc DATE_TAG = "d|";
106   /** Tag for a double parameter */
107   public static final String JavaDoc DOUBLE_TAG = "D|";
108   /** Tag for a float parameter */
109   public static final String JavaDoc FLOAT_TAG = "F|";
110   /** Tag for a integer parameter */
111   public static final String JavaDoc INTEGER_TAG = "I|";
112   /** Tag for a long parameter */
113   public static final String JavaDoc LONG_TAG = "L|";
114   /** Tag for a setNull call */
115   public static final String JavaDoc NULL_TAG = "N|";
116   /** Tag for a Null string parameter */
117   public static final String JavaDoc NULL_STRING_TAG = "n|";
118   /** Tag for an object parameter */
119   public static final String JavaDoc OBJECT_TAG = "O|";
120   /** Tag for a Ref parameter */
121   public static final String JavaDoc REF_TAG = "R|";
122   /** Tag for a short parameter */
123   public static final String JavaDoc SHORT_TAG = "s|";
124   /** Tag for a string parameter */
125   public static final String JavaDoc STRING_TAG = "S|";
126   /** Tag for a time parameter */
127   public static final String JavaDoc TIME_TAG = "t|";
128   /** Tag for a timestamp parameter */
129   public static final String JavaDoc TIMESTAMP_TAG = "T|";
130   /** Tag for an URL parameter */
131   public static final String JavaDoc URL_TAG = "U|";
132
133   /** Tag maker for parameters */
134   public static final String JavaDoc TAG_MARKER = "!%";
135   /** Escape for tag maker */
136   public static final String JavaDoc TAG_MARKER_ESCAPE = TAG_MARKER + ";";
137   /** Tag for parameters start delimiter */
138   public static final String JavaDoc START_PARAM_TAG = "<" + TAG_MARKER;
139   /** Tag for parameters end delimiter */
140   public static final String JavaDoc END_PARAM_TAG = "|" + TAG_MARKER + ">";
141
142   /** original, untouched request (only trimmed) */
143   protected String JavaDoc sql;
144   /** IN parameters, ready to be inlined in the request */
145   private String JavaDoc[] inStrings;
146   /** segments: the request splitted by question marks placeholders */
147   private String JavaDoc[] templateStrings;
148
149   // Some performance caches
150
private StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
151
152   /**
153    * Constructor. Parses/Splits the SQL statement into segments - string parts
154    * separated by question mark placeholders. When we rebuild the thing with the
155    * arguments, we can substitute the args by joining segments and parameters
156    * back together.
157    *
158    * @param connection the instanatiating connection
159    * @param sqlStatement the SQL statement with ? for IN markers
160    * @exception SQLException if something bad occurs
161    */

162   public PreparedStatement(Connection connection, String JavaDoc sqlStatement)
163       throws SQLException JavaDoc
164   {
165     super(connection);
166
167     /** temporary array for segments */
168     ArrayList JavaDoc segs = new ArrayList JavaDoc();
169     int lastParmEnd = 0;
170
171     // The following two boolean switches are used to make sure we're not
172
// counting "?" in either strings or metadata strings. For instance the
173
// following query:
174
// select '?' "A ? value" from dual
175
// doesn't have any parameters.
176

177     boolean inString = false;
178     boolean inMetaString = false;
179
180     this.sql = sqlStatement.trim();
181     this.connection = connection;
182     for (int i = 0; i < sql.length(); ++i)
183     {
184       if (sql.charAt(i) == '\'')
185         inString = !inString;
186       if (sql.charAt(i) == '"')
187         inMetaString = !inMetaString;
188       if ((sql.charAt(i) == '?') && (!(inString || inMetaString)))
189       {
190         segs.add(sql.substring(lastParmEnd, i));
191         lastParmEnd = i + 1;
192       }
193     }
194     segs.add(sql.substring(lastParmEnd, sql.length()));
195
196     int size = segs.size();
197     templateStrings = new String JavaDoc[size];
198     inStrings = new String JavaDoc[size - 1];
199     clearParameters();
200
201     for (int i = 0; i < size; ++i)
202       templateStrings[i] = (String JavaDoc) segs.get(i);
203   }
204
205   /**
206    * Release objects for garbage collection and call Statement.close().
207    *
208    * @throws SQLException if an error occurs
209    */

210   public void close() throws SQLException JavaDoc
211   {
212     sql = null;
213     templateStrings = null;
214     inStrings = null;
215
216     super.close();
217   }
218
219   /**
220    * A Prepared SQL query is executed and its <code>ResultSet</code> is
221    * returned.
222    *
223    * @return a <code>ResultSet</code> that contains the data produced by the *
224    * query - never <code>null</code>.
225    * @exception SQLException if a database access error occurs
226    */

227   public java.sql.ResultSet JavaDoc executeQuery() throws SQLException JavaDoc
228   {
229     return super.executeQuery(sql, compileQuery()); // in Statement class
230
}
231
232   /**
233    * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
234    * statements that return nothing such as SQL DDL statements can be executed.
235    *
236    * @return either the row count for <code>INSERT</code>,
237    * <code>UPDATE</code> or <code>DELETE</code>; or 0 for SQL
238    * statements that return nothing.
239    * @exception SQLException if a database access error occurs
240    */

241   public int executeUpdate() throws SQLException JavaDoc
242   {
243     return super.executeUpdateWithSkeleton(sql, compileQuery());
244     // in Statement class
245
}
246
247   /**
248    * Helper - this compiles the SQL query, inlining the parameters in the
249    * request String. This is identical to <code>this.toString()</code> except
250    * it throws an exception if a parameter was not set.
251    *
252    * @return the compiled query
253    * @throws SQLException if an error occurs
254    */

255   protected synchronized String JavaDoc compileQuery() throws SQLException JavaDoc
256   {
257     sbuf.setLength(0);
258     int i;
259
260     for (i = 0; i < inStrings.length; ++i)
261     {
262       if (inStrings[i] == null)
263         throw new SQLException JavaDoc("Parameter " + (i + 1) + " is incorrect");
264       sbuf.append(templateStrings[i]).append(inStrings[i]);
265     }
266     sbuf.append(templateStrings[inStrings.length]);
267     return sbuf.toString();
268   }
269
270   /**
271    * Escape the input string. <br>
272    * <char>' </char> is replaced by <char>\' </char> <br>
273    * <char>\ </char> is replaced by <char>\\' </char> <br>
274    * if connection.escapeProcessing is set to true, surround the new string with
275    * <char>\' </char>
276    *
277    * @param x the string to process
278    * @return escaped string
279    */

280   protected String JavaDoc doEscapeProcessing(String JavaDoc x)
281   {
282     // use the shared buffer object. Should never clash but this
283
// makes us thread safe!
284
synchronized (sbuf)
285     {
286       sbuf.setLength(0);
287       int i;
288       sbuf.append(connection.getEscapeChar());
289       for (i = 0; i < x.length(); ++i)
290       {
291         char c = x.charAt(i);
292         if ((c == '\'' && connection.isEscapeSingleQuote())
293             || (c == '\\' && connection.isEscapeBackslash()))
294           sbuf.append(c);
295         sbuf.append(c);
296       }
297       sbuf.append(connection.getEscapeChar());
298     }
299     return sbuf.toString();
300   }
301
302   /**
303    * Sets a parameter to SQL NULL.
304    * <p>
305    * <b>Note: </b> you must specify the parameters SQL type but we ignore it.
306    *
307    * @param parameterIndex the first parameter is 1, etc...
308    * @param sqlType the SQL type code defined in java.sql.Types
309    * @exception SQLException if a database access error occurs
310    */

311   public void setNull(int parameterIndex, int sqlType) throws SQLException JavaDoc
312   {
313     if (connection.isDriverProcessed())
314       set(parameterIndex, "null");
315     else
316       setWithTag(parameterIndex, NULL_TAG, String.valueOf(sqlType));
317   }
318
319   /**
320    * Sets a parameter to a Java boolean value. The driver converts this to a SQL
321    * BIT value when it sends it to the database.
322    *
323    * @param parameterIndex the first parameter is 1...
324    * @param x the parameter value
325    * @exception SQLException if a database access error occurs
326    */

327   public void setBoolean(int parameterIndex, boolean x) throws SQLException JavaDoc
328   {
329     if (connection.isDriverProcessed())
330     {
331       set(parameterIndex, x
332           ? connection.getPreparedStatementBooleanTrue()
333           : connection.getPreparedStatementBooleanFalse());
334     }
335     else
336     {
337       setWithTag(parameterIndex, BOOLEAN_TAG, String.valueOf(x));
338     }
339   }
340
341   /**
342    * Sets a parameter to a Java byte value.
343    *
344    * @param parameterIndex the first parameter is 1...
345    * @param x the parameter value
346    * @exception SQLException if a database access error occurs
347    */

348   public void setByte(int parameterIndex, byte x) throws SQLException JavaDoc
349   {
350     if (connection.isDriverProcessed())
351     {
352       set(parameterIndex, Integer.toString(x));
353     }
354     else
355     {
356       setWithTag(parameterIndex, BYTE_TAG, Integer.toString(x));
357     }
358   }
359
360   /**
361    * Sets a parameter to a Java short value. The driver converts this to a SQL
362    * SMALLINT value when it sends it to the database.
363    *
364    * @param parameterIndex the first parameter is 1...
365    * @param x the parameter value
366    * @exception SQLException if a database access error occurs
367    */

368   public void setShort(int parameterIndex, short x) throws SQLException JavaDoc
369   {
370     if (connection.isDriverProcessed())
371     {
372       set(parameterIndex, Integer.toString(x));
373     }
374     else
375     {
376       setWithTag(parameterIndex, SHORT_TAG, Integer.toString(x));
377     }
378   }
379
380   /**
381    * Sets a parameter to a Java int value. The driver converts this to a SQL
382    * INTEGER value when it sends it to the database.
383    *
384    * @param parameterIndex the first parameter is 1...
385    * @param x the parameter value
386    * @exception SQLException if a database access error occurs
387    */

388   public void setInt(int parameterIndex, int x) throws SQLException JavaDoc
389   {
390     if (connection.isDriverProcessed())
391     {
392       set(parameterIndex, Integer.toString(x));
393     }
394     else
395     {
396       setWithTag(parameterIndex, INTEGER_TAG, Integer.toString(x));
397     }
398   }
399
400   /**
401    * Sets a parameter to a Java long value. The driver converts this to a SQL
402    * BIGINT value when it sends it to the database.
403    *
404    * @param parameterIndex the first parameter is 1...
405    * @param x the parameter value
406    * @exception SQLException if a database access error occurs
407    */

408   public void setLong(int parameterIndex, long x) throws SQLException JavaDoc
409   {
410     if (connection.isDriverProcessed())
411     {
412       set(parameterIndex, Long.toString(x));
413     }
414     else
415     {
416       setWithTag(parameterIndex, LONG_TAG, Long.toString(x));
417     }
418   }
419
420   /**
421    * Sets a parameter to a Java float value. The driver converts this to a SQL
422    * FLOAT value when it sends it to the database.
423    *
424    * @param parameterIndex the first parameter is 1...
425    * @param x the parameter value
426    * @exception SQLException if a database access error occurs
427    */

428   public void setFloat(int parameterIndex, float x) throws SQLException JavaDoc
429   {
430     if (connection.isDriverProcessed())
431     {
432       set(parameterIndex, Float.toString(x));
433     }
434     else
435     {
436       setWithTag(parameterIndex, FLOAT_TAG, Float.toString(x));
437     }
438   }
439
440   /**
441    * Sets a parameter to a Java double value. The driver converts this to a SQL
442    * DOUBLE value when it sends it to the database.
443    *
444    * @param parameterIndex the first parameter is 1...
445    * @param x the parameter value
446    * @exception SQLException if a database access error occurs
447    */

448   public void setDouble(int parameterIndex, double x) throws SQLException JavaDoc
449   {
450     if (connection.isDriverProcessed())
451     {
452       set(parameterIndex, Double.toString(x));
453     }
454     else
455     {
456       setWithTag(parameterIndex, DOUBLE_TAG, Double.toString(x));
457     }
458   }
459
460   /**
461    * Sets a parameter to a java.lang.BigDecimal value. The driver converts this
462    * to a SQL NUMERIC value when it sends it to the database.
463    *
464    * @param parameterIndex the first parameter is 1...
465    * @param x the parameter value
466    * @exception SQLException if a database access error occurs
467    */

468   public void setBigDecimal(int parameterIndex, BigDecimal JavaDoc x)
469       throws SQLException JavaDoc
470   {
471     if (connection.isDriverProcessed())
472     {
473       if (x == null)
474         setNull(parameterIndex, Types.DECIMAL);
475       else
476         set(parameterIndex, x.toString());
477     }
478     else
479     {
480       if (x == null)
481         setWithTag(parameterIndex, BIG_DECIMAL_TAG, NULL_TAG);
482       else
483         setWithTag(parameterIndex, BIG_DECIMAL_TAG, x.toString());
484     }
485   }
486
487   /**
488    * Sets a parameter to a Java String value. The driver converts this to a SQL
489    * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
490    * the driver's limits on VARCHARs) when it sends it to the database.
491    *
492    * @param parameterIndex the first parameter is 1...
493    * @param x the parameter value
494    * @exception SQLException if a database access error occurs
495    */

496   public void setString(int parameterIndex, String JavaDoc x) throws SQLException JavaDoc
497   {
498     if (connection.isDriverProcessed())
499     {
500       if (x == null)
501         // if the passed string is null, then set this column to null
502
setNull(parameterIndex, Types.VARCHAR);
503       else
504       {
505         if (escapeProcessing
506             && (connection.isEscapeBackslash() || connection
507                 .isEscapeSingleQuote()))
508           set(parameterIndex, doEscapeProcessing(x));
509         else
510           // No escape processing
511
set(parameterIndex, x);
512       }
513     }
514     else
515     {
516       if (x == null)
517         setWithTag(parameterIndex, STRING_TAG, NULL_TAG);
518       else
519       {
520         if (NULL_TAG.equals(x))
521         { // Someone is trying to set a String that matches our NULL tag, a real
522
// bad luck, use our special NULL_STRING_TAG!
523
setWithTag(parameterIndex, NULL_STRING_TAG, x);
524         }
525         else
526         { // No escape processing is needed for queries not being parsed into
527
// statements.
528
setWithTag(parameterIndex, STRING_TAG, x);
529         }
530       }
531     }
532   }
533
534   /**
535    * Sets a parameter to a Java array of bytes.
536    * <p>
537    *
538    * @param parameterIndex the first parameter is 1...
539    * @param x the parameter value
540    * @exception SQLException if a database access error occurs
541    */

542   public void setBytes(int parameterIndex, byte[] x) throws SQLException JavaDoc
543   {
544     String JavaDoc blob;
545     try
546     {
547       synchronized (sbuf)
548       {
549         if (connection.isDriverProcessed())
550         {
551           /* Encoded for database storage */
552           blob = connection.getBlobFilter().encode(x);
553           sbuf.setLength(0);
554           sbuf.append(connection.escapeChar);
555           sbuf.append(blob);
556           sbuf.append(connection.escapeChar);
557           set(parameterIndex, sbuf.toString());
558         }
559         else
560         {
561           /**
562            * Encoded only for request inlining. Decoded right away by the
563            * controller at static
564            * {@link #setPreparedStatement(String, java.sql.PreparedStatement)}
565            */

566           blob = new HexaBlobFilter().encode(x);
567           setWithTag(parameterIndex, BYTES_TAG, blob);
568         }
569       }
570     }
571     catch (OutOfMemoryError JavaDoc oome)
572     {
573       blob = null;
574       sbuf = null;
575       System.gc();
576       throw new SQLException JavaDoc("Out of memory");
577     }
578   }
579
580   /**
581    * Sets a parameter to a java.sql.Date value. The driver converts this to a
582    * SQL DATE value when it sends it to the database.
583    *
584    * @param parameterIndex the first parameter is 1...
585    * @param x the parameter value
586    * @exception SQLException if a database access error occurs
587    */

588   public void setDate(int parameterIndex, java.sql.Date JavaDoc x) throws SQLException JavaDoc
589   {
590     if (connection.isDriverProcessed())
591     {
592       if (x == null)
593         setNull(parameterIndex, Types.DATE);
594       else
595         set(parameterIndex, "'" + new java.sql.Date JavaDoc(x.getTime()).toString()
596             + "'");
597     }
598     else
599     {
600       if (x == null)
601         setWithTag(parameterIndex, DATE_TAG, NULL_TAG);
602       else
603         setWithTag(parameterIndex, DATE_TAG, new java.sql.Date JavaDoc(x.getTime())
604             .toString());
605     }
606   }
607
608   /**
609    * Sets a parameter to a <code>java.sql.Time</code> value. The driver
610    * converts this to a SQL TIME value when it sends it to the database.
611    *
612    * @param parameterIndex the first parameter is 1...));
613    * @param x the parameter value
614    * @exception SQLException if a database access error occurs
615    */

616   public void setTime(int parameterIndex, Time JavaDoc x) throws SQLException JavaDoc
617   {
618     if (connection.isDriverProcessed())
619     {
620       if (x == null)
621         setNull(parameterIndex, Types.TIME);
622       else
623         set(parameterIndex, "{t '" + x.toString() + "'}");
624     }
625     else
626     {
627       if (x == null)
628         setWithTag(parameterIndex, TIME_TAG, NULL_TAG);
629       else
630         setWithTag(parameterIndex, TIME_TAG, x.toString());
631     }
632   }
633
634   /**
635    * Sets a parameter to a <code>java.sql.Timestamp</code> value. The driver
636    * converts this to a SQL TIMESTAMP value when it sends it to the database.
637    *
638    * @param parameterIndex the first parameter is 1...
639    * @param x the parameter value
640    * @exception SQLException if a database access error occurs
641    */

642   public void setTimestamp(int parameterIndex, Timestamp JavaDoc x) throws SQLException JavaDoc
643   {
644     if (connection.isDriverProcessed())
645     {
646       if (x == null)
647         setNull(parameterIndex, Types.TIMESTAMP);
648       else
649       {
650         // Be careful don't use instanceof here since it would match derived
651
// classes.
652
if (x.getClass().equals(Timestamp JavaDoc.class))
653           set(parameterIndex, "'" + x.toString() + "'");
654         else
655           set(parameterIndex, "'" + new Timestamp JavaDoc(x.getTime()).toString() + "'");
656       }
657     }
658     else
659     {
660       if (x == null)
661         setWithTag(parameterIndex, TIMESTAMP_TAG, NULL_TAG);
662       else
663       {
664         if (x.getClass().equals(Timestamp JavaDoc.class))
665           setWithTag(parameterIndex, TIMESTAMP_TAG, x.toString());
666         else
667           setWithTag(parameterIndex, TIMESTAMP_TAG, new Timestamp JavaDoc(x.getTime())
668               .toString());
669       }
670     }
671   }
672
673   /**
674    * When a very large ASCII value is input to a LONGVARCHAR parameter, it may
675    * be more practical to send it via a java.io.InputStream. JDBC will read the
676    * data from the stream as needed, until it reaches end-of-file. The JDBC
677    * driver will do any necessary conversion from ASCII to the database char
678    * format.
679    * <p>
680    * <b>Note: </b> this stream object can either be a standard Java stream
681    * object or your own subclass that implements the standard interface.
682    *
683    * @param parameterIndex the first parameter is 1...
684    * @param x the parameter value
685    * @param length the number of bytes in the stream
686    * @exception SQLException if a database access error occurs
687    */

688   public void setAsciiStream(int parameterIndex, InputStream JavaDoc x, int length)
689       throws SQLException JavaDoc
690   {
691     setBinaryStream(parameterIndex, x, length);
692   }
693
694   /**
695    * When a very large Unicode value is input to a LONGVARCHAR parameter, it may
696    * be more practical to send it via a java.io.InputStream. JDBC will read the
697    * data from the stream as needed, until it reaches end-of-file. The JDBC
698    * driver will do any necessary conversion from UNICODE to the database char
699    * format.
700    * <p>** DEPRECIATED IN JDBC 2 **
701    * <p>
702    * <b>Note: </b> this stream object can either be a standard Java stream
703    * object or your own subclass that implements the standard interface.
704    *
705    * @param parameterIndex the first parameter is 1...
706    * @param x the parameter value
707    * @param length the parameter length
708    * @exception SQLException if a database access error occurs
709    * @deprecated
710    */

711   public void setUnicodeStream(int parameterIndex, InputStream JavaDoc x, int length)
712       throws SQLException JavaDoc
713   {
714     setBinaryStream(parameterIndex, x, length);
715   }
716
717   /**
718    * Stores a binary stream into parameters array, using an intermediate byte[].
719    * When a very large binary value is input to a LONGVARBINARY parameter, it
720    * may be more practical to send it via a java.io.InputStream. JDBC will read
721    * the data from the stream as needed, until it reaches end-of-file. This
722    * should be more or less equivalent to setBytes(blob.getBytes()).
723    * <p>
724    * <b>Note: </b> This stream object can either be a standard Java stream
725    * object or your own subclass that implements the standard interface.
726    *
727    * @param parameterIndex the first parameter is 1...
728    * @param inStreamArg the parameter value
729    * @param length the parameter length
730    * @exception SQLException if a database access error occurs
731    * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream,
732    * int)
733    */

734   public void setBinaryStream(int parameterIndex, InputStream JavaDoc inStreamArg,
735       int length) throws SQLException JavaDoc
736   {
737     byte[] data = new byte[length];
738     try
739     {
740       inStreamArg.read(data, 0, length);
741     }
742     catch (Exception JavaDoc ioe)
743     {
744       throw new SQLException JavaDoc("Problem with streaming of data");
745     }
746     setBytes(parameterIndex, data);
747   }
748
749   /**
750    * In general, parameter values remain in force for repeated used of a
751    * <code>Statement</code>. Setting a parameter value automatically clears
752    * its previous value. However, in coms cases, it is useful to immediately
753    * release the resources used by the current parameter values; this can be
754    * done by calling <code>clearParameters()</code>.
755    *
756    * @exception SQLException if a database access error occurs
757    */

758   public void clearParameters() throws SQLException JavaDoc
759   {
760     int i;
761
762     for (i = 0; i < inStrings.length; i++)
763       inStrings[i] = null;
764   }
765
766   /**
767    * Sets the value of a parameter using an object; use the
768    * <code>java.lang</code> equivalent objects for integral values.
769    * <p>
770    * The given Java object will be converted to the targetSqlType before being
771    * sent to the database.
772    * <p>
773    * Note that this method may be used to pass database-specific abstract data
774    * types. This is done by using a Driver-specific Java type and using a
775    * <code>targetSqlType</code> of <code>java.sql.Types.OTHER</code>.
776    *
777    * @param parameterIndex the first parameter is 1...
778    * @param x the object containing the input parameter value
779    * @param targetSqlType The SQL type to be send to the database
780    * @param scale for <code>java.sql.Types.DECIMAL</code> or
781    * <code>java.sql.Types.NUMERIC</code> types this is the number of
782    * digits after the decimal. For all other types this value will be
783    * ignored.
784    * @exception SQLException if a database access error or an incompatible type
785    * match occurs
786    * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int, int)
787    */

788   public void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType,
789       int scale) throws SQLException JavaDoc
790   {
791     if (x == null)
792     {
793       setNull(parameterIndex, targetSqlType);
794       return;
795     }
796
797     try
798     {
799       boolean failed = false;
800       switch (targetSqlType)
801       {
802         /**
803          * Reference is table "Conversions Performed by setObject()..." in JDBC
804          * Reference Book (table 47.9.5 in 2nd edition, 50.5 in 3rd edition).
805          * Also available online in Sun's "JDBC Technology Guide: Getting
806          * Started", section "Mapping SQL and Java Types".
807          */

808         // using else setXXX( .toString()) below is a lax hack
809
case Types.TINYINT :
810         case Types.SMALLINT :
811         case Types.INTEGER :
812           if (x instanceof Number JavaDoc)
813             setInt(parameterIndex, ((Number JavaDoc) x).intValue());
814           else if (x instanceof Boolean JavaDoc)
815             setInt(parameterIndex, ((Boolean JavaDoc) x).booleanValue() ? 1 : 0);
816           else if (x instanceof String JavaDoc)
817             setInt(parameterIndex, Integer.parseInt((String JavaDoc) x));
818           else
819             failed = true;
820           break;
821         case Types.BIGINT :
822           if (x instanceof Number JavaDoc)
823             setLong(parameterIndex, ((Number JavaDoc) x).longValue());
824           else if (x instanceof String JavaDoc)
825             setLong(parameterIndex, Long.parseLong((String JavaDoc) x));
826           else if (x instanceof Boolean JavaDoc)
827             setLong(parameterIndex, ((Boolean JavaDoc) x).booleanValue() ? 1 : 0);
828           else
829             failed = true;
830           break;
831         case Types.REAL :
832         case Types.FLOAT :
833         case Types.DOUBLE :
834         case Types.DECIMAL :
835         case Types.NUMERIC :
836           // Cast to Number is not necessary. -- EC
837
// Hum, this is a lax shortcut to lower level code -- MH
838
if (connection.isDriverProcessed())
839             set(parameterIndex, x.toString());
840           else
841             setWithTag(parameterIndex, STRING_TAG, x.toString());
842           break;
843         case Types.BIT :
844         case Types.BOOLEAN :
845           if (x instanceof Number JavaDoc)
846             setBoolean(parameterIndex, 0 != ((Number JavaDoc) x).longValue());
847           else if (x instanceof Boolean JavaDoc)
848             setBoolean(parameterIndex, ((Boolean JavaDoc) x).booleanValue());
849           else if (x instanceof String JavaDoc)
850             setBoolean(parameterIndex, Boolean.valueOf((String JavaDoc) x)
851                 .booleanValue());
852           else
853             failed = true;
854           break;
855         case Types.CHAR :
856         case Types.VARCHAR :
857         case Types.LONGVARCHAR :
858           setString(parameterIndex, x.toString());
859           break;
860         case Types.BINARY :
861         case Types.VARBINARY :
862         case Types.LONGVARBINARY :
863           if (x instanceof byte[])
864             setBytes(parameterIndex, (byte[]) x);
865           else if (x instanceof Blob)
866             setBlob(parameterIndex, (Blob) x);
867           else if (x instanceof Serializable JavaDoc)
868             // Try it as an Object (serialized in bytes in setObject below)
869
setObject(parameterIndex, x);
870           else
871             failed = true;
872           break;
873         case Types.DATE :
874           if (x instanceof String JavaDoc)
875             setDate(parameterIndex, java.sql.Date.valueOf((String JavaDoc) x));
876           else if (x instanceof java.sql.Date JavaDoc)
877             setDate(parameterIndex, (java.sql.Date JavaDoc) x);
878           else if (x instanceof Timestamp JavaDoc)
879             setDate(parameterIndex,
880                 new java.sql.Date JavaDoc(((Timestamp JavaDoc) x).getTime()));
881           else
882             failed = true;
883           break;
884         case Types.TIME :
885           if (x instanceof String JavaDoc)
886             setTime(parameterIndex, Time.valueOf((String JavaDoc) x));
887           else if (x instanceof Time JavaDoc)
888             setTime(parameterIndex, (Time JavaDoc) x);
889           else if (x instanceof Timestamp JavaDoc)
890             setTime(parameterIndex, new Time JavaDoc(((Timestamp JavaDoc) x).getTime()));
891           else
892             failed = true;
893           break;
894         case