KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > PreparedStatement


1 /*
2    Copyright (C) 2002 MySQL AB
3
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8
9       This program is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12       GNU General Public License for more details.
13
14       You should have received a copy of the GNU General Public License
15       along with this program; if not, write to the Free Software
16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18  */

19 package com.mysql.jdbc;
20
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.ByteArrayOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.ObjectOutputStream JavaDoc;
26 import java.io.Reader JavaDoc;
27 import java.io.StringReader JavaDoc;
28 import java.io.UnsupportedEncodingException JavaDoc;
29
30 import java.math.BigDecimal JavaDoc;
31
32 import java.net.URL JavaDoc;
33
34 import java.sql.Array JavaDoc;
35 import java.sql.Clob 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
43 import java.text.ParsePosition JavaDoc;
44 import java.text.SimpleDateFormat JavaDoc;
45
46 import java.util.ArrayList JavaDoc;
47 import java.util.Calendar JavaDoc;
48 import java.util.TimeZone JavaDoc;
49
50
51 /**
52  * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
53  * This object can then be used to efficiently execute this statement multiple
54  * times.
55  *
56  * <p>
57  * <B>Note:</B> The setXXX methods for setting IN parameter values must specify
58  * types that are compatible with the defined SQL type of the input parameter.
59  * For instance, if the IN parameter has SQL type Integer, then setInt should
60  * be used.
61  * </p>
62  *
63  * <p>
64  * If arbitrary parameter type conversions are required, then the setObject
65  * method should be used with a target SQL type.
66  * </p>
67  *
68  * @author Mark Matthews
69  * @version $Id: PreparedStatement.java,v 1.27.2.33 2004/02/05 15:56:17 mmatthew Exp $
70  *
71  * @see java.sql.ResultSet
72  * @see java.sql.PreparedStatement
73  */

74 public class PreparedStatement extends com.mysql.jdbc.Statement
75     implements java.sql.PreparedStatement JavaDoc {
76     private java.sql.DatabaseMetaData JavaDoc dbmd = null;
77     private ParseInfo parseInfo;
78     private java.sql.ResultSetMetaData JavaDoc pstmtResultMetaData;
79     private SimpleDateFormat JavaDoc tsdf = null;
80     private String JavaDoc originalSql = null;
81     private boolean[] isNull = null;
82     private boolean[] isStream = null;
83     private InputStream JavaDoc[] parameterStreams = null;
84     private byte[][] parameterValues = null;
85     private byte[][] staticSqlStrings = null;
86     private byte[] streamConvertBuf = new byte[4096];
87     private int[] streamLengths = null;
88     private boolean hasLimitClause = false;
89     private boolean isLoadDataQuery = false;
90     private boolean retrieveGeneratedKeys = false;
91     private boolean useTrueBoolean = false;
92     private char firstCharOfStmt = 0;
93
94     /**
95      * Constructor for the PreparedStatement class.
96      *
97      * @param conn the connection creating this statement
98      * @param sql the SQL for this statement
99      * @param catalog the catalog/database this statement should be issued
100      * against
101      *
102      * @throws SQLException if a database error occurs.
103      */

104     public PreparedStatement(Connection conn, String JavaDoc sql, String JavaDoc catalog)
105         throws SQLException JavaDoc {
106         super(conn, catalog);
107
108         if (sql == null) {
109             throw new SQLException JavaDoc("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
110         }
111
112         originalSql = sql;
113
114         this.dbmd = this.connection.getMetaData();
115
116         useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23);
117
118         this.parseInfo = new ParseInfo(sql, this.connection, this.dbmd,
119                 this.charEncoding, this.charConverter);
120
121         initializeFromParseInfo();
122     }
123
124     /**
125      * Creates a new PreparedStatement object.
126      *
127      * @param conn the connection creating this statement
128      * @param sql the SQL for this statement
129      * @param catalog the catalog/database this statement should be issued
130      * against
131      * @param cachedParseInfo already created parseInfo.
132      *
133      * @throws SQLException DOCUMENT ME!
134      */

135     public PreparedStatement(Connection conn, String JavaDoc sql, String JavaDoc catalog,
136         ParseInfo cachedParseInfo) throws SQLException JavaDoc {
137         super(conn, catalog);
138
139         if (sql == null) {
140             throw new SQLException JavaDoc("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
141         }
142
143         originalSql = sql;
144
145         this.dbmd = this.connection.getMetaData();
146
147         useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23);
148
149         this.parseInfo = cachedParseInfo;
150
151         initializeFromParseInfo();
152     }
153
154     /**
155      * JDBC 2.0 Set an Array parameter.
156      *
157      * @param i the first parameter is 1, the second is 2, ...
158      * @param x an object representing an SQL array
159      *
160      * @throws SQLException because this method is not implemented.
161      * @throws NotImplemented DOCUMENT ME!
162      */

163     public void setArray(int i, Array JavaDoc x) throws SQLException JavaDoc {
164         throw new NotImplemented();
165     }
166
167     /**
168      * When a very large ASCII value is input to a LONGVARCHAR parameter, it
169      * may be more practical to send it via a java.io.InputStream. JDBC will
170      * read the data from the stream as needed, until it reaches end-of-file.
171      * The JDBC driver will do any necessary conversion from ASCII to the
172      * database char format.
173      *
174      * <P>
175      * <B>Note:</B> This stream object can either be a standard Java stream
176      * object or your own subclass that implements the standard interface.
177      * </p>
178      *
179      * @param parameterIndex the first parameter is 1...
180      * @param x the parameter value
181      * @param length the number of bytes in the stream
182      *
183      * @exception SQLException if a database access error occurs
184      */

185     public synchronized void setAsciiStream(int parameterIndex, InputStream JavaDoc x,
186         int length) throws SQLException JavaDoc {
187         if (x == null) {
188             setNull(parameterIndex, java.sql.Types.VARCHAR);
189         } else {
190             setBinaryStream(parameterIndex, x, length);
191         }
192     }
193
194     /**
195      * Set a parameter to a java.math.BigDecimal value. The driver converts
196      * this to a SQL NUMERIC value when it sends it to the database.
197      *
198      * @param parameterIndex the first parameter is 1...
199      * @param x the parameter value
200      *
201      * @exception SQLException if a database access error occurs
202      */

203     public void setBigDecimal(int parameterIndex, BigDecimal JavaDoc x)
204         throws SQLException JavaDoc {
205         if (x == null) {
206             setNull(parameterIndex, java.sql.Types.DECIMAL);
207         } else {
208             setInternal(parameterIndex, fixDecimalExponent(x.toString()));
209         }
210     }
211
212     /**
213      * When a very large binary value is input to a LONGVARBINARY parameter, it
214      * may be more practical to send it via a java.io.InputStream. JDBC will
215      * read the data from the stream as needed, until it reaches end-of-file.
216      *
217      * <P>
218      * <B>Note:</B> This stream object can either be a standard Java stream
219      * object or your own subclass that implements the standard interface.
220      * </p>
221      *
222      * @param parameterIndex the first parameter is 1...
223      * @param x the parameter value
224      * @param length the number of bytes to read from the stream (ignored)
225      *
226      * @throws SQLException if a database access error occurs
227      * @throws java.sql.SQLException DOCUMENT ME!
228      */

229     public void setBinaryStream(int parameterIndex, InputStream JavaDoc x, int length)
230         throws SQLException JavaDoc {
231         if (x == null) {
232             setNull(parameterIndex, java.sql.Types.BINARY);
233         } else {
234             if ((parameterIndex < 1)
235                     || (parameterIndex > staticSqlStrings.length)) {
236                 throw new java.sql.SQLException JavaDoc(
237                     "Parameter index out of range (" + parameterIndex + " > "
238                     + staticSqlStrings.length + ")", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
239             }
240
241             parameterStreams[parameterIndex - 1] = x;
242             isStream[parameterIndex - 1] = true;
243             streamLengths[parameterIndex - 1] = length;
244             isNull[parameterIndex - 1] = false;
245         }
246     }
247
248     /**
249      * JDBC 2.0 Set a BLOB parameter.
250      *
251      * @param i the first parameter is 1, the second is 2, ...
252      * @param x an object representing a BLOB
253      *
254      * @throws SQLException if a database error occurs
255      */

256     public void setBlob(int i, java.sql.Blob JavaDoc x) throws SQLException JavaDoc {
257         setBinaryStream(i, x.getBinaryStream(), (int) x.length());
258     }
259
260     /**
261      * Set a parameter to a Java boolean value. The driver converts this to a
262      * SQL BIT value when it sends it to the database.
263      *
264      * @param parameterIndex the first parameter is 1...
265      * @param x the parameter value
266      *
267      * @throws SQLException if a database access error occurs
268      */

269     public void setBoolean(int parameterIndex, boolean x)
270         throws SQLException JavaDoc {
271         if (useTrueBoolean) {
272             setInternal(parameterIndex, x ? "'1'" : "'0'");
273         } else {
274             setInternal(parameterIndex, x ? "'t'" : "'f'");
275         }
276     }
277
278     /**
279      * Set a parameter to a Java byte value. The driver converts this to a SQL
280      * TINYINT value when it sends it to the database.
281      *
282      * @param parameterIndex the first parameter is 1...
283      * @param x the parameter value
284      *
285      * @exception SQLException if a database access error occurs
286      */

287     public void setByte(int parameterIndex, byte x) throws SQLException JavaDoc {
288         setInternal(parameterIndex, String.valueOf(x));
289     }
290
291     /**
292      * Set a parameter to a Java array of bytes. The driver converts this to a
293      * SQL VARBINARY or LONGVARBINARY (depending on the argument's size
294      * relative to the driver's limits on VARBINARYs) when it sends it to the
295      * database.
296      *
297      * @param parameterIndex the first parameter is 1...
298      * @param x the parameter value
299      *
300      * @exception SQLException if a database access error occurs
301      */

302     public void setBytes(int parameterIndex, byte[] x)
303         throws SQLException JavaDoc {
304         if (x == null) {
305             setNull(parameterIndex, java.sql.Types.BINARY);
306         } else {
307             // escape them
308
int numBytes = x.length;
309
310             ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc(numBytes);
311
312             bOut.write('\'');
313
314             for (int i = 0; i < numBytes; ++i) {
315                 byte b = x[i];
316
317                 switch (b) {
318                 case 0: /* Must be escaped for 'mysql' */
319                     bOut.write('\\');
320                     bOut.write('0');
321
322                     break;
323
324                 case '\n': /* Must be escaped for logs */
325                     bOut.write('\\');
326                     bOut.write('n');
327
328                     break;
329
330                 case '\r':
331                     bOut.write('\\');
332                     bOut.write('r');
333
334                     break;
335
336                 case '\\':
337                     bOut.write('\\');
338                     bOut.write('\\');
339
340                     break;
341
342                 case '\'':
343                     bOut.write('\\');
344                     bOut.write('\'');
345
346                     break;
347
348                 case '"': /* Better safe than sorry */
349                     bOut.write('\\');
350                     bOut.write('"');
351
352                     break;
353
354                 case '\032': /* This gives problems on Win32 */
355                     bOut.write('\\');
356                     bOut.write('Z');
357
358                     break;
359
360                 default:
361                     bOut.write(b);
362                 }
363             }
364
365             bOut.write('\'');
366
367             setInternal(parameterIndex, bOut.toByteArray());
368         }
369     }
370
371     /**
372      * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR
373      * parameter, it may be more practical to send it via a java.io.Reader.
374      * JDBC will read the data from the stream as needed, until it reaches
375      * end-of-file. The JDBC driver will do any necessary conversion from
376      * UNICODE to the database char format.
377      *
378      * <P>
379      * <B>Note:</B> This stream object can either be a standard Java stream
380      * object or your own subclass that implements the standard interface.
381      * </p>
382      *
383      * @param parameterIndex the first parameter is 1, the second is 2, ...
384      * @param reader the java reader which contains the UNICODE data
385      * @param length the number of characters in the stream
386      *
387      * @throws SQLException if a database-access error occurs.
388      */

389     public void setCharacterStream(int parameterIndex, java.io.Reader JavaDoc reader,
390         int length) throws SQLException JavaDoc {
391         try {
392             if (reader == null) {
393                 setNull(parameterIndex, Types.LONGVARCHAR);
394             } else {
395                 char[] c = null;
396                 int len = 0;
397
398                 boolean useLength = this.connection.useStreamLengthsInPrepStmts();
399
400                 if (useLength && (length != -1)) {
401                     c = new char[length];
402
403                     int numCharsRead = readFully(reader, c, length); // blocks until all read
404

405                     setString(parameterIndex, new String JavaDoc(c, 0, numCharsRead));
406                 } else {
407                     c = new char[4096];
408
409                     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
410
411                     while ((len = reader.read(c)) != -1) {
412                         buf.append(c, 0, len);
413                     }
414
415                     setString(parameterIndex, buf.toString());
416                 }
417             }
418         } catch (java.io.IOException JavaDoc ioEx) {
419             throw new SQLException JavaDoc(ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
420         }
421     }
422
423     /**
424      * JDBC 2.0 Set a CLOB parameter.
425      *
426      * @param i the first parameter is 1, the second is 2, ...
427      * @param x an object representing a CLOB
428      *
429      * @throws SQLException if a database error occurs
430      */

431     public void setClob(int i, Clob x) throws SQLException JavaDoc {
432         setString(i, x.getSubString(1L, (int) x.length()));
433     }
434
435     /**
436      * Set a parameter to a java.sql.Date value. The driver converts this to a
437      * SQL DATE value when it sends it to the database.
438      *
439      * @param parameterIndex the first parameter is 1...
440      * @param x the parameter value
441      *
442      * @exception SQLException if a database access error occurs
443      */

444     public void setDate(int parameterIndex, java.sql.Date JavaDoc x)
445         throws SQLException JavaDoc {
446         if (x == null) {
447             setNull(parameterIndex, java.sql.Types.DATE);
448         } else {
449             // FIXME: Have instance version of this, problem as it's
450
// not thread-safe :(
451
SimpleDateFormat JavaDoc dateFormatter = new SimpleDateFormat JavaDoc(
452                     "''yyyy-MM-dd''");
453             setInternal(parameterIndex, dateFormatter.format(x));
454         }
455     }
456
457     /**
458      * Set a parameter to a java.sql.Date value. The driver converts this to a
459      * SQL DATE value when it sends it to the database.
460      *
461      * @param parameterIndex the first parameter is 1, the second is 2, ...
462      * @param x the parameter value
463      * @param cal the calendar to interpret the date with
464      *
465      * @throws SQLException if a database-access error occurs.
466      */

467     public void setDate(int parameterIndex, java.sql.Date JavaDoc x, Calendar JavaDoc cal)
468         throws SQLException JavaDoc {
469         setDate(parameterIndex, x);
470     }
471
472     /**
473      * Set a parameter to a Java double value. The driver converts this to a
474      * SQL DOUBLE value when it sends it to the database
475      *
476      * @param parameterIndex the first parameter is 1...
477      * @param x the parameter value
478      *
479      * @throws SQLException if a database access error occurs
480      */

481     public void setDouble(int parameterIndex, double x)
482         throws SQLException JavaDoc {
483         setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x)));
484     }
485
486     /**
487      * Set a parameter to a Java float value. The driver converts this to a
488      * SQL FLOAT value when it sends it to the database.
489      *
490      * @param parameterIndex the first parameter is 1...
491      * @param x the parameter value
492      *
493      * @throws SQLException if a database access error occurs
494      */

