PreparedStatement.java
上传用户:sxlinghang
上传日期:2022-07-20
资源大小:1405k
文件大小:93k
源码类别:

数据库编程

开发平台:

Java

  1. /*
  2.    Copyright (C) 2002 MySQL AB
  3.       This program is free software; you can redistribute it and/or modify
  4.       it under the terms of the GNU General Public License as published by
  5.       the Free Software Foundation; either version 2 of the License, or
  6.       (at your option) any later version.
  7.       This program is distributed in the hope that it will be useful,
  8.       but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.       GNU General Public License for more details.
  11.       You should have received a copy of the GNU General Public License
  12.       along with this program; if not, write to the Free Software
  13.       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14.  */
  15. package com.mysql.jdbc;
  16. import java.io.ByteArrayInputStream;
  17. import java.io.ByteArrayOutputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.io.ObjectOutputStream;
  21. import java.io.Reader;
  22. import java.io.StringReader;
  23. import java.io.UnsupportedEncodingException;
  24. import java.math.BigDecimal;
  25. import java.net.URL;
  26. import java.sql.Array;
  27. import java.sql.Clob;
  28. import java.sql.ParameterMetaData;
  29. import java.sql.Ref;
  30. import java.sql.SQLException;
  31. import java.sql.Time;
  32. import java.sql.Timestamp;
  33. import java.sql.Types;
  34. import java.text.ParsePosition;
  35. import java.text.SimpleDateFormat;
  36. import java.util.ArrayList;
  37. import java.util.Calendar;
  38. import java.util.TimeZone;
  39. /**
  40.  * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
  41.  * This object can then be used to efficiently execute this statement multiple
  42.  * times.
  43.  * 
  44.  * <p>
  45.  * <B>Note:</B> The setXXX methods for setting IN parameter values must specify
  46.  * types that are compatible with the defined SQL type of the input parameter.
  47.  * For instance, if the IN parameter has SQL type Integer, then setInt should
  48.  * be used.
  49.  * </p>
  50.  * 
  51.  * <p>
  52.  * If arbitrary parameter type conversions are required, then the setObject
  53.  * method should be used with a target SQL type.
  54.  * </p>
  55.  *
  56.  * @author Mark Matthews
  57.  * @version $Id: PreparedStatement.java,v 1.27.2.33 2004/02/05 15:56:17 mmatthew Exp $
  58.  *
  59.  * @see java.sql.ResultSet
  60.  * @see java.sql.PreparedStatement
  61.  */
  62. public class PreparedStatement extends com.mysql.jdbc.Statement
  63.     implements java.sql.PreparedStatement {
  64.     private java.sql.DatabaseMetaData dbmd = null;
  65.     private ParseInfo parseInfo;
  66.     private java.sql.ResultSetMetaData pstmtResultMetaData;
  67.     private SimpleDateFormat tsdf = null;
  68.     private String originalSql = null;
  69.     private boolean[] isNull = null;
  70.     private boolean[] isStream = null;
  71.     private InputStream[] parameterStreams = null;
  72.     private byte[][] parameterValues = null;
  73.     private byte[][] staticSqlStrings = null;
  74.     private byte[] streamConvertBuf = new byte[4096];
  75.     private int[] streamLengths = null;
  76.     private boolean hasLimitClause = false;
  77.     private boolean isLoadDataQuery = false;
  78.     private boolean retrieveGeneratedKeys = false;
  79.     private boolean useTrueBoolean = false;
  80.     private char firstCharOfStmt = 0;
  81.     /**
  82.      * Constructor for the PreparedStatement class.
  83.      *
  84.      * @param conn the connection creating this statement
  85.      * @param sql the SQL for this statement
  86.      * @param catalog the catalog/database this statement should be issued
  87.      *        against
  88.      *
  89.      * @throws SQLException if a database error occurs.
  90.      */
  91.     public PreparedStatement(Connection conn, String sql, String catalog)
  92.         throws SQLException {
  93.         super(conn, catalog);
  94.         if (sql == null) {
  95.             throw new SQLException("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  96.         }
  97.         originalSql = sql;
  98.         this.dbmd = this.connection.getMetaData();
  99.         useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23);
  100.         this.parseInfo = new ParseInfo(sql, this.connection, this.dbmd,
  101.                 this.charEncoding, this.charConverter);
  102.         initializeFromParseInfo();
  103.     }
  104.     /**
  105.      * Creates a new PreparedStatement object.
  106.      *
  107.      * @param conn the connection creating this statement
  108.      * @param sql the SQL for this statement
  109.      * @param catalog the catalog/database this statement should be issued
  110.      *        against
  111.      * @param cachedParseInfo already created parseInfo.
  112.      *
  113.      * @throws SQLException DOCUMENT ME!
  114.      */
  115.     public PreparedStatement(Connection conn, String sql, String catalog,
  116.         ParseInfo cachedParseInfo) throws SQLException {
  117.         super(conn, catalog);
  118.         if (sql == null) {
  119.             throw new SQLException("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  120.         }
  121.         originalSql = sql;
  122.         this.dbmd = this.connection.getMetaData();
  123.         useTrueBoolean = connection.getIO().versionMeetsMinimum(3, 21, 23);
  124.         this.parseInfo = cachedParseInfo;
  125.         initializeFromParseInfo();
  126.     }
  127.     /**
  128.      * JDBC 2.0 Set an Array parameter.
  129.      *
  130.      * @param i the first parameter is 1, the second is 2, ...
  131.      * @param x an object representing an SQL array
  132.      *
  133.      * @throws SQLException because this method is not implemented.
  134.      * @throws NotImplemented DOCUMENT ME!
  135.      */
  136.     public void setArray(int i, Array x) throws SQLException {
  137.         throw new NotImplemented();
  138.     }
  139.     /**
  140.      * When a very large ASCII value is input to a LONGVARCHAR parameter, it
  141.      * may be more practical to send it via a java.io.InputStream. JDBC will
  142.      * read the data from the stream as needed, until it reaches end-of-file.
  143.      * The JDBC driver will do any necessary conversion from ASCII to the
  144.      * database char format.
  145.      * 
  146.      * <P>
  147.      * <B>Note:</B> This stream object can either be a standard Java stream
  148.      * object or your own subclass that implements the standard interface.
  149.      * </p>
  150.      *
  151.      * @param parameterIndex the first parameter is 1...
  152.      * @param x the parameter value
  153.      * @param length the number of bytes in the stream
  154.      *
  155.      * @exception SQLException if a database access error occurs
  156.      */
  157.     public synchronized void setAsciiStream(int parameterIndex, InputStream x,
  158.         int length) throws SQLException {
  159.         if (x == null) {
  160.             setNull(parameterIndex, java.sql.Types.VARCHAR);
  161.         } else {
  162.             setBinaryStream(parameterIndex, x, length);
  163.         }
  164.     }
  165.     /**
  166.      * Set a parameter to a java.math.BigDecimal value.  The driver converts
  167.      * this to a SQL NUMERIC value when it sends it to the database.
  168.      *
  169.      * @param parameterIndex the first parameter is 1...
  170.      * @param x the parameter value
  171.      *
  172.      * @exception SQLException if a database access error occurs
  173.      */
  174.     public void setBigDecimal(int parameterIndex, BigDecimal x)
  175.         throws SQLException {
  176.         if (x == null) {
  177.             setNull(parameterIndex, java.sql.Types.DECIMAL);
  178.         } else {
  179.             setInternal(parameterIndex, fixDecimalExponent(x.toString()));
  180.         }
  181.     }
  182.     /**
  183.      * When a very large binary value is input to a LONGVARBINARY parameter, it
  184.      * may be more practical to send it via a java.io.InputStream. JDBC will
  185.      * read the data from the stream as needed, until it reaches end-of-file.
  186.      * 
  187.      * <P>
  188.      * <B>Note:</B> This stream object can either be a standard Java stream
  189.      * object or your own subclass that implements the standard interface.
  190.      * </p>
  191.      *
  192.      * @param parameterIndex the first parameter is 1...
  193.      * @param x the parameter value
  194.      * @param length the number of bytes to read from the stream (ignored)
  195.      *
  196.      * @throws SQLException if a database access error occurs
  197.      * @throws java.sql.SQLException DOCUMENT ME!
  198.      */
  199.     public void setBinaryStream(int parameterIndex, InputStream x, int length)
  200.         throws SQLException {
  201.         if (x == null) {
  202.             setNull(parameterIndex, java.sql.Types.BINARY);
  203.         } else {
  204.             if ((parameterIndex < 1)
  205.                     || (parameterIndex > staticSqlStrings.length)) {
  206.                 throw new java.sql.SQLException(
  207.                     "Parameter index out of range (" + parameterIndex + " > "
  208.                     + staticSqlStrings.length + ")", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  209.             }
  210.             parameterStreams[parameterIndex - 1] = x;
  211.             isStream[parameterIndex - 1] = true;
  212.             streamLengths[parameterIndex - 1] = length;
  213.             isNull[parameterIndex - 1] = false;
  214.         }
  215.     }
  216.     /**
  217.      * JDBC 2.0 Set a BLOB parameter.
  218.      *
  219.      * @param i the first parameter is 1, the second is 2, ...
  220.      * @param x an object representing a BLOB
  221.      *
  222.      * @throws SQLException if a database error occurs
  223.      */
  224.     public void setBlob(int i, java.sql.Blob x) throws SQLException {
  225.         setBinaryStream(i, x.getBinaryStream(), (int) x.length());
  226.     }
  227.     /**
  228.      * Set a parameter to a Java boolean value.  The driver converts this to a
  229.      * SQL BIT value when it sends it to the database.
  230.      *
  231.      * @param parameterIndex the first parameter is 1...
  232.      * @param x the parameter value
  233.      *
  234.      * @throws SQLException if a database access error occurs
  235.      */
  236.     public void setBoolean(int parameterIndex, boolean x)
  237.         throws SQLException {
  238.         if (useTrueBoolean) {
  239.             setInternal(parameterIndex, x ? "'1'" : "'0'");
  240.         } else {
  241.             setInternal(parameterIndex, x ? "'t'" : "'f'");
  242.         }
  243.     }
  244.     /**
  245.      * Set a parameter to a Java byte value.  The driver converts this to a SQL
  246.      * TINYINT value when it sends it to the database.
  247.      *
  248.      * @param parameterIndex the first parameter is 1...
  249.      * @param x the parameter value
  250.      *
  251.      * @exception SQLException if a database access error occurs
  252.      */
  253.     public void setByte(int parameterIndex, byte x) throws SQLException {
  254.         setInternal(parameterIndex, String.valueOf(x));
  255.     }
  256.     /**
  257.      * Set a parameter to a Java array of bytes.  The driver converts this to a
  258.      * SQL VARBINARY or LONGVARBINARY (depending on the argument's size
  259.      * relative to the driver's limits on VARBINARYs) when it sends it to the
  260.      * database.
  261.      *
  262.      * @param parameterIndex the first parameter is 1...
  263.      * @param x the parameter value
  264.      *
  265.      * @exception SQLException if a database access error occurs
  266.      */
  267.     public void setBytes(int parameterIndex, byte[] x)
  268.         throws SQLException {
  269.         if (x == null) {
  270.             setNull(parameterIndex, java.sql.Types.BINARY);
  271.         } else {
  272.             // escape them
  273.             int numBytes = x.length;
  274.             ByteArrayOutputStream bOut = new ByteArrayOutputStream(numBytes);
  275.             bOut.write(''');
  276.             for (int i = 0; i < numBytes; ++i) {
  277.                 byte b = x[i];
  278.                 switch (b) {
  279.                 case 0: /* Must be escaped for 'mysql' */
  280.                     bOut.write('\');
  281.                     bOut.write('0');
  282.                     break;
  283.                 case 'n': /* Must be escaped for logs */
  284.                     bOut.write('\');
  285.                     bOut.write('n');
  286.                     break;
  287.                 case 'r':
  288.                     bOut.write('\');
  289.                     bOut.write('r');
  290.                     break;
  291.                 case '\':
  292.                     bOut.write('\');
  293.                     bOut.write('\');
  294.                     break;
  295.                 case ''':
  296.                     bOut.write('\');
  297.                     bOut.write(''');
  298.                     break;
  299.                 case '"': /* Better safe than sorry */
  300.                     bOut.write('\');
  301.                     bOut.write('"');
  302.                     break;
  303.                 case '32': /* This gives problems on Win32 */
  304.                     bOut.write('\');
  305.                     bOut.write('Z');
  306.                     break;
  307.                 default:
  308.                     bOut.write(b);
  309.                 }
  310.             }
  311.             bOut.write(''');
  312.             setInternal(parameterIndex, bOut.toByteArray());
  313.         }
  314.     }
  315.     /**
  316.      * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR
  317.      * parameter, it may be more practical to send it via a java.io.Reader.
  318.      * JDBC will read the data from the stream as needed, until it reaches
  319.      * end-of-file.  The JDBC driver will do any necessary conversion from
  320.      * UNICODE to the database char format.
  321.      * 
  322.      * <P>
  323.      * <B>Note:</B> This stream object can either be a standard Java stream
  324.      * object or your own subclass that implements the standard interface.
  325.      * </p>
  326.      *
  327.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  328.      * @param reader the java reader which contains the UNICODE data
  329.      * @param length the number of characters in the stream
  330.      *
  331.      * @throws SQLException if a database-access error occurs.
  332.      */
  333.     public void setCharacterStream(int parameterIndex, java.io.Reader reader,
  334.         int length) throws SQLException {
  335.         try {
  336.             if (reader == null) {
  337.                 setNull(parameterIndex, Types.LONGVARCHAR);
  338.             } else {
  339.                 char[] c = null;
  340.                 int len = 0;
  341.                 boolean useLength = this.connection.useStreamLengthsInPrepStmts();
  342.                 if (useLength && (length != -1)) {
  343.                     c = new char[length];
  344.                     int numCharsRead = readFully(reader, c, length); // blocks until all read
  345.                     setString(parameterIndex, new String(c, 0, numCharsRead));
  346.                 } else {
  347.                     c = new char[4096];
  348.                     StringBuffer buf = new StringBuffer();
  349.                     while ((len = reader.read(c)) != -1) {
  350.                         buf.append(c, 0, len);
  351.                     }
  352.                     setString(parameterIndex, buf.toString());
  353.                 }
  354.             }
  355.         } catch (java.io.IOException ioEx) {
  356.             throw new SQLException(ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
  357.         }
  358.     }
  359.     /**
  360.      * JDBC 2.0 Set a CLOB parameter.
  361.      *
  362.      * @param i the first parameter is 1, the second is 2, ...
  363.      * @param x an object representing a CLOB
  364.      *
  365.      * @throws SQLException if a database error occurs
  366.      */
  367.     public void setClob(int i, Clob x) throws SQLException {
  368.         setString(i, x.getSubString(1L, (int) x.length()));
  369.     }
  370.     /**
  371.      * Set a parameter to a java.sql.Date value.  The driver converts this to a
  372.      * SQL DATE value when it sends it to the database.
  373.      *
  374.      * @param parameterIndex the first parameter is 1...
  375.      * @param x the parameter value
  376.      *
  377.      * @exception SQLException if a database access error occurs
  378.      */
  379.     public void setDate(int parameterIndex, java.sql.Date x)
  380.         throws SQLException {
  381.         if (x == null) {
  382.             setNull(parameterIndex, java.sql.Types.DATE);
  383.         } else {
  384.             // FIXME: Have instance version of this, problem as it's
  385.             //        not thread-safe :(
  386.             SimpleDateFormat dateFormatter = new SimpleDateFormat(
  387.                     "''yyyy-MM-dd''");
  388.             setInternal(parameterIndex, dateFormatter.format(x));
  389.         }
  390.     }
  391.     /**
  392.      * Set a parameter to a java.sql.Date value.  The driver converts this to a
  393.      * SQL DATE value when it sends it to the database.
  394.      *
  395.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  396.      * @param x the parameter value
  397.      * @param cal the calendar to interpret the date with
  398.      *
  399.      * @throws SQLException if a database-access error occurs.
  400.      */
  401.     public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
  402.         throws SQLException {
  403.         setDate(parameterIndex, x);
  404.     }
  405.     /**
  406.      * Set a parameter to a Java double value.  The driver converts this to a
  407.      * SQL DOUBLE value when it sends it to the database
  408.      *
  409.      * @param parameterIndex the first parameter is 1...
  410.      * @param x the parameter value
  411.      *
  412.      * @throws SQLException if a database access error occurs
  413.      */
  414.     public void setDouble(int parameterIndex, double x)
  415.         throws SQLException {
  416.         setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x)));
  417.     }
  418.     /**
  419.      * Set a parameter to a Java float value.  The driver converts this to a
  420.      * SQL FLOAT value when it sends it to the database.
  421.      *
  422.      * @param parameterIndex the first parameter is 1...
  423.      * @param x the parameter value
  424.      *
  425.      * @throws SQLException if a database access error occurs
  426.      */
  427.     public void setFloat(int parameterIndex, float x) throws SQLException {
  428.         setInternal(parameterIndex, fixDecimalExponent(String.valueOf(x)));
  429.     }
  430.     /**
  431.      * Set a parameter to a Java int value.  The driver converts this to a SQL
  432.      * INTEGER value when it sends it to the database.
  433.      *
  434.      * @param parameterIndex the first parameter is 1...
  435.      * @param x the parameter value
  436.      *
  437.      * @throws SQLException if a database access error occurs
  438.      */
  439.     public void setInt(int parameterIndex, int x) throws SQLException {
  440.         setInternal(parameterIndex, String.valueOf(x));
  441.     }
  442.     /**
  443.      * Set a parameter to a Java long value.  The driver converts this to a SQL
  444.      * BIGINT value when it sends it to the database.
  445.      *
  446.      * @param parameterIndex the first parameter is 1...
  447.      * @param x the parameter value
  448.      *
  449.      * @throws SQLException if a database access error occurs
  450.      */
  451.     public void setLong(int parameterIndex, long x) throws SQLException {
  452.         setInternal(parameterIndex, String.valueOf(x));
  453.     }
  454.     /**
  455.      * The number, types and properties of a ResultSet's columns are provided
  456.      * by the getMetaData method.
  457.      *
  458.      * @return the description of a ResultSet's columns
  459.      *
  460.      * @throws SQLException if a database-access error occurs.
  461.      */
  462.     public synchronized java.sql.ResultSetMetaData getMetaData() throws SQLException {
  463.         PreparedStatement mdStmt = null;
  464.         java.sql.ResultSet mdRs = null;
  465.         if (this.pstmtResultMetaData == null) {
  466.             try {
  467.                 mdStmt = new PreparedStatement(this.connection,
  468.                         this.originalSql, this.currentCatalog, this.parseInfo);
  469.                 mdStmt.setMaxRows(0);
  470.                 int paramCount = this.parameterValues.length;
  471.                 for (int i = 1; i <= paramCount; i++) {
  472.                     mdStmt.setString(i, "");
  473.                 }
  474.                 boolean hadResults = mdStmt.execute();
  475.                 if (hadResults) {
  476.                     mdRs = mdStmt.getResultSet();
  477.                     this.pstmtResultMetaData = mdRs.getMetaData();
  478.                 } else {
  479.                     this.pstmtResultMetaData = new ResultSetMetaData(new Field[0]);
  480.                 }
  481.             } finally {
  482.                 SQLException sqlExRethrow = null;
  483.                 if (mdRs != null) {
  484.                     try {
  485.                         mdRs.close();
  486.                     } catch (SQLException sqlEx) {
  487.                         sqlExRethrow = sqlEx;
  488.                     }
  489.                     mdRs = null;
  490.                 }
  491.                 if (mdStmt != null) {
  492.                     try {
  493.                         mdStmt.close();
  494.                     } catch (SQLException sqlEx) {
  495.                         sqlExRethrow = sqlEx;
  496.                     }
  497.                     mdStmt = null;
  498.                 }
  499.                 if (sqlExRethrow != null) {
  500.                     throw sqlExRethrow;
  501.                 }
  502.             }
  503.         }
  504.         return this.pstmtResultMetaData;
  505.     }
  506.     /**
  507.      * Set a parameter to SQL NULL
  508.      * 
  509.      * <p>
  510.      * <B>Note:</B> You must specify the parameters SQL type (although MySQL
  511.      * ignores it)
  512.      * </p>
  513.      *
  514.      * @param parameterIndex the first parameter is 1, etc...
  515.      * @param sqlType the SQL type code defined in java.sql.Types
  516.      *
  517.      * @throws SQLException if a database access error occurs
  518.      */
  519.     public void setNull(int parameterIndex, int sqlType)
  520.         throws SQLException {
  521.         setInternal(parameterIndex, "null");
  522.         isNull[parameterIndex - 1] = true;
  523.     }
  524.     //--------------------------JDBC 2.0-----------------------------
  525.     /**
  526.      * Set a parameter to SQL NULL.
  527.      * 
  528.      * <P>
  529.      * <B>Note:</B> You must specify the parameter's SQL type.
  530.      * </p>
  531.      *
  532.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  533.      * @param sqlType SQL type code defined by java.sql.Types
  534.      * @param arg argument parameters for null
  535.      *
  536.      * @throws SQLException if a database-access error occurs.
  537.      */
  538.     public void setNull(int parameterIndex, int sqlType, String arg)
  539.         throws SQLException {
  540.         setNull(parameterIndex, sqlType);
  541.     }
  542.     /**
  543.      * Set the value of a parameter using an object; use the java.lang
  544.      * equivalent objects for integral values.
  545.      * 
  546.      * <P>
  547.      * The given Java object will be converted to the targetSqlType before
  548.      * being sent to the database.
  549.      * </p>
  550.      * 
  551.      * <P>
  552.      * note that this method may be used to pass database-specific abstract
  553.      * data types.  This is done by using a Driver-specific Java type and
  554.      * using a targetSqlType of java.sql.Types.OTHER
  555.      * </p>
  556.      *
  557.      * @param parameterIndex the first parameter is 1...
  558.      * @param parameterObj the object containing the input parameter value
  559.      * @param targetSqlType The SQL type to be send to the database
  560.      * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
  561.      *        this is the number of digits after the decimal.  For all other
  562.      *        types this value will be ignored.
  563.      *
  564.      * @throws SQLException if a database access error occurs
  565.      * @throws java.sql.SQLException DOCUMENT ME!
  566.      */
  567.     public void setObject(int parameterIndex, Object parameterObj,
  568.         int targetSqlType, int scale) throws SQLException {
  569.         if (parameterObj == null) {
  570.             setNull(parameterIndex, java.sql.Types.OTHER);
  571.         } else {
  572.             try {
  573.                 switch (targetSqlType) {
  574.                 case Types.BIT:
  575.                 case Types.TINYINT:
  576.                 case Types.SMALLINT:
  577.                 case Types.INTEGER:
  578.                 case Types.BIGINT:
  579.                 case Types.REAL:
  580.                 case Types.FLOAT:
  581.                 case Types.DOUBLE:
  582.                 case Types.DECIMAL:
  583.                 case Types.NUMERIC:
  584.                     Number parameterAsNum;
  585.                     if (parameterObj instanceof Boolean) {
  586.                         parameterAsNum = ((Boolean) parameterObj).booleanValue()
  587.                             ? new Integer(1) : new Integer(0);
  588.                     } else if (parameterObj instanceof String) {
  589.                         switch (targetSqlType) {
  590.                         case Types.BIT:
  591.                             parameterAsNum = (Boolean.getBoolean((String) parameterObj)
  592.                                 ? new Integer("1") : new Integer("0"));
  593.                             break;
  594.                         case Types.TINYINT:
  595.                         case Types.SMALLINT:
  596.                         case Types.INTEGER:
  597.                             parameterAsNum = Integer.valueOf((String) parameterObj);
  598.                             break;
  599.                         case Types.BIGINT:
  600.                             parameterAsNum = Long.valueOf((String) parameterObj);
  601.                             break;
  602.                         case Types.REAL:
  603.                             parameterAsNum = Float.valueOf((String) parameterObj);
  604.                             break;
  605.                         case Types.FLOAT:
  606.                         case Types.DOUBLE:
  607.                             parameterAsNum = Double.valueOf((String) parameterObj);
  608.                             break;
  609.                         case Types.DECIMAL:
  610.                         case Types.NUMERIC:default:
  611.                             parameterAsNum = new java.math.BigDecimal((String) parameterObj);
  612.                         }
  613.                     } else {
  614.                         parameterAsNum = (Number) parameterObj;
  615.                     }
  616.                     switch (targetSqlType) {
  617.                     case Types.BIT:
  618.                     case Types.TINYINT:
  619.                     case Types.SMALLINT:
  620.                     case Types.INTEGER:
  621.                         setInt(parameterIndex, parameterAsNum.intValue());
  622.                         break;
  623.                     case Types.BIGINT:
  624.                         setLong(parameterIndex, parameterAsNum.longValue());
  625.                         break;
  626.                     case Types.REAL:
  627.                         setFloat(parameterIndex, parameterAsNum.floatValue());
  628.                         break;
  629.                     case Types.FLOAT:
  630.                     case Types.DOUBLE:
  631.                         setDouble(parameterIndex, parameterAsNum.doubleValue());
  632.                         break;
  633.                     case Types.DECIMAL:
  634.                     case Types.NUMERIC:default:
  635.                         if (parameterAsNum instanceof java.math.BigDecimal) {
  636.                             setBigDecimal(parameterIndex,
  637.                                 (java.math.BigDecimal) parameterAsNum);
  638.                         } else if (parameterAsNum instanceof java.math.BigInteger) {
  639.                             setBigDecimal(parameterIndex,
  640.                                 new java.math.BigDecimal(
  641.                                     (java.math.BigInteger) parameterAsNum, scale));
  642.                         } else {
  643.                             setBigDecimal(parameterIndex,
  644.                                 new java.math.BigDecimal(
  645.                                     parameterAsNum.doubleValue()));
  646.                         }
  647.                         break;
  648.                     }
  649.                     break;
  650.                 case Types.CHAR:
  651.                 case Types.VARCHAR:
  652.                 case Types.LONGVARCHAR:
  653.                     setString(parameterIndex, parameterObj.toString());
  654.                     break;
  655.                 case Types.CLOB:
  656.                     if (parameterObj instanceof java.sql.Clob) {
  657.                         setClob(parameterIndex, (java.sql.Clob) parameterObj);
  658.                     } else {
  659.                         setString(parameterIndex, parameterObj.toString());
  660.                     }
  661.                     break;
  662.                 case Types.BINARY:
  663.                 case Types.VARBINARY:
  664.                 case Types.LONGVARBINARY:
  665.                 case Types.BLOB:
  666.                     if (parameterObj instanceof byte[]) {
  667.                         setBytes(parameterIndex, (byte[]) parameterObj);
  668.                     } else if (parameterObj instanceof java.sql.Blob) {
  669.                         setBlob(parameterIndex, (java.sql.Blob) parameterObj);
  670.                     } else {
  671.                         setBytes(parameterIndex,
  672.                             StringUtils.getBytes(parameterObj.toString(),
  673.                                 this.charConverter, this.charEncoding));
  674.                     }
  675.                     break;
  676.                 case Types.DATE:
  677.                 case Types.TIMESTAMP:
  678.                     java.util.Date parameterAsDate;
  679.                     if (parameterObj instanceof String) {
  680.                         ParsePosition pp = new ParsePosition(0);
  681.                         java.text.DateFormat sdf = new java.text.SimpleDateFormat(getDateTimePattern(
  682.                                     (String) parameterObj, false));
  683.                         parameterAsDate = sdf.parse((String) parameterObj, pp);
  684.                     } else {
  685.                         parameterAsDate = (java.util.Date) parameterObj;
  686.                     }
  687.                     switch (targetSqlType) {
  688.                     case Types.DATE:
  689.                         if (parameterAsDate instanceof java.sql.Date) {
  690.                             setDate(parameterIndex,
  691.                                 (java.sql.Date) parameterAsDate);
  692.                         } else {
  693.                             setDate(parameterIndex,
  694.                                 new java.sql.Date(parameterAsDate.getTime()));
  695.                         }
  696.                         break;
  697.                     case Types.TIMESTAMP:
  698.                         if (parameterAsDate instanceof java.sql.Timestamp) {
  699.                             setTimestamp(parameterIndex,
  700.                                 (java.sql.Timestamp) parameterAsDate);
  701.                         } else {
  702.                             setTimestamp(parameterIndex,
  703.                                 new java.sql.Timestamp(
  704.                                     parameterAsDate.getTime()));
  705.                         }
  706.                         break;
  707.                     }
  708.                     break;
  709.                 case Types.TIME:
  710.                     if (parameterObj instanceof String) {
  711.                         java.text.DateFormat sdf = new java.text.SimpleDateFormat(getDateTimePattern(
  712.                                     (String) parameterObj, true));
  713.                         setTime(parameterIndex,
  714.                             new java.sql.Time(sdf.parse((String) parameterObj)
  715.                                                  .getTime()));
  716.                     } else if (parameterObj instanceof Timestamp) {
  717.                         Timestamp xT = (Timestamp) parameterObj;
  718.                         setTime(parameterIndex, new java.sql.Time(xT.getTime()));
  719.                     } else {
  720.                         setTime(parameterIndex, (java.sql.Time) parameterObj);
  721.                     }
  722.                     break;
  723.                 case Types.OTHER:
  724.                     setSerializableObject(parameterIndex, parameterObj);
  725.                     break;
  726.                 default:
  727.                     throw new java.sql.SQLException("Unknown Types value",
  728.                         SQLError.SQL_STATE_GENERAL_ERROR);
  729.                 }
  730.             } catch (Exception ex) {
  731.                 if (ex instanceof java.sql.SQLException) {
  732.                     throw (java.sql.SQLException) ex;
  733.                 } else {
  734.                     throw new java.sql.SQLException("Cannot convert "
  735.                         + parameterObj.getClass().toString()
  736.                         + " to SQL type requested due to "
  737.                         + ex.getClass().getName() + " - " + ex.getMessage(),
  738.                         SQLError.SQL_STATE_GENERAL_ERROR);
  739.                 }
  740.             }
  741.         }
  742.     }
  743.     /**
  744.      * Set the value of a parameter using an object; use the java.lang
  745.      * equivalent objects for integral values.
  746.      *
  747.      * @param parameterIndex the first parameter is 1...
  748.      * @param parameterObj the object containing the input parameter value
  749.      * @param targetSqlType The SQL type to be send to the database
  750.      *
  751.      * @throws SQLException if an error occurs
  752.      */
  753.     public void setObject(int parameterIndex, Object parameterObj,
  754.         int targetSqlType) throws SQLException {
  755.         setObject(parameterIndex, parameterObj, targetSqlType, 0);
  756.     }
  757.     /**
  758.      * Sets the given parameter to the given object.
  759.      *
  760.      * @param parameterIndex the parameter to set.
  761.      * @param parameterObj the object to use as a value for the parameter.
  762.      *
  763.      * @throws SQLException if an error occurs.
  764.      */
  765.     public void setObject(int parameterIndex, Object parameterObj)
  766.         throws SQLException {
  767.         if (parameterObj == null) {
  768.             setNull(parameterIndex, java.sql.Types.OTHER);
  769.         } else {
  770.             if (parameterObj instanceof Byte) {
  771.                 setInt(parameterIndex, ((Byte) parameterObj).intValue());
  772.             } else if (parameterObj instanceof String) {
  773.                 setString(parameterIndex, (String) parameterObj);
  774.             } else if (parameterObj instanceof BigDecimal) {
  775.                 setBigDecimal(parameterIndex, (BigDecimal) parameterObj);
  776.             } else if (parameterObj instanceof Short) {
  777.                 setShort(parameterIndex, ((Short) parameterObj).shortValue());
  778.             } else if (parameterObj instanceof Integer) {
  779.                 setInt(parameterIndex, ((Integer) parameterObj).intValue());
  780.             } else if (parameterObj instanceof Long) {
  781.                 setLong(parameterIndex, ((Long) parameterObj).longValue());
  782.             } else if (parameterObj instanceof Float) {
  783.                 setFloat(parameterIndex, ((Float) parameterObj).floatValue());
  784.             } else if (parameterObj instanceof Double) {
  785.                 setDouble(parameterIndex, ((Double) parameterObj).doubleValue());
  786.             } else if (parameterObj instanceof byte[]) {
  787.                 setBytes(parameterIndex, (byte[]) parameterObj);
  788.             } else if (parameterObj instanceof java.sql.Date) {
  789.                 setDate(parameterIndex, (java.sql.Date) parameterObj);
  790.             } else if (parameterObj instanceof Time) {
  791.                 setTime(parameterIndex, (Time) parameterObj);
  792.             } else if (parameterObj instanceof Timestamp) {
  793.                 setTimestamp(parameterIndex, (Timestamp) parameterObj);
  794.             } else if (parameterObj instanceof Boolean) {
  795.                 setBoolean(parameterIndex,
  796.                     ((Boolean) parameterObj).booleanValue());
  797.             } else if (parameterObj instanceof InputStream) {
  798.                 setBinaryStream(parameterIndex, (InputStream) parameterObj, -1);
  799.             } else if (parameterObj instanceof java.sql.Blob) {
  800.                 setBlob(parameterIndex, (java.sql.Blob) parameterObj);
  801.             } else if (parameterObj instanceof java.sql.Clob) {
  802.                 setClob(parameterIndex, (java.sql.Clob) parameterObj);
  803.             } else {
  804.                 setSerializableObject(parameterIndex, parameterObj);
  805.             }
  806.         }
  807.     }
  808.     /**
  809.      * @see PreparedStatement#getParameterMetaData()
  810.      */
  811.     public ParameterMetaData getParameterMetaData() throws SQLException {
  812.         throw new NotImplemented();
  813.     }
  814.     /**
  815.      * JDBC 2.0 Set a REF(&lt;structured-type&gt;) parameter.
  816.      *
  817.      * @param i the first parameter is 1, the second is 2, ...
  818.      * @param x an object representing data of an SQL REF Type
  819.      *
  820.      * @throws SQLException if a database error occurs
  821.      * @throws NotImplemented DOCUMENT ME!
  822.      */
  823.     public void setRef(int i, Ref x) throws SQLException {
  824.         throw new NotImplemented();
  825.     }
  826.     /**
  827.      * Set a parameter to a Java short value.  The driver converts this to a
  828.      * SQL SMALLINT value when it sends it to the database.
  829.      *
  830.      * @param parameterIndex the first parameter is 1...
  831.      * @param x the parameter value
  832.      *
  833.      * @throws SQLException if a database access error occurs
  834.      */
  835.     public void setShort(int parameterIndex, short x) throws SQLException {
  836.         setInternal(parameterIndex, String.valueOf(x));
  837.     }
  838.     /**
  839.      * Set a parameter to a Java String value.  The driver converts this to a
  840.      * SQL VARCHAR or LONGVARCHAR value (depending on the arguments size
  841.      * relative to the driver's limits on VARCHARs) when it sends it to the
  842.      * database.
  843.      *
  844.      * @param parameterIndex the first parameter is 1...
  845.      * @param x the parameter value
  846.      *
  847.      * @throws SQLException if a database error occurs.
  848.      */
  849.     public void setString(int parameterIndex, String x)
  850.         throws SQLException {
  851.         // if the passed string is null, then set this column to null
  852.         if (x == null) {
  853.             try {
  854.                 setInternal(parameterIndex,
  855.                     StringUtils.getBytes("null", this.charConverter,
  856.                         this.charEncoding));
  857.             } catch (UnsupportedEncodingException uue) {
  858.                 throw new SQLException("Unsupported character encoding '"
  859.                     + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  860.             }
  861.         } else {
  862.             StringBuffer buf = new StringBuffer((int) (x.length() * 1.1));
  863.             buf.append(''');
  864.             int stringLength = x.length();
  865.             for (int i = 0; i < stringLength; ++i) {
  866.                 char c = x.charAt(i);
  867.                 switch (c) {
  868.                 case 0: /* Must be escaped for 'mysql' */
  869.                     buf.append('\');
  870.                     buf.append('0');
  871.                     break;
  872.                 case 'n': /* Must be escaped for logs */
  873.                     buf.append('\');
  874.                     buf.append('n');
  875.                     break;
  876.                 case 'r':
  877.                     buf.append('\');
  878.                     buf.append('r');
  879.                     break;
  880.                 case '\':
  881.                     buf.append('\');
  882.                     buf.append('\');
  883.                     break;
  884.                 case ''':
  885.                     buf.append('\');
  886.                     buf.append(''');
  887.                     break;
  888.                 case '"': /* Better safe than sorry */
  889.                     buf.append('\');
  890.                     buf.append('"');
  891.                     break;
  892.                 case '32': /* This gives problems on Win32 */
  893.                     buf.append('\');
  894.                     buf.append('Z');
  895.                     break;
  896.                 default:
  897.                     buf.append(c);
  898.                 }
  899.             }
  900.             buf.append(''');
  901.             String parameterAsString = buf.toString();
  902.             try {
  903.                 byte[] parameterAsBytes = null;
  904.                 if (!this.isLoadDataQuery) {
  905.                     parameterAsBytes = StringUtils.getBytes(parameterAsString,
  906.                             this.charConverter, this.charEncoding);
  907.                 } else {
  908.                     // Send with platform character encoding
  909.                     parameterAsBytes = parameterAsString.getBytes();
  910.                 }
  911.                 setInternal(parameterIndex, parameterAsBytes);
  912.             } catch (UnsupportedEncodingException uue) {
  913.                 throw new SQLException("Unsupported character encoding '"
  914.                     + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  915.             }
  916.         }
  917.     }
  918.     /**
  919.      * Set a parameter to a java.sql.Time value.  The driver converts this to a
  920.      * SQL TIME value when it sends it to the database.
  921.      *
  922.      * @param parameterIndex the first parameter is 1...));
  923.      * @param x the parameter value
  924.      *
  925.      * @throws SQLException if a database access error occurs
  926.      */
  927.     public void setTime(int parameterIndex, Time x) throws SQLException {
  928.         setTimeInternal(parameterIndex, x, this.connection.getDefaultTimeZone());
  929.     }
  930.     /**
  931.      * Set a parameter to a java.sql.Time value.  The driver converts this to a
  932.      * SQL TIME value when it sends it to the database.
  933.      *
  934.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  935.      * @param x the parameter value
  936.      * @param cal the cal specifying the timezone
  937.      *
  938.      * @throws SQLException if a database-access error occurs.
  939.      */
  940.     public void setTime(int parameterIndex, java.sql.Time x, Calendar cal)
  941.         throws SQLException {
  942.         setTimeInternal(parameterIndex, x, cal.getTimeZone());
  943.     }
  944.     /**
  945.      * Set a parameter to a java.sql.Timestamp value.  The driver converts this
  946.      * to a SQL TIMESTAMP value when it sends it to the database.
  947.      *
  948.      * @param parameterIndex the first parameter is 1...
  949.      * @param x the parameter value
  950.      *
  951.      * @throws SQLException if a database access error occurs
  952.      */
  953.     public void setTimestamp(int parameterIndex, Timestamp x)
  954.         throws SQLException {
  955.         setTimestampInternal(parameterIndex, x, this.connection.getDefaultTimeZone());
  956.     }
  957.     /**
  958.      * Set a parameter to a java.sql.Timestamp value.  The driver converts this
  959.      * to a SQL TIMESTAMP value when it sends it to the database.
  960.      *
  961.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  962.      * @param x the parameter value
  963.      * @param cal the calendar specifying the timezone to use
  964.      *
  965.      * @throws SQLException if a database-access error occurs.
  966.      */
  967.     public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
  968.         Calendar cal) throws SQLException {
  969.         setTimestampInternal(parameterIndex, x, cal.getTimeZone());
  970.     }
  971.     /**
  972.      * @see PreparedStatement#setURL(int, URL)
  973.      */
  974.     public void setURL(int parameterIndex, URL arg) throws SQLException {
  975.         if (arg != null) {
  976.             setString(parameterIndex, arg.toString());
  977.         } else {
  978.             setNull(parameterIndex, Types.CHAR);
  979.         }
  980.     }
  981.     /**
  982.      * When a very large Unicode value is input to a LONGVARCHAR parameter, it
  983.      * may be more practical to send it via a java.io.InputStream. JDBC will
  984.      * read the data from the stream as needed, until it reaches end-of-file.
  985.      * The JDBC driver will do any necessary conversion from UNICODE to the
  986.      * database char format.
  987.      * 
  988.      * <P>
  989.      * <B>Note:</B> This stream object can either be a standard Java stream
  990.      * object or your own subclass that implements the standard interface.
  991.      * </p>
  992.      *
  993.      * @param parameterIndex the first parameter is 1...
  994.      * @param x the parameter value
  995.      * @param length the number of bytes to read from the stream
  996.      *
  997.      * @throws SQLException if a database access error occurs
  998.      *
  999.      * @deprecated
  1000.      */
  1001.     public void setUnicodeStream(int parameterIndex, InputStream x, int length)
  1002.         throws SQLException {
  1003.         if (x == null) {
  1004.             setNull(parameterIndex, java.sql.Types.VARCHAR);
  1005.         } else {
  1006.             setBinaryStream(parameterIndex, x, length);
  1007.         }
  1008.     }
  1009.     /**
  1010.      * JDBC 2.0 Add a set of parameters to the batch.
  1011.      *
  1012.      * @throws SQLException if a database-access error occurs.
  1013.      *
  1014.      * @see Statement#addBatch
  1015.      */
  1016.     public void addBatch() throws SQLException {
  1017.         if (batchedArgs == null) {
  1018.             batchedArgs = new ArrayList();
  1019.         }
  1020.         batchedArgs.add(new BatchParams(parameterValues, parameterStreams,
  1021.                 isStream, streamLengths, isNull));
  1022.     }
  1023.     /**
  1024.      * In general, parameter values remain in force for repeated used of a
  1025.      * Statement.  Setting a parameter value automatically clears its previous
  1026.      * value.  However, in some cases, it is useful to immediately release the
  1027.      * resources used by the current parameter values; this can be done by
  1028.      * calling clearParameters
  1029.      *
  1030.      * @throws SQLException if a database access error occurs
  1031.      */
  1032.     public void clearParameters() throws SQLException {
  1033.         for (int i = 0; i < parameterValues.length; i++) {
  1034.             parameterValues[i] = null;
  1035.             parameterStreams[i] = null;
  1036.             isStream[i] = false;
  1037.             isNull[i] = false;
  1038.         }
  1039.     }
  1040.     /**
  1041.      * Closes this prepared statement and releases all resources.
  1042.      *
  1043.      * @throws SQLException if database error occurs.
  1044.      */
  1045.     public void close() throws SQLException {
  1046.         super.close();
  1047.         this.parseInfo = null;
  1048.         this.dbmd = null;
  1049.         this.originalSql = null;
  1050.         this.staticSqlStrings = null;
  1051.         this.parameterValues = null;
  1052.         this.parameterStreams = null;
  1053.         this.isStream = null;
  1054.         this.streamLengths = null;
  1055.         this.isNull = null;
  1056.         this.streamConvertBuf = null;
  1057.     }
  1058.     /**
  1059.      * Some prepared statements return multiple results; the execute method
  1060.      * handles these complex statements as well as the simpler form of
  1061.      * statements handled by executeQuery and executeUpdate
  1062.      *
  1063.      * @return true if the next result is a ResultSet; false if it is an update
  1064.      *         count or there are no more results
  1065.      *
  1066.      * @throws SQLException if a database error occurs.
  1067.      */
  1068.     public boolean execute() throws SQLException {
  1069.         if (connection.isReadOnly() && (firstCharOfStmt != 'S')) {
  1070.             throw new SQLException("Connection is read-only. "
  1071.                 + "Queries leading to data modification are not allowed",
  1072.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1073.         }
  1074.         checkClosed();
  1075.         ResultSet rs = null;
  1076.         synchronized (connection.getMutex()) {
  1077.             Buffer sendPacket = fillSendPacket();
  1078.             String oldCatalog = null;
  1079.             if (!this.connection.getCatalog().equals(currentCatalog)) {
  1080.                 oldCatalog = this.connection.getCatalog();
  1081.                 this.connection.setCatalog(currentCatalog);
  1082.             }
  1083.             boolean oldInfoMsgState = false;
  1084.             if (this.retrieveGeneratedKeys) {
  1085.                 oldInfoMsgState = this.connection.isReadInfoMsgEnabled();
  1086.                 this.connection.setReadInfoMsgEnabled(true);
  1087.             }
  1088.             // If there isn't a limit clause in the SQL
  1089.             // then limit the number of rows to return in
  1090.             // an efficient manner. Only do this if
  1091.             // setMaxRows() hasn't been used on any Statements
  1092.             // generated from the current Connection (saves
  1093.             // a query, and network traffic).
  1094.             //
  1095.             // Only apply max_rows to selects
  1096.             //
  1097.             if (this.connection.useMaxRows()) {
  1098.                 if (firstCharOfStmt == 'S') {
  1099.                     if (hasLimitClause) {
  1100.                         rs = this.connection.execSQL((String) null, maxRows,
  1101.                                 sendPacket, resultSetConcurrency,
  1102.                                 createStreamingResultSet(), true,
  1103.                                 this.currentCatalog);
  1104.                     } else {
  1105.                         if (maxRows <= 0) {
  1106.                             this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
  1107.                                 -1, this.currentCatalog);
  1108.                         } else {
  1109.                             this.connection.execSQL(
  1110.                                 "SET OPTION SQL_SELECT_LIMIT=" + maxRows, -1,
  1111.                                 this.currentCatalog);
  1112.                         }
  1113.                     }
  1114.                 } else {
  1115.                     this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
  1116.                         -1, this.currentCatalog);
  1117.                 }
  1118.                 // Finally, execute the query
  1119.                 rs = this.connection.execSQL(null, -1, sendPacket,
  1120.                         resultSetConcurrency, createStreamingResultSet(),
  1121.                         (firstCharOfStmt == 'S'), this.currentCatalog);
  1122.             } else {
  1123.                 rs = this.connection.execSQL(null, -1, sendPacket,
  1124.                         resultSetConcurrency, createStreamingResultSet(),
  1125.                         (firstCharOfStmt == 'S'), this.currentCatalog);
  1126.             }
  1127.             if (this.retrieveGeneratedKeys) {
  1128.                 this.connection.setReadInfoMsgEnabled(oldInfoMsgState);
  1129.             }
  1130.             if (oldCatalog != null) {
  1131.                 this.connection.setCatalog(oldCatalog);
  1132.             }
  1133.         }
  1134.         lastInsertId = rs.getUpdateID();
  1135.         if (rs != null) {
  1136.             this.results = rs;
  1137.         }
  1138.         rs.setFirstCharOfQuery(this.firstCharOfStmt);
  1139.         rs.setConnection(connection);
  1140.         rs.setResultSetType(resultSetType);
  1141.         rs.setResultSetConcurrency(resultSetConcurrency);
  1142.         rs.setStatement(this);
  1143.         return ((rs != null) && rs.reallyResult());
  1144.     }
  1145.     /**
  1146.      * JDBC 2.0 Submit a batch of commands to the database for execution. This
  1147.      * method is optional.
  1148.      *
  1149.      * @return an array of update counts containing one element for each
  1150.      *         command in the batch.  The array is ordered according to the
  1151.      *         order in which commands were inserted into the batch
  1152.      *
  1153.      * @throws SQLException if a database-access error occurs, or the driver
  1154.      *         does not support batch statements
  1155.      * @throws java.sql.BatchUpdateException DOCUMENT ME!
  1156.      */
  1157.     public int[] executeBatch() throws SQLException {
  1158.         if (connection.isReadOnly()) {
  1159.             throw new SQLException("Connection is read-only. "
  1160.                 + "Queries leading to data modification are not allowed",
  1161.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1162.         }
  1163.         try {
  1164.             int[] updateCounts = null;
  1165.             if (batchedArgs != null) {
  1166.                 int nbrCommands = batchedArgs.size();
  1167.                 updateCounts = new int[nbrCommands];
  1168.                 for (int i = 0; i < nbrCommands; i++) {
  1169.                     updateCounts[i] = -3;
  1170.                 }
  1171.                 SQLException sqlEx = null;
  1172.                 int commandIndex = 0;
  1173.                 for (commandIndex = 0; commandIndex < nbrCommands;
  1174.                         commandIndex++) {
  1175.                     Object arg = batchedArgs.get(commandIndex);
  1176.                     if (arg instanceof String) {
  1177.                         updateCounts[commandIndex] = executeUpdate((String) arg);
  1178.                     } else {
  1179.                         BatchParams paramArg = (BatchParams) arg;
  1180.                         try {
  1181.                             updateCounts[commandIndex] = executeUpdate(paramArg.parameterStrings,
  1182.                                     paramArg.parameterStreams,
  1183.                                     paramArg.isStream, paramArg.streamLengths,
  1184.                                     paramArg.isNull);
  1185.                         } catch (SQLException ex) {
  1186.                             updateCounts[commandIndex] = EXECUTE_FAILED;
  1187.                             if (this.connection.continueBatchOnError()) {
  1188.                                 sqlEx = ex;
  1189.                             } else {
  1190.                                 int[] newUpdateCounts = new int[commandIndex];
  1191.                                 System.arraycopy(updateCounts, 0,
  1192.                                     newUpdateCounts, 0, commandIndex);
  1193.                                 throw new java.sql.BatchUpdateException(ex
  1194.                                     .getMessage(), ex.getSQLState(),
  1195.                                     ex.getErrorCode(), newUpdateCounts);
  1196.                             }
  1197.                         }
  1198.                     }
  1199.                 }
  1200.                 if (sqlEx != null) {
  1201.                     throw new java.sql.BatchUpdateException(sqlEx.getMessage(),
  1202.                         sqlEx.getSQLState(), sqlEx.getErrorCode(), updateCounts);
  1203.                 }
  1204.             }
  1205.             return (updateCounts != null) ? updateCounts : new int[0];
  1206.         } finally {
  1207.             clearBatch();
  1208.         }
  1209.     }
  1210.     /**
  1211.      * A Prepared SQL query is executed and its ResultSet is returned
  1212.      *
  1213.      * @return a ResultSet that contains the data produced by the query - never
  1214.      *         null
  1215.      *
  1216.      * @throws SQLException if a database error occurs.
  1217.      */
  1218.     public synchronized java.sql.ResultSet executeQuery()
  1219.         throws SQLException {
  1220.         checkClosed();
  1221.         if ((this.firstCharOfStmt == 'I') || (this.firstCharOfStmt == 'U')
  1222.                 || (this.firstCharOfStmt == 'D')
  1223.                 || (this.firstCharOfStmt == 'A')
  1224.                 || (this.firstCharOfStmt == 'C')) {
  1225.             if (StringUtils.startsWithIgnoreCaseAndWs(this.originalSql, "INSERT")
  1226.                     || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1227.                         "UPDATE")
  1228.                     || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1229.                         "DELETE")
  1230.                     || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1231.                         "DROP")
  1232.                     || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1233.                         "CREATE")
  1234.                     || StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1235.                         "ALTER")) {
  1236.                 throw new SQLException("Can not issue data manipulation statements with executeQuery()",
  1237.                     SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1238.             }
  1239.         }
  1240.         // We need to execute this all together
  1241.         // So synchronize on the Connection's mutex (because
  1242.         // even queries going through there synchronize
  1243.         // on the same mutex.
  1244.         synchronized (connection.getMutex()) {
  1245.             Buffer sendPacket = fillSendPacket();
  1246.             if (this.results != null) {
  1247.                 this.results.close();
  1248.             }
  1249.             String oldCatalog = null;
  1250.             if (!this.connection.getCatalog().equals(currentCatalog)) {
  1251.                 oldCatalog = this.connection.getCatalog();
  1252.                 this.connection.setCatalog(currentCatalog);
  1253.             }
  1254.             if (this.connection.useMaxRows()) {
  1255.                 // If there isn't a limit clause in the SQL
  1256.                 // then limit the number of rows to return in
  1257.                 // an efficient manner. Only do this if
  1258.                 // setMaxRows() hasn't been used on any Statements
  1259.                 // generated from the current Connection (saves
  1260.                 // a query, and network traffic).
  1261.                 if (hasLimitClause) {
  1262.                     results = this.connection.execSQL((String) null, maxRows,
  1263.                             sendPacket, resultSetConcurrency,
  1264.                             createStreamingResultSet(), true,
  1265.                             this.currentCatalog);
  1266.                 } else {
  1267.                     if (maxRows <= 0) {
  1268.                         this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
  1269.                             -1, this.currentCatalog);
  1270.                     } else {
  1271.                         this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT="
  1272.                             + maxRows, -1, this.currentCatalog);
  1273.                     }
  1274.                     this.results = this.connection.execSQL(null, -1,
  1275.                             sendPacket, resultSetConcurrency,
  1276.                             createStreamingResultSet(), true,
  1277.                             this.currentCatalog);
  1278.                     if (oldCatalog != null) {
  1279.                         this.connection.setCatalog(oldCatalog);
  1280.                     }
  1281.                 }
  1282.             } else {
  1283.                 this.results = this.connection.execSQL(null, -1, sendPacket,
  1284.                         resultSetConcurrency, createStreamingResultSet(), true,
  1285.                         this.currentCatalog);
  1286.             }
  1287.             if (oldCatalog != null) {
  1288.                 this.connection.setCatalog(oldCatalog);
  1289.             }
  1290.         }
  1291.         lastInsertId = this.results.getUpdateID();
  1292.         nextResults = this.results;
  1293.         this.results.setConnection(connection);
  1294.         this.results.setResultSetType(resultSetType);
  1295.         this.results.setResultSetConcurrency(resultSetConcurrency);
  1296.         this.results.setStatement(this);
  1297.         return (java.sql.ResultSet) this.results;
  1298.     }
  1299.     /**
  1300.      * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition, SQL
  1301.      * statements that return nothing such as SQL DDL statements can be
  1302.      * executed.
  1303.      *
  1304.      * @return either the row count for INSERT, UPDATE or DELETE; or 0 for SQL
  1305.      *         statements that return nothing.
  1306.      *
  1307.      * @throws SQLException if a database access error occurs
  1308.      */
  1309.     public synchronized int executeUpdate() throws SQLException {
  1310.         return executeUpdate(parameterValues, parameterStreams, isStream,
  1311.             streamLengths, isNull);
  1312.     }
  1313.     /**
  1314.      * Returns this PreparedStatement represented as a string.
  1315.      *
  1316.      * @return this PreparedStatement represented as a string.
  1317.      *
  1318.      * @throws RuntimeException if an error occurs
  1319.      */
  1320.     public String toString() {
  1321.         StringBuffer buf = new StringBuffer();
  1322.         buf.append(super.toString());
  1323.         buf.append(": ");
  1324.         try {
  1325.             for (int i = 0; i < parameterValues.length; ++i) {
  1326.                 if (this.charEncoding != null) {
  1327.                     buf.append(new String(staticSqlStrings[i], this.charEncoding));
  1328.                 } else {
  1329.                     buf.append(new String(staticSqlStrings[i]));
  1330.                 }
  1331.                 if ((parameterValues[i] == null) && !isStream[i]) {
  1332.                     buf.append("** NOT SPECIFIED **");
  1333.                 } else if (isStream[i]) {
  1334.                     buf.append("** STREAM DATA **");
  1335.                 } else {
  1336.                     if (this.charConverter != null) {
  1337.                         buf.append(this.charConverter.toString(
  1338.                                 parameterValues[i]));
  1339.                     } else {
  1340.                         if (this.charEncoding != null) {
  1341.                             buf.append(new String(parameterValues[i],
  1342.                                     this.charEncoding));
  1343.                         } else {
  1344.                             buf.append(StringUtils.toAsciiString(
  1345.                                     parameterValues[i]));
  1346.                         }
  1347.                     }
  1348.                 }
  1349.             }
  1350.             if (this.charEncoding != null) {
  1351.                 buf.append(new String(
  1352.                         staticSqlStrings[parameterValues.length],
  1353.                         this.charEncoding));
  1354.             } else {
  1355.                 buf.append(staticSqlStrings[parameterValues.length]);
  1356.             }
  1357.         } catch (UnsupportedEncodingException uue) {
  1358.             throw new RuntimeException("Unsupported character encoding '"
  1359.                 + this.charEncoding + "'");
  1360.         }
  1361.         return buf.toString();
  1362.     }
  1363.     /**
  1364.      * Used by updatable result sets for refreshRow() because the parameter has
  1365.      * already been escaped for updater or inserter prepared statements.
  1366.      *
  1367.      * @param parameterIndex the parameter to set.
  1368.      * @param parameterAsBytes the parameter as a string.
  1369.      *
  1370.      * @throws SQLException if an error occurs
  1371.      */
  1372.     protected void setBytesNoEscape(int parameterIndex, byte[] parameterAsBytes)
  1373.         throws SQLException {
  1374.         byte[] parameterWithQuotes = new byte[parameterAsBytes.length + 2];
  1375.         parameterWithQuotes[0] = ''';
  1376.         System.arraycopy(parameterAsBytes, 0, parameterWithQuotes, 1,
  1377.             parameterAsBytes.length);
  1378.         parameterWithQuotes[parameterAsBytes.length + 1] = ''';
  1379.         setInternal(parameterIndex, parameterWithQuotes);
  1380.     }
  1381.     /**
  1382.      * Sets wheather or not this statement should retreive generated keys.
  1383.      *
  1384.      * @param retrieveGeneratedKeys
  1385.      */
  1386.     protected void setRetrieveGeneratedKeys(boolean retrieveGeneratedKeys) {
  1387.         this.retrieveGeneratedKeys = retrieveGeneratedKeys;
  1388.     }
  1389.     /**
  1390.      * Added to allow batch-updates
  1391.      *
  1392.      * @param batchedParameterStrings string values used in single statement
  1393.      * @param batchedParameterStreams stream values used in single statement
  1394.      * @param batchedIsStream flags for streams used in single statement
  1395.      * @param batchedStreamLengths lengths of streams to be read.
  1396.      * @param batchedIsNull flags for parameters that are null
  1397.      *
  1398.      * @return the update count
  1399.      *
  1400.      * @throws SQLException if a database error occurs
  1401.      * @throws java.sql.SQLException DOCUMENT ME!
  1402.      */
  1403.     protected synchronized int executeUpdate(byte[][] batchedParameterStrings,
  1404.         InputStream[] batchedParameterStreams, boolean[] batchedIsStream,
  1405.         int[] batchedStreamLengths, boolean[] batchedIsNull)
  1406.         throws SQLException {
  1407.         if (connection.isReadOnly()) {
  1408.             throw new SQLException("Connection is read-only. "
  1409.                 + "Queries leading to data modification are not allowed",
  1410.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1411.         }
  1412.         checkClosed();
  1413.         if ((this.firstCharOfStmt == 'S')
  1414.                 && StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
  1415.                     "SELECT")) {
  1416.             throw new java.sql.SQLException("Can not issue executeUpdate() for SELECTs",
  1417.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1418.         }
  1419.         ResultSet rs = null;
  1420.         // The checking and changing of catalogs
  1421.         // must happen in sequence, so synchronize
  1422.         // on the same mutex that _conn is using
  1423.         synchronized (connection.getMutex()) {
  1424.             Buffer sendPacket = fillSendPacket(batchedParameterStrings,
  1425.                     batchedParameterStreams, batchedIsStream,
  1426.                     batchedStreamLengths);
  1427.             String oldCatalog = null;
  1428.             if (!this.connection.getCatalog().equals(currentCatalog)) {
  1429.                 oldCatalog = this.connection.getCatalog();
  1430.                 this.connection.setCatalog(currentCatalog);
  1431.             }
  1432.             //
  1433.             // Only apply max_rows to selects
  1434.             //
  1435.             if (this.connection.useMaxRows()) {
  1436.                 this.connection.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT",
  1437.                     -1, this.currentCatalog);
  1438.             }
  1439.             boolean oldInfoMsgState = false;
  1440.             if (this.retrieveGeneratedKeys) {
  1441.                 oldInfoMsgState = this.connection.isReadInfoMsgEnabled();
  1442.                 this.connection.setReadInfoMsgEnabled(true);
  1443.             }
  1444.             rs = this.connection.execSQL(null, -1, sendPacket,
  1445.                     resultSetConcurrency, false, false, this.currentCatalog);
  1446.             if (this.retrieveGeneratedKeys) {
  1447.                 this.connection.setReadInfoMsgEnabled(oldInfoMsgState);
  1448.             }
  1449.             if (oldCatalog != null) {
  1450.                 this.connection.setCatalog(oldCatalog);
  1451.             }
  1452.         }
  1453.         this.results = rs;
  1454.         rs.setFirstCharOfQuery(this.firstCharOfStmt);
  1455.         updateCount = rs.getUpdateCount();
  1456.         int truncatedUpdateCount = 0;
  1457.         if (updateCount > Integer.MAX_VALUE) {
  1458.             truncatedUpdateCount = Integer.MAX_VALUE;
  1459.         } else {
  1460.             truncatedUpdateCount = (int) updateCount;
  1461.         }
  1462.         lastInsertId = rs.getUpdateID();
  1463.         this.results = rs;
  1464.         return truncatedUpdateCount;
  1465.     }
  1466.     byte[] getBytes(int parameterIndex) throws SQLException {
  1467.         if (isStream[parameterIndex]) {
  1468.             return streamToBytes(parameterStreams[parameterIndex], false,
  1469.                 streamLengths[parameterIndex],
  1470.                 this.connection.useStreamLengthsInPrepStmts());
  1471.         } else {
  1472.             byte[] parameterVal = parameterValues[parameterIndex];
  1473.             if (parameterVal == null) {
  1474.                 return null;
  1475.             }
  1476.             if ((parameterVal[0] == ''')
  1477.                     && (parameterVal[parameterVal.length - 1] == ''')) {
  1478.                 byte[] valNoQuotes = new byte[parameterVal.length - 2];
  1479.                 System.arraycopy(parameterVal, 1, valNoQuotes, 0,
  1480.                     parameterVal.length - 2);
  1481.                 return valNoQuotes;
  1482.             } else {
  1483.                 return parameterVal;
  1484.             }
  1485.         }
  1486.     }
  1487.     boolean isNull(int paramIndex) {
  1488.         return isNull[paramIndex];
  1489.     }
  1490.     ParseInfo getParseInfo() {
  1491.         return this.parseInfo;
  1492.     }
  1493.     /**
  1494.      * Sets the concurrency for result sets generated by this statement
  1495.      *
  1496.      * @param concurrencyFlag the result set concurrency flag from the
  1497.      *        ResultSet interface.
  1498.      */
  1499.     void setResultSetConcurrency(int concurrencyFlag) {
  1500.         resultSetConcurrency = concurrencyFlag;
  1501.     }
  1502.     /**
  1503.      * Sets the result set type for result sets generated by this statement
  1504.      *
  1505.      * @param typeFlag the result set type from the ResultSet interface
  1506.      */
  1507.     void setResultSetType(int typeFlag) {
  1508.         resultSetType = typeFlag;
  1509.     }
  1510.     private final String getDateTimePattern(String dt, boolean toTime)
  1511.         throws Exception {
  1512.         //
  1513.         // Special case
  1514.         //
  1515.         int dtLength = (dt != null) ? dt.length() : 0;
  1516.         if ((dtLength >= 8) && (dtLength <= 10)) {
  1517.             int dashCount = 0;
  1518.             boolean isDateOnly = true;
  1519.             for (int i = 0; i < dtLength; i++) {
  1520.                 char c = dt.charAt(i);
  1521.                 if (!Character.isDigit(c) && (c != '-')) {
  1522.                     isDateOnly = false;
  1523.                     break;
  1524.                 }
  1525.                 if (c == '-') {
  1526.                     dashCount++;
  1527.                 }
  1528.             }
  1529.             if (isDateOnly && (dashCount == 2)) {
  1530.                 return "yyyy-MM-dd";
  1531.             }
  1532.         }
  1533.         //
  1534.         // Special case - time-only
  1535.         //
  1536.         boolean colonsOnly = true;
  1537.         for (int i = 0; i < dtLength; i++) {
  1538.             char c = dt.charAt(i);
  1539.             if (!Character.isDigit(c) && (c != ':')) {
  1540.                 colonsOnly = false;
  1541.                 break;
  1542.             }
  1543.         }
  1544.         if (colonsOnly) {
  1545.             return "HH:mm:ss";
  1546.         }
  1547.         int n;
  1548.         int z;
  1549.         int count;
  1550.         int maxvecs;
  1551.         char c;
  1552.         char separator;
  1553.         StringReader reader = new StringReader(dt + " ");
  1554.         ArrayList vec = new ArrayList();
  1555.         ArrayList vecRemovelist = new ArrayList();
  1556.         Object[] nv = new Object[3];
  1557.         Object[] v;
  1558.         nv[0] = new Character('y');
  1559.         nv[1] = new StringBuffer();
  1560.         nv[2] = new Integer(0);
  1561.         vec.add(nv);
  1562.         if (toTime) {
  1563.             nv = new Object[3];
  1564.             nv[0] = new Character('h');
  1565.             nv[1] = new StringBuffer();
  1566.             nv[2] = new Integer(0);
  1567.             vec.add(nv);
  1568.         }
  1569.         while ((z = reader.read()) != -1) {
  1570.             separator = (char) z;
  1571.             maxvecs = vec.size();
  1572.             for (count = 0; count < maxvecs; count++) {
  1573.                 v = (Object[]) vec.get(count);
  1574.                 n = ((Integer) v[2]).intValue();
  1575.                 c = getSuccessor(((Character) v[0]).charValue(), n);
  1576.                 if (!Character.isLetterOrDigit(separator)) {
  1577.                     if ((c == ((Character) v[0]).charValue()) && (c != 'S')) {
  1578.                         vecRemovelist.add(v);
  1579.                     } else {
  1580.                         ((StringBuffer) v[1]).append(separator);
  1581.                         if ((c == 'X') || (c == 'Y')) {
  1582.                             v[2] = new Integer(4);
  1583.                         }
  1584.                     }
  1585.                 } else {
  1586.                     if (c == 'X') {
  1587.                         c = 'y';
  1588.                         nv = new Object[3];
  1589.                         nv[1] = (new StringBuffer(((StringBuffer) v[1])
  1590.                                 .toString())).append('M');
  1591.                         nv[0] = new Character('M');
  1592.                         nv[2] = new Integer(1);
  1593.                         vec.add(nv);
  1594.                     } else if (c == 'Y') {
  1595.                         c = 'M';
  1596.                         nv = new Object[3];
  1597.                         nv[1] = (new StringBuffer(((StringBuffer) v[1])
  1598.                                 .toString())).append('d');
  1599.                         nv[0] = new Character('d');
  1600.                         nv[2] = new Integer(1);
  1601.                         vec.add(nv);
  1602.                     }
  1603.                     ((StringBuffer) v[1]).append(c);
  1604.                     if (c == ((Character) v[0]).charValue()) {
  1605.                         v[2] = new Integer(n + 1);
  1606.                     } else {
  1607.                         v[0] = new Character(c);
  1608.                         v[2] = new Integer(1);
  1609.                     }
  1610.                 }
  1611.             }
  1612.             int size = vecRemovelist.size();
  1613.             for (int i = 0; i < size; i++) {
  1614.                 v = (Object[]) vecRemovelist.get(i);
  1615.                 vec.remove(v);
  1616.             }
  1617.             vecRemovelist.clear();
  1618.         }
  1619.         int size = vec.size();
  1620.         for (int i = 0; i < size; i++) {
  1621.             v = (Object[]) vec.get(i);
  1622.             c = ((Character) v[0]).charValue();
  1623.             n = ((Integer) v[2]).intValue();
  1624.             boolean bk = getSuccessor(c, n) != c;
  1625.             boolean atEnd = (((c == 's') || (c == 'm')
  1626.                 || ((c == 'h') && toTime)) && bk);
  1627.             boolean finishesAtDate = (bk && (c == 'd') && !toTime);
  1628.             boolean containsEnd = (((StringBuffer) v[1]).toString().indexOf('W') != -1);
  1629.             if ((!atEnd && !finishesAtDate) || (containsEnd)) {
  1630.                 vecRemovelist.add(v);
  1631.             }
  1632.         }
  1633.         size = vecRemovelist.size();
  1634.         for (int i = 0; i < size; i++) {
  1635.             vec.remove(vecRemovelist.get(i));
  1636.         }
  1637.         vecRemovelist.clear();
  1638.         v = (Object[]) vec.get(0); //might throw exception
  1639.         StringBuffer format = (StringBuffer) v[1];
  1640.         format.setLength(format.length() - 1);
  1641.         return format.toString();
  1642.     }
  1643.     private final void setInternal(int paramIndex, byte[] val)
  1644.         throws SQLException {
  1645.         if (this.isClosed) {
  1646.             throw new SQLException("PreparedStatement has been closed. No further operations allowed.",
  1647.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1648.         }
  1649.         if ((paramIndex < 1)) {
  1650.             throw new SQLException("Parameter index out of range ("
  1651.                 + paramIndex + " < 1 ).", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1652.         } else if (paramIndex >= staticSqlStrings.length) {
  1653.             throw new SQLException("Parameter index out of range ("
  1654.                 + paramIndex + " > " + (staticSqlStrings.length - 1) + ").",
  1655.                 SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1656.         }
  1657.         isStream[paramIndex - 1] = false;
  1658.         isNull[paramIndex - 1] = false;
  1659.         parameterStreams[paramIndex - 1] = null;
  1660.         parameterValues[paramIndex - 1] = val;
  1661.     }
  1662.     private final void setInternal(int paramIndex, String val)
  1663.         throws SQLException {
  1664.         byte[] parameterAsBytes = null;
  1665.         if (this.charConverter != null) {
  1666.             parameterAsBytes = this.charConverter.toBytes(val);
  1667.         } else {
  1668.             try {
  1669.                 parameterAsBytes = StringUtils.getBytes(val,
  1670.                         this.charConverter, this.charEncoding);
  1671.             } catch (UnsupportedEncodingException uEE) {
  1672.                 throw new SQLException("Unsupported encoding '"
  1673.                     + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1674.             }
  1675.         }
  1676.         setInternal(paramIndex, parameterAsBytes);
  1677.     }
  1678.     /**
  1679.      * Sets the value for the placeholder as a serialized Java object (used by
  1680.      * various forms of setObject()
  1681.      *
  1682.      * @param parameterIndex DOCUMENT ME!
  1683.      * @param parameterObj DOCUMENT ME!
  1684.      *
  1685.      * @throws SQLException if a database error occurs.
  1686.      * @throws java.sql.SQLException DOCUMENT ME!
  1687.      */
  1688.     private final void setSerializableObject(int parameterIndex,
  1689.         Object parameterObj) throws SQLException {
  1690.         try {
  1691.             ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
  1692.             ObjectOutputStream objectOut = new ObjectOutputStream(bytesOut);
  1693.             objectOut.writeObject(parameterObj);
  1694.             objectOut.flush();
  1695.             objectOut.close();
  1696.             bytesOut.flush();
  1697.             bytesOut.close();
  1698.             byte[] buf = bytesOut.toByteArray();
  1699.             ByteArrayInputStream bytesIn = new ByteArrayInputStream(buf);
  1700.             setBinaryStream(parameterIndex, bytesIn, buf.length);
  1701.         } catch (Exception ex) {
  1702.             throw new java.sql.SQLException("Invalid argument value: "
  1703.                 + ex.getClass().getName(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  1704.         }
  1705.     }
  1706.     private final char getSuccessor(char c, int n) {
  1707.         return ((c == 'y') && (n == 2)) ? 'X'
  1708.                                         : (((c == 'y') && (n < 4)) ? 'y'
  1709.                                                                    : ((c == 'y')
  1710.         ? 'M'
  1711.         : (((c == 'M') && (n == 2)) ? 'Y'
  1712.                                     : (((c == 'M') && (n < 3)) ? 'M'
  1713.                                                                : ((c == 'M')
  1714.         ? 'd'
  1715.         : (((c == 'd') && (n < 2)) ? 'd'
  1716.                                    : ((c == 'd') ? 'H'
  1717.                                                  : (((c == 'H') && (n < 2))
  1718.         ? 'H'
  1719.         : ((c == 'H') ? 'm'
  1720.                       : (((c == 'm') && (n < 2)) ? 'm'
  1721.                                                  : ((c == 'm') ? 's'
  1722.                                                                : (((c == 's')
  1723.         && (n < 2)) ? 's' : 'W'))))))))))));
  1724.     }
  1725.     /**
  1726.      * Set a parameter to a java.sql.Time value.  The driver converts this to a
  1727.      * SQL TIME value when it sends it to the database, using the given
  1728.      * timezone.
  1729.      *
  1730.      * @param parameterIndex the first parameter is 1...));
  1731.      * @param x the parameter value
  1732.      * @param tz the timezone to use
  1733.      *
  1734.      * @throws SQLException if a database access error occurs
  1735.      */
  1736.     private void setTimeInternal(int parameterIndex, Time x, TimeZone tz)
  1737.         throws SQLException {
  1738.         if (x == null) {
  1739.             setNull(parameterIndex, java.sql.Types.TIME);
  1740.         } else {
  1741.             x = TimeUtil.changeTimezone(this.connection, x, tz,
  1742.                     this.connection.getServerTimezone());
  1743.             setInternal(parameterIndex, "'" + x.toString() + "'");
  1744.         }
  1745.     }
  1746.     /**
  1747.      * Set a parameter to a java.sql.Timestamp value.  The driver converts this
  1748.      * to a SQL TIMESTAMP value when it sends it to the database.
  1749.      *
  1750.      * @param parameterIndex the first parameter is 1, the second is 2, ...
  1751.      * @param x the parameter value
  1752.      * @param tz the timezone to use
  1753.      *
  1754.      * @throws SQLException if a database-access error occurs.
  1755.      */
  1756.     private synchronized void setTimestampInternal(int parameterIndex,
  1757.         Timestamp x, TimeZone tz) throws SQLException {
  1758.         if (x == null) {
  1759.             setNull(parameterIndex, java.sql.Types.TIMESTAMP);
  1760.         } else {
  1761.             String timestampString = null;
  1762.             x = TimeUtil.changeTimezone(this.connection, x, tz,
  1763.                     this.connection.getServerTimezone());
  1764.             if (this.tsdf == null) {
  1765.                 this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''");
  1766.             }
  1767.             timestampString = this.tsdf.format(x);
  1768.             setInternal(parameterIndex, timestampString); // SimpleDateFormat is not thread-safe
  1769.         }
  1770.     }
  1771.     private final void escapeblockFast(byte[] buf,
  1772.         ByteArrayOutputStream bytesOut, int size) {
  1773.         int lastwritten = 0;
  1774.         for (int i = 0; i < size; i++) {
  1775.             byte b = buf[i];
  1776.             if (b == '') {
  1777.                 //write stuff not yet written
  1778.                 if (i > lastwritten) {
  1779.                     bytesOut.write(buf, lastwritten, i - lastwritten);
  1780.                 }
  1781.                 //write escape
  1782.                 bytesOut.write('\');
  1783.                 bytesOut.write('0');
  1784.                 lastwritten = i + 1;
  1785.             } else {
  1786.                 if ((b == '\') || (b == ''') || (b == '"')) {
  1787.                     //write stuff not yet written
  1788.                     if (i > lastwritten) {
  1789.                         bytesOut.write(buf, lastwritten, i - lastwritten);
  1790.                     }
  1791.                     //write escape
  1792.                     bytesOut.write('\');
  1793.                     lastwritten = i; //not i+1 as b wasn't written.
  1794.                 }
  1795.             }
  1796.         }
  1797.         //write out remaining stuff from buffer
  1798.         if (lastwritten < size) {
  1799.             bytesOut.write(buf, lastwritten, size - lastwritten);
  1800.         }
  1801.     }
  1802.     private final void escapeblockFast(byte[] buf, Buffer packet, int size)
  1803.         throws SQLException {
  1804.         int lastwritten = 0;
  1805.         for (int i = 0; i < size; i++) {
  1806.             byte b = buf[i];
  1807.             if (b == '') {
  1808.                 //write stuff not yet written
  1809.                 if (i > lastwritten) {
  1810.                     packet.writeBytesNoNull(buf, lastwritten, i - lastwritten);
  1811.                 }
  1812.                 //write escape
  1813.                 packet.writeByte((byte) '\');
  1814.                 packet.writeByte((byte) '0');
  1815.                 lastwritten = i + 1;
  1816.             } else {
  1817.                 if ((b == '\') || (b == ''') || (b == '"')) {
  1818.                     //write stuff not yet written
  1819.                     if (i > lastwritten) {
  1820.                         packet.writeBytesNoNull(buf, lastwritten,
  1821.                             i - lastwritten);
  1822.                     }
  1823.                     //write escape
  1824.                     packet.writeByte((byte) '\');
  1825.                     lastwritten = i; //not i+1 as b wasn't written.
  1826.                 }
  1827.             }
  1828.         }
  1829.         //write out remaining stuff from buffer
  1830.         if (lastwritten < size) {
  1831.             packet.writeBytesNoNull(buf, lastwritten, size - lastwritten);
  1832.         }
  1833.     }
  1834.     /**
  1835.      * Creates the packet that contains the query to be sent to the server.
  1836.      *
  1837.      * @return the packet to send to the server to issue the query.
  1838.      *
  1839.      * @throws SQLException if a database error occurs.
  1840.      */
  1841.     private Buffer fillSendPacket() throws SQLException {
  1842.         return fillSendPacket(this.parameterValues, this.parameterStreams,
  1843.             this.isStream, this.streamLengths);
  1844.     }
  1845.     /**
  1846.      * Creates the packet that contains the query to be sent to the server.
  1847.      *
  1848.      * @param batchedParameterStrings DOCUMENT ME!
  1849.      * @param batchedParameterStreams DOCUMENT ME!
  1850.      * @param batchedIsStream DOCUMENT ME!
  1851.      * @param batchedStreamLengths DOCUMENT ME!
  1852.      *
  1853.      * @return DOCUMENT ME!
  1854.      *
  1855.      * @throws SQLException if a database error occurs.
  1856.      * @throws java.sql.SQLException DOCUMENT ME!
  1857.      */
  1858.     private Buffer fillSendPacket(byte[][] batchedParameterStrings,
  1859.         InputStream[] batchedParameterStreams, boolean[] batchedIsStream,
  1860.         int[] batchedStreamLengths) throws SQLException {
  1861.         Buffer sendPacket = this.connection.getIO().getSharedSendPacket();
  1862.         sendPacket.clear();
  1863.         sendPacket.writeByte((byte) MysqlDefs.QUERY);
  1864.         boolean useStreamLengths = this.connection.useStreamLengthsInPrepStmts();
  1865.         //
  1866.         // Try and get this allocation as close as possible
  1867.         // for BLOBs
  1868.         //
  1869.         int ensurePacketSize = 0;
  1870.         for (int i = 0; i < batchedParameterStrings.length; i++) {
  1871.             if (batchedIsStream[i] && useStreamLengths) {
  1872.                 ensurePacketSize += batchedStreamLengths[i];
  1873.             }
  1874.         }
  1875.         if (ensurePacketSize != 0) {
  1876.             sendPacket.ensureCapacity(ensurePacketSize);
  1877.         }
  1878.         for (int i = 0; i < batchedParameterStrings.length; i++) {
  1879.             if ((batchedParameterStrings[i] == null)
  1880.                     && (batchedParameterStreams[i] == null)) {
  1881.                 throw new java.sql.SQLException(
  1882.                     "No value specified for parameter " + (i + 1), SQLError.SQL_STATE_WRONG_NO_OF_PARAMETERS);
  1883.             }
  1884.             sendPacket.writeBytesNoNull(staticSqlStrings[i]);
  1885.             if (batchedIsStream[i]) {
  1886.                 streamToBytes(sendPacket, batchedParameterStreams[i], true,
  1887.                     batchedStreamLengths[i], useStreamLengths);
  1888.             } else {
  1889.                 sendPacket.writeBytesNoNull(batchedParameterStrings[i]);
  1890.             }
  1891.         }
  1892.         sendPacket.writeBytesNoNull(staticSqlStrings[batchedParameterStrings.length]);
  1893.         return sendPacket;
  1894.     }
  1895.     //
  1896.     // Adds '+' to decimal numbers that are positive (MySQL doesn't
  1897.     // understand them otherwise
  1898.     //
  1899.     private static final String fixDecimalExponent(String dString) {
  1900.         int ePos = dString.indexOf("E");
  1901.         if (ePos == -1) {
  1902.             ePos = dString.indexOf("e");
  1903.         }
  1904.         if (ePos != -1) {
  1905.             if (dString.length() > (ePos + 1)) {
  1906.                 char maybeMinusChar = dString.charAt(ePos + 1);
  1907.                 if (maybeMinusChar != '-') {
  1908.                     StringBuffer buf = new StringBuffer(dString.length() + 1);
  1909.                     buf.append(dString.substring(0, ePos + 1));
  1910.                     buf.append('+');
  1911.                     buf.append(dString.substring(ePos + 1, dString.length()));
  1912.                     dString = buf.toString();
  1913.                 }
  1914.             }
  1915.         }
  1916.         return dString;
  1917.     }
  1918.     private void initializeFromParseInfo() throws SQLException {
  1919.         this.staticSqlStrings = this.parseInfo.staticSql;
  1920.         this.hasLimitClause = this.parseInfo.foundLimitClause;
  1921.         this.isLoadDataQuery = this.parseInfo.foundLoadData;
  1922.         this.firstCharOfStmt = this.parseInfo.firstStmtChar;
  1923.         
  1924.         int numberOfParameters = staticSqlStrings.length - 1;
  1925.         parameterValues = new byte[numberOfParameters][];
  1926.         parameterStreams = new InputStream[numberOfParameters];
  1927.         isStream = new boolean[numberOfParameters];
  1928.         streamLengths = new int[numberOfParameters];
  1929.         isNull = new boolean[numberOfParameters];
  1930.         clearParameters();
  1931.         for (int j = 0; j < numberOfParameters; j++) {
  1932.             isStream[j] = false;
  1933.         }
  1934.     }
  1935.     private final int readblock(InputStream i, byte[] b, int length)
  1936.         throws SQLException {
  1937.         try {
  1938.             int lengthToRead = length;
  1939.             if (lengthToRead > b.length) {
  1940.                 lengthToRead = b.length;
  1941.             }
  1942.             return i.read(b, 0, lengthToRead);
  1943.         } catch (Throwable E) {
  1944.             throw new java.sql.SQLException("Error reading from InputStream "
  1945.                 + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR);
  1946.         }
  1947.     }
  1948.     private final int readblock(InputStream i, byte[] b)
  1949.         throws SQLException {
  1950.         try {
  1951.             return i.read(b);
  1952.         } catch (Throwable E) {
  1953.             throw new java.sql.SQLException("Error reading from InputStream "
  1954.                 + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR);
  1955.         }
  1956.     }
  1957.     /**
  1958.      * For the setXXXStream() methods. Basically converts an InputStream into a
  1959.      * String. Not very efficient, but it works.
  1960.      *
  1961.      * @param in DOCUMENT ME!
  1962.      * @param streamLength DOCUMENT ME!
  1963.      * @param useLength DOCUMENT ME!
  1964.      *
  1965.      * @return DOCUMENT ME!
  1966.      *
  1967.      * @throws SQLException DOCUMENT ME!
  1968.      */
  1969.     private final byte[] streamToBytes(InputStream in, int streamLength,
  1970.         boolean useLength) throws SQLException {
  1971.         return streamToBytes(in, true, streamLength, useLength);
  1972.     }
  1973.     private final byte[] streamToBytes(InputStream in, boolean escape,
  1974.         int streamLength, boolean useLength) throws SQLException {
  1975.         try {
  1976.             if (streamLength == -1) {
  1977.                 useLength = false;
  1978.             }
  1979.             ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
  1980.             int bc = -1;
  1981.             if (useLength) {
  1982.                 bc = readblock(in, streamConvertBuf, streamLength);
  1983.             } else {
  1984.                 bc = readblock(in, streamConvertBuf);
  1985.             }
  1986.             int lengthLeftToRead = streamLength - bc;
  1987.             if (escape) {
  1988.                 bytesOut.write(''');
  1989.             }
  1990.             while (bc > 0) {
  1991.                 if (escape) {
  1992.                     escapeblockFast(streamConvertBuf, bytesOut, bc);
  1993.                 } else {
  1994.                     bytesOut.write(streamConvertBuf, 0, bc);
  1995.                 }
  1996.                 if (useLength) {
  1997.                     bc = readblock(in, streamConvertBuf, lengthLeftToRead);
  1998.                     if (bc > 0) {
  1999.                         lengthLeftToRead -= bc;
  2000.                     }
  2001.                 } else {
  2002.                     bc = readblock(in, streamConvertBuf);
  2003.                 }
  2004.             }
  2005.             if (escape) {
  2006.                 bytesOut.write(''');
  2007.             }
  2008.             return bytesOut.toByteArray();
  2009.         } finally {
  2010.             try {
  2011.                 in.close();
  2012.             } catch (IOException ioEx) {
  2013.                 ;
  2014.             }
  2015.             in = null;
  2016.         }
  2017.     }
  2018.     private final void streamToBytes(Buffer packet, InputStream in,
  2019.         boolean escape, int streamLength, boolean useLength)
  2020.         throws SQLException {
  2021.         try {
  2022.             if (streamLength == -1) {
  2023.                 useLength = false;
  2024.             }
  2025.             int bc = -1;
  2026.             if (useLength) {
  2027.                 bc = readblock(in, streamConvertBuf, streamLength);
  2028.             } else {
  2029.                 bc = readblock(in, streamConvertBuf);
  2030.             }
  2031.             int lengthLeftToRead = streamLength - bc;
  2032.             if (escape) {
  2033.                 packet.writeByte((byte) ''');
  2034.             }
  2035.             while (bc > 0) {
  2036.                 if (escape) {
  2037.                     escapeblockFast(streamConvertBuf, packet, bc);
  2038.                 } else {
  2039.                     packet.writeBytesNoNull(streamConvertBuf, 0, bc);
  2040.                 }
  2041.                 if (useLength) {
  2042.                     bc = readblock(in, streamConvertBuf, lengthLeftToRead);
  2043.                     if (bc > 0) {
  2044.                         lengthLeftToRead -= bc;
  2045.                     }
  2046.                 } else {
  2047.                     bc = readblock(in, streamConvertBuf);
  2048.                 }
  2049.             }
  2050.             if (escape) {
  2051.                 packet.writeByte((byte) ''');
  2052.             }
  2053.         } finally {
  2054.             try {
  2055.                 in.close();
  2056.             } catch (IOException ioEx) {
  2057.                 ;
  2058.             }
  2059.             in = null;
  2060.         }
  2061.     }
  2062.     /**
  2063.      * Reads length bytes from reader into buf. Blocks until enough input is
  2064.      * available
  2065.      *
  2066.      * @param reader DOCUMENT ME!
  2067.      * @param buf DOCUMENT ME!
  2068.      * @param length DOCUMENT ME!
  2069.      *
  2070.      * @return DOCUMENT ME!
  2071.      *
  2072.      * @throws IOException DOCUMENT ME!
  2073.      */
  2074.     private static int readFully(Reader reader, char[] buf, int length)
  2075.         throws IOException {
  2076.         int numCharsRead = 0;
  2077.         while (numCharsRead < length) {
  2078.             int count = reader.read(buf, numCharsRead, length - numCharsRead);
  2079.             if (count < 0) {
  2080.                 break;
  2081.             }
  2082.             numCharsRead += count;
  2083.         }
  2084.         return numCharsRead;
  2085.     }
  2086.     class BatchParams {
  2087.         boolean[] isNull = null;
  2088.         boolean[] isStream = null;
  2089.         InputStream[] parameterStreams = null;
  2090.         byte[][] parameterStrings = null;
  2091.         int[] streamLengths = null;
  2092.         BatchParams(byte[][] strings, InputStream[] streams,
  2093.             boolean[] isStreamFlags, int[] lengths, boolean[] isNullFlags) {
  2094.             //
  2095.             // Make copies
  2096.             //
  2097.             parameterStrings = new byte[strings.length][];
  2098.             parameterStreams = new InputStream[streams.length];
  2099.             isStream = new boolean[isStreamFlags.length];
  2100.             streamLengths = new int[lengths.length];
  2101.             isNull = new boolean[isNullFlags.length];
  2102.             System.arraycopy(strings, 0, parameterStrings, 0, strings.length);
  2103.             System.arraycopy(streams, 0, parameterStreams, 0, streams.length);
  2104.             System.arraycopy(isStreamFlags, 0, isStream, 0, isStreamFlags.length);
  2105.             System.arraycopy(lengths, 0, streamLengths, 0, lengths.length);
  2106.             System.arraycopy(isNullFlags, 0, isNull, 0, isNullFlags.length);
  2107.         }
  2108.     }
  2109.     class ParseInfo {
  2110.         byte[][] staticSql = null;
  2111.         boolean foundLimitClause = false;
  2112.         boolean foundLoadData = false;
  2113.         char firstStmtChar = 0;
  2114.         int statementLength = 0;
  2115.         long lastUsed = 0;
  2116.         /**
  2117.                   *
  2118.                   */
  2119.         public ParseInfo(String sql, Connection conn,
  2120.             java.sql.DatabaseMetaData dbmd, String encoding,
  2121.             SingleByteCharsetConverter converter) throws SQLException {
  2122.             if (sql == null) {
  2123.                 throw new SQLException("SQL String can not be NULL", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
  2124.             }
  2125.             lastUsed = System.currentTimeMillis();
  2126.             String quotedIdentifierString = dbmd.getIdentifierQuoteString();
  2127.             char quotedIdentifierChar = 0;
  2128.             if ((quotedIdentifierString != null)
  2129.                     && !quotedIdentifierString.equals(" ")
  2130.                     && (quotedIdentifierString.length() > 0)) {
  2131.                 quotedIdentifierChar = quotedIdentifierString.charAt(0);
  2132.             }
  2133.             statementLength = sql.length();
  2134.             ArrayList endpointList = new ArrayList();
  2135.             boolean inQuotes = false;
  2136.             boolean inQuotedId = false;
  2137.             int lastParmEnd = 0;
  2138.             int i;
  2139.             int pre1 = 0;
  2140.             int pre2 = 0;
  2141.             int lastAlphaCharPos = 0;
  2142.             int stopLookingForLimitClause = statementLength - 5;
  2143.             foundLimitClause = false;
  2144.             for (i = 0; i < statementLength; ++i) {
  2145.                 char c = sql.charAt(i);
  2146.                 if ((firstStmtChar == 0) && !Character.isWhitespace(c)) {
  2147.                     // Determine what kind of statement we're doing (_S_elect, _I_nsert, etc.)
  2148.                     firstStmtChar = Character.toUpperCase(c);
  2149.                 }
  2150.                 if (Character.isLetter(c)) {
  2151.                     lastAlphaCharPos = i;
  2152.                 }
  2153.                 // are we in a quoted identifier?
  2154.                 // (only valid when the id is not inside a 'string')
  2155.                 if (!inQuotes && (quotedIdentifierChar != 0)
  2156.                         && (c == quotedIdentifierChar)) {
  2157.                     inQuotedId = !inQuotedId;
  2158.                 }
  2159.                 // only respect quotes when not in a quoted identifier
  2160.                 if (!inQuotedId) {
  2161.                     if ((c == ''') && (pre1 == '\') && (pre2 == '\')) {
  2162.                         inQuotes = !inQuotes;
  2163.                     } else if ((c == ''') && (pre1 != '\')) {
  2164.                         inQuotes = !inQuotes;
  2165.                     }
  2166.                 }
  2167.                 if ((c == '?') && !inQuotes) {
  2168.                     endpointList.add(new int[] { lastParmEnd, i });
  2169.                     lastParmEnd = i + 1;
  2170.                 }
  2171.                 if (!inQuotes && (i < stopLookingForLimitClause)) {
  2172.                     if ((c == 'L') || (c == 'l')) {
  2173.                         char posI1 = sql.charAt(i + 1);
  2174.                         if ((posI1 == 'I') || (posI1 == 'i')) {
  2175.                             char posM = sql.charAt(i + 2);
  2176.                             if ((posM == 'M') || (posM == 'm')) {
  2177.                                 char posI2 = sql.charAt(i + 3);
  2178.                                 if ((posI2 == 'I') || (posI2 == 'i')) {
  2179.                                     char posT = sql.charAt(i + 4);
  2180.                                     if ((posT == 'T') || (posT == 't')) {
  2181.                                         foundLimitClause = true;
  2182.                                     }
  2183.                                 }
  2184.                             }
  2185.                         }
  2186.                     }
  2187.                 }
  2188.                 pre2 = pre1;
  2189.                 pre1 = c;
  2190.             }
  2191.             if (firstStmtChar == 'L') {
  2192.                 if (StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) {
  2193.                     foundLoadData = true;
  2194.                 } else {
  2195.                     foundLoadData = false;
  2196.                 }
  2197.             } else {
  2198.                 foundLoadData = false;
  2199.             }
  2200.             endpointList.add(new int[] { lastParmEnd, statementLength });
  2201.             staticSql = new byte[endpointList.size()][];
  2202.             for (i = 0; i < staticSql.length; i++) {
  2203.                 int[] ep = (int[]) endpointList.get(i);
  2204.                 int end = ep[1];
  2205.                 int begin = ep[0];
  2206.                 int len = end - begin;
  2207.                 if (foundLoadData) {
  2208.                     String temp = new String(sql.toCharArray(), begin, len);
  2209.                     staticSql[i] = temp.getBytes();
  2210.                 } else if (encoding == null) {
  2211.                     byte[] buf = new byte[len];
  2212.                     for (int j = 0; j < len; j++) {
  2213.                         buf[j] = (byte) sql.charAt(begin + j);
  2214.                     }
  2215.                     staticSql[i] = buf;
  2216.                 } else {
  2217.                     try {
  2218.                         if (converter != null) {
  2219.                             staticSql[i] = StringUtils.getBytes(sql, converter,
  2220.                                     encoding, begin, len);
  2221.                         } else {
  2222.                             String temp = new String(sql.toCharArray(), begin,
  2223.                                     len);
  2224.                             staticSql[i] = StringUtils.getBytes(temp, null,
  2225.                                     encoding);
  2226.                         }
  2227.                     } catch (java.io.UnsupportedEncodingException ue) {
  2228.                         throw new SQLException(ue.toString());
  2229.                     }
  2230.                 }
  2231.             }
  2232.             int numberOfParameters = staticSql.length - 1;
  2233.         }
  2234.     }
  2235. }