495     public void setFloat(int parameterIndex, float x) throws SQLException JavaDoc {
496         setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x)));
497     }
498
499     /**
500      * Set a parameter to a Java int value. The driver converts this to a SQL
501      * INTEGER value when it sends it to the database.
502      *
503      * @param parameterIndex the first parameter is 1...
504      * @param x the parameter value
505      *
506      * @throws SQLException if a database access error occurs
507      */

508     public void setInt(int parameterIndex, int x) throws SQLException JavaDoc {
509         setInternal(parameterIndex, String.valueOf(x));
510     }
511
512     /**
513      * Set a parameter to a Java long value. The driver converts this to a SQL
514      * BIGINT value when it sends it to the database.
515      *
516      * @param parameterIndex the first parameter is 1...
517      * @param x the parameter value
518      *
519      * @throws SQLException if a database access error occurs
520      */

521     public void setLong(int parameterIndex, long x) throws SQLException JavaDoc {
522         setInternal(parameterIndex, String.valueOf(x));
523     }
524
525     /**
526      * The number, types and properties of a ResultSet's columns are provided
527      * by the getMetaData method.
528      *
529      * @return the description of a ResultSet's columns
530      *
531      * @throws SQLException if a database-access error occurs.
532      */

533     public synchronized java.sql.ResultSetMetaData JavaDoc getMetaData() throws SQLException JavaDoc {
534         PreparedStatement mdStmt = null;
535         java.sql.ResultSet JavaDoc mdRs = null;
536
537         if (this.pstmtResultMetaData == null) {
538             try {
539                 mdStmt = new PreparedStatement(this.connection,
540                         this.originalSql, this.currentCatalog, this.parseInfo);
541
542                 mdStmt.setMaxRows(0);
543
544                 int paramCount = this.parameterValues.length;
545
546                 for (int i = 1; i <= paramCount; i++) {
547                     mdStmt.setString(i, "");
548                 }
549
550                 boolean hadResults = mdStmt.execute();
551
552                 if (hadResults) {
553                     mdRs = mdStmt.getResultSet();
554
555                     this.pstmtResultMetaData = mdRs.getMetaData();
556                 } else {
557                     this.pstmtResultMetaData = new ResultSetMetaData(new Field[0]);
558                 }
559             } finally {
560                 SQLException JavaDoc sqlExRethrow = null;
561
562                 if (mdRs != null) {
563                     try {
564                         mdRs.close();
565                     } catch (SQLException JavaDoc sqlEx) {
566                         sqlExRethrow = sqlEx;
567                     }
568
569                     mdRs = null;
570                 }
571
572                 if (mdStmt != null) {
573                     try {
574                         mdStmt.close();
575                     } catch (SQLException JavaDoc sqlEx) {
576                         sqlExRethrow = sqlEx;
577                     }
578
579                     mdStmt = null;
580                 }
581
582                 if (sqlExRethrow != null) {
583                     throw sqlExRethrow;
584                 }
585             }
586         }
587
588         return this.pstmtResultMetaData;
589     }
590
591     /**
592      * Set a parameter to SQL NULL
593      *
594      * <p>
595      * <B>Note:</B> You must specify the parameters SQL type (although MySQL
596      * ignores it)
597      * </p>
598      *
599      * @param parameterIndex the first parameter is 1, etc...
600      * @param sqlType the SQL type code defined in java.sql.Types
601      *
602      * @throws SQLException if a database access error occurs
603      */

604     public void setNull(int parameterIndex, int sqlType)
605         throws SQLException JavaDoc {
606         setInternal(parameterIndex, "null");
607         isNull[parameterIndex - 1] = true;
608     }
609
610     //--------------------------JDBC 2.0-----------------------------
611

612     /**
613      * Set a parameter to SQL NULL.
614      *
615      * <P>
616      * <B>Note:</B> You must specify the parameter's SQL type.
617      * </p>
618      *
619      * @param parameterIndex the first parameter is 1, the second is 2, ...
620      * @param sqlType SQL type code defined by java.sql.Types
621      * @param arg argument parameters for null
622      *
623      * @throws SQLException if a database-access error occurs.
624      */

625     public void setNull(int parameterIndex, int sqlType, String JavaDoc arg)
626         throws SQLException JavaDoc {
627         setNull(parameterIndex, sqlType);
628     }
629
630     /**
631      * Set the value of a parameter using an object; use the java.lang
632      * equivalent objects for integral values.
633      *
634      * <P>
635      * The given Java object will be converted to the targetSqlType before
636      * being sent to the database.
637      * </p>
638      *
639      * <P>
640      * note that this method may be used to pass database-specific abstract
641      * data types. This is done by using a Driver-specific Java type and
642      * using a targetSqlType of java.sql.Types.OTHER
643      * </p>
644      *
645      * @param parameterIndex the first parameter is 1...
646      * @param parameterObj the object containing the input parameter value
647      * @param targetSqlType The SQL type to be send to the database
648      * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
649      * this is the number of digits after the decimal. For all other
650      * types this value will be ignored.
651      *
652      * @throws SQLException if a database access error occurs
653      * @throws java.sql.SQLException DOCUMENT ME!
654      */

655     public void setObject(int parameterIndex, Object JavaDoc parameterObj,
656         int targetSqlType, int scale) throws SQLException JavaDoc {
657         if (parameterObj == null) {
658             setNull(parameterIndex, java.sql.Types.OTHER);
659         } else {
660             try {
661                 switch (targetSqlType) {
662                 case Types.BIT:
663                 case Types.TINYINT:
664                 case Types.SMALLINT:
665                 case Types.INTEGER:
666                 case Types.BIGINT:
667                 case Types.REAL:
668                 case Types.FLOAT:
669                 case Types.DOUBLE:
670                 case Types.DECIMAL:
671                 case Types.NUMERIC:
672
673                     Number JavaDoc parameterAsNum;
674
675                     if (parameterObj instanceof Boolean JavaDoc) {
676                         parameterAsNum = ((Boolean JavaDoc) parameterObj).booleanValue()
677                             ? new Integer JavaDoc(1) : new Integer JavaDoc(0);
678                     } else if (parameterObj instanceof String JavaDoc) {
679                         switch (targetSqlType) {
680                         case Types.BIT:
681                             parameterAsNum = (Boolean.getBoolean((String JavaDoc) parameterObj)
682                                 ? new Integer JavaDoc("1") : new Integer JavaDoc("0"));
683
684                             break;
685
686                         case Types.TINYINT:
687                         case Types.SMALLINT:
688                         case Types.INTEGER:
689                             parameterAsNum = Integer.valueOf((String JavaDoc) parameterObj);
690
691                             break;
692
693                         case Types.BIGINT:
694                             parameterAsNum = Long.valueOf((String JavaDoc) parameterObj);
695
696                             break;
697
698                         case Types.REAL:
699                             parameterAsNum = Float.valueOf((String JavaDoc) parameterObj);
700
701                             break;
702
703                         case Types.FLOAT:
704                         case Types.DOUBLE:
705                             parameterAsNum = Double.valueOf((String JavaDoc) parameterObj);
706
707                             break;
708
709                         case Types.DECIMAL:
710                         case Types.NUMERIC:default:
711                             parameterAsNum = new java.math.BigDecimal JavaDoc((String JavaDoc) parameterObj);
712                         }
713                     } else {
714                         parameterAsNum = (Number JavaDoc) parameterObj;
715                     }
716
717                     switch (targetSqlType) {
718                     case Types.BIT:
719                     case Types.TINYINT:
720                     case Types.SMALLINT:
721                     case Types.INTEGER:
722                         setInt(parameterIndex, parameterAsNum.intValue());
723
724                         break;
725
726                     case Types.BIGINT:
727                         setLong(parameterIndex, parameterAsNum.longValue());
728
729                         break;
730
731                     case Types.REAL:
732                         setFloat(parameterIndex, parameterAsNum.floatValue());
733
734                         break;
735
736                     case Types.FLOAT:
737                     case Types.DOUBLE:
738                         setDouble(parameterIndex, parameterAsNum.doubleValue());
739
740                         break;
741
742                     case Types.DECIMAL:
743                     case Types.NUMERIC:default:
744
745                         if (parameterAsNum instanceof java.math.BigDecimal JavaDoc) {
746                             setBigDecimal(parameterIndex,
747                                 (java.math.BigDecimal JavaDoc) parameterAsNum);
748                         } else if (parameterAsNum instanceof java.math.BigInteger JavaDoc) {
749                             setBigDecimal(parameterIndex,
750                                 new java.math.BigDecimal JavaDoc(
751                                     (java.math.BigInteger JavaDoc) parameterAsNum, scale));
752                         } else {
753                             setBigDecimal(parameterIndex,
754                                 new java.math.BigDecimal JavaDoc(
755                                     parameterAsNum.doubleValue()));
756                         }
757
758                         break;
759                     }
760
761                     break;
762
763                 case Types.CHAR:
764                 case Types.VARCHAR:
765                 case Types.LONGVARCHAR:
766                     setString(parameterIndex, parameterObj.toString());
767
768                     break;
769
770                 case Types.CLOB:
771
772                     if (parameterObj instanceof java.sql.Clob JavaDoc) {
773                         setClob(parameterIndex, (java.sql.Clob JavaDoc) parameterObj);
774                     } else {
775                         setString(parameterIndex, parameterObj.toString());
776                     }
777
778                     break;
779
780                 case Types.BINARY:
781                 case Types.VARBINARY:
782                 case Types.LONGVARBINARY:
783                 case Types.BLOB:
784
785                     if (parameterObj instanceof byte[]) {
786                         setBytes(parameterIndex, (byte[]) parameterObj);
787                     } else if (parameterObj instanceof java.sql.Blob JavaDoc) {
788                         setBlob(parameterIndex, (java.sql.Blob JavaDoc) parameterObj);
789                     } else {
790                         setBytes(parameterIndex,
791                             StringUtils.getBytes(parameterObj.toString(),
792                                 this.charConverter, this.charEncoding));
793                     }
794
795                     break;
796
797                 case Types.DATE:
798                 case Types.TIMESTAMP:
799
800                     java.util.Date JavaDoc parameterAsDate;
801
802                     if (parameterObj instanceof String JavaDoc) {
803                         ParsePosition JavaDoc pp = new ParsePosition JavaDoc(0);
804                         java.text.DateFormat JavaDoc sdf = new java.text.SimpleDateFormat JavaDoc(getDateTimePattern(
805                                     (String JavaDoc) parameterObj, false));
806                         parameterAsDate = sdf.parse((String JavaDoc) parameterObj, pp);
807                     } else {
808                         parameterAsDate = (java.util.Date JavaDoc) parameterObj;
809                     }
810
811                     switch (targetSqlType) {
812                     case Types.DATE:
813
814                         if (parameterAsDate instanceof java.sql.Date JavaDoc) {
815                             setDate(parameterIndex,
816                                 (java.sql.Date JavaDoc) parameterAsDate);
817                         } else {
818                             setDate(parameterIndex,
819                                 new java.sql.Date JavaDoc(parameterAsDate.getTime()));
820                         }
821
822                         break;
823
824                     case Types.TIMESTAMP:
825
826                         if (parameterAsDate instanceof java.sql.Timestamp JavaDoc) {
827                             setTimestamp(parameterIndex,
828                                 (java.sql.Timestamp JavaDoc) parameterAsDate);
829                         } else {
830                             setTimestamp(parameterIndex,
831                                 new java.sql.Timestamp JavaDoc(
832                                     parameterAsDate.getTime()));
833                         }
834
835                         break;
836                     }
837
838                     break;
839
840                 case Types.TIME:
841
842                     if (parameterObj instanceof String JavaDoc) {
843                         java.text.DateFormat JavaDoc sdf = new java.text.SimpleDateFormat JavaDoc(getDateTimePattern(
844                                     (String JavaDoc) parameterObj, true));
845                         setTime(parameterIndex,
846                             new java.sql.Time JavaDoc(sdf.parse((String JavaDoc) parameterObj)
847                                                  .getTime()));
848                     } else if (parameterObj instanceof Timestamp JavaDoc) {
849                         Timestamp JavaDoc xT = (Timestamp JavaDoc) parameterObj;
850                         setTime(parameterIndex, new java.sql.Time JavaDoc(xT.getTime()));
851                     } else {
852                         setTime(parameterIndex, (java.sql.Time JavaDoc) parameterObj);
853                     }
854
855                     break;
856
857                 case Types.OTHER:
858                     setSerializableObject(parameterIndex, parameterObj);
859
860                     break;
861
862                 default:
863                     throw new java.sql.SQLException JavaDoc("Unknown Types value",
864                         SQLError.SQL_STATE_GENERAL_ERROR);
865                 }
866             } catch (Exception JavaDoc ex) {
867                 if (ex instanceof java.sql.SQLException JavaDoc) {
868                     throw (java.sql.SQLException JavaDoc) ex;
869                 } else {
870                     throw new java.sql.SQLException JavaDoc("Cannot convert "
871                         + parameterObj.getClass().toString()
872                         + " to SQL type requested due to "
873                         + ex.getClass().getName() + " - " + ex.getMessage(),
874                         SQLError.SQL_STATE_GENERAL_ERROR);
875                 }
876             }
877         }
878     }
879
880     /**
881      * Set the value of a parameter using an object; use the java.lang
882      * equivalent objects for integral values.
883      *
884      * @param parameterIndex the first parameter is 1...
885      * @param parameterObj the object containing the input parameter value
886      * @param targetSqlType The SQL type to be send to the database
887      *
888      * @throws SQLException if an error occurs
889      */

890     public void setObject(int parameterIndex, Object JavaDoc parameterObj,
891         int targetSqlType) throws SQLException JavaDoc {
892         setObject(parameterIndex, parameterObj, targetSqlType, 0);
893     }
894
895     /**
896      * Sets the given parameter to the given object.
897      *
898      * @param parameterIndex the parameter to set.
899      * @param parameterObj the object to use as a value for the parameter.
900      *
901      * @throws SQLException if an error occurs.
902      */

903     public void setObject(int parameterIndex, Object JavaDoc parameterObj)
904         throws SQLException JavaDoc {
905         if (parameterObj == null) {
906             setNull(parameterIndex, java.sql.Types.OTHER);
907         } else {
908             if (parameterObj instanceof Byte JavaDoc) {
909                 setInt(parameterIndex, ((Byte JavaDoc) parameterObj).intValue());
910             } else if (parameterObj instanceof String JavaDoc) {
911                 setString(parameterIndex, (String JavaDoc) parameterObj);
912             } else if (parameterObj instanceof BigDecimal JavaDoc) {
913                 setBigDecimal(parameterIndex, (BigDecimal JavaDoc) parameterObj);
914             } else if (parameterObj instanceof Short JavaDoc) {
915                 setShort(parameterIndex, ((Short JavaDoc) parameterObj).shortValue());
916             } else if (parameterObj instanceof Integer JavaDoc) {
917                 setInt(parameterIndex, ((Integer JavaDoc) parameterObj).intValue());
918             } else if (parameterObj instanceof Long JavaDoc) {
919                 setLong(parameterIndex, ((Long JavaDoc) parameterObj).longValue());
920             } else if (parameterObj instanceof Float JavaDoc) {
921                 setFloat(parameterIndex, ((Float JavaDoc) parameterObj).floatValue());
922             } else if (parameterObj instanceof Double JavaDoc) {
923                 setDouble(parameterIndex, ((Double JavaDoc) parameterObj).doubleValue());
924             } else if (parameterObj instanceof byte[]) {
925                 setBytes(parameterIndex, (byte[]) parameterObj);
926             } else if (parameterObj instanceof java.sql.Date JavaDoc) {
927                 setDate(parameterIndex, (java.sql.Date JavaDoc) parameterObj);
928             } else if (parameterObj instanceof Time JavaDoc) {
929                 setTime(parameterIndex, (Time JavaDoc) parameterObj);
930             } else if (parameterObj instanceof Timestamp JavaDoc) {
931                 setTimestamp(parameterIndex, (Timestamp JavaDoc) parameterObj);
932             } else if (parameterObj instanceof Boolean JavaDoc) {
933                 setBoolean(parameterIndex,
934                     ((Boolean JavaDoc) parameterObj).booleanValue());
935             } else if (parameterObj instanceof InputStream JavaDoc) {
936                 setBinaryStream(parameterIndex, (InputStream JavaDoc) parameterObj, -1);
937             } else if (parameterObj instanceof java.sql.Blob JavaDoc) {
938                 setBlob(parameterIndex, (java.sql.Blob JavaDoc) parameterObj);
939             } else if (parameterObj instanceof java.sql.Clob JavaDoc) {
940                 setClob(parameterIndex, (java.sql.Clob JavaDoc) parameterObj);
941             } else {
942                 setSerializableObject(parameterIndex, parameterObj);
943             }
944         }
945     }
946
947     /**
948      * @see PreparedStatement#getParameterMetaData()
949      */

950     public ParameterMetaData JavaDoc getParameterMetaData() throws SQLException JavaDoc {
951         throw new NotImplemented();
952     }
953
954     /**
955      * JDBC 2.0 Set a REF(&lt;structured-type&gt;) parameter.
956      *
957      * @param i the first parameter is 1, the second is 2, ...
958      * @param x an object representing data of an SQL REF Type
959      *
960      * @throws SQLException if a database error occurs
961      * @throws NotImplemented DOCUMENT ME!
962      */

963     public void setRef(int i, Ref JavaDoc x) throws SQLException JavaDoc {
964         throw new NotImplemented();
965     }
966
967     /**
968      * Set a parameter to a Java short value. The driver converts this to a
969      * SQL SMALLINT value when it sends it to the database.
970      *
971      * @param parameterIndex the first parameter is 1...
972      * @param x the parameter value
973      *
974      * @throws SQLException if a database access error occurs
975      */

976     public void setShort(int parameterIndex, short x) throws SQLException JavaDoc {
977         setInternal(parameterIndex, String.valueOf(x));
978     }
979
980     /**
981      * Set a parameter to a Java String value. The driver converts this to a
982      * SQL VARCHAR or LONGVARCHAR value (depending on the arguments size
983      * relative to the driver's limits on VARCHARs) when it sends it to the
984      * database.
985      *
986      * @param parameterIndex the first parameter is 1...
987      * @param x the parameter value
988      *
989      * @throws SQLException if a database error occurs.
990      */

991     public void setString(int parameterIndex, String JavaDoc x)
992         throws SQLException JavaDoc {
993         // if the passed string is null, then set this column to null
994
if (x == null) {
995             try {
996                 setInternal(parameterIndex,
997                     StringUtils.getBytes("null", this.charConverter,
998                         this.charEncoding));
999             } catch (UnsupportedEncodingException JavaDoc uue) {
1000                throw new SQLException JavaDoc("Unsupported character encoding '"
1001                    + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1002            }
1003        } else {
1004            StringBuffer JavaDoc buf = new StringBuffer JavaDoc((int) (x.length() * 1.1));
1005            buf.append('\'');
1006
1007            int stringLength = x.length();
1008
1009            for (int i = 0; i < stringLength; ++i) {
1010                char c = x.charAt(i);
1011
1012                switch (c) {
1013                case 0: /* Must be escaped for 'mysql' */
1014                    buf.append('\\');
1015                    buf.append('0');
1016
1017                    break;
1018
1019                case '\n': /* Must be escaped for logs */
1020                    buf.append('\\');
1021                    buf.append('n');
1022
1023                    break;
1024
1025                case '\r':
1026                    buf.append('\\');
1027                    buf.append('r');
1028
1029                    break;
1030
1031                case '\\':
1032                    buf.append('\\');
1033                    buf.append('\\');
1034
1035                    break;
1036
1037                case '\'':
1038                    buf.append('\\');
1039                    buf.append('\'');
1040
1041                    break;
1042
1043                case '"': /* Better safe than sorry */
1044                    buf.append('\\');
1045                    buf.append('"');
1046
1047                    break;
1048
1049                case '\032': /* This gives problems on Win32 */
1050                    buf.append('\\');
1051                    buf.append('Z');
1052
1053                    break;
1054
1055                default:
1056                    buf.append(c);
1057                }
1058            }
1059
1060            buf.append('\'');
1061
1062            String JavaDoc parameterAsString = buf.toString();
1063
1064            try {
1065                byte[] parameterAsBytes = null;
1066
1067                if (!this.isLoadDataQuery) {
1068                    parameterAsBytes = StringUtils.getBytes(parameterAsString,
1069                            this.charConverter, this.charEncoding);
1070                } else {
1071                    // Send with platform character encoding
1072
parameterAsBytes = parameterAsString.getBytes();
1073                }
1074
1075                setInternal(parameterIndex, parameterAsBytes);
1076            } catch (UnsupportedEncodingException JavaDoc uue) {
1077                throw new SQLException JavaDoc("Unsupported character encoding '"
1078                    + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1079            }
1080        }
1081    }
1082
1083    /**
1084     * Set a parameter to a java.sql.Time value. The driver converts this to a
1085     * SQL TIME value when it sends it to the database.
1086     *
1087     * @param parameterIndex the first parameter is 1...));
1088     * @param x the parameter value
1089     *
1090     * @throws SQLException if a database access error occurs
1091     */

1092    public void setTime(int parameterIndex, Time JavaDoc x) throws SQLException JavaDoc {
1093        setTimeInternal(parameterIndex, x, this.connection.getDefaultTimeZone());
1094    }
1095
1096    /**
1097     * Set a parameter to a java.sql.Time value. The driver converts this to a
1098     * SQL TIME value when it sends it to the database.
1099     *
1100     * @param parameterIndex the first parameter is 1, the second is 2, ...
1101     * @param x the parameter value
1102     * @param cal the cal specifying the timezone
1103     *
1104     * @throws SQLException if a database-access error occurs.
1105     */

1106    public void setTime(int parameterIndex, java.sql.Time JavaDoc x, Calendar JavaDoc cal)
1107        throws SQLException JavaDoc {
1108        setTimeInternal(parameterIndex, x, cal.getTimeZone());
1109    }
1110
1111    /**
1112     * Set a parameter to a java.sql.Timestamp value. The driver converts this
1113     * to a SQL TIMESTAMP value when it sends it to the database.
1114     *
1115     * @param parameterIndex the first parameter is 1...
1116     * @param x the parameter value
1117     *
1118     * @throws SQLException if a database access error occurs
1119     */

1120    public void setTimestamp(int parameterIndex, Timestamp JavaDoc x)
1121        throws SQLException JavaDoc {
1122        setTimestampInternal(parameterIndex, x, this.connection.getDefaultTimeZone());
1123    }
1124
1125    /**
1126     * Set a parameter to a java.sql.Timestamp value. The driver converts this
1127     * to a SQL TIMESTAMP value when it sends it to the database.
1128     *
1129     * @param parameterIndex the first parameter is 1, the second is 2, ...
1130     * @param x the parameter value
1131     * @param cal the calendar specifying the timezone to use
1132     *
1133     * @throws SQLException if a database-access error occurs.
1134     */

1135    public void setTimestamp(int parameterIndex, java.sql.Timestamp JavaDoc x,
1136        Calendar JavaDoc cal) throws SQLException JavaDoc {
1137        setTimestampInternal(parameterIndex, x, cal.getTimeZone());
1138    }
1139
1140    /**
1141     * @see PreparedStatement#setURL(int, URL)
1142     */

1143    public void setURL(int parameterIndex, URL JavaDoc arg) throws SQLException JavaDoc {
1144        if (arg != null) {
1145            setString(parameterIndex, arg.toString());
1146        } else {
1147            setNull(parameterIndex, Types.CHAR);
1148        }
1149    }
1150
1151    /**
1152     * When a very large Unicode value is input to a LONGVARCHAR parameter, it
1153     * may be more practical to send it via a java.io.InputStream. JDBC will
1154     * read the data from the stream as needed, until it reaches end-of-file.
1155     * The JDBC driver will do any necessary conversion from UNICODE to the
1156     * database char format.
1157     *
1158     * <P>
1159     * <B>Note:</B> This stream object can either be a standard Java stream
1160     * object or your own subclass that implements the standard interface.
1161     * </p>
1162     *
1163     * @param parameterIndex the first parameter is 1...
1164     * @param x the parameter value
1165     * @param length the number of bytes to read from the stream
1166     *
1167     * @throws SQLException if a database access error occurs
1168     *
1169     * @deprecated
1170     */

1171    public void setUnicodeStream(int parameterIndex, InputStream JavaDoc x, int length)
1172        throws SQLException JavaDoc {
1173        if (x == null) {
1174            setNull(parameterIndex, java.sql.Types.VARCHAR);
1175        } else {
1176            setBinaryStream(parameterIndex, x, length);
1177        }
1178    }
1179
1180    /**
1181     * JDBC 2.0 Add a set of parameters to the batch.
1182     *
1183     * @throws SQLException if a database-access error occurs.
1184     *
1185     * @see Statement#addBatch
1186     */

1187    public void addBatch() throws SQLException JavaDoc {
1188        if (batchedArgs == null) {
1189            batchedArgs = new ArrayList JavaDoc();
1190        }
1191
1192        batchedArgs.add(new BatchParams(parameterValues, parameterStreams,
1193                isStream, streamLengths, isNull));
1194    }
1195
1196    /**
1197     * In general, parameter values remain in force for repeated used of a
1198     * Statement. Setting a parameter value automatically clears its previous
1199     * value. However, in some cases, it is useful to immediately release the
1200     * resources used by the current parameter values; this can be done by
1201     * calling clearParameters
1202     *
1203     * @throws SQLException if a database access error occurs
1204     */

1205    public void clearParameters() throws SQLException JavaDoc {
1206        for (int i = 0; i < parameterValues.length; i++) {
1207            parameterValues[i] = null;
1208            parameterStreams[i] = null;
1209            isStream[i] = false;
1210            isNull[i] = false;
1211        }
1212    }
1213
1214    /**
1215     * Closes this prepared statement and releases all resources.
1216     *
1217     * @throws SQLException if database error occurs.
1218     */

1219    public void close() throws SQLException JavaDoc {
1220        super.close();
1221
1222        this.parseInfo = null;
1223        this.dbmd = null;
1224        this.originalSql = null;
1225        this.staticSqlStrings = null;
1226        this.parameterValues = null;
1227        this.parameterStreams = null;
1228        this.isStream = null;
1229        this.streamLengths = null;
1230        this.isNull = null;
1231        this.streamConvertBuf = null;
1232    }
1233
1234    /**
1235     * Some prepared statements return multiple results; the execute method
1236     * handles these complex statements as well as the simpler form of
1237     * statements handled by executeQuery and executeUpdate
1238     *
1239     * @return true if the next result is a ResultSet; false if it is an update
1240     * count or there are no more results
1241     *
1242     * @throws SQLException if a database error occurs.
1243     */

1244    public boolean execute() throws SQLException JavaDoc {
1245        if (connection.isReadOnly() && (firstCharOfStmt != 'S')) {
1246            throw new SQLException JavaDoc("Connection is read-only. "
1247                + "Queries leading to data modification are not allowed",
1248                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1249        }
1250
1251        checkClosed();
1252
1253        ResultSet rs = null;
1254
1255        synchronized (connection.getMutex()) {
1256            Buffer sendPacket = fillSendPacket();
1257
1258            String JavaDoc oldCatalog = null;
1259
1260            if (!this.connection.getCatalog().equals(currentCatalog)) {
1261                oldCatalog = this.connection.getCatalog();
1262                this.connection.setCatalog(currentCatalog);
1263            }
1264
1265            boolean oldInfoMsgState = false;
1266
1267            if (this.retrieveGeneratedKeys) {
1268                oldInfoMsgState = this.connection.isReadInfoMsgEnabled();
1269                this.connection.setReadInfoMsgEnabled(true);
1270            }
1271
1272            // If there isn't a limit clause in the SQL
1273
// then limit the number of rows to return in
1274
// an efficient manner. Only do this if
1275
// setMaxRows() hasn't been used on any Statements
1276
// generated from the current Connection (saves
1277
// a query, and network traffic).
1278
//
1279
// Only apply max_rows to selects
1280
//
1281
if (this.connection.useMaxRows()) {
1282                if (firstCharOfStmt == 'S') {
1283                    if (hasLimitClause) {
1284                        rs = this.connection.execSQL((String JavaDoc) null, maxRows,
1285                                sendPacket, resultSetConcurrency,
1286                                createStreamingResultSet(), true,
1287                                this.currentCatalog);
1288                    } else {
1289                        if (maxRows <= 0) {
1290                            this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
1291                                -1, this.currentCatalog);
1292                        } else {
1293                            this.connection.execSQL(
1294                                "SET OPTION SQL_SELECT_LIMIT=" + maxRows, -1,
1295                                this.currentCatalog);
1296                        }
1297                    }
1298                } else {
1299                    this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
1300                        -1, this.currentCatalog);
1301                }
1302
1303                // Finally, execute the query
1304
rs = this.connection.execSQL(null, -1, sendPacket,
1305                        resultSetConcurrency, createStreamingResultSet(),
1306                        (firstCharOfStmt == 'S'), this.currentCatalog);
1307            } else {
1308                rs = this.connection.execSQL(null, -1, sendPacket,
1309                        resultSetConcurrency, createStreamingResultSet(),
1310                        (firstCharOfStmt == 'S'), this.currentCatalog);
1311            }
1312
1313            if (this.retrieveGeneratedKeys) {
1314                this.connection.setReadInfoMsgEnabled(oldInfoMsgState);
1315            }
1316
1317            if (oldCatalog != null) {
1318                this.connection.setCatalog(oldCatalog);
1319            }
1320        }
1321
1322        lastInsertId = rs.getUpdateID();
1323
1324        if (rs != null) {
1325            this.results = rs;
1326        }
1327
1328        rs.setFirstCharOfQuery(this.firstCharOfStmt);
1329        rs.setConnection(connection);
1330        rs.setResultSetType(resultSetType);
1331        rs.setResultSetConcurrency(resultSetConcurrency);
1332        rs.setStatement(this);
1333
1334        return ((rs != null) && rs.reallyResult());
1335    }
1336
1337    /**
1338     * JDBC 2.0 Submit a batch of commands to the database for execution. This
1339     * method is optional.
1340     *
1341     * @return an array of update counts containing one element for each
1342     * command in the batch. The array is ordered according to the
1343     * order in which commands were inserted into the batch
1344     *
1345     * @throws SQLException if a database-access error occurs, or the driver
1346     * does not support batch statements
1347     * @throws java.sql.BatchUpdateException DOCUMENT ME!
1348     */

1349    public int[] executeBatch() throws SQLException JavaDoc {
1350        if (connection.isReadOnly()) {
1351            throw new SQLException JavaDoc("Connection is read-only. "
1352                + "Queries leading to data modification are not allowed",
1353                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1354        }
1355
1356        try {
1357            int[] updateCounts = null;
1358
1359            if (batchedArgs != null) {
1360                int nbrCommands = batchedArgs.size();
1361                updateCounts = new int[nbrCommands];
1362
1363                for (int i = 0; i < nbrCommands; i++) {
1364                    updateCounts[i] = -3;
1365                }
1366
1367                SQLException JavaDoc sqlEx = null;
1368
1369                int commandIndex = 0;
1370
1371                for (commandIndex = 0; commandIndex < nbrCommands;
1372                        commandIndex++) {
1373                    Object JavaDoc arg = batchedArgs.get(commandIndex);
1374
1375                    if (arg instanceof String JavaDoc) {
1376                        updateCounts[commandIndex] = executeUpdate((String JavaDoc) arg);
1377                    } else {
1378                        BatchParams paramArg = (BatchParams) arg;
1379
1380                        try {
1381                            updateCounts[commandIndex] = executeUpdate(paramArg.parameterStrings,
1382                                    paramArg.parameterStreams,
1383                                    paramArg.isStream, paramArg.streamLengths,
1384                                    paramArg.isNull);
1385                        } catch (SQLException JavaDoc ex) {
1386                            updateCounts[commandIndex] = EXECUTE_FAILED;
1387
1388                            if (this.connection.continueBatchOnError()) {
1389                                sqlEx = ex;
1390                            } else {
1391                                int[] newUpdateCounts = new int[commandIndex];
1392                                System.arraycopy(updateCounts, 0,
1393                                    newUpdateCounts, 0, commandIndex);
1394
1395                                throw new java.sql.BatchUpdateException JavaDoc(ex
1396                                    .getMessage(), ex.getSQLState(),
1397                                    ex.getErrorCode(), newUpdateCounts);
1398                            }
1399                        }
1400                    }
1401                }
1402
1403                if (sqlEx != null) {
1404                    throw new java.sql.BatchUpdateException JavaDoc(sqlEx.getMessage(),
1405                        sqlEx.getSQLState(), sqlEx.getErrorCode(), updateCounts);
1406                }
1407            }
1408
1409            return (updateCounts != null) ? updateCounts : new int[0];
1410        } finally {
1411            clearBatch();
1412        }
1413    }
1414
1415    /**
1416     * A Prepared SQL query is executed and its ResultSet is returned
1417     *
1418     * @return a ResultSet that contains the data produced by the query - never
1419     * null
1420     *
1421     * @throws SQLException if a database error occurs.
1422     */

1423    public synchronized java.sql.ResultSet JavaDoc executeQuery()
1424        throws SQLException JavaDoc {
1425        checkClosed();
1426
1427        if ((this.firstCharOfStmt == 'I') || (this.firstCharOfStmt == 'U')
1428                || (this.firstCharOfStmt == 'D')
1429                || (this.firstCharOfStmt == 'A')
1430                || (this.firstCharOfStmt == 'C')) {
1431            if (StringUtils.startsWithIgnoreCaseAndWs(this.originalSql, "INSERT")
1432                    || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1433                        "UPDATE")
1434                    || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1435                        "DELETE")
1436                    || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1437                        "DROP")
1438                    || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1439                        "CREATE")
1440                    || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1441                        "ALTER")) {
1442                throw new SQLException JavaDoc("Can not issue data manipulation statements with executeQuery()",
1443                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1444            }
1445        }
1446
1447        // We need to execute this all together
1448
// So synchronize on the Connection's mutex (because
1449
// even queries going through there synchronize
1450
// on the same mutex.
1451
synchronized (connection.getMutex()) {
1452            Buffer sendPacket = fillSendPacket();
1453
1454            if (this.results != null) {
1455                this.results.close();
1456            }
1457
1458            String JavaDoc oldCatalog = null;
1459
1460            if (!this.connection.getCatalog().equals(currentCatalog)) {
1461                oldCatalog = this.connection.getCatalog();
1462                this.connection.setCatalog(currentCatalog);
1463            }
1464
1465            if (this.connection.useMaxRows()) {
1466                // If there isn't a limit clause in the SQL
1467
// then limit the number of rows to return in
1468
// an efficient manner. Only do this if
1469
// setMaxRows() hasn't been used on any Statements
1470
// generated from the current Connection (saves
1471
// a query, and network traffic).
1472
if (hasLimitClause) {
1473                    results = this.connection.execSQL((String JavaDoc) null, maxRows,
1474                            sendPacket, resultSetConcurrency,
1475                            createStreamingResultSet(), true,
1476                            this.currentCatalog);
1477                } else {
1478                    if (maxRows <= 0) {
1479                        this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
1480                            -1, this.currentCatalog);
1481                    } else {
1482                        this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT="
1483                            + maxRows, -1, this.currentCatalog);
1484                    }
1485
1486                    this.results = this.connection.execSQL(null, -1,
1487                            sendPacket, resultSetConcurrency,
1488                            createStreamingResultSet(), true,
1489                            this.currentCatalog);
1490
1491                    if (oldCatalog != null) {
1492                        this.connection.setCatalog(oldCatalog);
1493                    }
1494                }
1495            } else {
1496                this.results = this.connection.execSQL(null, -1, sendPacket,
1497                        resultSetConcurrency, createStreamingResultSet(), true,
1498                        this.currentCatalog);
1499            }
1500
1501            if (oldCatalog != null) {
1502                this.connection.setCatalog(oldCatalog);
1503            }
1504        }
1505
1506        lastInsertId = this.results.getUpdateID();
1507        nextResults = this.results;
1508        this.results.setConnection(connection);
1509        this.results.setResultSetType(resultSetType);
1510        this.results.setResultSetConcurrency(resultSetConcurrency);
1511        this.results.setStatement(this);
1512
1513        return (java.sql.ResultSet JavaDoc) this.results;
1514    }
1515
1516    /**
1517     * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
1518     * statements that return nothing such as SQL DDL statements can be
1519     * executed.
1520     *
1521     * @return either the row count for INSERT, UPDATE or DELETE; or 0 for SQL
1522     * statements that return nothing.
1523     *
1524     * @throws SQLException if a database access error occurs
1525     */

1526    public synchronized int executeUpdate() throws SQLException JavaDoc {
1527        return executeUpdate(parameterValues, parameterStreams, isStream,
1528            streamLengths, isNull);
1529    }
1530
1531    /**
1532     * Returns this PreparedStatement represented as a string.
1533     *
1534     * @return this PreparedStatement represented as a string.
1535     *
1536     * @throws RuntimeException if an error occurs
1537     */

1538    public String JavaDoc toString() {
1539        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1540        buf.append(super.toString());
1541        buf.append(": ");
1542
1543        try {
1544            for (int i = 0; i < parameterValues.length; ++i) {
1545                if (this.charEncoding != null) {
1546                    buf.append(new String JavaDoc(staticSqlStrings[i], this.charEncoding));
1547                } else {
1548                    buf.append(new String JavaDoc(staticSqlStrings[i]));
1549                }
1550
1551                if ((parameterValues[i] == null) && !isStream[i]) {
1552                    buf.append("** NOT SPECIFIED **");
1553                } else if (isStream[i]) {
1554                    buf.append("** STREAM DATA **");
1555                } else {
1556                    if (this.charConverter != null) {
1557                        buf.append(this.charConverter.toString(
1558                                parameterValues[i]));
1559                    } else {
1560                        if (this.charEncoding != null) {
1561                            buf.append(new String JavaDoc(parameterValues[i],
1562                                    this.charEncoding));
1563                        } else {
1564                            buf.append(StringUtils.toAsciiString(
1565                                    parameterValues[i]));
1566                        }
1567                    }
1568                }
1569            }
1570
1571            if (this.charEncoding != null) {
1572                buf.append(new String JavaDoc(
1573                        staticSqlStrings[parameterValues.length],
1574                        this.charEncoding));
1575            } else {
1576                buf.append(staticSqlStrings[parameterValues.length]);
1577            }
1578        } catch (UnsupportedEncodingException JavaDoc uue) {
1579            throw new RuntimeException JavaDoc("Unsupported character encoding '"
1580                + this.charEncoding + "'");
1581        }
1582
1583        return buf.toString();
1584    }
1585
1586    /**
1587     * Used by updatable result sets for refreshRow() because the parameter has
1588     * already been escaped for updater or inserter prepared statements.
1589     *
1590     * @param parameterIndex the parameter to set.
1591     * @param parameterAsBytes the parameter as a string.
1592     *
1593     * @throws SQLException if an error occurs
1594     */

1595    protected void setBytesNoEscape(int parameterIndex, byte[] parameterAsBytes)
1596        throws SQLException JavaDoc {
1597        byte[] parameterWithQuotes = new byte[parameterAsBytes.length + 2];
1598        parameterWithQuotes[0] = '\'';
1599        System.arraycopy(parameterAsBytes, 0, parameterWithQuotes, 1,
1600            parameterAsBytes.length);
1601        parameterWithQuotes[parameterAsBytes.length + 1] = '\'';
1602
1603        setInternal(parameterIndex, parameterWithQuotes);
1604    }
1605
1606    /**
1607     * Sets wheather or not this statement should retreive generated keys.
1608     *
1609     * @param retrieveGeneratedKeys
1610     */

1611    protected void setRetrieveGeneratedKeys(boolean retrieveGeneratedKeys) {
1612        this.retrieveGeneratedKeys = retrieveGeneratedKeys;
1613    }
1614
1615    /**
1616     * Added to allow batch-updates
1617     *
1618     * @param batchedParameterStrings string values used in single statement
1619     * @param batchedParameterStreams stream values used in single statement
1620     * @param batchedIsStream flags for streams used in single statement
1621     * @param batchedStreamLengths lengths of streams to be read.
1622     * @param batchedIsNull flags for parameters that are null
1623     *
1624     * @return the update count
1625     *
1626     * @throws SQLException if a database error occurs
1627     * @throws java.sql.SQLException DOCUMENT ME!
1628     */

1629    protected synchronized int executeUpdate(byte[][] batchedParameterStrings,
1630        InputStream JavaDoc[] batchedParameterStreams, boolean[] batchedIsStream,
1631        int[] batchedStreamLengths, boolean[] batchedIsNull)
1632        throws SQLException JavaDoc {
1633        if (connection.isReadOnly()) {
1634            throw new SQLException JavaDoc("Connection is read-only. "
1635                + "Queries leading to data modification are not allowed",
1636                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1637        }
1638
1639        checkClosed();
1640
1641        if ((this.firstCharOfStmt == 'S')
1642                && StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
1643                    "SELECT")) {
1644            throw new java.sql.SQLException JavaDoc("Can not issue executeUpdate() for SELECTs",
1645                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1646        }
1647
1648        ResultSet rs = null;
1649
1650        // The checking and changing of catalogs
1651
// must happen in sequence, so synchronize
1652
// on the same mutex that _conn is using
1653
synchronized (connection.getMutex()) {
1654            Buffer sendPacket = fillSendPacket(batchedParameterStrings,
1655                    batchedParameterStreams, batchedIsStream,
1656                    batchedStreamLengths);
1657
1658            String JavaDoc oldCatalog = null;
1659
1660            if (!this.connection.getCatalog().equals(currentCatalog)) {
1661                oldCatalog = this.connection.getCatalog();
1662                this.connection.setCatalog(currentCatalog);
1663            }
1664
1665            //
1666
// Only apply max_rows to selects
1667
//
1668
if (this.connection.useMaxRows()) {
1669                this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
1670                    -1, this.currentCatalog);
1671            }
1672
1673            boolean oldInfoMsgState = false;
1674
1675            if (this.retrieveGeneratedKeys) {
1676                oldInfoMsgState = this.connection.isReadInfoMsgEnabled();
1677                this.connection.setReadInfoMsgEnabled(true);
1678            }
1679
1680            rs = this.connection.execSQL(null, -1, sendPacket,
1681                    resultSetConcurrency, false, false, this.currentCatalog);
1682
1683            if (this.retrieveGeneratedKeys) {
1684                this.connection.setReadInfoMsgEnabled(oldInfoMsgState);
1685            }
1686
1687            if (oldCatalog != null) {
1688                this.connection.setCatalog(oldCatalog);
1689            }
1690        }
1691
1692        this.results = rs;
1693
1694        rs.setFirstCharOfQuery(this.firstCharOfStmt);
1695
1696        updateCount = rs.getUpdateCount();
1697
1698        int truncatedUpdateCount = 0;
1699
1700        if (updateCount > Integer.MAX_VALUE) {
1701            truncatedUpdateCount = Integer.MAX_VALUE;
1702        } else {
1703            truncatedUpdateCount = (int) updateCount;
1704        }
1705
1706        lastInsertId = rs.getUpdateID();
1707        this.results = rs;
1708
1709        return truncatedUpdateCount;
1710    }
1711
1712    byte[] getBytes(int parameterIndex) throws SQLException JavaDoc {
1713        if (isStream[parameterIndex]) {
1714            return streamToBytes(parameterStreams[parameterIndex], false,
1715                streamLengths[parameterIndex],
1716                this.connection.useStreamLengthsInPrepStmts());
1717        } else {
1718            byte[] parameterVal = parameterValues[parameterIndex];
1719
1720            if (parameterVal == null) {
1721                return null;
1722            }
1723
1724            if ((parameterVal[0] == '\'')
1725                    && (parameterVal[parameterVal.length - 1] == '\'')) {
1726                byte[] valNoQuotes = new byte[parameterVal.length - 2];
1727                System.arraycopy(parameterVal, 1, valNoQuotes, 0,
1728                    parameterVal.length - 2);
1729
1730                return valNoQuotes;
1731            } else {
1732                return parameterVal;
1733            }
1734        }
1735    }
1736
1737    boolean isNull(int paramIndex) {
1738        return isNull[paramIndex];
1739    }
1740
1741    ParseInfo getParseInfo() {
1742        return this.parseInfo;
1743    }
1744
1745    /**
1746     * Sets the concurrency for result sets generated by this statement
1747     *
1748     * @param concurrencyFlag the result set concurrency flag from the
1749     * ResultSet interface.
1750     */

1751    void setResultSetConcurrency(int concurrencyFlag) {
1752        resultSetConcurrency = concurrencyFlag;
1753    }
1754
1755    /**
1756     * Sets the result set type for result sets generated by this statement
1757     *
1758     * @param typeFlag the result set type from the ResultSet interface
1759     */

1760    void setResultSetType(int typeFlag) {
1761        resultSetType = typeFlag;
1762    }
1763
1764    private final String JavaDoc getDateTimePattern(String JavaDoc dt, boolean toTime)
1765        throws Exception JavaDoc {
1766        //
1767
// Special case
1768
//
1769
int dtLength = (dt != null) ? dt.length() : 0;
1770
1771        if ((dtLength >= 8) && (dtLength <= 10)) {
1772            int dashCount = 0;
1773            boolean isDateOnly = true;
1774
1775            for (int i = 0; i < dtLength; i++) {
1776                char c = dt.charAt(i);
1777
1778                if (!Character.isDigit(c) && (c != '-')) {
1779                    isDateOnly = false;
1780
1781                    break;
1782                }
1783
1784                if (c == '-') {
1785                    dashCount++;
1786                }
1787            }
1788
1789            if (isDateOnly && (dashCount == 2)) {
1790                return "yyyy-MM-dd";
1791            }
1792        }
1793
1794        //
1795
// Special case - time-only
1796
//
1797
boolean colonsOnly = true;
1798
1799        for (int i = 0; i < dtLength; i++) {
1800            char c = dt.charAt(i);
1801
1802            if (!Character.isDigit(c) && (c != ':')) {
1803                colonsOnly = false;
1804
1805                break;
1806            }
1807        }
1808
1809        if (colonsOnly) {
1810            return "HH:mm:ss";
1811        }
1812
1813        int n;
1814        int z;
1815        int count;
1816        int maxvecs;
1817        char c;
1818        char separator;
1819        StringReader JavaDoc reader = new StringReader JavaDoc(dt + " ");
1820        ArrayList JavaDoc vec = new ArrayList JavaDoc();
1821        ArrayList JavaDoc vecRemovelist = new ArrayList JavaDoc();
1822        Object JavaDoc[] nv = new Object JavaDoc[3];
1823        Object JavaDoc[] v;
1824        nv[0] = new Character JavaDoc('y');
1825        nv[1] = new StringBuffer JavaDoc();
1826        nv[2] = new Integer JavaDoc(0);
1827        vec.add(nv);
1828
1829        if (toTime) {
1830            nv = new Object JavaDoc[3];
1831            nv[0] = new Character JavaDoc('h');
1832            nv[1] = new StringBuffer JavaDoc();
1833            nv[2] = new Integer JavaDoc(0);
1834            vec.add(nv);
1835        }
1836
1837        while ((z = reader.read()) != -1) {
1838            separator = (char) z;
1839            maxvecs = vec.size();
1840
1841            for (count = 0; count < maxvecs; count++) {
1842                v = (Object JavaDoc[]) vec.get(count);
1843                n = ((Integer JavaDoc) v[2]).intValue();
1844                c = getSuccessor(((Character JavaDoc) v[0]).charValue(), n);
1845
1846                if (!Character.isLetterOrDigit(separator)) {
1847                    if ((c == ((Character JavaDoc) v[0]).charValue()) && (c != 'S')) {
1848                        vecRemovelist.add(v);
1849                    } else {
1850                        ((StringBuffer JavaDoc) v[1]).append(separator);
1851
1852                        if ((c == 'X') || (c == 'Y')) {
1853                            v[2] = new Integer JavaDoc(4);
1854                        }
1855                    }
1856                } else {
1857                    if (c == 'X') {
1858                        c = 'y';
1859                        nv = new Object JavaDoc[3];
1860                        nv[1] = (new StringBuffer JavaDoc(((StringBuffer JavaDoc) v[1])
1861                                .toString())).append('M');
1862                        nv[0] = new Character JavaDoc('M');
1863                        nv[2] = new Integer JavaDoc(1);
1864                        vec.add(nv);
1865                    } else if (c == 'Y') {
1866                        c = 'M';
1867                        nv = new Object JavaDoc[3];
1868                        nv[1] = (new StringBuffer JavaDoc(((StringBuffer JavaDoc) v[1])
1869                                .toString())).append('d');
1870                        nv[0] = new Character JavaDoc('d');
1871                        nv[2] = new Integer JavaDoc(1);
1872                        vec.add(nv);
1873                    }
1874
1875                    ((StringBuffer JavaDoc) v[1]).append(c);
1876
1877                    if (c == ((Character JavaDoc) v[0]).charValue()) {
1878                        v[2] = new Integer JavaDoc(n + 1);
1879                    } else {
1880                        v[0] = new Character JavaDoc(c);
1881                        v[2] = new Integer JavaDoc(1);
1882                    }
1883                }
1884            }
1885
1886            int size = vecRemovelist.size();
1887
1888            for (int i = 0; i < size; i++) {
1889                v = (Object JavaDoc[]) vecRemovelist.get(i);
1890                vec.remove(v);
1891            }
1892
1893            vecRemovelist.clear();
1894        }
1895
1896        int size = vec.size();
1897
1898        for (int i = 0; i < size; i++) {
1899            v = (Object JavaDoc[]) vec.get(i);
1900            c = ((Character JavaDoc) v[0]).charValue();
1901            n = ((Integer JavaDoc) v[2]).intValue();
1902
1903            boolean bk = getSuccessor(c, n) != c;
1904            boolean atEnd = (((c == 's') || (c == 'm')
1905                || ((c == 'h') && toTime)) && bk);
1906            boolean finishesAtDate = (bk && (c == 'd') && !toTime);
1907            boolean containsEnd = (((StringBuffer JavaDoc) v[1]).toString().indexOf('W') != -1);
1908
1909            if ((!atEnd && !finishesAtDate) || (containsEnd)) {
1910                vecRemovelist.add(v);
1911            }
1912        }
1913
1914        size = vecRemovelist.size();
1915
1916        for (int i = 0; i < size; i++) {
1917            vec.remove(vecRemovelist.get(i));
1918        }
1919
1920        vecRemovelist.clear();
1921        v = (Object JavaDoc[]) vec.get(0); //might throw exception
1922

1923        StringBuffer JavaDoc format = (StringBuffer JavaDoc) v[1];
1924        format.setLength(format.length() - 1);
1925
1926        return format.toString();
1927    }
1928
1929    private final void setInternal(int paramIndex, byte[] val)
1930        throws SQLException JavaDoc {
1931        if (this.isClosed) {
1932            throw new SQLException JavaDoc("PreparedStatement has been closed. No further operations allowed.",
1933                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1934        }
1935
1936        if ((paramIndex < 1)) {
1937            throw new SQLException JavaDoc("Parameter index out of range ("
1938                + paramIndex + " < 1 ).", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1939        } else if (paramIndex >= staticSqlStrings.length) {
1940            throw new SQLException JavaDoc("Parameter index out of range ("
1941                + paramIndex + " > " + (staticSqlStrings.length - 1) + ").",
1942                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1943        }
1944
1945        isStream[paramIndex - 1] = false;
1946        isNull[paramIndex - 1] = false;
1947        parameterStreams[paramIndex - 1] = null;
1948        parameterValues[paramIndex - 1] = val;
1949    }
1950
1951    private final void setInternal(int paramIndex, String JavaDoc val)
1952        throws SQLException JavaDoc {
1953        byte[] parameterAsBytes = null;
1954
1955        if (this.charConverter != null) {
1956            parameterAsBytes = this.charConverter.toBytes(val);
1957        } else {
1958            try {
1959                parameterAsBytes = StringUtils.getBytes(val,
1960                        this.charConverter, this.charEncoding);
1961            } catch (UnsupportedEncodingException JavaDoc uEE) {
1962                throw new SQLException JavaDoc("Unsupported encoding '"
1963                    + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1964            }
1965        }
1966
1967        setInternal(paramIndex, parameterAsBytes);
1968    }
1969
1970    /**
1971     * Sets the value for the placeholder as a serialized Java object (used by
1972     * various forms of setObject()
1973     *
1974     * @param parameterIndex DOCUMENT ME!
1975     * @param parameterObj DOCUMENT ME!
1976     *
1977     * @throws SQLException if a database error occurs.
1978     * @throws java.sql.SQLException DOCUMENT ME!
1979     */

1980    private final void setSerializableObject(int parameterIndex,
1981        Object JavaDoc parameterObj) throws SQLException JavaDoc {
1982        try {
1983            ByteArrayOutputStream JavaDoc bytesOut = new ByteArrayOutputStream JavaDoc();
1984            ObjectOutputStream JavaDoc objectOut = new ObjectOutputStream JavaDoc(bytesOut);
1985            objectOut.writeObject(parameterObj);
1986            objectOut.flush();
1987            objectOut.close();
1988            bytesOut.flush();
1989            bytesOut.close();
1990
1991            byte[] buf = bytesOut.toByteArray();
1992            ByteArrayInputStream JavaDoc bytesIn = new ByteArrayInputStream JavaDoc(buf);
1993            setBinaryStream(parameterIndex, bytesIn, buf.length);
1994        } catch (Exception JavaDoc ex) {
1995            throw new java.sql.SQLException JavaDoc("Invalid argument value: "
1996                + ex.getClass().getName(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1997        }
1998    }
1999
2000    private final char getSuccessor(char c, int n) {
2001        return ((c == 'y') && (n == 2)) ? 'X'
2002                                        : (((c == 'y') && (n < 4)) ? 'y'
2003                                                                   : ((c == 'y')
2004        ? 'M'
2005        : (((c == 'M') && (n == 2)) ? 'Y'
2006                                    : (((c == 'M') && (n < 3)) ? 'M'
2007                                                               : ((c == 'M')
2008        ? 'd'
2009        : (((c == 'd') && (n < 2)) ? 'd'
2010                                   : ((c == 'd') ? 'H'
2011                                                 : (((c == 'H') && (n < 2))
2012        ? 'H'
2013        : ((c == 'H') ? 'm'
2014                      : (((c == 'm') && (n < 2)) ? 'm'
2015                                                 : ((c == 'm') ? 's'
2016                                                               : (((c == 's')
2017        && (n < 2)) ? 's' : 'W'))))))))))));
2018    }
2019
2020    /**
2021     * Set a parameter to a java.sql.Time value. The driver converts this to a
2022     * SQL TIME value when it sends it to the database, using the given
2023     * timezone.
2024     *
2025     * @param parameterIndex the first parameter is 1...));
2026     * @param x the parameter value
2027     * @param tz the timezone to use
2028     *
2029     * @throws SQLException if a database access error occurs
2030     */

2031    private void setTimeInternal(int parameterIndex, Time JavaDoc x, TimeZone JavaDoc tz)
2032        throws SQLException JavaDoc {
2033        if (x == null) {
2034            setNull(parameterIndex, java.sql.Types.TIME);
2035        } else {
2036            x = TimeUtil.changeTimezone(this.connection, x, tz,
2037                    this.connection.getServerTimezone());
2038            setInternal(parameterIndex, "'" + x.toString() + "'");
2039        }
2040    }
2041
2042    /**
2043     * Set a parameter to a java.sql.Timestamp value. The driver converts this
2044     * to a SQL TIMESTAMP value when it sends it to the database.
2045     *
2046     * @param parameterIndex the first parameter is 1, the second is 2, ...
2047     * @param x the parameter value
2048     * @param tz the timezone to use
2049     *
2050     * @throws SQLException if a database-access error occurs.
2051     */

2052    private synchronized void setTimestampInternal(int parameterIndex,
2053        Timestamp JavaDoc x, TimeZone JavaDoc tz) throws SQLException JavaDoc {
2054        if (x == null) {
2055            setNull(parameterIndex, java.sql.Types.TIMESTAMP);
2056        } else {
2057            String JavaDoc timestampString = null;
2058            x = TimeUtil.changeTimezone(this.connection, x, tz,
2059                    this.connection.getServerTimezone());
2060
2061            if (this.tsdf == null) {
2062                this.tsdf = new SimpleDateFormat JavaDoc("''yyyy-MM-dd HH:mm:ss''");
2063            }
2064
2065            timestampString = this.tsdf.format(x);
2066
2067            setInternal(parameterIndex, timestampString); // SimpleDateFormat is not thread-safe
2068
}
2069    }
2070
2071    private final void escapeblockFast(byte[] buf,
2072        ByteArrayOutputStream JavaDoc bytesOut, int size) {
2073        int lastwritten = 0;
2074
2075        for (int i = 0; i < size; i++) {
2076            byte b = buf[i];
2077
2078            if (b == '\0') {
2079                //write stuff not yet written
2080
if (i > lastwritten) {
2081                    bytesOut.write(buf, lastwritten, i - lastwritten);
2082                }
2083
2084                //write escape
2085
bytesOut.write('\\');
2086                bytesOut.write('0');
2087                lastwritten = i + 1;
2088            } else {
2089                if ((b == '\\') || (b == '\'') || (b == '"')) {
2090                    //write stuff not yet written
2091
if (i > lastwritten) {
2092                        bytesOut.write(buf, lastwritten, i - lastwritten);
2093                    }
2094
2095                    //write escape
2096
bytesOut.write('\\');
2097                    lastwritten = i; //not i+1 as b wasn't written.
2098
}
2099            }
2100        }
2101
2102        //write out remaining stuff from buffer
2103
if (lastwritten < size) {
2104            bytesOut.write(buf, lastwritten, size - lastwritten);
2105        }
2106    }
2107
2108    private final void escapeblockFast(byte[] buf, Buffer packet, int size)
2109        throws SQLException JavaDoc {
2110        int lastwritten = 0;
2111
2112        for (int i = 0; i < size; i++) {
2113            byte b = buf[i];
2114
2115            if (b == '\0') {
2116                //write stuff not yet written
2117
if (i > lastwritten) {
2118                    packet.writeBytesNoNull(buf, lastwritten, i - lastwritten);
2119                }
2120
2121                //write escape
2122
packet.writeByte((byte) '\\');
2123                packet.writeByte((byte) '0');
2124                lastwritten = i + 1;
2125            } else {
2126                if ((b == '\\') || (b == '\'') || (b == '"')) {
2127                    //write stuff not yet written
2128
if (i > lastwritten) {
2129                        packet.writeBytesNoNull(buf, lastwritten,
2130                            i - lastwritten);
2131                    }
2132
2133                    //write escape
2134
packet.writeByte((byte) '\\');
2135                    lastwritten = i; //not i+1 as b wasn't written.
2136
}
2137            }
2138        }
2139
2140        //write out remaining stuff from buffer
2141
if (lastwritten < size) {
2142            packet.writeBytesNoNull(buf, lastwritten, size - lastwritten);
2143        }
2144    }
2145
2146    /**
2147     * Creates the packet that contains the query to be sent to the server.
2148     *
2149     * @return the packet to send to the server to issue the query.
2150     *
2151     * @throws SQLException if a database error occurs.
2152     */

2153    private Buffer fillSendPacket() throws SQLException JavaDoc {
2154        return fillSendPacket(this.parameterValues, this.parameterStreams,
2155            this.isStream, this.streamLengths);
2156    }
2157
2158    /**
2159     * Creates the packet that contains the query to be sent to the server.
2160     *
2161     * @param batchedParameterStrings DOCUMENT ME!
2162     * @param batchedParameterStreams DOCUMENT ME!
2163     * @param batchedIsStream DOCUMENT ME!
2164     * @param batchedStreamLengths DOCUMENT ME!
2165     *
2166     * @return DOCUMENT ME!
2167     *
2168     * @throws SQLException if a database error occurs.
2169     * @throws java.sql.SQLException DOCUMENT ME!
2170     */

2171    private Buffer fillSendPacket(byte[][] batchedParameterStrings,
2172        InputStream JavaDoc[] batchedParameterStreams, boolean[] batchedIsStream,
2173        int[] batchedStreamLengths) throws SQLException JavaDoc {
2174        Buffer sendPacket = this.connection.getIO().getSharedSendPacket();
2175
2176        sendPacket.clear();
2177
2178        sendPacket.writeByte((byte) MysqlDefs.QUERY);
2179
2180        boolean useStreamLengths = this.connection.useStreamLengthsInPrepStmts();
2181
2182        //
2183
// Try and get this allocation as close as possible
2184
// for BLOBs
2185
//
2186
int ensurePacketSize = 0;
2187
2188        for (int i = 0; i < batchedParameterStrings.length; i++) {
2189            if (batchedIsStream[i] && useStreamLengths) {
2190                ensurePacketSize += batchedStreamLengths[i];
2191            }
2192        }
2193
2194        if (ensurePacketSize != 0) {
2195            sendPacket.ensureCapacity(ensurePacketSize);
2196        }
2197
2198        for (int i = 0; i < batchedParameterStrings.length; i++) {
2199            if ((batchedParameterStrings[i] == null)
2200                    && (batchedParameterStreams[i] == null)) {
2201                throw new java.sql.SQLException JavaDoc(
2202                    "No value specified for parameter " + (i + 1), SQLError.SQL_STATE_WRONG_NO_OF_PARAMETERS);
2203            }
2204
2205            sendPacket.writeBytesNoNull(staticSqlStrings[i]);
2206
2207            if (batchedIsStream[i]) {
2208                streamToBytes(sendPacket, batchedParameterStreams[i], true,
2209                    batchedStreamLengths[i], useStreamLengths);
2210            } else {
2211                sendPacket.writeBytesNoNull(batchedParameterStrings[i]);
2212            }
2213        }
2214
2215        sendPacket.writeBytesNoNull(staticSqlStrings[batchedParameterStrings.length]);
2216
2217        return sendPacket;
2218    }
2219
2220    //
2221
// Adds '+' to decimal numbers that are positive (MySQL doesn't
2222
// understand them otherwise
2223
//
2224
private static final String JavaDoc fixDecimalExponent(String JavaDoc dString) {
2225        int ePos = dString.indexOf("E");
2226
2227        if (ePos == -1) {
2228            ePos = dString.indexOf("e");
2229        }
2230
2231        if (ePos != -1) {
2232            if (dString.length() > (ePos + 1)) {
2233                char maybeMinusChar = dString.charAt(ePos + 1);
2234
2235                if (maybeMinusChar != '-') {
2236                    StringBuffer JavaDoc buf = new StringBuffer JavaDoc(dString.length() + 1);
2237                    buf.append(dString.substring(0, ePos + 1));
2238                    buf.append('+');
2239                    buf.append(dString.substring(ePos + 1, dString.length()));
2240                    dString = buf.toString();
2241                }
2242            }
2243        }
2244
2245        return dString;
2246    }
2247
2248    private void initializeFromParseInfo() throws SQLException JavaDoc {
2249        this.staticSqlStrings = this.parseInfo.staticSql;
2250        this.hasLimitClause = this.parseInfo.foundLimitClause;
2251        this.isLoadDataQuery = this.parseInfo.foundLoadData;
2252        this.firstCharOfStmt = this.parseInfo.firstStmtChar;
2253        
2254        int numberOfParameters = staticSqlStrings.length - 1;
2255
2256        parameterValues = new byte[numberOfParameters][];
2257        parameterStreams = new InputStream JavaDoc[numberOfParameters];
2258        isStream = new boolean[numberOfParameters];
2259        streamLengths = new int[numberOfParameters];
2260        isNull = new boolean[numberOfParameters];
2261
2262        clearParameters();
2263
2264        for (int j = 0; j < numberOfParameters; j++) {
2265            isStream[j] = false;
2266        }
2267    }
2268
2269    private final int readblock(InputStream JavaDoc i, byte[] b, int length)
2270        throws SQLException JavaDoc {
2271        try {
2272            int lengthToRead = length;
2273
2274            if (lengthToRead > b.length) {
2275                lengthToRead = b.length;
2276            }
2277
2278            return i.read(b, 0, lengthToRead);
2279        } catch (Throwable JavaDoc E) {
2280            throw new java.sql.SQLException JavaDoc("Error reading from InputStream "
2281                + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR);
2282        }
2283    }
2284
2285    private final int readblock(InputStream JavaDoc i, byte[] b)
2286        throws SQLException JavaDoc {
2287        try {
2288            return i.read(b);
2289        } catch (Throwable JavaDoc E) {
2290            throw new java.sql.SQLException JavaDoc("Error reading from InputStream "
2291                + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR);
2292        }
2293    }
2294
2295    /**
2296     * For the setXXXStream() methods. Basically converts an InputStream into a
2297     * String. Not very efficient, but it works.
2298     *
2299     * @param in DOCUMENT ME!
2300     * @param streamLength DOCUMENT ME!
2301     * @param useLength DOCUMENT ME!
2302     *
2303     * @return DOCUMENT ME!
2304     *
2305     * @throws SQLException DOCUMENT ME!
2306     */

2307    private final byte[] streamToBytes(InputStream JavaDoc in, int streamLength,
2308        boolean useLength) throws SQLException JavaDoc {
2309        return streamToBytes(in, true, streamLength, useLength);
2310    }
2311
2312    private final byte[] streamToBytes(InputStream JavaDoc in, boolean escape,
2313        int streamLength, boolean useLength) throws SQLException JavaDoc {
2314        try {
2315            if (streamLength == -1) {
2316                useLength = false;
2317            }
2318
2319            ByteArrayOutputStream JavaDoc bytesOut = new ByteArrayOutputStream JavaDoc();
2320
2321            int bc = -1;
2322
2323            if (useLength) {
2324                bc = readblock(in, streamConvertBuf, streamLength);
2325            } else {
2326                bc = readblock(in, streamConvertBuf);
2327            }
2328
2329            int lengthLeftToRead = streamLength - bc;
2330
2331            if (escape) {
2332                bytesOut.write('\'');
2333            }
2334
2335            while (bc > 0) {
2336                if (escape) {
2337                    escapeblockFast(streamConvertBuf, bytesOut, bc);
2338                } else {
2339                    bytesOut.write(streamConvertBuf, 0, bc);
2340                }
2341
2342                if (useLength) {
2343                    bc = readblock(in, streamConvertBuf, lengthLeftToRead);
2344
2345                    if (bc > 0) {
2346                        lengthLeftToRead -= bc;
2347                    }
2348                } else {
2349                    bc = readblock(in, streamConvertBuf);
2350                }
2351            }
2352
2353            if (escape) {
2354                bytesOut.write('\'');
2355            }
2356
2357            return bytesOut.toByteArray();
2358        } finally {
2359            try {
2360                in.close();
2361            } catch (IOException JavaDoc ioEx) {
2362                ;
2363            }
2364
2365            in = null;
2366        }
2367    }
2368
2369    private final void streamToBytes(Buffer packet, InputStream JavaDoc in,
2370        boolean escape, int streamLength, boolean useLength)
2371        throws SQLException JavaDoc {
2372        try {
2373            if (streamLength == -1) {
2374                useLength = false;
2375            }
2376
2377            int bc = -1;
2378
2379            if (useLength) {
2380                bc = readblock(in, streamConvertBuf, streamLength);
2381            } else {
2382                bc = readblock(in, streamConvertBuf);
2383            }
2384
2385            int lengthLeftToRead = streamLength - bc;
2386
2387            if (escape) {
2388                packet.writeByte((byte) '\'');
2389            }
2390
2391            while (bc > 0) {
2392                if (escape) {
2393                    escapeblockFast(streamConvertBuf, packet, bc);
2394                } else {
2395                    packet.writeBytesNoNull(streamConvertBuf, 0, bc);
2396                }
2397
2398                if (useLength) {
2399                    bc = readblock(in, streamConvertBuf, lengthLeftToRead);
2400
2401                    if (bc > 0) {
2402                        lengthLeftToRead -= bc;
2403                    }
2404                } else {
2405                    bc = readblock(in, streamConvertBuf);
2406                }
2407            }
2408
2409            if (escape) {
2410                packet.writeByte((byte) '\'');
2411            }
2412        } finally {
2413            try {
2414                in.close();
2415            } catch (IOException JavaDoc ioEx) {
2416                ;
2417            }
2418
2419            in = null;
2420        }
2421    }
2422
2423    /**
2424     * Reads length bytes from reader into buf. Blocks until enough input is
2425     * available
2426     *
2427     * @param reader DOCUMENT ME!
2428     * @param buf DOCUMENT ME!
2429     * @param length DOCUMENT ME!
2430     *
2431     * @return DOCUMENT ME!
2432     *
2433     * @throws IOException DOCUMENT ME!
2434     */

2435    private static int readFully(Reader JavaDoc reader, char[] buf, int length)
2436        throws IOException JavaDoc {
2437        int numCharsRead = 0;
2438
2439        while (numCharsRead < length) {
2440            int count = reader.read(buf, numCharsRead, length - numCharsRead);
2441
2442            if (count < 0) {
2443                break;
2444            }
2445
2446            numCharsRead += count;
2447        }
2448
2449        return numCharsRead;
2450    }
2451
2452    class BatchParams {
2453        boolean[] isNull = null;
2454        boolean[] isStream = null;
2455        InputStream JavaDoc[] parameterStreams = null;
2456        byte[][] parameterStrings = null;
2457        int[] streamLengths = null;
2458
2459        BatchParams(byte[][] strings, InputStream JavaDoc[] streams,
2460            boolean[] isStreamFlags, int[] lengths, boolean[] isNullFlags) {
2461            //
2462
// Make copies
2463
//
2464
parameterStrings = new byte[strings.length][];
2465            parameterStreams = new InputStream JavaDoc[streams.length];
2466            isStream = new boolean[isStreamFlags.length];
2467            streamLengths = new int[lengths.length];
2468            isNull = new boolean[isNullFlags.length];
2469            System.arraycopy(strings, 0, parameterStrings, 0, strings.length);
2470            System.arraycopy(streams, 0, parameterStreams, 0, streams.length);
2471            System.arraycopy(isStreamFlags, 0, isStream, 0, isStreamFlags.length);
2472            System.arraycopy(lengths, 0, streamLengths, 0, lengths.length);
2473            System.arraycopy(isNullFlags, 0, isNull, 0, isNullFlags.length);
2474        }
2475    }
2476
2477    class ParseInfo {
2478        byte[][] staticSql = null;
2479        boolean foundLimitClause = false;
2480        boolean foundLoadData = false;
2481        char firstStmtChar = 0;
2482        int statementLength = 0;
2483        long lastUsed = 0;
2484
2485        /**
2486                             *
2487                             */

2488        public ParseInfo(String JavaDoc sql, Connection conn,
2489            java.sql.DatabaseMetaData JavaDoc dbmd, String JavaDoc encoding,
2490            SingleByteCharsetConverter converter) throws SQLException JavaDoc {
2491            if (sql == null) {
2492                throw new SQLException JavaDoc("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2493            }
2494
2495            lastUsed = System.currentTimeMillis();
2496
2497            String JavaDoc quotedIdentifierString = dbmd.getIdentifierQuoteString();
2498
2499            char quotedIdentifierChar = 0;
2500
2501            if ((quotedIdentifierString != null)
2502                    && !quotedIdentifierString.equals(" ")
2503                    && (quotedIdentifierString.length() > 0)) {
2504                quotedIdentifierChar = quotedIdentifierString.charAt(0);
2505            }
2506
2507            statementLength = sql.length();
2508
2509            ArrayList JavaDoc endpointList = new ArrayList JavaDoc();
2510            boolean inQuotes = false;
2511            boolean inQuotedId = false;
2512            int lastParmEnd = 0;
2513            int i;
2514
2515            int pre1 = 0;
2516            int pre2 = 0;
2517
2518            int lastAlphaCharPos = 0;
2519            int stopLookingForLimitClause = statementLength - 5;
2520
2521            foundLimitClause = false;
2522
2523            for (i = 0; i < statementLength; ++i) {
2524                char c = sql.charAt(i);
2525
2526                if ((firstStmtChar == 0) && !Character.isWhitespace(c)) {
2527                    // Determine what kind of statement we're doing (_S_elect, _I_nsert, etc.)
2528
firstStmtChar = Character.toUpperCase(c);
2529                }
2530
2531                if (Character.isLetter(c)) {
2532                    lastAlphaCharPos = i;
2533                }
2534
2535                // are we in a quoted identifier?
2536
// (only valid when the id is not inside a 'string')
2537
if (!inQuotes && (quotedIdentifierChar != 0)
2538                        && (c == quotedIdentifierChar)) {
2539                    inQuotedId = !inQuotedId;
2540                }
2541
2542                // only respect quotes when not in a quoted identifier
2543
if (!inQuotedId) {
2544                    if ((c == '\'') && (pre1 == '\\') && (pre2 == '\\')) {
2545                        inQuotes = !inQuotes;
2546                    } else if ((c == '\'') && (pre1 != '\\')) {
2547                        inQuotes = !inQuotes;
2548                    }
2549                }
2550
2551                if ((c == '?') && !inQuotes) {
2552                    endpointList.add(new int[] { lastParmEnd, i });
2553                    lastParmEnd = i + 1;
2554                }
2555
2556                if (!inQuotes && (i < stopLookingForLimitClause)) {
2557                    if ((c == 'L') || (c == 'l')) {
2558                        char posI1 = sql.charAt(i + 1);
2559
2560                        if ((posI1 == 'I') || (posI1 == 'i')) {
2561                            char posM = sql.charAt(i + 2);
2562
2563                            if ((posM == 'M') || (posM == 'm')) {
2564                                char posI2 = sql.charAt(i + 3);
2565
2566                                if ((posI2 == 'I') || (posI2 == 'i')) {
2567                                    char posT = sql.charAt(i + 4);
2568
2569                                    if ((posT == 'T') || (posT == 't')) {
2570                                        foundLimitClause = true;
2571                                    }
2572                                }
2573                            }
2574                        }
2575                    }
2576                }
2577
2578                pre2 = pre1;
2579                pre1 = c;
2580            }
2581
2582            if (firstStmtChar == 'L') {
2583                if (StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) {
2584                    foundLoadData = true;
2585                } else {
2586                    foundLoadData = false;
2587                }
2588            } else {
2589                foundLoadData = false;
2590            }
2591
2592            endpointList.add(new int[] { lastParmEnd, statementLength });
2593            staticSql = new byte[endpointList.size()][];
2594
2595            for (i = 0; i < staticSql.length; i++) {
2596                int[] ep = (int[]) endpointList.get(i);
2597                int end = ep[1];
2598                int begin = ep[0];
2599                int len = end - begin;
2600
2601                if (foundLoadData) {
2602                    String JavaDoc temp = new String JavaDoc(sql.toCharArray(), begin, len);
2603                    staticSql[i] = temp.getBytes();
2604                } else if (encoding == null) {
2605                    byte[] buf = new byte[len];
2606
2607                    for (int j = 0; j < len; j++) {
2608                        buf[j] = (byte) sql.charAt(begin + j);
2609                    }
2610
2611                    staticSql[i] = buf;
2612                } else {
2613                    try {
2614                        if (converter != null) {
2615                            staticSql[i] = StringUtils.getBytes(sql, converter,
2616                                    encoding, begin, len);
2617                        } else {
2618                            String JavaDoc temp = new String JavaDoc(sql.toCharArray(), begin,
2619                                    len);
2620                            staticSql[i] = StringUtils.getBytes(temp, null,
2621                                    encoding);
2622                        }
2623                    } catch (java.io.UnsupportedEncodingException JavaDoc ue) {
2624                        throw new SQLException JavaDoc(ue.toString());
2625                    }
2626                }
2627            }
2628
2629            int numberOfParameters = staticSql.length - 1;
2630        }
2631    }
2632}
2633
Popular Tags