Source Code Cross Referenced for PreparedStatement.java in  » Database-JDBC-Connection-Pool » mysql-connector-java-5.1.3 » com » mysql » jdbc » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » mysql connector java 5.1.3 » com.mysql.jdbc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         Copyright (C) 2002-2007 MySQL AB
0003:
0004:         This program is free software; you can redistribute it and/or modify
0005:         it under the terms of version 2 of the GNU General Public License as 
0006:         published by the Free Software Foundation.
0007:
0008:         There are special exceptions to the terms and conditions of the GPL 
0009:         as it is applied to this software. View the full text of the 
0010:         exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
0011:         software distribution.
0012:
0013:         This program is distributed in the hope that it will be useful,
0014:         but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016:         GNU General Public License for more details.
0017:
0018:         You should have received a copy of the GNU General Public License
0019:         along with this program; if not, write to the Free Software
0020:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0021:
0022:
0023:
0024:         */
0025:        package com.mysql.jdbc;
0026:
0027:        import java.io.ByteArrayInputStream;
0028:        import java.io.ByteArrayOutputStream;
0029:        import java.io.IOException;
0030:        import java.io.InputStream;
0031:        import java.io.ObjectOutputStream;
0032:        import java.io.Reader;
0033:        import java.io.StringReader;
0034:        import java.io.UnsupportedEncodingException;
0035:        import java.lang.reflect.Constructor;
0036:        import java.lang.reflect.InvocationTargetException;
0037:        import java.math.BigDecimal;
0038:        import java.math.BigInteger;
0039:        import java.net.URL;
0040:        import java.sql.Array;
0041:        import java.sql.BatchUpdateException;
0042:        import java.sql.Clob;
0043:        import java.sql.Date;
0044:        import java.sql.ParameterMetaData;
0045:        import java.sql.Ref;
0046:        import java.sql.ResultSet;
0047:        import java.sql.SQLException;
0048:        import java.sql.Time;
0049:        import java.sql.Timestamp;
0050:        import java.sql.Types;
0051:        import java.text.ParsePosition;
0052:        import java.text.SimpleDateFormat;
0053:        import java.util.ArrayList;
0054:        import java.util.Calendar;
0055:        import java.util.List;
0056:        import java.util.Locale;
0057:        import java.util.Properties;
0058:        import java.util.TimeZone;
0059:
0060:        import com.mysql.jdbc.StatementImpl.CancelTask;
0061:        import com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
0062:        import com.mysql.jdbc.exceptions.NotYetImplementedException;
0063:        import com.mysql.jdbc.exceptions.MySQLTimeoutException;
0064:        import com.mysql.jdbc.profiler.ProfilerEvent;
0065:
0066:        /**
0067:         * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
0068:         * This object can then be used to efficiently execute this statement multiple
0069:         * times.
0070:         * 
0071:         * <p>
0072:         * <B>Note:</B> The setXXX methods for setting IN parameter values must specify
0073:         * types that are compatible with the defined SQL type of the input parameter.
0074:         * For instance, if the IN parameter has SQL type Integer, then setInt should be
0075:         * used.
0076:         * </p>
0077:         * 
0078:         * <p>
0079:         * If arbitrary parameter type conversions are required, then the setObject
0080:         * method should be used with a target SQL type.
0081:         * </p>
0082:         * 
0083:         * @author Mark Matthews
0084:         * @version $Id: PreparedStatement.java,v 1.1.2.1 2005/05/13 18:58:38 mmatthews
0085:         *          Exp $
0086:         * 
0087:         * @see java.sql.ResultSet
0088:         * @see java.sql.PreparedStatement
0089:         */
0090:        public class PreparedStatement extends com.mysql.jdbc.StatementImpl
0091:                implements  java.sql.PreparedStatement {
0092:            private static final Constructor JDBC_4_PSTMT_2_ARG_CTOR;
0093:            private static final Constructor JDBC_4_PSTMT_3_ARG_CTOR;
0094:            private static final Constructor JDBC_4_PSTMT_4_ARG_CTOR;
0095:
0096:            static {
0097:                if (Util.isJdbc4()) {
0098:                    try {
0099:                        JDBC_4_PSTMT_2_ARG_CTOR = Class.forName(
0100:                                "com.mysql.jdbc.JDBC4PreparedStatement")
0101:                                .getConstructor(
0102:                                        new Class[] { ConnectionImpl.class,
0103:                                                String.class });
0104:                        JDBC_4_PSTMT_3_ARG_CTOR = Class.forName(
0105:                                "com.mysql.jdbc.JDBC4PreparedStatement")
0106:                                .getConstructor(
0107:                                        new Class[] { ConnectionImpl.class,
0108:                                                String.class, String.class });
0109:                        JDBC_4_PSTMT_4_ARG_CTOR = Class.forName(
0110:                                "com.mysql.jdbc.JDBC4PreparedStatement")
0111:                                .getConstructor(
0112:                                        new Class[] { ConnectionImpl.class,
0113:                                                String.class, String.class,
0114:                                                ParseInfo.class });
0115:                    } catch (SecurityException e) {
0116:                        throw new RuntimeException(e);
0117:                    } catch (NoSuchMethodException e) {
0118:                        throw new RuntimeException(e);
0119:                    } catch (ClassNotFoundException e) {
0120:                        throw new RuntimeException(e);
0121:                    }
0122:                } else {
0123:                    JDBC_4_PSTMT_2_ARG_CTOR = null;
0124:                    JDBC_4_PSTMT_3_ARG_CTOR = null;
0125:                    JDBC_4_PSTMT_4_ARG_CTOR = null;
0126:                }
0127:            }
0128:
0129:            class BatchParams {
0130:                boolean[] isNull = null;
0131:
0132:                boolean[] isStream = null;
0133:
0134:                InputStream[] parameterStreams = null;
0135:
0136:                byte[][] parameterStrings = null;
0137:
0138:                int[] streamLengths = null;
0139:
0140:                BatchParams(byte[][] strings, InputStream[] streams,
0141:                        boolean[] isStreamFlags, int[] lengths,
0142:                        boolean[] isNullFlags) {
0143:                    //
0144:                    // Make copies
0145:                    //
0146:                    this .parameterStrings = new byte[strings.length][];
0147:                    this .parameterStreams = new InputStream[streams.length];
0148:                    this .isStream = new boolean[isStreamFlags.length];
0149:                    this .streamLengths = new int[lengths.length];
0150:                    this .isNull = new boolean[isNullFlags.length];
0151:                    System.arraycopy(strings, 0, this .parameterStrings, 0,
0152:                            strings.length);
0153:                    System.arraycopy(streams, 0, this .parameterStreams, 0,
0154:                            streams.length);
0155:                    System.arraycopy(isStreamFlags, 0, this .isStream, 0,
0156:                            isStreamFlags.length);
0157:                    System.arraycopy(lengths, 0, this .streamLengths, 0,
0158:                            lengths.length);
0159:                    System.arraycopy(isNullFlags, 0, this .isNull, 0,
0160:                            isNullFlags.length);
0161:                }
0162:            }
0163:
0164:            class EndPoint {
0165:                int begin;
0166:
0167:                int end;
0168:
0169:                EndPoint(int b, int e) {
0170:                    this .begin = b;
0171:                    this .end = e;
0172:                }
0173:            }
0174:
0175:            class ParseInfo {
0176:                char firstStmtChar = 0;
0177:
0178:                boolean foundLimitClause = false;
0179:
0180:                boolean foundLoadData = false;
0181:
0182:                long lastUsed = 0;
0183:
0184:                int statementLength = 0;
0185:
0186:                int statementStartPos = 0;
0187:
0188:                byte[][] staticSql = null;
0189:
0190:                /**
0191:                 * Represents the "parsed" state of a client-side
0192:                 * prepared statement, with the statement broken up into
0193:                 * it's static and dynamic (where parameters are bound) 
0194:                 * parts.
0195:                 */
0196:                public ParseInfo(String sql, ConnectionImpl conn,
0197:                        java.sql.DatabaseMetaData dbmd, String encoding,
0198:                        SingleByteCharsetConverter converter)
0199:                        throws SQLException {
0200:                    try {
0201:                        if (sql == null) {
0202:                            throw SQLError.createSQLException(Messages
0203:                                    .getString("PreparedStatement.61"), //$NON-NLS-1$
0204:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0205:                        }
0206:
0207:                        this .lastUsed = System.currentTimeMillis();
0208:
0209:                        String quotedIdentifierString = dbmd
0210:                                .getIdentifierQuoteString();
0211:
0212:                        char quotedIdentifierChar = 0;
0213:
0214:                        if ((quotedIdentifierString != null)
0215:                                && !quotedIdentifierString.equals(" ") //$NON-NLS-1$
0216:                                && (quotedIdentifierString.length() > 0)) {
0217:                            quotedIdentifierChar = quotedIdentifierString
0218:                                    .charAt(0);
0219:                        }
0220:
0221:                        this .statementLength = sql.length();
0222:
0223:                        ArrayList endpointList = new ArrayList();
0224:                        boolean inQuotes = false;
0225:                        char quoteChar = 0;
0226:                        boolean inQuotedId = false;
0227:                        int lastParmEnd = 0;
0228:                        int i;
0229:
0230:                        int stopLookingForLimitClause = this .statementLength - 5;
0231:
0232:                        this .foundLimitClause = false;
0233:
0234:                        boolean noBackslashEscapes = connection
0235:                                .isNoBackslashEscapesSet();
0236:
0237:                        // we're not trying to be real pedantic here, but we'd like to 
0238:                        // skip comments at the beginning of statements, as frameworks
0239:                        // such as Hibernate use them to aid in debugging
0240:
0241:                        statementStartPos = findStartOfStatement(sql);
0242:
0243:                        for (i = statementStartPos; i < this .statementLength; ++i) {
0244:                            char c = sql.charAt(i);
0245:
0246:                            if ((this .firstStmtChar == 0)
0247:                                    && !Character.isWhitespace(c)) {
0248:                                // Determine what kind of statement we're doing (_S_elect,
0249:                                // _I_nsert, etc.)
0250:                                this .firstStmtChar = Character.toUpperCase(c);
0251:                            }
0252:
0253:                            if (!noBackslashEscapes && c == '\\'
0254:                                    && i < (this .statementLength - 1)) {
0255:                                i++;
0256:                                continue; // next character is escaped
0257:                            }
0258:
0259:                            // are we in a quoted identifier?
0260:                            // (only valid when the id is not inside a 'string')
0261:                            if (!inQuotes && (quotedIdentifierChar != 0)
0262:                                    && (c == quotedIdentifierChar)) {
0263:                                inQuotedId = !inQuotedId;
0264:                            } else if (!inQuotedId) {
0265:                                //	only respect quotes when not in a quoted identifier
0266:
0267:                                if (inQuotes) {
0268:                                    if (((c == '\'') || (c == '"'))
0269:                                            && c == quoteChar) {
0270:                                        if (i < (this .statementLength - 1)
0271:                                                && sql.charAt(i + 1) == quoteChar) {
0272:                                            i++;
0273:                                            continue; // inline quote escape
0274:                                        }
0275:
0276:                                        inQuotes = !inQuotes;
0277:                                        quoteChar = 0;
0278:                                    } else if (((c == '\'') || (c == '"'))
0279:                                            && c == quoteChar) {
0280:                                        inQuotes = !inQuotes;
0281:                                        quoteChar = 0;
0282:                                    }
0283:                                } else {
0284:                                    if (c == '#'
0285:                                            || (c == '-'
0286:                                                    && (i + 1) < this .statementLength && sql
0287:                                                    .charAt(i + 1) == '-')) {
0288:                                        // run out to end of statement, or newline,
0289:                                        // whichever comes first
0290:                                        int endOfStmt = this .statementLength - 1;
0291:
0292:                                        for (; i < endOfStmt; i++) {
0293:                                            c = sql.charAt(i);
0294:
0295:                                            if (c == '\r' || c == '\n') {
0296:                                                break;
0297:                                            }
0298:                                        }
0299:
0300:                                        continue;
0301:                                    } else if (c == '/'
0302:                                            && (i + 1) < this .statementLength) {
0303:                                        // Comment?
0304:                                        char cNext = sql.charAt(i + 1);
0305:
0306:                                        if (cNext == '*') {
0307:                                            i += 2;
0308:
0309:                                            for (int j = i; j < this .statementLength; j++) {
0310:                                                i++;
0311:                                                cNext = sql.charAt(j);
0312:
0313:                                                if (cNext == '*'
0314:                                                        && (j + 1) < this .statementLength) {
0315:                                                    if (sql.charAt(j + 1) == '/') {
0316:                                                        i++;
0317:
0318:                                                        if (i < this .statementLength) {
0319:                                                            c = sql.charAt(i);
0320:                                                        }
0321:
0322:                                                        break; // comment done
0323:                                                    }
0324:                                                }
0325:                                            }
0326:                                        }
0327:                                    } else if ((c == '\'') || (c == '"')) {
0328:                                        inQuotes = true;
0329:                                        quoteChar = c;
0330:                                    }
0331:                                }
0332:                            }
0333:
0334:                            if ((c == '?') && !inQuotes && !inQuotedId) {
0335:                                endpointList.add(new int[] { lastParmEnd, i });
0336:                                lastParmEnd = i + 1;
0337:                            }
0338:
0339:                            if (!inQuotes && (i < stopLookingForLimitClause)) {
0340:                                if ((c == 'L') || (c == 'l')) {
0341:                                    char posI1 = sql.charAt(i + 1);
0342:
0343:                                    if ((posI1 == 'I') || (posI1 == 'i')) {
0344:                                        char posM = sql.charAt(i + 2);
0345:
0346:                                        if ((posM == 'M') || (posM == 'm')) {
0347:                                            char posI2 = sql.charAt(i + 3);
0348:
0349:                                            if ((posI2 == 'I')
0350:                                                    || (posI2 == 'i')) {
0351:                                                char posT = sql.charAt(i + 4);
0352:
0353:                                                if ((posT == 'T')
0354:                                                        || (posT == 't')) {
0355:                                                    foundLimitClause = true;
0356:                                                }
0357:                                            }
0358:                                        }
0359:                                    }
0360:                                }
0361:                            }
0362:                        }
0363:
0364:                        if (this .firstStmtChar == 'L') {
0365:                            if (StringUtils.startsWithIgnoreCaseAndWs(sql,
0366:                                    "LOAD DATA")) { //$NON-NLS-1$
0367:                                this .foundLoadData = true;
0368:                            } else {
0369:                                this .foundLoadData = false;
0370:                            }
0371:                        } else {
0372:                            this .foundLoadData = false;
0373:                        }
0374:
0375:                        endpointList.add(new int[] { lastParmEnd,
0376:                                this .statementLength });
0377:                        this .staticSql = new byte[endpointList.size()][];
0378:                        char[] asCharArray = sql.toCharArray();
0379:
0380:                        for (i = 0; i < this .staticSql.length; i++) {
0381:                            int[] ep = (int[]) endpointList.get(i);
0382:                            int end = ep[1];
0383:                            int begin = ep[0];
0384:                            int len = end - begin;
0385:
0386:                            if (this .foundLoadData) {
0387:                                String temp = new String(asCharArray, begin,
0388:                                        len);
0389:                                this .staticSql[i] = temp.getBytes();
0390:                            } else if (encoding == null) {
0391:                                byte[] buf = new byte[len];
0392:
0393:                                for (int j = 0; j < len; j++) {
0394:                                    buf[j] = (byte) sql.charAt(begin + j);
0395:                                }
0396:
0397:                                this .staticSql[i] = buf;
0398:                            } else {
0399:                                if (converter != null) {
0400:                                    this .staticSql[i] = StringUtils
0401:                                            .getBytes(
0402:                                                    sql,
0403:                                                    converter,
0404:                                                    encoding,
0405:                                                    connection
0406:                                                            .getServerCharacterEncoding(),
0407:                                                    begin,
0408:                                                    len,
0409:                                                    connection
0410:                                                            .parserKnowsUnicode());
0411:                                } else {
0412:                                    String temp = new String(asCharArray,
0413:                                            begin, len);
0414:
0415:                                    this .staticSql[i] = StringUtils
0416:                                            .getBytes(
0417:                                                    temp,
0418:                                                    encoding,
0419:                                                    connection
0420:                                                            .getServerCharacterEncoding(),
0421:                                                    connection
0422:                                                            .parserKnowsUnicode(),
0423:                                                    conn);
0424:                                }
0425:                            }
0426:                        }
0427:                    } catch (StringIndexOutOfBoundsException oobEx) {
0428:                        SQLException sqlEx = new SQLException(
0429:                                "Parse error for " + sql);
0430:                        sqlEx.initCause(oobEx);
0431:
0432:                        throw sqlEx;
0433:                    }
0434:                }
0435:            }
0436:
0437:            private final static byte[] HEX_DIGITS = new byte[] { (byte) '0',
0438:                    (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5',
0439:                    (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'A',
0440:                    (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F' };
0441:
0442:            /**
0443:             * Reads length bytes from reader into buf. Blocks until enough input is
0444:             * available
0445:             * 
0446:             * @param reader
0447:             *            DOCUMENT ME!
0448:             * @param buf
0449:             *            DOCUMENT ME!
0450:             * @param length
0451:             *            DOCUMENT ME!
0452:             * 
0453:             * @return DOCUMENT ME!
0454:             * 
0455:             * @throws IOException
0456:             *             DOCUMENT ME!
0457:             */
0458:            protected static int readFully(Reader reader, char[] buf, int length)
0459:                    throws IOException {
0460:                int numCharsRead = 0;
0461:
0462:                while (numCharsRead < length) {
0463:                    int count = reader.read(buf, numCharsRead, length
0464:                            - numCharsRead);
0465:
0466:                    if (count < 0) {
0467:                        break;
0468:                    }
0469:
0470:                    numCharsRead += count;
0471:                }
0472:
0473:                return numCharsRead;
0474:            }
0475:
0476:            /**
0477:             * Does the batch (if any) contain "plain" statements added by
0478:             * Statement.addBatch(String)?
0479:             * 
0480:             * If so, we can't re-write it to use multi-value or multi-queries.
0481:             */
0482:            protected boolean batchHasPlainStatements = false;
0483:
0484:            private java.sql.DatabaseMetaData dbmd = null;
0485:
0486:            /**
0487:             * What is the first character of the prepared statement (used to check for
0488:             * SELECT vs. INSERT/UPDATE/DELETE)
0489:             */
0490:            protected char firstCharOfStmt = 0;
0491:
0492:            /** Does the SQL for this statement contain a 'limit' clause? */
0493:            protected boolean hasLimitClause = false;
0494:
0495:            /** Is this query a LOAD DATA query? */
0496:            protected boolean isLoadDataQuery = false;
0497:
0498:            private boolean[] isNull = null;
0499:
0500:            private boolean[] isStream = null;
0501:
0502:            protected int numberOfExecutions = 0;
0503:
0504:            /** The SQL that was passed in to 'prepare' */
0505:            protected String originalSql = null;
0506:
0507:            /** The number of parameters in this PreparedStatement */
0508:            protected int parameterCount;
0509:
0510:            protected MysqlParameterMetadata parameterMetaData;
0511:
0512:            private InputStream[] parameterStreams = null;
0513:
0514:            private byte[][] parameterValues = null;
0515:
0516:            /**
0517:             * Only used by statement interceptors at the moment to
0518:             * provide introspection of bound values
0519:             */
0520:            protected int[] parameterTypes = null;
0521:
0522:            private ParseInfo parseInfo;
0523:
0524:            private java.sql.ResultSetMetaData pstmtResultMetaData;
0525:
0526:            private byte[][] staticSqlStrings = null;
0527:
0528:            private byte[] streamConvertBuf = new byte[4096];
0529:
0530:            private int[] streamLengths = null;
0531:
0532:            private SimpleDateFormat tsdf = null;
0533:
0534:            /**
0535:             * Are we using a version of MySQL where we can use 'true' boolean values?
0536:             */
0537:            protected boolean useTrueBoolean = false;
0538:
0539:            protected boolean usingAnsiMode;
0540:
0541:            protected String batchedValuesClause;
0542:
0543:            /** Where does the statement text actually start? */
0544:
0545:            private int statementAfterCommentsPos;
0546:
0547:            /**
0548:             * have we checked whether we can rewrite this statement as a multi-value
0549:             * insert?
0550:             */
0551:
0552:            private boolean hasCheckedForRewrite = false;
0553:
0554:            /** Can we actually rewrite this statement as a multi-value insert? */
0555:
0556:            private boolean canRewrite = false;
0557:
0558:            private boolean doPingInstead;
0559:
0560:            /**
0561:             * Creates a prepared statement instance -- We need to provide factory-style
0562:             * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
0563:             * otherwise the class verifier complains when it tries to load JDBC4-only
0564:             * interface classes that are present in JDBC4 method signatures.
0565:             */
0566:
0567:            protected static PreparedStatement getInstance(ConnectionImpl conn,
0568:                    String catalog) throws SQLException {
0569:                if (!Util.isJdbc4()) {
0570:                    return new PreparedStatement(conn, catalog);
0571:                }
0572:
0573:                return (PreparedStatement) Util
0574:                        .handleNewInstance(JDBC_4_PSTMT_2_ARG_CTOR,
0575:                                new Object[] { conn, catalog });
0576:            }
0577:
0578:            /**
0579:             * Creates a prepared statement instance -- We need to provide factory-style
0580:             * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
0581:             * otherwise the class verifier complains when it tries to load JDBC4-only
0582:             * interface classes that are present in JDBC4 method signatures.
0583:             */
0584:
0585:            protected static PreparedStatement getInstance(ConnectionImpl conn,
0586:                    String sql, String catalog) throws SQLException {
0587:                if (!Util.isJdbc4()) {
0588:                    return new PreparedStatement(conn, sql, catalog);
0589:                }
0590:
0591:                return (PreparedStatement) Util.handleNewInstance(
0592:                        JDBC_4_PSTMT_3_ARG_CTOR, new Object[] { conn, sql,
0593:                                catalog });
0594:            }
0595:
0596:            /**
0597:             * Creates a prepared statement instance -- We need to provide factory-style
0598:             * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
0599:             * otherwise the class verifier complains when it tries to load JDBC4-only
0600:             * interface classes that are present in JDBC4 method signatures.
0601:             */
0602:
0603:            protected static PreparedStatement getInstance(ConnectionImpl conn,
0604:                    String sql, String catalog, ParseInfo cachedParseInfo)
0605:                    throws SQLException {
0606:                if (!Util.isJdbc4()) {
0607:                    return new PreparedStatement(conn, sql, catalog,
0608:                            cachedParseInfo);
0609:                }
0610:
0611:                return (PreparedStatement) Util.handleNewInstance(
0612:                        JDBC_4_PSTMT_4_ARG_CTOR, new Object[] { conn, sql,
0613:                                catalog, cachedParseInfo });
0614:            }
0615:
0616:            /**
0617:             * Constructor used by server-side prepared statements
0618:             * 
0619:             * @param conn
0620:             *            the connection that created us
0621:             * @param catalog
0622:             *            the catalog in use when we were created
0623:             * 
0624:             * @throws SQLException
0625:             *             if an error occurs
0626:             */
0627:            public PreparedStatement(ConnectionImpl conn, String catalog)
0628:                    throws SQLException {
0629:                super (conn, catalog);
0630:            }
0631:
0632:            /**
0633:             * Constructor for the PreparedStatement class.
0634:             * 
0635:             * @param conn
0636:             *            the connection creating this statement
0637:             * @param sql
0638:             *            the SQL for this statement
0639:             * @param catalog
0640:             *            the catalog/database this statement should be issued against
0641:             * 
0642:             * @throws SQLException
0643:             *             if a database error occurs.
0644:             */
0645:            public PreparedStatement(ConnectionImpl conn, String sql,
0646:                    String catalog) throws SQLException {
0647:                super (conn, catalog);
0648:
0649:                if (sql == null) {
0650:                    throw SQLError.createSQLException(Messages
0651:                            .getString("PreparedStatement.0"), //$NON-NLS-1$
0652:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0653:                }
0654:
0655:                this .originalSql = sql;
0656:
0657:                if (this .originalSql.startsWith(PING_MARKER)) {
0658:                    this .doPingInstead = true;
0659:                } else {
0660:                    this .doPingInstead = false;
0661:                }
0662:
0663:                this .dbmd = this .connection.getMetaData();
0664:
0665:                this .useTrueBoolean = this .connection.versionMeetsMinimum(3,
0666:                        21, 23);
0667:
0668:                this .parseInfo = new ParseInfo(sql, this .connection, this .dbmd,
0669:                        this .charEncoding, this .charConverter);
0670:
0671:                initializeFromParseInfo();
0672:            }
0673:
0674:            /**
0675:             * Creates a new PreparedStatement object.
0676:             * 
0677:             * @param conn
0678:             *            the connection creating this statement
0679:             * @param sql
0680:             *            the SQL for this statement
0681:             * @param catalog
0682:             *            the catalog/database this statement should be issued against
0683:             * @param cachedParseInfo
0684:             *            already created parseInfo.
0685:             * 
0686:             * @throws SQLException
0687:             *             DOCUMENT ME!
0688:             */
0689:            public PreparedStatement(ConnectionImpl conn, String sql,
0690:                    String catalog, ParseInfo cachedParseInfo)
0691:                    throws SQLException {
0692:                super (conn, catalog);
0693:
0694:                if (sql == null) {
0695:                    throw SQLError.createSQLException(Messages
0696:                            .getString("PreparedStatement.1"), //$NON-NLS-1$
0697:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0698:                }
0699:
0700:                this .originalSql = sql;
0701:
0702:                this .dbmd = this .connection.getMetaData();
0703:
0704:                this .useTrueBoolean = this .connection.versionMeetsMinimum(3,
0705:                        21, 23);
0706:
0707:                this .parseInfo = cachedParseInfo;
0708:
0709:                this .usingAnsiMode = !this .connection
0710:                        .useAnsiQuotedIdentifiers();
0711:
0712:                initializeFromParseInfo();
0713:            }
0714:
0715:            /**
0716:             * JDBC 2.0 Add a set of parameters to the batch.
0717:             * 
0718:             * @exception SQLException
0719:             *                if a database-access error occurs.
0720:             * 
0721:             * @see StatementImpl#addBatch
0722:             */
0723:            public void addBatch() throws SQLException {
0724:                if (this .batchedArgs == null) {
0725:                    this .batchedArgs = new ArrayList();
0726:                }
0727:
0728:                this .batchedArgs.add(new BatchParams(this .parameterValues,
0729:                        this .parameterStreams, this .isStream,
0730:                        this .streamLengths, this .isNull));
0731:            }
0732:
0733:            public synchronized void addBatch(String sql) throws SQLException {
0734:                this .batchHasPlainStatements = true;
0735:
0736:                super .addBatch(sql);
0737:            }
0738:
0739:            protected String asSql() throws SQLException {
0740:                return asSql(false);
0741:            }
0742:
0743:            protected String asSql(boolean quoteStreamsAndUnknowns)
0744:                    throws SQLException {
0745:                if (this .isClosed) {
0746:                    return "statement has been closed, no further internal information available";
0747:                }
0748:
0749:                StringBuffer buf = new StringBuffer();
0750:
0751:                try {
0752:                    for (int i = 0; i < this .parameterCount; ++i) {
0753:                        if (this .charEncoding != null) {
0754:                            buf.append(new String(this .staticSqlStrings[i],
0755:                                    this .charEncoding));
0756:                        } else {
0757:                            buf.append(new String(this .staticSqlStrings[i]));
0758:                        }
0759:
0760:                        if ((this .parameterValues[i] == null)
0761:                                && !this .isStream[i]) {
0762:                            if (quoteStreamsAndUnknowns) {
0763:                                buf.append("'");
0764:                            }
0765:
0766:                            buf.append("** NOT SPECIFIED **"); //$NON-NLS-1$
0767:
0768:                            if (quoteStreamsAndUnknowns) {
0769:                                buf.append("'");
0770:                            }
0771:                        } else if (this .isStream[i]) {
0772:                            if (quoteStreamsAndUnknowns) {
0773:                                buf.append("'");
0774:                            }
0775:
0776:                            buf.append("** STREAM DATA **"); //$NON-NLS-1$
0777:
0778:                            if (quoteStreamsAndUnknowns) {
0779:                                buf.append("'");
0780:                            }
0781:                        } else {
0782:                            if (this .charConverter != null) {
0783:                                buf.append(this .charConverter
0784:                                        .toString(this .parameterValues[i]));
0785:                            } else {
0786:                                if (this .charEncoding != null) {
0787:                                    buf.append(new String(
0788:                                            this .parameterValues[i],
0789:                                            this .charEncoding));
0790:                                } else {
0791:                                    buf
0792:                                            .append(StringUtils
0793:                                                    .toAsciiString(this .parameterValues[i]));
0794:                                }
0795:                            }
0796:                        }
0797:                    }
0798:
0799:                    if (this .charEncoding != null) {
0800:                        buf.append(new String(
0801:                                this .staticSqlStrings[this .parameterCount],
0802:                                this .charEncoding));
0803:                    } else {
0804:                        buf
0805:                                .append(StringUtils
0806:                                        .toAsciiString(this .staticSqlStrings[this .parameterCount]));
0807:                    }
0808:                } catch (UnsupportedEncodingException uue) {
0809:                    throw new RuntimeException(Messages
0810:                            .getString("PreparedStatement.32") //$NON-NLS-1$
0811:                            + this .charEncoding
0812:                            + Messages.getString("PreparedStatement.33")); //$NON-NLS-1$
0813:                }
0814:
0815:                return buf.toString();
0816:            }
0817:
0818:            public synchronized void clearBatch() throws SQLException {
0819:                this .batchHasPlainStatements = false;
0820:
0821:                super .clearBatch();
0822:            }
0823:
0824:            /**
0825:             * In general, parameter values remain in force for repeated used of a
0826:             * Statement. Setting a parameter value automatically clears its previous
0827:             * value. However, in some cases, it is useful to immediately release the
0828:             * resources used by the current parameter values; this can be done by
0829:             * calling clearParameters
0830:             * 
0831:             * @exception SQLException
0832:             *                if a database access error occurs
0833:             */
0834:            public synchronized void clearParameters() throws SQLException {
0835:                checkClosed();
0836:
0837:                for (int i = 0; i < this .parameterValues.length; i++) {
0838:                    this .parameterValues[i] = null;
0839:                    this .parameterStreams[i] = null;
0840:                    this .isStream[i] = false;
0841:                    this .isNull[i] = false;
0842:                    this .parameterTypes[i] = Types.NULL;
0843:                }
0844:            }
0845:
0846:            /**
0847:             * Closes this prepared statement and releases all resources.
0848:             * 
0849:             * @throws SQLException
0850:             *             if database error occurs.
0851:             */
0852:            public synchronized void close() throws SQLException {
0853:                realClose(true, true);
0854:            }
0855:
0856:            private final void escapeblockFast(byte[] buf, Buffer packet,
0857:                    int size) throws SQLException {
0858:                int lastwritten = 0;
0859:
0860:                for (int i = 0; i < size; i++) {
0861:                    byte b = buf[i];
0862:
0863:                    if (b == '\0') {
0864:                        // write stuff not yet written
0865:                        if (i > lastwritten) {
0866:                            packet.writeBytesNoNull(buf, lastwritten, i
0867:                                    - lastwritten);
0868:                        }
0869:
0870:                        // write escape
0871:                        packet.writeByte((byte) '\\');
0872:                        packet.writeByte((byte) '0');
0873:                        lastwritten = i + 1;
0874:                    } else {
0875:                        if ((b == '\\') || (b == '\'')
0876:                                || (!this .usingAnsiMode && b == '"')) {
0877:                            // write stuff not yet written
0878:                            if (i > lastwritten) {
0879:                                packet.writeBytesNoNull(buf, lastwritten, i
0880:                                        - lastwritten);
0881:                            }
0882:
0883:                            // write escape
0884:                            packet.writeByte((byte) '\\');
0885:                            lastwritten = i; // not i+1 as b wasn't written.
0886:                        }
0887:                    }
0888:                }
0889:
0890:                // write out remaining stuff from buffer
0891:                if (lastwritten < size) {
0892:                    packet.writeBytesNoNull(buf, lastwritten, size
0893:                            - lastwritten);
0894:                }
0895:            }
0896:
0897:            private final void escapeblockFast(byte[] buf,
0898:                    ByteArrayOutputStream bytesOut, int size) {
0899:                int lastwritten = 0;
0900:
0901:                for (int i = 0; i < size; i++) {
0902:                    byte b = buf[i];
0903:
0904:                    if (b == '\0') {
0905:                        // write stuff not yet written
0906:                        if (i > lastwritten) {
0907:                            bytesOut.write(buf, lastwritten, i - lastwritten);
0908:                        }
0909:
0910:                        // write escape
0911:                        bytesOut.write('\\');
0912:                        bytesOut.write('0');
0913:                        lastwritten = i + 1;
0914:                    } else {
0915:                        if ((b == '\\') || (b == '\'')
0916:                                || (!this .usingAnsiMode && b == '"')) {
0917:                            // write stuff not yet written
0918:                            if (i > lastwritten) {
0919:                                bytesOut.write(buf, lastwritten, i
0920:                                        - lastwritten);
0921:                            }
0922:
0923:                            // write escape
0924:                            bytesOut.write('\\');
0925:                            lastwritten = i; // not i+1 as b wasn't written.
0926:                        }
0927:                    }
0928:                }
0929:
0930:                // write out remaining stuff from buffer
0931:                if (lastwritten < size) {
0932:                    bytesOut.write(buf, lastwritten, size - lastwritten);
0933:                }
0934:            }
0935:
0936:            /**
0937:             * Some prepared statements return multiple results; the execute method
0938:             * handles these complex statements as well as the simpler form of
0939:             * statements handled by executeQuery and executeUpdate
0940:             * 
0941:             * @return true if the next result is a ResultSet; false if it is an update
0942:             *         count or there are no more results
0943:             * 
0944:             * @exception SQLException
0945:             *                if a database access error occurs
0946:             */
0947:            public boolean execute() throws SQLException {
0948:                checkClosed();
0949:
0950:                ConnectionImpl locallyScopedConn = this .connection;
0951:
0952:                if (locallyScopedConn.isReadOnly()
0953:                        && (this .firstCharOfStmt != 'S')) {
0954:                    throw SQLError.createSQLException(Messages
0955:                            .getString("PreparedStatement.20") //$NON-NLS-1$
0956:                            + Messages.getString("PreparedStatement.21"), //$NON-NLS-1$
0957:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0958:                }
0959:
0960:                ResultSetInternalMethods rs = null;
0961:
0962:                CachedResultSetMetaData cachedMetadata = null;
0963:
0964:                synchronized (locallyScopedConn.getMutex()) {
0965:                    boolean doStreaming = createStreamingResultSet();
0966:
0967:                    clearWarnings();
0968:
0969:                    // Adjust net_write_timeout to a higher value if we're
0970:                    // streaming result sets. More often than not, someone runs into
0971:                    // an issue where they blow net_write_timeout when using this
0972:                    // feature, and if they're willing to hold a result set open
0973:                    // for 30 seconds or more, one more round-trip isn't going to hurt
0974:                    //
0975:                    // This is reset by RowDataDynamic.close().
0976:
0977:                    if (doStreaming
0978:                            && this .connection
0979:                                    .getNetTimeoutForStreamingResults() > 0) {
0980:                        executeSimpleNonQuery(
0981:                                locallyScopedConn,
0982:                                "SET net_write_timeout="
0983:                                        + this .connection
0984:                                                .getNetTimeoutForStreamingResults());
0985:                    }
0986:
0987:                    this .batchedGeneratedKeys = null;
0988:
0989:                    Buffer sendPacket = fillSendPacket();
0990:
0991:                    String oldCatalog = null;
0992:
0993:                    if (!locallyScopedConn.getCatalog().equals(
0994:                            this .currentCatalog)) {
0995:                        oldCatalog = locallyScopedConn.getCatalog();
0996:                        locallyScopedConn.setCatalog(this .currentCatalog);
0997:                    }
0998:
0999:                    //
1000:                    // Check if we have cached metadata for this query...
1001:                    //
1002:                    if (locallyScopedConn.getCacheResultSetMetadata()) {
1003:                        cachedMetadata = locallyScopedConn
1004:                                .getCachedMetaData(this .originalSql);
1005:                    }
1006:
1007:                    Field[] metadataFromCache = null;
1008:
1009:                    if (cachedMetadata != null) {
1010:                        metadataFromCache = cachedMetadata.fields;
1011:                    }
1012:
1013:                    boolean oldInfoMsgState = false;
1014:
1015:                    if (this .retrieveGeneratedKeys) {
1016:                        oldInfoMsgState = locallyScopedConn
1017:                                .isReadInfoMsgEnabled();
1018:                        locallyScopedConn.setReadInfoMsgEnabled(true);
1019:                    }
1020:
1021:                    // If there isn't a limit clause in the SQL
1022:                    // then limit the number of rows to return in
1023:                    // an efficient manner. Only do this if
1024:                    // setMaxRows() hasn't been used on any Statements
1025:                    // generated from the current Connection (saves
1026:                    // a query, and network traffic).
1027:                    //
1028:                    // Only apply max_rows to selects
1029:                    //
1030:                    if (locallyScopedConn.useMaxRows()) {
1031:                        int rowLimit = -1;
1032:
1033:                        if (this .firstCharOfStmt == 'S') {
1034:                            if (this .hasLimitClause) {
1035:                                rowLimit = this .maxRows;
1036:                            } else {
1037:                                if (this .maxRows <= 0) {
1038:                                    executeSimpleNonQuery(locallyScopedConn,
1039:                                            "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
1040:                                } else {
1041:                                    executeSimpleNonQuery(locallyScopedConn,
1042:                                            "SET OPTION SQL_SELECT_LIMIT="
1043:                                                    + this .maxRows);
1044:                                }
1045:                            }
1046:                        } else {
1047:                            executeSimpleNonQuery(locallyScopedConn,
1048:                                    "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
1049:                        }
1050:
1051:                        // Finally, execute the query
1052:                        rs = executeInternal(rowLimit, sendPacket, doStreaming,
1053:                                (this .firstCharOfStmt == 'S'),
1054:                                metadataFromCache, false);
1055:                    } else {
1056:                        rs = executeInternal(-1, sendPacket, doStreaming,
1057:                                (this .firstCharOfStmt == 'S'),
1058:                                metadataFromCache, false);
1059:                    }
1060:
1061:                    if (cachedMetadata != null) {
1062:                        locallyScopedConn.initializeResultsMetadataFromCache(
1063:                                this .originalSql, cachedMetadata, this .results);
1064:                    } else {
1065:                        if (rs.reallyResult()
1066:                                && locallyScopedConn
1067:                                        .getCacheResultSetMetadata()) {
1068:                            locallyScopedConn
1069:                                    .initializeResultsMetadataFromCache(
1070:                                            this .originalSql,
1071:                                            null /* will be created */,
1072:                                            this .results);
1073:                        }
1074:                    }
1075:
1076:                    if (this .retrieveGeneratedKeys) {
1077:                        locallyScopedConn
1078:                                .setReadInfoMsgEnabled(oldInfoMsgState);
1079:                        rs.setFirstCharOfQuery(this .firstCharOfStmt);
1080:                    }
1081:
1082:                    if (oldCatalog != null) {
1083:                        locallyScopedConn.setCatalog(oldCatalog);
1084:                    }
1085:
1086:                    if (rs != null) {
1087:                        this .lastInsertId = rs.getUpdateID();
1088:
1089:                        this .results = rs;
1090:                    }
1091:                }
1092:
1093:                return ((rs != null) && rs.reallyResult());
1094:            }
1095:
1096:            /**
1097:             * JDBC 2.0 Submit a batch of commands to the database for execution. This
1098:             * method is optional.
1099:             * 
1100:             * @return an array of update counts containing one element for each command
1101:             *         in the batch. The array is ordered according to the order in
1102:             *         which commands were inserted into the batch
1103:             * 
1104:             * @exception SQLException
1105:             *                if a database-access error occurs, or the driver does not
1106:             *                support batch statements
1107:             * @throws java.sql.BatchUpdateException
1108:             *             DOCUMENT ME!
1109:             */
1110:            public int[] executeBatch() throws SQLException {
1111:                checkClosed();
1112:
1113:                if (this .connection.isReadOnly()) {
1114:                    throw new SQLException(Messages
1115:                            .getString("PreparedStatement.25") //$NON-NLS-1$
1116:                            + Messages.getString("PreparedStatement.26"), //$NON-NLS-1$
1117:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1118:                }
1119:
1120:                synchronized (this .connection.getMutex()) {
1121:                    if (this .batchedArgs == null
1122:                            || this .batchedArgs.size() == 0) {
1123:                        return new int[0];
1124:                    }
1125:
1126:                    // we timeout the entire batch, not individual statements
1127:                    int batchTimeout = this .timeoutInMillis;
1128:                    this .timeoutInMillis = 0;
1129:
1130:                    resetCancelledState();
1131:
1132:                    try {
1133:                        clearWarnings();
1134:
1135:                        if (!this .batchHasPlainStatements
1136:                                && this .connection
1137:                                        .getRewriteBatchedStatements()) {
1138:
1139:                            if (canRewriteAsMultivalueInsertStatement()) {
1140:                                return executeBatchedInserts(batchTimeout);
1141:                            }
1142:
1143:                            if (this .connection.versionMeetsMinimum(4, 1, 0)
1144:                                    && !this .batchHasPlainStatements
1145:                                    && this .batchedArgs != null
1146:                                    && this .batchedArgs.size() > 3 /* cost of option setting rt-wise */) {
1147:                                return executePreparedBatchAsMultiStatement(batchTimeout);
1148:                            }
1149:                        }
1150:
1151:                        return executeBatchSerially(batchTimeout);
1152:                    } finally {
1153:                        clearBatch();
1154:                    }
1155:                }
1156:            }
1157:
1158:            public synchronized boolean canRewriteAsMultivalueInsertStatement() {
1159:                if (!this .hasCheckedForRewrite) {
1160:                    // Needs to be INSERT, can't have INSERT ... SELECT or
1161:                    // INSERT ... ON DUPLICATE KEY UPDATE
1162:                    //
1163:                    // We're not smart enough to re-write to
1164:                    //
1165:                    //    INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
1166:                    //    ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
1167:                    //
1168:                    // (yet)
1169:
1170:                    this .canRewrite = StringUtils.startsWithIgnoreCaseAndWs(
1171:                            this .originalSql, "INSERT",
1172:                            this .statementAfterCommentsPos)
1173:                            && StringUtils.indexOfIgnoreCaseRespectMarker(
1174:                                    this .statementAfterCommentsPos,
1175:                                    this .originalSql, "SELECT", "\"'`", "\"'`",
1176:                                    false) == -1
1177:                            && StringUtils.indexOfIgnoreCaseRespectMarker(
1178:                                    this .statementAfterCommentsPos,
1179:                                    this .originalSql, "UPDATE", "\"'`", "\"'`",
1180:                                    false) == -1;
1181:
1182:                    this .hasCheckedForRewrite = true;
1183:                }
1184:
1185:                return this .canRewrite;
1186:            }
1187:
1188:            /**
1189:             * Rewrites the already prepared statement into a multi-statement
1190:             * query of 'statementsPerBatch' values and executes the entire batch
1191:             * using this new statement.
1192:             * 
1193:             * @return update counts in the same fashion as executeBatch()
1194:             * 
1195:             * @throws SQLException
1196:             */
1197:
1198:            protected int[] executePreparedBatchAsMultiStatement(
1199:                    int batchTimeout) throws SQLException {
1200:                synchronized (this .connection.getMutex()) {
1201:                    // This is kind of an abuse, but it gets the job done
1202:                    if (this .batchedValuesClause == null) {
1203:                        this .batchedValuesClause = this .originalSql + ";";
1204:                    }
1205:
1206:                    ConnectionImpl locallyScopedConn = this .connection;
1207:
1208:                    boolean multiQueriesEnabled = locallyScopedConn
1209:                            .getAllowMultiQueries();
1210:                    CancelTask timeoutTask = null;
1211:
1212:                    try {
1213:                        clearWarnings();
1214:
1215:                        int numBatchedArgs = this .batchedArgs.size();
1216:
1217:                        if (this .retrieveGeneratedKeys) {
1218:                            this .batchedGeneratedKeys = new ArrayList(
1219:                                    numBatchedArgs);
1220:                        }
1221:
1222:                        int numValuesPerBatch = computeBatchSize(numBatchedArgs);
1223:
1224:                        if (numBatchedArgs < numValuesPerBatch) {
1225:                            numValuesPerBatch = numBatchedArgs;
1226:                        }
1227:
1228:                        java.sql.PreparedStatement batchedStatement = null;
1229:
1230:                        int batchedParamIndex = 1;
1231:                        int numberToExecuteAsMultiValue = 0;
1232:                        int batchCounter = 0;
1233:                        int updateCountCounter = 0;
1234:                        int[] updateCounts = new int[numBatchedArgs];
1235:                        SQLException sqlEx = null;
1236:
1237:                        try {
1238:                            if (!multiQueriesEnabled) {
1239:                                locallyScopedConn.getIO().enableMultiQueries();
1240:                            }
1241:
1242:                            if (this .retrieveGeneratedKeys) {
1243:                                batchedStatement = locallyScopedConn
1244:                                        .prepareStatement(
1245:                                                generateMultiStatementForBatch(numValuesPerBatch),
1246:                                                RETURN_GENERATED_KEYS);
1247:                            } else {
1248:                                batchedStatement = locallyScopedConn
1249:                                        .prepareStatement(generateMultiStatementForBatch(numValuesPerBatch));
1250:                            }
1251:
1252:                            if (locallyScopedConn.getEnableQueryTimeouts()
1253:                                    && batchTimeout != 0
1254:                                    && locallyScopedConn.versionMeetsMinimum(5,
1255:                                            0, 0)) {
1256:                                timeoutTask = new CancelTask(
1257:                                        (StatementImpl) batchedStatement);
1258:                                ConnectionImpl.getCancelTimer().schedule(
1259:                                        timeoutTask, batchTimeout);
1260:                            }
1261:
1262:                            if (numBatchedArgs < numValuesPerBatch) {
1263:                                numberToExecuteAsMultiValue = numBatchedArgs;
1264:                            } else {
1265:                                numberToExecuteAsMultiValue = numBatchedArgs
1266:                                        / numValuesPerBatch;
1267:                            }
1268:
1269:                            int numberArgsToExecute = numberToExecuteAsMultiValue
1270:                                    * numValuesPerBatch;
1271:
1272:                            for (int i = 0; i < numberArgsToExecute; i++) {
1273:                                if (i != 0 && i % numValuesPerBatch == 0) {
1274:                                    try {
1275:                                        batchedStatement.execute();
1276:                                    } catch (SQLException ex) {
1277:                                        sqlEx = handleExceptionForBatch(
1278:                                                batchCounter,
1279:                                                numValuesPerBatch,
1280:                                                updateCounts, ex);
1281:                                    }
1282:
1283:                                    updateCountCounter = processMultiCountsAndKeys(
1284:                                            (StatementImpl) batchedStatement,
1285:                                            updateCountCounter, updateCounts);
1286:
1287:                                    batchedStatement.clearParameters();
1288:                                    batchedParamIndex = 1;
1289:                                }
1290:
1291:                                batchedParamIndex = setOneBatchedParameterSet(
1292:                                        batchedStatement, batchedParamIndex,
1293:                                        this .batchedArgs.get(batchCounter++));
1294:                            }
1295:
1296:                            try {
1297:                                batchedStatement.execute();
1298:                            } catch (SQLException ex) {
1299:                                sqlEx = handleExceptionForBatch(
1300:                                        batchCounter - 1, numValuesPerBatch,
1301:                                        updateCounts, ex);
1302:                            }
1303:
1304:                            updateCountCounter = processMultiCountsAndKeys(
1305:                                    (StatementImpl) batchedStatement,
1306:                                    updateCountCounter, updateCounts);
1307:
1308:                            batchedStatement.clearParameters();
1309:
1310:                            numValuesPerBatch = numBatchedArgs - batchCounter;
1311:                        } finally {
1312:                            if (batchedStatement != null) {
1313:                                batchedStatement.close();
1314:                            }
1315:                        }
1316:
1317:                        try {
1318:                            if (numValuesPerBatch > 0) {
1319:
1320:                                if (this .retrieveGeneratedKeys) {
1321:                                    batchedStatement = locallyScopedConn
1322:                                            .prepareStatement(
1323:                                                    generateMultiStatementForBatch(numValuesPerBatch),
1324:                                                    RETURN_GENERATED_KEYS);
1325:                                } else {
1326:                                    batchedStatement = locallyScopedConn
1327:                                            .prepareStatement(generateMultiStatementForBatch(numValuesPerBatch));
1328:                                }
1329:
1330:                                if (timeoutTask != null) {
1331:                                    timeoutTask.toCancel = (StatementImpl) batchedStatement;
1332:                                }
1333:
1334:                                batchedParamIndex = 1;
1335:
1336:                                while (batchCounter < numBatchedArgs) {
1337:                                    batchedParamIndex = setOneBatchedParameterSet(
1338:                                            batchedStatement,
1339:                                            batchedParamIndex, this .batchedArgs
1340:                                                    .get(batchCounter++));
1341:                                }
1342:
1343:                                try {
1344:                                    batchedStatement.execute();
1345:                                } catch (SQLException ex) {
1346:                                    sqlEx = handleExceptionForBatch(
1347:                                            batchCounter - 1,
1348:                                            numValuesPerBatch, updateCounts, ex);
1349:                                }
1350:
1351:                                updateCountCounter = processMultiCountsAndKeys(
1352:                                        (StatementImpl) batchedStatement,
1353:                                        updateCountCounter, updateCounts);
1354:
1355:                                batchedStatement.clearParameters();
1356:                            }
1357:
1358:                            if (timeoutTask != null) {
1359:                                if (timeoutTask.caughtWhileCancelling != null) {
1360:                                    throw timeoutTask.caughtWhileCancelling;
1361:                                }
1362:
1363:                                timeoutTask.cancel();
1364:                                timeoutTask = null;
1365:                            }
1366:
1367:                            if (sqlEx != null) {
1368:                                throw new java.sql.BatchUpdateException(sqlEx
1369:                                        .getMessage(), sqlEx.getSQLState(),
1370:                                        sqlEx.getErrorCode(), updateCounts);
1371:                            }
1372:
1373:                            return updateCounts;
1374:                        } finally {
1375:                            if (batchedStatement != null) {
1376:                                batchedStatement.close();
1377:                            }
1378:                        }
1379:                    } finally {
1380:                        if (timeoutTask != null) {
1381:                            timeoutTask.cancel();
1382:                        }
1383:
1384:                        resetCancelledState();
1385:
1386:                        if (!multiQueriesEnabled) {
1387:                            locallyScopedConn.getIO().disableMultiQueries();
1388:                        }
1389:
1390:                        clearBatch();
1391:                    }
1392:                }
1393:            }
1394:
1395:            private String generateMultiStatementForBatch(int numBatches) {
1396:                StringBuffer newStatementSql = new StringBuffer(
1397:                        (this .originalSql.length() + 1) * numBatches);
1398:
1399:                newStatementSql.append(this .originalSql);
1400:
1401:                for (int i = 0; i < numBatches - 1; i++) {
1402:                    newStatementSql.append(';');
1403:                    newStatementSql.append(this .originalSql);
1404:                }
1405:
1406:                return newStatementSql.toString();
1407:            }
1408:
1409:            /**
1410:             * Rewrites the already prepared statement into a multi-value insert
1411:             * statement of 'statementsPerBatch' values and executes the entire batch
1412:             * using this new statement.
1413:             * 
1414:             * @return update counts in the same fashion as executeBatch()
1415:             * 
1416:             * @throws SQLException
1417:             */
1418:            protected int[] executeBatchedInserts(int batchTimeout)
1419:                    throws SQLException {
1420:                String valuesClause = extractValuesClause();
1421:
1422:                Connection locallyScopedConn = this .connection;
1423:
1424:                if (valuesClause == null) {
1425:                    return executeBatchSerially(batchTimeout);
1426:                }
1427:
1428:                int numBatchedArgs = this .batchedArgs.size();
1429:
1430:                if (this .retrieveGeneratedKeys) {
1431:                    this .batchedGeneratedKeys = new ArrayList(numBatchedArgs);
1432:                }
1433:
1434:                int numValuesPerBatch = computeBatchSize(numBatchedArgs);
1435:
1436:                if (numBatchedArgs < numValuesPerBatch) {
1437:                    numValuesPerBatch = numBatchedArgs;
1438:                }
1439:
1440:                java.sql.PreparedStatement batchedStatement = null;
1441:
1442:                int batchedParamIndex = 1;
1443:                int updateCountRunningTotal = 0;
1444:                int numberToExecuteAsMultiValue = 0;
1445:                int batchCounter = 0;
1446:                CancelTask timeoutTask = null;
1447:                SQLException sqlEx = null;
1448:
1449:                int[] updateCounts = new int[numBatchedArgs];
1450:
1451:                for (int i = 0; i < this .batchedArgs.size(); i++) {
1452:                    updateCounts[i] = 1;
1453:                }
1454:
1455:                try {
1456:                    try {
1457:                        if (this .retrieveGeneratedKeys) {
1458:                            batchedStatement = locallyScopedConn
1459:                                    .prepareStatement(generateBatchedInsertSQL(
1460:                                            valuesClause, numValuesPerBatch),
1461:                                            RETURN_GENERATED_KEYS);
1462:                        } else {
1463:                            batchedStatement = locallyScopedConn
1464:                                    .prepareStatement(generateBatchedInsertSQL(
1465:                                            valuesClause, numValuesPerBatch));
1466:                        }
1467:
1468:                        if (this .connection.getEnableQueryTimeouts()
1469:                                && batchTimeout != 0
1470:                                && this .connection.versionMeetsMinimum(5, 0, 0)) {
1471:                            timeoutTask = new CancelTask(
1472:                                    (StatementImpl) batchedStatement);
1473:                            ConnectionImpl.getCancelTimer().schedule(
1474:                                    timeoutTask, batchTimeout);
1475:                        }
1476:
1477:                        if (numBatchedArgs < numValuesPerBatch) {
1478:                            numberToExecuteAsMultiValue = numBatchedArgs;
1479:                        } else {
1480:                            numberToExecuteAsMultiValue = numBatchedArgs
1481:                                    / numValuesPerBatch;
1482:                        }
1483:
1484:                        int numberArgsToExecute = numberToExecuteAsMultiValue
1485:                                * numValuesPerBatch;
1486:
1487:                        for (int i = 0; i < numberArgsToExecute; i++) {
1488:                            if (i != 0 && i % numValuesPerBatch == 0) {
1489:                                try {
1490:                                    updateCountRunningTotal += batchedStatement
1491:                                            .executeUpdate();
1492:                                } catch (SQLException ex) {
1493:                                    sqlEx = handleExceptionForBatch(
1494:                                            batchCounter - 1,
1495:                                            numValuesPerBatch, updateCounts, ex);
1496:                                }
1497:
1498:                                getBatchedGeneratedKeys(batchedStatement);
1499:                                batchedStatement.clearParameters();
1500:                                batchedParamIndex = 1;
1501:
1502:                            }
1503:
1504:                            batchedParamIndex = setOneBatchedParameterSet(
1505:                                    batchedStatement, batchedParamIndex,
1506:                                    this .batchedArgs.get(batchCounter++));
1507:                        }
1508:
1509:                        try {
1510:                            updateCountRunningTotal += batchedStatement
1511:                                    .executeUpdate();
1512:                        } catch (SQLException ex) {
1513:                            sqlEx = handleExceptionForBatch(batchCounter - 1,
1514:                                    numValuesPerBatch, updateCounts, ex);
1515:                        }
1516:
1517:                        getBatchedGeneratedKeys(batchedStatement);
1518:
1519:                        numValuesPerBatch = numBatchedArgs - batchCounter;
1520:                    } finally {
1521:                        if (batchedStatement != null) {
1522:                            batchedStatement.close();
1523:                        }
1524:                    }
1525:
1526:                    try {
1527:                        if (numValuesPerBatch > 0) {
1528:
1529:                            if (this .retrieveGeneratedKeys) {
1530:                                batchedStatement = locallyScopedConn
1531:                                        .prepareStatement(
1532:                                                generateBatchedInsertSQL(
1533:                                                        valuesClause,
1534:                                                        numValuesPerBatch),
1535:                                                RETURN_GENERATED_KEYS);
1536:                            } else {
1537:                                batchedStatement = locallyScopedConn
1538:                                        .prepareStatement(generateBatchedInsertSQL(
1539:                                                valuesClause, numValuesPerBatch));
1540:                            }
1541:
1542:                            if (timeoutTask != null) {
1543:                                timeoutTask.toCancel = (StatementImpl) batchedStatement;
1544:                            }
1545:
1546:                            batchedParamIndex = 1;
1547:
1548:                            while (batchCounter < numBatchedArgs) {
1549:                                batchedParamIndex = setOneBatchedParameterSet(
1550:                                        batchedStatement, batchedParamIndex,
1551:                                        this .batchedArgs.get(batchCounter++));
1552:                            }
1553:
1554:                            try {
1555:                                updateCountRunningTotal += batchedStatement
1556:                                        .executeUpdate();
1557:                            } catch (SQLException ex) {
1558:                                sqlEx = handleExceptionForBatch(
1559:                                        batchCounter - 1, numValuesPerBatch,
1560:                                        updateCounts, ex);
1561:                            }
1562:
1563:                            getBatchedGeneratedKeys(batchedStatement);
1564:                        }
1565:
1566:                        if (sqlEx != null) {
1567:                            throw new java.sql.BatchUpdateException(sqlEx
1568:                                    .getMessage(), sqlEx.getSQLState(), sqlEx
1569:                                    .getErrorCode(), updateCounts);
1570:                        }
1571:
1572:                        return updateCounts;
1573:                    } finally {
1574:                        if (batchedStatement != null) {
1575:                            batchedStatement.close();
1576:                        }
1577:                    }
1578:                } finally {
1579:                    if (timeoutTask != null) {
1580:                        timeoutTask.cancel();
1581:                    }
1582:
1583:                    resetCancelledState();
1584:                }
1585:            }
1586:
1587:            /**
1588:             * Computes the optimum number of batched parameter lists to send
1589:             * without overflowing max_allowed_packet.
1590:             * 
1591:             * @param numBatchedArgs
1592:             * @return
1593:             */
1594:            protected int computeBatchSize(int numBatchedArgs) {
1595:                long[] combinedValues = computeMaxParameterSetSizeAndBatchSize(numBatchedArgs);
1596:
1597:                long maxSizeOfParameterSet = combinedValues[0];
1598:                long sizeOfEntireBatch = combinedValues[1];
1599:
1600:                int maxAllowedPacket = this .connection.getMaxAllowedPacket();
1601:
1602:                if (sizeOfEntireBatch < maxAllowedPacket
1603:                        - this .originalSql.length()) {
1604:                    return numBatchedArgs;
1605:                }
1606:
1607:                return (int) Math.max(1, (maxAllowedPacket - this .originalSql
1608:                        .length())
1609:                        / maxSizeOfParameterSet);
1610:            }
1611:
1612:            /** 
1613:             *  Computes the maximum parameter set size, and entire batch size given 
1614:             *  the number of arguments in the batch.
1615:             */
1616:            protected long[] computeMaxParameterSetSizeAndBatchSize(
1617:                    int numBatchedArgs) {
1618:                long sizeOfEntireBatch = 0;
1619:                long maxSizeOfParameterSet = 0;
1620:
1621:                for (int i = 0; i < numBatchedArgs; i++) {
1622:                    BatchParams paramArg = (BatchParams) this .batchedArgs
1623:                            .get(i);
1624:
1625:                    boolean[] isNullBatch = paramArg.isNull;
1626:                    boolean[] isStreamBatch = paramArg.isStream;
1627:
1628:                    long sizeOfParameterSet = 0;
1629:
1630:                    for (int j = 0; j < isNullBatch.length; j++) {
1631:                        if (!isNullBatch[j]) {
1632:
1633:                            if (isStreamBatch[j]) {
1634:                                int streamLength = paramArg.streamLengths[j];
1635:
1636:                                if (streamLength != -1) {
1637:                                    sizeOfParameterSet += streamLength * 2; // for safety in escaping
1638:                                } else {
1639:                                    int paramLength = paramArg.parameterStrings[j].length;
1640:                                    sizeOfParameterSet += paramLength;
1641:                                }
1642:                            } else {
1643:                                sizeOfParameterSet += paramArg.parameterStrings[j].length;
1644:                            }
1645:                        } else {
1646:                            sizeOfParameterSet += 4; // for NULL literal in SQL 
1647:                        }
1648:                    }
1649:
1650:                    //
1651:                    // Account for static part of values clause
1652:                    // This is a little naiive, because the ?s will be replaced
1653:                    // but it gives us some padding, and is less housekeeping
1654:                    // to ignore them. We're looking for a "fuzzy" value here
1655:                    // anyway
1656:                    //
1657:
1658:                    if (this .batchedValuesClause != null) {
1659:                        sizeOfParameterSet += this .batchedValuesClause.length() + 1;
1660:                    }
1661:
1662:                    sizeOfEntireBatch += sizeOfParameterSet;
1663:
1664:                    if (sizeOfParameterSet > maxSizeOfParameterSet) {
1665:                        maxSizeOfParameterSet = sizeOfParameterSet;
1666:                    }
1667:                }
1668:
1669:                return new long[] { maxSizeOfParameterSet, sizeOfEntireBatch };
1670:            }
1671:
1672:            /**
1673:             * Executes the current batch of statements by executing them one-by-one.
1674:             * 
1675:             * @return a list of update counts
1676:             * @throws SQLException
1677:             *             if an error occurs
1678:             */
1679:            protected int[] executeBatchSerially(int batchTimeout)
1680:                    throws SQLException {
1681:
1682:                Connection locallyScopedConn = this .connection;
1683:
1684:                if (locallyScopedConn == null) {
1685:                    checkClosed();
1686:                }
1687:
1688:                int[] updateCounts = null;
1689:
1690:                if (this .batchedArgs != null) {
1691:                    int nbrCommands = this .batchedArgs.size();
1692:                    updateCounts = new int[nbrCommands];
1693:
1694:                    for (int i = 0; i < nbrCommands; i++) {
1695:                        updateCounts[i] = -3;
1696:                    }
1697:
1698:                    SQLException sqlEx = null;
1699:
1700:                    int commandIndex = 0;
1701:
1702:                    CancelTask timeoutTask = null;
1703:
1704:                    try {
1705:                        if (this .connection.getEnableQueryTimeouts()
1706:                                && batchTimeout != 0
1707:                                && this .connection.versionMeetsMinimum(5, 0, 0)) {
1708:                            timeoutTask = new CancelTask(this );
1709:                            ConnectionImpl.getCancelTimer().schedule(
1710:                                    timeoutTask, batchTimeout);
1711:                        }
1712:
1713:                        if (this .retrieveGeneratedKeys) {
1714:                            this .batchedGeneratedKeys = new ArrayList(
1715:                                    nbrCommands);
1716:                        }
1717:
1718:                        for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
1719:                            Object arg = this .batchedArgs.get(commandIndex);
1720:
1721:                            if (arg instanceof  String) {
1722:                                updateCounts[commandIndex] = executeUpdate((String) arg);
1723:                            } else {
1724:                                BatchParams paramArg = (BatchParams) arg;
1725:
1726:                                try {
1727:                                    updateCounts[commandIndex] = executeUpdate(
1728:                                            paramArg.parameterStrings,
1729:                                            paramArg.parameterStreams,
1730:                                            paramArg.isStream,
1731:                                            paramArg.streamLengths,
1732:                                            paramArg.isNull, true);
1733:
1734:                                    if (this .retrieveGeneratedKeys) {
1735:                                        java.sql.ResultSet rs = null;
1736:
1737:                                        try {
1738:                                            rs = getGeneratedKeysInternal();
1739:
1740:                                            while (rs.next()) {
1741:                                                this .batchedGeneratedKeys
1742:                                                        .add(new ByteArrayRow(
1743:                                                                new byte[][] { rs
1744:                                                                        .getBytes(1) }));
1745:                                            }
1746:                                        } finally {
1747:                                            if (rs != null) {
1748:                                                rs.close();
1749:                                            }
1750:                                        }
1751:                                    }
1752:                                } catch (SQLException ex) {
1753:                                    updateCounts[commandIndex] = EXECUTE_FAILED;
1754:
1755:                                    if (this .continueBatchOnError
1756:                                            && !(ex instanceof  MySQLTimeoutException)
1757:                                            && !(ex instanceof  MySQLStatementCancelledException)) {
1758:                                        sqlEx = ex;
1759:                                    } else {
1760:                                        int[] newUpdateCounts = new int[commandIndex];
1761:                                        System.arraycopy(updateCounts, 0,
1762:                                                newUpdateCounts, 0,
1763:                                                commandIndex);
1764:
1765:                                        throw new java.sql.BatchUpdateException(
1766:                                                ex.getMessage(), ex
1767:                                                        .getSQLState(), ex
1768:                                                        .getErrorCode(),
1769:                                                newUpdateCounts);
1770:                                    }
1771:                                }
1772:                            }
1773:                        }
1774:
1775:                        if (sqlEx != null) {
1776:                            throw new java.sql.BatchUpdateException(sqlEx
1777:                                    .getMessage(), sqlEx.getSQLState(), sqlEx
1778:                                    .getErrorCode(), updateCounts);
1779:                        }
1780:                    } finally {
1781:                        if (timeoutTask != null) {
1782:                            timeoutTask.cancel();
1783:                        }
1784:
1785:                        resetCancelledState();
1786:                    }
1787:                }
1788:
1789:                return (updateCounts != null) ? updateCounts : new int[0];
1790:
1791:            }
1792:
1793:            /**
1794:             * Actually execute the prepared statement. This is here so server-side
1795:             * PreparedStatements can re-use most of the code from this class.
1796:             * 
1797:             * @param maxRowsToRetrieve
1798:             *            the max number of rows to return
1799:             * @param sendPacket
1800:             *            the packet to send
1801:             * @param createStreamingResultSet
1802:             *            should a 'streaming' result set be created?
1803:             * @param queryIsSelectOnly
1804:             *            is this query doing a SELECT?
1805:             * @param unpackFields
1806:             *            DOCUMENT ME!
1807:             * 
1808:             * @return the results as a ResultSet
1809:             * 
1810:             * @throws SQLException
1811:             *             if an error occurs.
1812:             */
1813:            protected ResultSetInternalMethods executeInternal(
1814:                    int maxRowsToRetrieve, Buffer sendPacket,
1815:                    boolean createStreamingResultSet,
1816:                    boolean queryIsSelectOnly, Field[] metadataFromCache,
1817:                    boolean isBatch) throws SQLException {
1818:                try {
1819:
1820:                    resetCancelledState();
1821:
1822:                    ConnectionImpl locallyScopedConnection = this .connection;
1823:
1824:                    this .numberOfExecutions++;
1825:
1826:                    if (this .doPingInstead) {
1827:                        doPingInstead();
1828:
1829:                        return this .results;
1830:                    }
1831:
1832:                    ResultSetInternalMethods rs;
1833:
1834:                    CancelTask timeoutTask = null;
1835:
1836:                    try {
1837:                        if (locallyScopedConnection.getEnableQueryTimeouts()
1838:                                && this .timeoutInMillis != 0
1839:                                && locallyScopedConnection.versionMeetsMinimum(
1840:                                        5, 0, 0)) {
1841:                            timeoutTask = new CancelTask(this );
1842:                            ConnectionImpl.getCancelTimer().schedule(
1843:                                    timeoutTask, this .timeoutInMillis);
1844:                        }
1845:
1846:                        rs = locallyScopedConnection.execSQL(this , null,
1847:                                maxRowsToRetrieve, sendPacket,
1848:                                this .resultSetType, this .resultSetConcurrency,
1849:                                createStreamingResultSet, this .currentCatalog,
1850:                                metadataFromCache, isBatch);
1851:
1852:                        if (timeoutTask != null) {
1853:                            timeoutTask.cancel();
1854:
1855:                            if (timeoutTask.caughtWhileCancelling != null) {
1856:                                throw timeoutTask.caughtWhileCancelling;
1857:                            }
1858:
1859:                            timeoutTask = null;
1860:                        }
1861:
1862:                        synchronized (this .cancelTimeoutMutex) {
1863:                            if (this .wasCancelled) {
1864:                                SQLException cause = null;
1865:
1866:                                if (this .wasCancelledByTimeout) {
1867:                                    cause = new MySQLTimeoutException();
1868:                                } else {
1869:                                    cause = new MySQLStatementCancelledException();
1870:                                }
1871:
1872:                                resetCancelledState();
1873:
1874:                                throw cause;
1875:                            }
1876:                        }
1877:                    } finally {
1878:                        if (timeoutTask != null) {
1879:                            timeoutTask.cancel();
1880:                        }
1881:                    }
1882:
1883:                    return rs;
1884:                } catch (NullPointerException npe) {
1885:                    checkClosed(); // we can't synchronize ourselves against async connection-close
1886:                    // due to deadlock issues, so this is the next best thing for
1887:                    // this particular corner case.
1888:
1889:                    throw npe;
1890:                }
1891:            }
1892:
1893:            /**
1894:             * A Prepared SQL query is executed and its ResultSet is returned
1895:             * 
1896:             * @return a ResultSet that contains the data produced by the query - never
1897:             *         null
1898:             * 
1899:             * @exception SQLException
1900:             *                if a database access error occurs
1901:             */
1902:            public java.sql.ResultSet executeQuery() throws SQLException {
1903:                checkClosed();
1904:
1905:                ConnectionImpl locallyScopedConn = this .connection;
1906:
1907:                checkForDml(this .originalSql, this .firstCharOfStmt);
1908:
1909:                CachedResultSetMetaData cachedMetadata = null;
1910:
1911:                // We need to execute this all together
1912:                // So synchronize on the Connection's mutex (because
1913:                // even queries going through there synchronize
1914:                // on the same mutex.
1915:                synchronized (locallyScopedConn.getMutex()) {
1916:                    clearWarnings();
1917:
1918:                    boolean doStreaming = createStreamingResultSet();
1919:
1920:                    this .batchedGeneratedKeys = null;
1921:
1922:                    // Adjust net_write_timeout to a higher value if we're
1923:                    // streaming result sets. More often than not, someone runs into
1924:                    // an issue where they blow net_write_timeout when using this
1925:                    // feature, and if they're willing to hold a result set open
1926:                    // for 30 seconds or more, one more round-trip isn't going to hurt
1927:                    //
1928:                    // This is reset by RowDataDynamic.close().
1929:
1930:                    if (doStreaming
1931:                            && this .connection
1932:                                    .getNetTimeoutForStreamingResults() > 0) {
1933:                        locallyScopedConn
1934:                                .execSQL(
1935:                                        this ,
1936:                                        "SET net_write_timeout="
1937:                                                + this .connection
1938:                                                        .getNetTimeoutForStreamingResults(),
1939:                                        -1, null, ResultSet.TYPE_FORWARD_ONLY,
1940:                                        ResultSet.CONCUR_READ_ONLY, false,
1941:                                        this .currentCatalog, null, false);
1942:                    }
1943:
1944:                    Buffer sendPacket = fillSendPacket();
1945:
1946:                    if (this .results != null) {
1947:                        if (!this .connection
1948:                                .getHoldResultsOpenOverStatementClose()) {
1949:                            if (!this .holdResultsOpenOverClose) {
1950:                                this .results.realClose(false);
1951:                            }
1952:                        }
1953:                    }
1954:
1955:                    String oldCatalog = null;
1956:
1957:                    if (!locallyScopedConn.getCatalog().equals(
1958:                            this .currentCatalog)) {
1959:                        oldCatalog = locallyScopedConn.getCatalog();
1960:                        locallyScopedConn.setCatalog(this .currentCatalog);
1961:                    }
1962:
1963:                    //
1964:                    // Check if we have cached metadata for this query...
1965:                    //
1966:                    if (locallyScopedConn.getCacheResultSetMetadata()) {
1967:                        cachedMetadata = locallyScopedConn
1968:                                .getCachedMetaData(this .originalSql);
1969:                    }
1970:
1971:                    Field[] metadataFromCache = null;
1972:
1973:                    if (cachedMetadata != null) {
1974:                        metadataFromCache = cachedMetadata.fields;
1975:                    }
1976:
1977:                    if (locallyScopedConn.useMaxRows()) {
1978:                        // If there isn't a limit clause in the SQL
1979:                        // then limit the number of rows to return in
1980:                        // an efficient manner. Only do this if
1981:                        // setMaxRows() hasn't been used on any Statements
1982:                        // generated from the current Connection (saves
1983:                        // a query, and network traffic).
1984:                        if (this .hasLimitClause) {
1985:                            this .results = executeInternal(this .maxRows,
1986:                                    sendPacket, createStreamingResultSet(),
1987:                                    true, metadataFromCache, false);
1988:                        } else {
1989:                            if (this .maxRows <= 0) {
1990:                                executeSimpleNonQuery(locallyScopedConn,
1991:                                        "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
1992:                            } else {
1993:                                executeSimpleNonQuery(locallyScopedConn,
1994:                                        "SET OPTION SQL_SELECT_LIMIT="
1995:                                                + this .maxRows);
1996:                            }
1997:
1998:                            this .results = executeInternal(-1, sendPacket,
1999:                                    doStreaming, true, metadataFromCache, false);
2000:
2001:                            if (oldCatalog != null) {
2002:                                this .connection.setCatalog(oldCatalog);
2003:                            }
2004:                        }
2005:                    } else {
2006:                        this .results = executeInternal(-1, sendPacket,
2007:                                doStreaming, true, metadataFromCache, false);
2008:                    }
2009:
2010:                    if (oldCatalog != null) {
2011:                        locallyScopedConn.setCatalog(oldCatalog);
2012:                    }
2013:
2014:                    if (cachedMetadata != null) {
2015:                        locallyScopedConn.initializeResultsMetadataFromCache(
2016:                                this .originalSql, cachedMetadata, this .results);
2017:                    } else {
2018:                        if (locallyScopedConn.getCacheResultSetMetadata()) {
2019:                            locallyScopedConn
2020:                                    .initializeResultsMetadataFromCache(
2021:                                            this .originalSql,
2022:                                            null /* will be created */,
2023:                                            this .results);
2024:                        }
2025:                    }
2026:                }
2027:
2028:                this .lastInsertId = this .results.getUpdateID();
2029:
2030:                return this .results;
2031:            }
2032:
2033:            /**
2034:             * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
2035:             * statements that return nothing such as SQL DDL statements can be
2036:             * executed.
2037:             * 
2038:             * @return either the row count for INSERT, UPDATE or DELETE; or 0 for SQL
2039:             *         statements that return nothing.
2040:             * 
2041:             * @exception SQLException
2042:             *                if a database access error occurs
2043:             */
2044:            public int executeUpdate() throws SQLException {
2045:                return executeUpdate(true, false);
2046:            }
2047:
2048:            /*
2049:             * We need this variant, because ServerPreparedStatement calls this for
2050:             * batched updates, which will end up clobbering the warnings and generated
2051:             * keys we need to gather for the batch.
2052:             */
2053:            protected int executeUpdate(
2054:                    boolean clearBatchedGeneratedKeysAndWarnings,
2055:                    boolean isBatch) throws SQLException {
2056:                if (clearBatchedGeneratedKeysAndWarnings) {
2057:                    clearWarnings();
2058:                    this .batchedGeneratedKeys = null;
2059:                }
2060:
2061:                return executeUpdate(this .parameterValues,
2062:                        this .parameterStreams, this .isStream,
2063:                        this .streamLengths, this .isNull, isBatch);
2064:            }
2065:
2066:            /**
2067:             * Added to allow batch-updates
2068:             * 
2069:             * @param batchedParameterStrings
2070:             *            string values used in single statement
2071:             * @param batchedParameterStreams
2072:             *            stream values used in single statement
2073:             * @param batchedIsStream
2074:             *            flags for streams used in single statement
2075:             * @param batchedStreamLengths
2076:             *            lengths of streams to be read.
2077:             * @param batchedIsNull
2078:             *            flags for parameters that are null
2079:             * 
2080:             * @return the update count
2081:             * 
2082:             * @throws SQLException
2083:             *             if a database error occurs
2084:             */
2085:            protected int executeUpdate(byte[][] batchedParameterStrings,
2086:                    InputStream[] batchedParameterStreams,
2087:                    boolean[] batchedIsStream, int[] batchedStreamLengths,
2088:                    boolean[] batchedIsNull, boolean isReallyBatch)
2089:                    throws SQLException {
2090:
2091:                checkClosed();
2092:
2093:                ConnectionImpl locallyScopedConn = this .connection;
2094:
2095:                if (locallyScopedConn.isReadOnly()) {
2096:                    throw SQLError.createSQLException(Messages
2097:                            .getString("PreparedStatement.34") //$NON-NLS-1$
2098:                            + Messages.getString("PreparedStatement.35"), //$NON-NLS-1$
2099:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2100:                }
2101:
2102:                if ((this .firstCharOfStmt == 'S') && isSelectQuery()) { //$NON-NLS-1$
2103:                    throw SQLError.createSQLException(Messages
2104:                            .getString("PreparedStatement.37"), //$NON-NLS-1$
2105:                            "01S03"); //$NON-NLS-1$
2106:                }
2107:
2108:                if (this .results != null) {
2109:                    if (!locallyScopedConn
2110:                            .getHoldResultsOpenOverStatementClose()) {
2111:                        this .results.realClose(false);
2112:                    }
2113:                }
2114:
2115:                ResultSetInternalMethods rs = null;
2116:
2117:                // The checking and changing of catalogs
2118:                // must happen in sequence, so synchronize
2119:                // on the same mutex that _conn is using
2120:                synchronized (locallyScopedConn.getMutex()) {
2121:                    Buffer sendPacket = fillSendPacket(batchedParameterStrings,
2122:                            batchedParameterStreams, batchedIsStream,
2123:                            batchedStreamLengths);
2124:
2125:                    String oldCatalog = null;
2126:
2127:                    if (!locallyScopedConn.getCatalog().equals(
2128:                            this .currentCatalog)) {
2129:                        oldCatalog = locallyScopedConn.getCatalog();
2130:                        locallyScopedConn.setCatalog(this .currentCatalog);
2131:                    }
2132:
2133:                    //
2134:                    // Only apply max_rows to selects
2135:                    //
2136:                    if (locallyScopedConn.useMaxRows()) {
2137:                        executeSimpleNonQuery(locallyScopedConn,
2138:                                "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
2139:                    }
2140:
2141:                    boolean oldInfoMsgState = false;
2142:
2143:                    if (this .retrieveGeneratedKeys) {
2144:                        oldInfoMsgState = locallyScopedConn
2145:                                .isReadInfoMsgEnabled();
2146:                        locallyScopedConn.setReadInfoMsgEnabled(true);
2147:                    }
2148:
2149:                    rs = executeInternal(-1, sendPacket, false, false, null,
2150:                            isReallyBatch);
2151:
2152:                    if (this .retrieveGeneratedKeys) {
2153:                        locallyScopedConn
2154:                                .setReadInfoMsgEnabled(oldInfoMsgState);
2155:                        rs.setFirstCharOfQuery(this .firstCharOfStmt);
2156:                    }
2157:
2158:                    if (oldCatalog != null) {
2159:                        locallyScopedConn.setCatalog(oldCatalog);
2160:                    }
2161:                }
2162:
2163:                this .results = rs;
2164:
2165:                this .updateCount = rs.getUpdateCount();
2166:
2167:                int truncatedUpdateCount = 0;
2168:
2169:                if (this .updateCount > Integer.MAX_VALUE) {
2170:                    truncatedUpdateCount = Integer.MAX_VALUE;
2171:                } else {
2172:                    truncatedUpdateCount = (int) this .updateCount;
2173:                }
2174:
2175:                this .lastInsertId = rs.getUpdateID();
2176:
2177:                return truncatedUpdateCount;
2178:            }
2179:
2180:            private String extractValuesClause() throws SQLException {
2181:                if (this .batchedValuesClause == null) {
2182:                    String quoteCharStr = this .connection.getMetaData()
2183:                            .getIdentifierQuoteString();
2184:
2185:                    int indexOfValues = -1;
2186:
2187:                    if (quoteCharStr.length() > 0) {
2188:                        indexOfValues = StringUtils
2189:                                .indexOfIgnoreCaseRespectQuotes(
2190:                                        this .statementAfterCommentsPos,
2191:                                        this .originalSql, "VALUES ",
2192:                                        quoteCharStr.charAt(0), false);
2193:                    } else {
2194:                        indexOfValues = StringUtils.indexOfIgnoreCase(
2195:                                this .statementAfterCommentsPos,
2196:                                this .originalSql, "VALUES ");
2197:                    }
2198:
2199:                    if (indexOfValues == -1) {
2200:                        return null;
2201:                    }
2202:
2203:                    int indexOfFirstParen = this .originalSql.indexOf('(',
2204:                            indexOfValues + 7);
2205:
2206:                    if (indexOfFirstParen == -1) {
2207:                        return null;
2208:                    }
2209:
2210:                    int indexOfLastParen = this .originalSql.lastIndexOf(')');
2211:
2212:                    if (indexOfLastParen == -1) {
2213:                        return null;
2214:                    }
2215:
2216:                    this .batchedValuesClause = this .originalSql.substring(
2217:                            indexOfFirstParen, indexOfLastParen + 1);
2218:                }
2219:
2220:                return this .batchedValuesClause;
2221:            }
2222:
2223:            /**
2224:             * Creates the packet that contains the query to be sent to the server.
2225:             * 
2226:             * @return A Buffer filled with the query representing the
2227:             *         PreparedStatement.
2228:             * 
2229:             * @throws SQLException
2230:             *             if an error occurs.
2231:             */
2232:            protected Buffer fillSendPacket() throws SQLException {
2233:                return fillSendPacket(this .parameterValues,
2234:                        this .parameterStreams, this .isStream,
2235:                        this .streamLengths);
2236:            }
2237:
2238:            /**
2239:             * Creates the packet that contains the query to be sent to the server.
2240:             * 
2241:             * @param batchedParameterStrings
2242:             *            the parameters as strings
2243:             * @param batchedParameterStreams
2244:             *            the parameters as streams
2245:             * @param batchedIsStream
2246:             *            is the given parameter a stream?
2247:             * @param batchedStreamLengths
2248:             *            the lengths of the streams (if appropriate)
2249:             * 
2250:             * @return a Buffer filled with the query that represents this statement
2251:             * 
2252:             * @throws SQLException
2253:             *             if an error occurs.
2254:             */
2255:            protected Buffer fillSendPacket(byte[][] batchedParameterStrings,
2256:                    InputStream[] batchedParameterStreams,
2257:                    boolean[] batchedIsStream, int[] batchedStreamLengths)
2258:                    throws SQLException {
2259:                Buffer sendPacket = this .connection.getIO()
2260:                        .getSharedSendPacket();
2261:
2262:                sendPacket.clear();
2263:
2264:                sendPacket.writeByte((byte) MysqlDefs.QUERY);
2265:
2266:                boolean useStreamLengths = this .connection
2267:                        .getUseStreamLengthsInPrepStmts();
2268:
2269:                //
2270:                // Try and get this allocation as close as possible
2271:                // for BLOBs
2272:                //
2273:                int ensurePacketSize = 0;
2274:
2275:                String statementComment = this .connection.getStatementComment();
2276:
2277:                byte[] commentAsBytes = null;
2278:
2279:                if (statementComment != null) {
2280:                    if (this .charConverter != null) {
2281:                        commentAsBytes = this .charConverter
2282:                                .toBytes(statementComment);
2283:                    } else {
2284:                        commentAsBytes = StringUtils.getBytes(statementComment,
2285:                                this .charConverter, this .charEncoding,
2286:                                this .connection.getServerCharacterEncoding(),
2287:                                this .connection.parserKnowsUnicode());
2288:                    }
2289:
2290:                    ensurePacketSize += commentAsBytes.length;
2291:                    ensurePacketSize += 6; // for /*[space] [space]*/
2292:                }
2293:
2294:                for (int i = 0; i < batchedParameterStrings.length; i++) {
2295:                    if (batchedIsStream[i] && useStreamLengths) {
2296:                        ensurePacketSize += batchedStreamLengths[i];
2297:                    }
2298:                }
2299:
2300:                if (ensurePacketSize != 0) {
2301:                    sendPacket.ensureCapacity(ensurePacketSize);
2302:                }
2303:
2304:                if (commentAsBytes != null) {
2305:                    sendPacket
2306:                            .writeBytesNoNull(Constants.SLASH_STAR_SPACE_AS_BYTES);
2307:                    sendPacket.writeBytesNoNull(commentAsBytes);
2308:                    sendPacket
2309:                            .writeBytesNoNull(Constants.SPACE_STAR_SLASH_SPACE_AS_BYTES);
2310:                }
2311:
2312:                for (int i = 0; i < batchedParameterStrings.length; i++) {
2313:                    if ((batchedParameterStrings[i] == null)
2314:                            && (batchedParameterStreams[i] == null)) {
2315:                        throw SQLError.createSQLException(Messages
2316:                                .getString("PreparedStatement.40") //$NON-NLS-1$
2317:                                + (i + 1),
2318:                                SQLError.SQL_STATE_WRONG_NO_OF_PARAMETERS);
2319:                    }
2320:
2321:                    sendPacket.writeBytesNoNull(this .staticSqlStrings[i]);
2322:
2323:                    if (batchedIsStream[i]) {
2324:                        streamToBytes(sendPacket, batchedParameterStreams[i],
2325:                                true, batchedStreamLengths[i], useStreamLengths);
2326:                    } else {
2327:                        sendPacket.writeBytesNoNull(batchedParameterStrings[i]);
2328:                    }
2329:                }
2330:
2331:                sendPacket
2332:                        .writeBytesNoNull(this .staticSqlStrings[batchedParameterStrings.length]);
2333:
2334:                return sendPacket;
2335:            }
2336:
2337:            private String generateBatchedInsertSQL(String valuesClause,
2338:                    int numBatches) {
2339:                StringBuffer newStatementSql = new StringBuffer(
2340:                        this .originalSql.length()
2341:                                + (numBatches * (valuesClause.length() + 1)));
2342:
2343:                newStatementSql.append(this .originalSql);
2344:
2345:                for (int i = 0; i < numBatches - 1; i++) {
2346:                    newStatementSql.append(',');
2347:                    newStatementSql.append(valuesClause);
2348:                }
2349:
2350:                return newStatementSql.toString();
2351:            }
2352:
2353:            /**
2354:             * DOCUMENT ME!
2355:             * 
2356:             * @param parameterIndex
2357:             *            DOCUMENT ME!
2358:             * 
2359:             * @return DOCUMENT ME!
2360:             * 
2361:             * @throws SQLException
2362:             *             DOCUMENT ME!
2363:             */
2364:            public byte[] getBytesRepresentation(int parameterIndex)
2365:                    throws SQLException {
2366:                if (this .isStream[parameterIndex]) {
2367:                    return streamToBytes(this .parameterStreams[parameterIndex],
2368:                            false, this .streamLengths[parameterIndex],
2369:                            this .connection.getUseStreamLengthsInPrepStmts());
2370:                }
2371:
2372:                byte[] parameterVal = this .parameterValues[parameterIndex];
2373:
2374:                if (parameterVal == null) {
2375:                    return null;
2376:                }
2377:
2378:                if ((parameterVal[0] == '\'')
2379:                        && (parameterVal[parameterVal.length - 1] == '\'')) {
2380:                    byte[] valNoQuotes = new byte[parameterVal.length - 2];
2381:                    System.arraycopy(parameterVal, 1, valNoQuotes, 0,
2382:                            parameterVal.length - 2);
2383:
2384:                    return valNoQuotes;
2385:                }
2386:
2387:                return parameterVal;
2388:            }
2389:
2390:            // --------------------------JDBC 2.0-----------------------------
2391:
2392:            private final String getDateTimePattern(String dt, boolean toTime)
2393:                    throws Exception {
2394:                //
2395:                // Special case
2396:                //
2397:                int dtLength = (dt != null) ? dt.length() : 0;
2398:
2399:                if ((dtLength >= 8) && (dtLength <= 10)) {
2400:                    int dashCount = 0;
2401:                    boolean isDateOnly = true;
2402:
2403:                    for (int i = 0; i < dtLength; i++) {
2404:                        char c = dt.charAt(i);
2405:
2406:                        if (!Character.isDigit(c) && (c != '-')) {
2407:                            isDateOnly = false;
2408:
2409:                            break;
2410:                        }
2411:
2412:                        if (c == '-') {
2413:                            dashCount++;
2414:                        }
2415:                    }
2416:
2417:                    if (isDateOnly && (dashCount == 2)) {
2418:                        return "yyyy-MM-dd"; //$NON-NLS-1$
2419:                    }
2420:                }
2421:
2422:                //
2423:                // Special case - time-only
2424:                //
2425:                boolean colonsOnly = true;
2426:
2427:                for (int i = 0; i < dtLength; i++) {
2428:                    char c = dt.charAt(i);
2429:
2430:                    if (!Character.isDigit(c) && (c != ':')) {
2431:                        colonsOnly = false;
2432:
2433:                        break;
2434:                    }
2435:                }
2436:
2437:                if (colonsOnly) {
2438:                    return "HH:mm:ss"; //$NON-NLS-1$
2439:                }
2440:
2441:                int n;
2442:                int z;
2443:                int count;
2444:                int maxvecs;
2445:                char c;
2446:                char separator;
2447:                StringReader reader = new StringReader(dt + " "); //$NON-NLS-1$
2448:                ArrayList vec = new ArrayList();
2449:                ArrayList vecRemovelist = new ArrayList();
2450:                Object[] nv = new Object[3];
2451:                Object[] v;
2452:                nv[0] = Constants.characterValueOf('y');
2453:                nv[1] = new StringBuffer();
2454:                nv[2] = Constants.integerValueOf(0);
2455:                vec.add(nv);
2456:
2457:                if (toTime) {
2458:                    nv = new Object[3];
2459:                    nv[0] = Constants.characterValueOf('h');
2460:                    nv[1] = new StringBuffer();
2461:                    nv[2] = Constants.integerValueOf(0);
2462:                    vec.add(nv);
2463:                }
2464:
2465:                while ((z = reader.read()) != -1) {
2466:                    separator = (char) z;
2467:                    maxvecs = vec.size();
2468:
2469:                    for (count = 0; count < maxvecs; count++) {
2470:                        v = (Object[]) vec.get(count);
2471:                        n = ((Integer) v[2]).intValue();
2472:                        c = getSuccessor(((Character) v[0]).charValue(), n);
2473:
2474:                        if (!Character.isLetterOrDigit(separator)) {
2475:                            if ((c == ((Character) v[0]).charValue())
2476:                                    && (c != 'S')) {
2477:                                vecRemovelist.add(v);
2478:                            } else {
2479:                                ((StringBuffer) v[1]).append(separator);
2480:
2481:                                if ((c == 'X') || (c == 'Y')) {
2482:                                    v[2] = Constants.integerValueOf(4);
2483:                                }
2484:                            }
2485:                        } else {
2486:                            if (c == 'X') {
2487:                                c = 'y';
2488:                                nv = new Object[3];
2489:                                nv[1] = (new StringBuffer(((StringBuffer) v[1])
2490:                                        .toString())).append('M');
2491:                                nv[0] = Constants.characterValueOf('M');
2492:                                nv[2] = Constants.integerValueOf(1);
2493:                                vec.add(nv);
2494:                            } else if (c == 'Y') {
2495:                                c = 'M';
2496:                                nv = new Object[3];
2497:                                nv[1] = (new StringBuffer(((StringBuffer) v[1])
2498:                                        .toString())).append('d');
2499:                                nv[0] = Constants.characterValueOf('d');
2500:                                nv[2] = Constants.integerValueOf(1);
2501:                                vec.add(nv);
2502:                            }
2503:
2504:                            ((StringBuffer) v[1]).append(c);
2505:
2506:                            if (c == ((Character) v[0]).charValue()) {
2507:                                v[2] = Constants.integerValueOf(n + 1);
2508:                            } else {
2509:                                v[0] = Constants.characterValueOf(c);
2510:                                v[2] = Constants.integerValueOf(1);
2511:                            }
2512:                        }
2513:                    }
2514:
2515:                    int size = vecRemovelist.size();
2516:
2517:                    for (int i = 0; i < size; i++) {
2518:                        v = (Object[]) vecRemovelist.get(i);
2519:                        vec.remove(v);
2520:                    }
2521:
2522:                    vecRemovelist.clear();
2523:                }
2524:
2525:                int size = vec.size();
2526:
2527:                for (int i = 0; i < size; i++) {
2528:                    v = (Object[]) vec.get(i);
2529:                    c = ((Character) v[0]).charValue();
2530:                    n = ((Integer) v[2]).intValue();
2531:
2532:                    boolean bk = getSuccessor(c, n) != c;
2533:                    boolean atEnd = (((c == 's') || (c == 'm') || ((c == 'h') && toTime)) && bk);
2534:                    boolean finishesAtDate = (bk && (c == 'd') && !toTime);
2535:                    boolean containsEnd = (((StringBuffer) v[1]).toString()
2536:                            .indexOf('W') != -1);
2537:
2538:                    if ((!atEnd && !finishesAtDate) || (containsEnd)) {
2539:                        vecRemovelist.add(v);
2540:                    }
2541:                }
2542:
2543:                size = vecRemovelist.size();
2544:
2545:                for (int i = 0; i < size; i++) {
2546:                    vec.remove(vecRemovelist.get(i));
2547:                }
2548:
2549:                vecRemovelist.clear();
2550:                v = (Object[]) vec.get(0); // might throw exception
2551:
2552:                StringBuffer format = (StringBuffer) v[1];
2553:                format.setLength(format.length() - 1);
2554:
2555:                return format.toString();
2556:            }
2557:
2558:            /**
2559:             * The number, types and properties of a ResultSet's columns are provided by
2560:             * the getMetaData method.
2561:             * 
2562:             * @return the description of a ResultSet's columns
2563:             * 
2564:             * @exception SQLException
2565:             *                if a database-access error occurs.
2566:             */
2567:            public java.sql.ResultSetMetaData getMetaData() throws SQLException {
2568:
2569:                //
2570:                // We could just tack on a LIMIT 0 here no matter what the 
2571:                // statement, and check if a result set was returned or not,
2572:                // but I'm not comfortable with that, myself, so we take
2573:                // the "safer" road, and only allow metadata for _actual_
2574:                // SELECTS (but not SHOWs).
2575:                // 
2576:                // CALL's are trapped further up and you end up with a 
2577:                // CallableStatement anyway.
2578:                //
2579:
2580:                if (!isSelectQuery()) {
2581:                    return null;
2582:                }
2583:
2584:                PreparedStatement mdStmt = null;
2585:                java.sql.ResultSet mdRs = null;
2586:
2587:                if (this .pstmtResultMetaData == null) {
2588:                    try {
2589:                        mdStmt = new PreparedStatement(this .connection,
2590:                                this .originalSql, this .currentCatalog,
2591:                                this .parseInfo);
2592:
2593:                        mdStmt.setMaxRows(0);
2594:
2595:                        int paramCount = this .parameterValues.length;
2596:
2597:                        for (int i = 1; i <= paramCount; i++) {
2598:                            mdStmt.setString(i, ""); //$NON-NLS-1$
2599:                        }
2600:
2601:                        boolean hadResults = mdStmt.execute();
2602:
2603:                        if (hadResults) {
2604:                            mdRs = mdStmt.getResultSet();
2605:
2606:                            this .pstmtResultMetaData = mdRs.getMetaData();
2607:                        } else {
2608:                            this .pstmtResultMetaData = new ResultSetMetaData(
2609:                                    new Field[0], this .connection
2610:                                            .getUseOldAliasMetadataBehavior());
2611:                        }
2612:                    } finally {
2613:                        SQLException sqlExRethrow = null;
2614:
2615:                        if (mdRs != null) {
2616:                            try {
2617:                                mdRs.close();
2618:                            } catch (SQLException sqlEx) {
2619:                                sqlExRethrow = sqlEx;
2620:                            }
2621:
2622:                            mdRs = null;
2623:                        }
2624:
2625:                        if (mdStmt != null) {
2626:                            try {
2627:                                mdStmt.close();
2628:                            } catch (SQLException sqlEx) {
2629:                                sqlExRethrow = sqlEx;
2630:                            }
2631:
2632:                            mdStmt = null;
2633:                        }
2634:
2635:                        if (sqlExRethrow != null) {
2636:                            throw sqlExRethrow;
2637:                        }
2638:                    }
2639:                }
2640:
2641:                return this .pstmtResultMetaData;
2642:            }
2643:
2644:            protected boolean isSelectQuery() {
2645:                return StringUtils.startsWithIgnoreCaseAndWs(StringUtils
2646:                        .stripComments(this .originalSql, "'\"", "'\"", true,
2647:                                false, true, true), "SELECT");
2648:            }
2649:
2650:            /**
2651:             * @see PreparedStatement#getParameterMetaData()
2652:             */
2653:            public ParameterMetaData getParameterMetaData() throws SQLException {
2654:                if (this .parameterMetaData == null) {
2655:                    if (this .connection.getGenerateSimpleParameterMetadata()) {
2656:                        this .parameterMetaData = new MysqlParameterMetadata(
2657:                                this .parameterCount);
2658:                    } else {
2659:                        this .parameterMetaData = new MysqlParameterMetadata(
2660:                                null, this .parameterCount);
2661:                    }
2662:                }
2663:
2664:                return this .parameterMetaData;
2665:            }
2666:
2667:            ParseInfo getParseInfo() {
2668:                return this .parseInfo;
2669:            }
2670:
2671:            private final char getSuccessor(char c, int n) {
2672:                return ((c == 'y') && (n == 2)) ? 'X'
2673:                        : (((c == 'y') && (n < 4)) ? 'y'
2674:                                : ((c == 'y') ? 'M'
2675:                                        : (((c == 'M') && (n == 2)) ? 'Y'
2676:                                                : (((c == 'M') && (n < 3)) ? 'M'
2677:                                                        : ((c == 'M') ? 'd'
2678:                                                                : (((c == 'd') && (n < 2)) ? 'd'
2679:                                                                        : ((c == 'd') ? 'H'
2680:                                                                                : (((c == 'H') && (n < 2)) ? 'H'
2681:                                                                                        : ((c == 'H') ? 'm'
2682:                                                                                                : (((c == 'm') && (n < 2)) ? 'm'
2683:                                                                                                        : ((c == 'm') ? 's'
2684:                                                                                                                : (((c == 's') && (n < 2)) ? 's'
2685:                                                                                                                        : 'W'))))))))))));
2686:            }
2687:
2688:            /**
2689:             * Used to escape binary data with hex for mb charsets
2690:             * 
2691:             * @param buf
2692:             * @param packet
2693:             * @param size
2694:             * @throws SQLException
2695:             */
2696:            private final void hexEscapeBlock(byte[] buf, Buffer packet,
2697:                    int size) throws SQLException {
2698:                for (int i = 0; i < size; i++) {
2699:                    byte b = buf[i];
2700:                    int lowBits = (b & 0xff) / 16;
2701:                    int highBits = (b & 0xff) % 16;
2702:
2703:                    packet.writeByte(HEX_DIGITS[lowBits]);
2704:                    packet.writeByte(HEX_DIGITS[highBits]);
2705:                }
2706:            }
2707:
2708:            private void initializeFromParseInfo() throws SQLException {
2709:                this .staticSqlStrings = this .parseInfo.staticSql;
2710:                this .hasLimitClause = this .parseInfo.foundLimitClause;
2711:                this .isLoadDataQuery = this .parseInfo.foundLoadData;
2712:                this .firstCharOfStmt = this .parseInfo.firstStmtChar;
2713:
2714:                this .parameterCount = this .staticSqlStrings.length - 1;
2715:
2716:                this .parameterValues = new byte[this .parameterCount][];
2717:                this .parameterStreams = new InputStream[this .parameterCount];
2718:                this .isStream = new boolean[this .parameterCount];
2719:                this .streamLengths = new int[this .parameterCount];
2720:                this .isNull = new boolean[this .parameterCount];
2721:                this .parameterTypes = new int[this .parameterCount];
2722:
2723:                clearParameters();
2724:
2725:                for (int j = 0; j < this .parameterCount; j++) {
2726:                    this .isStream[j] = false;
2727:                }
2728:
2729:                this .statementAfterCommentsPos = this .parseInfo.statementStartPos;
2730:            }
2731:
2732:            boolean isNull(int paramIndex) {
2733:                return this .isNull[paramIndex];
2734:            }
2735:
2736:            private final int readblock(InputStream i, byte[] b)
2737:                    throws SQLException {
2738:                try {
2739:                    return i.read(b);
2740:                } catch (Throwable E) {
2741:                    throw SQLError.createSQLException(Messages
2742:                            .getString("PreparedStatement.56") //$NON-NLS-1$
2743:                            + E.getClass().getName(),
2744:                            SQLError.SQL_STATE_GENERAL_ERROR);
2745:                }
2746:            }
2747:
2748:            private final int readblock(InputStream i, byte[] b, int length)
2749:                    throws SQLException {
2750:                try {
2751:                    int lengthToRead = length;
2752:
2753:                    if (lengthToRead > b.length) {
2754:                        lengthToRead = b.length;
2755:                    }
2756:
2757:                    return i.read(b, 0, lengthToRead);
2758:                } catch (Throwable E) {
2759:                    throw SQLError.createSQLException(Messages
2760:                            .getString("PreparedStatement.55") //$NON-NLS-1$
2761:                            + E.getClass().getName(),
2762:                            SQLError.SQL_STATE_GENERAL_ERROR);
2763:                }
2764:            }
2765:
2766:            /**
2767:             * Closes this statement, releasing all resources
2768:             * 
2769:             * @param calledExplicitly
2770:             *            was this called by close()?
2771:             * 
2772:             * @throws SQLException
2773:             *             if an error occurs
2774:             */
2775:            protected void realClose(boolean calledExplicitly,
2776:                    boolean closeOpenResults) throws SQLException {
2777:                if (this .useUsageAdvisor) {
2778:                    if (this .numberOfExecutions <= 1) {
2779:                        String message = Messages
2780:                                .getString("PreparedStatement.43"); //$NON-NLS-1$
2781:
2782:                        this .eventSink.consumeEvent(new ProfilerEvent(
2783:                                ProfilerEvent.TYPE_WARN,
2784:                                "", this .currentCatalog, //$NON-NLS-1$
2785:                                this .connectionId, this .getId(), -1, System
2786:                                        .currentTimeMillis(), 0,
2787:                                Constants.MILLIS_I18N, null,
2788:                                this .pointOfOrigin, message));
2789:                    }
2790:                }
2791:
2792:                super .realClose(calledExplicitly, closeOpenResults);
2793:
2794:                this .dbmd = null;
2795:                this .originalSql = null;
2796:                this .staticSqlStrings = null;
2797:                this .parameterValues = null;
2798:                this .parameterStreams = null;
2799:                this .isStream = null;
2800:                this .streamLengths = null;
2801:                this .isNull = null;
2802:                this .streamConvertBuf = null;
2803:                this .parameterTypes = null;
2804:            }
2805:
2806:            /**
2807:             * JDBC 2.0 Set an Array parameter.
2808:             * 
2809:             * @param i
2810:             *            the first parameter is 1, the second is 2, ...
2811:             * @param x
2812:             *            an object representing an SQL array
2813:             * 
2814:             * @throws SQLException
2815:             *             because this method is not implemented.
2816:             * @throws NotImplemented
2817:             *             DOCUMENT ME!
2818:             */
2819:            public void setArray(int i, Array x) throws SQLException {
2820:                throw new NotImplemented();
2821:            }
2822:
2823:            /**
2824:             * When a very large ASCII value is input to a LONGVARCHAR parameter, it may
2825:             * be more practical to send it via a java.io.InputStream. JDBC will read
2826:             * the data from the stream as needed, until it reaches end-of-file. The
2827:             * JDBC driver will do any necessary conversion from ASCII to the database
2828:             * char format.
2829:             * 
2830:             * <P>
2831:             * <B>Note:</B> This stream object can either be a standard Java stream
2832:             * object or your own subclass that implements the standard interface.
2833:             * </p>
2834:             * 
2835:             * @param parameterIndex
2836:             *            the first parameter is 1...
2837:             * @param x
2838:             *            the parameter value
2839:             * @param length
2840:             *            the number of bytes in the stream
2841:             * 
2842:             * @exception SQLException
2843:             *                if a database access error occurs
2844:             */
2845:            public void setAsciiStream(int parameterIndex, InputStream x,
2846:                    int length) throws SQLException {
2847:                if (x == null) {
2848:                    setNull(parameterIndex, java.sql.Types.VARCHAR);
2849:                } else {
2850:                    setBinaryStream(parameterIndex, x, length);
2851:                }
2852:            }
2853:
2854:            /**
2855:             * Set a parameter to a java.math.BigDecimal value. The driver converts this
2856:             * to a SQL NUMERIC value when it sends it to the database.
2857:             * 
2858:             * @param parameterIndex
2859:             *            the first parameter is 1...
2860:             * @param x
2861:             *            the parameter value
2862:             * 
2863:             * @exception SQLException
2864:             *                if a database access error occurs
2865:             */
2866:            public void setBigDecimal(int parameterIndex, BigDecimal x)
2867:                    throws SQLException {
2868:                if (x == null) {
2869:                    setNull(parameterIndex, java.sql.Types.DECIMAL);
2870:                } else {
2871:                    setInternal(parameterIndex, StringUtils
2872:                            .fixDecimalExponent(StringUtils
2873:                                    .consistentToString(x)));
2874:
2875:                    this .parameterTypes[parameterIndex - 1
2876:                            + getParameterIndexOffset()] = Types.DECIMAL;
2877:                }
2878:            }
2879:
2880:            /**
2881:             * When a very large binary value is input to a LONGVARBINARY parameter, it
2882:             * may be more practical to send it via a java.io.InputStream. JDBC will
2883:             * read the data from the stream as needed, until it reaches end-of-file.
2884:             * 
2885:             * <P>
2886:             * <B>Note:</B> This stream object can either be a standard Java stream
2887:             * object or your own subclass that implements the standard interface.
2888:             * </p>
2889:             * 
2890:             * @param parameterIndex
2891:             *            the first parameter is 1...
2892:             * @param x
2893:             *            the parameter value
2894:             * @param length
2895:             *            the number of bytes to read from the stream (ignored)
2896:             * 
2897:             * @throws SQLException
2898:             *             if a database access error occurs
2899:             */
2900:            public void setBinaryStream(int parameterIndex, InputStream x,
2901:                    int length) throws SQLException {
2902:                if (x == null) {
2903:                    setNull(parameterIndex, java.sql.Types.BINARY);
2904:                } else {
2905:                    int parameterIndexOffset = getParameterIndexOffset();
2906:
2907:                    if ((parameterIndex < 1)
2908:                            || (parameterIndex > this .staticSqlStrings.length)) {
2909:                        throw SQLError
2910:                                .createSQLException(
2911:                                        Messages
2912:                                                .getString("PreparedStatement.2") //$NON-NLS-1$
2913:                                                + parameterIndex
2914:                                                + Messages
2915:                                                        .getString("PreparedStatement.3") + this .staticSqlStrings.length + Messages.getString("PreparedStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$
2916:                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2917:                    } else if (parameterIndexOffset == -1
2918:                            && parameterIndex == 1) {
2919:                        throw SQLError
2920:                                .createSQLException(
2921:                                        "Can't set IN parameter for return value of stored function call.",
2922:                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2923:                    }
2924:
2925:                    this .parameterStreams[parameterIndex - 1
2926:                            + parameterIndexOffset] = x;
2927:                    this .isStream[parameterIndex - 1 + parameterIndexOffset] = true;
2928:                    this .streamLengths[parameterIndex - 1
2929:                            + parameterIndexOffset] = length;
2930:                    this .isNull[parameterIndex - 1 + parameterIndexOffset] = false;
2931:                    this .parameterTypes[parameterIndex - 1
2932:                            + getParameterIndexOffset()] = Types.BLOB;
2933:                }
2934:            }
2935:
2936:            public void setBlob(int parameterIndex, InputStream inputStream,
2937:                    long length) throws SQLException {
2938:                setBinaryStream(parameterIndex, inputStream, (int) length);
2939:            }
2940:
2941:            /**
2942:             * JDBC 2.0 Set a BLOB parameter.
2943:             * 
2944:             * @param i
2945:             *            the first parameter is 1, the second is 2, ...
2946:             * @param x
2947:             *            an object representing a BLOB
2948:             * 
2949:             * @throws SQLException
2950:             *             if a database error occurs
2951:             */
2952:            public void setBlob(int i, java.sql.Blob x) throws SQLException {
2953:                if (x == null) {
2954:                    setNull(i, Types.BLOB);
2955:                } else {
2956:                    ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
2957:
2958:                    bytesOut.write('\'');
2959:                    escapeblockFast(x.getBytes(1, (int) x.length()), bytesOut,
2960:                            (int) x.length());
2961:                    bytesOut.write('\'');
2962:
2963:                    setInternal(i, bytesOut.toByteArray());
2964:
2965:                    this .parameterTypes[i - 1 + getParameterIndexOffset()] = Types.BLOB;
2966:                }
2967:            }
2968:
2969:            /**
2970:             * Set a parameter to a Java boolean value. The driver converts this to a
2971:             * SQL BIT value when it sends it to the database.
2972:             * 
2973:             * @param parameterIndex
2974:             *            the first parameter is 1...
2975:             * @param x
2976:             *            the parameter value
2977:             * 
2978:             * @throws SQLException
2979:             *             if a database access error occurs
2980:             */
2981:            public void setBoolean(int parameterIndex, boolean x)
2982:                    throws SQLException {
2983:                if (this .useTrueBoolean) {
2984:                    setInternal(parameterIndex, x ? "1" : "0"); //$NON-NLS-1$ //$NON-NLS-2$
2985:                } else {
2986:                    setInternal(parameterIndex, x ? "'t'" : "'f'"); //$NON-NLS-1$ //$NON-NLS-2$
2987:
2988:                    this .parameterTypes[parameterIndex - 1
2989:                            + getParameterIndexOffset()] = Types.BOOLEAN;
2990:                }
2991:            }
2992:
2993:            /**
2994:             * Set a parameter to a Java byte value. The driver converts this to a SQL
2995:             * TINYINT value when it sends it to the database.
2996:             * 
2997:             * @param parameterIndex
2998:             *            the first parameter is 1...
2999:             * @param x
3000:             *            the parameter value
3001:             * 
3002:             * @exception SQLException
3003:             *                if a database access error occurs
3004:             */
3005:            public void setByte(int parameterIndex, byte x) throws SQLException {
3006:                setInternal(parameterIndex, String.valueOf(x));
3007:
3008:                this .parameterTypes[parameterIndex - 1
3009:                        + getParameterIndexOffset()] = Types.TINYINT;
3010:            }
3011:
3012:            /**
3013:             * Set a parameter to a Java array of bytes. The driver converts this to a
3014:             * SQL VARBINARY or LONGVARBINARY (depending on the argument's size relative
3015:             * to the driver's limits on VARBINARYs) when it sends it to the database.
3016:             * 
3017:             * @param parameterIndex
3018:             *            the first parameter is 1...
3019:             * @param x
3020:             *            the parameter value
3021:             * 
3022:             * @exception SQLException
3023:             *                if a database access error occurs
3024:             */
3025:            public void setBytes(int parameterIndex, byte[] x)
3026:                    throws SQLException {
3027:                setBytes(parameterIndex, x, true, true);
3028:
3029:                if (x != null) {
3030:                    this .parameterTypes[parameterIndex - 1
3031:                            + getParameterIndexOffset()] = Types.BINARY;
3032:                }
3033:            }
3034:
3035:            protected void setBytes(int parameterIndex, byte[] x,
3036:                    boolean checkForIntroducer, boolean escapeForMBChars)
3037:                    throws SQLException {
3038:                if (x == null) {
3039:                    setNull(parameterIndex, java.sql.Types.BINARY);
3040:                } else {
3041:                    String connectionEncoding = this .connection.getEncoding();
3042:
3043:                    if (this .connection.isNoBackslashEscapesSet()
3044:                            || (escapeForMBChars
3045:                                    && this .connection.getUseUnicode()
3046:                                    && connectionEncoding != null && CharsetMapping
3047:                                    .isMultibyteCharset(connectionEncoding))) {
3048:
3049:                        // Send as hex
3050:
3051:                        ByteArrayOutputStream bOut = new ByteArrayOutputStream(
3052:                                (x.length * 2) + 3);
3053:                        bOut.write('x');
3054:                        bOut.write('\'');
3055:
3056:                        for (int i = 0; i < x.length; i++) {
3057:                            int lowBits = (x[i] & 0xff) / 16;
3058:                            int highBits = (x[i] & 0xff) % 16;
3059:
3060:                            bOut.write(HEX_DIGITS[lowBits]);
3061:                            bOut.write(HEX_DIGITS[highBits]);
3062:                        }
3063:
3064:                        bOut.write('\'');
3065:
3066:                        setInternal(parameterIndex, bOut.toByteArray());
3067:
3068:                        return;
3069:                    }
3070:
3071:                    // escape them
3072:                    int numBytes = x.length;
3073:
3074:                    int pad = 2;
3075:
3076:                    boolean needsIntroducer = checkForIntroducer
3077:                            && this .connection.versionMeetsMinimum(4, 1, 0);
3078:
3079:                    if (needsIntroducer) {
3080:                        pad += 7;
3081:                    }
3082:
3083:                    ByteArrayOutputStream bOut = new ByteArrayOutputStream(
3084:                            numBytes + pad);
3085:
3086:                    if (needsIntroducer) {
3087:                        bOut.write('_');
3088:                        bOut.write('b');
3089:                        bOut.write('i');
3090:                        bOut.write('n');
3091:                        bOut.write('a');
3092:                        bOut.write('r');
3093:                        bOut.write('y');
3094:                    }
3095:                    bOut.write('\'');
3096:
3097:                    for (int i = 0; i < numBytes; ++i) {
3098:                        byte b = x[i];
3099:
3100:                        switch (b) {
3101:                        case 0: /* Must be escaped for 'mysql' */
3102:                            bOut.write('\\');
3103:                            bOut.write('0');
3104:
3105:                            break;
3106:
3107:                        case '\n': /* Must be escaped for logs */
3108:                            bOut.write('\\');
3109:                            bOut.write('n');
3110:
3111:                            break;
3112:
3113:                        case '\r':
3114:                            bOut.write('\\');
3115:                            bOut.write('r');
3116:
3117:                            break;
3118:
3119:                        case '\\':
3120:                            bOut.write('\\');
3121:                            bOut.write('\\');
3122:
3123:                            break;
3124:
3125:                        case '\'':
3126:                            bOut.write('\\');
3127:                            bOut.write('\'');
3128:
3129:                            break;
3130:
3131:                        case '"': /* Better safe than sorry */
3132:                            bOut.write('\\');
3133:                            bOut.write('"');
3134:
3135:                            break;
3136:
3137:                        case '\032': /* This gives problems on Win32 */
3138:                            bOut.write('\\');
3139:                            bOut.write('Z');
3140:
3141:                            break;
3142:
3143:                        default:
3144:                            bOut.write(b);
3145:                        }
3146:                    }
3147:
3148:                    bOut.write('\'');
3149:
3150:                    setInternal(parameterIndex, bOut.toByteArray());
3151:                }
3152:            }
3153:
3154:            /**
3155:             * Used by updatable result sets for refreshRow() because the parameter has
3156:             * already been escaped for updater or inserter prepared statements.
3157:             * 
3158:             * @param parameterIndex
3159:             *            the parameter to set.
3160:             * @param parameterAsBytes
3161:             *            the parameter as a string.
3162:             * 
3163:             * @throws SQLException
3164:             *             if an error occurs
3165:             */
3166:            protected void setBytesNoEscape(int parameterIndex,
3167:                    byte[] parameterAsBytes) throws SQLException {
3168:                byte[] parameterWithQuotes = new byte[parameterAsBytes.length + 2];
3169:                parameterWithQuotes[0] = '\'';
3170:                System.arraycopy(parameterAsBytes, 0, parameterWithQuotes, 1,
3171:                        parameterAsBytes.length);
3172:                parameterWithQuotes[parameterAsBytes.length + 1] = '\'';
3173:
3174:                setInternal(parameterIndex, parameterWithQuotes);
3175:            }
3176:
3177:            protected void setBytesNoEscapeNoQuotes(int parameterIndex,
3178:                    byte[] parameterAsBytes) throws SQLException {
3179:                setInternal(parameterIndex, parameterAsBytes);
3180:            }
3181:
3182:            /**
3183:             * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR
3184:             * parameter, it may be more practical to send it via a java.io.Reader. JDBC
3185:             * will read the data from the stream as needed, until it reaches
3186:             * end-of-file. The JDBC driver will do any necessary conversion from
3187:             * UNICODE to the database char format.
3188:             * 
3189:             * <P>
3190:             * <B>Note:</B> This stream object can either be a standard Java stream
3191:             * object or your own subclass that implements the standard interface.
3192:             * </p>
3193:             * 
3194:             * @param parameterIndex
3195:             *            the first parameter is 1, the second is 2, ...
3196:             * @param reader
3197:             *            the java reader which contains the UNICODE data
3198:             * @param length
3199:             *            the number of characters in the stream
3200:             * 
3201:             * @exception SQLException
3202:             *                if a database-access error occurs.
3203:             */
3204:            public void setCharacterStream(int parameterIndex,
3205:                    java.io.Reader reader, int length) throws SQLException {
3206:                try {
3207:                    if (reader == null) {
3208:                        setNull(parameterIndex, Types.LONGVARCHAR);
3209:                    } else {
3210:                        char[] c = null;
3211:                        int len = 0;
3212:
3213:                        boolean useLength = this .connection
3214:                                .getUseStreamLengthsInPrepStmts();
3215:
3216:                        String forcedEncoding = this .connection
3217:                                .getClobCharacterEncoding();
3218:
3219:                        if (useLength && (length != -1)) {
3220:                            c = new char[length];
3221:
3222:                            int numCharsRead = readFully(reader, c, length); // blocks
3223:                            // until
3224:                            // all
3225:                            // read
3226:
3227:                            if (forcedEncoding == null) {
3228:                                setString(parameterIndex, new String(c, 0,
3229:                                        numCharsRead));
3230:                            } else {
3231:                                try {
3232:                                    setBytes(parameterIndex, new String(c, 0,
3233:                                            numCharsRead)
3234:                                            .getBytes(forcedEncoding));
3235:                                } catch (UnsupportedEncodingException uee) {
3236:                                    throw SQLError
3237:                                            .createSQLException(
3238:                                                    "Unsupported character encoding "
3239:                                                            + forcedEncoding,
3240:                                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3241:                                }
3242:                            }
3243:                        } else {
3244:                            c = new char[4096];
3245:
3246:                            StringBuffer buf = new StringBuffer();
3247:
3248:                            while ((len = reader.read(c)) != -1) {
3249:                                buf.append(c, 0, len);
3250:                            }
3251:
3252:                            if (forcedEncoding == null) {
3253:                                setString(parameterIndex, buf.toString());
3254:                            } else {
3255:                                try {
3256:                                    setBytes(parameterIndex, buf.toString()
3257:                                            .getBytes(forcedEncoding));
3258:                                } catch (UnsupportedEncodingException uee) {
3259:                                    throw SQLError
3260:                                            .createSQLException(
3261:                                                    "Unsupported character encoding "
3262:                                                            + forcedEncoding,
3263:                                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3264:                                }
3265:                            }
3266:                        }
3267:
3268:                        this .parameterTypes[parameterIndex - 1
3269:                                + getParameterIndexOffset()] = Types.CLOB;
3270:                    }
3271:                } catch (java.io.IOException ioEx) {
3272:                    throw SQLError.createSQLException(ioEx.toString(),
3273:                            SQLError.SQL_STATE_GENERAL_ERROR);
3274:                }
3275:            }
3276:
3277:            /**
3278:             * JDBC 2.0 Set a CLOB parameter.
3279:             * 
3280:             * @param i
3281:             *            the first parameter is 1, the second is 2, ...
3282:             * @param x
3283:             *            an object representing a CLOB
3284:             * 
3285:             * @throws SQLException
3286:             *             if a database error occurs
3287:             */
3288:            public void setClob(int i, Clob x) throws SQLException {
3289:                if (x == null) {
3290:                    setNull(i, Types.CLOB);
3291:                } else {
3292:
3293:                    String forcedEncoding = this .connection
3294:                            .getClobCharacterEncoding();
3295:
3296:                    if (forcedEncoding == null) {
3297:                        setString(i, x.getSubString(1L, (int) x.length()));
3298:                    } else {
3299:                        try {
3300:                            setBytes(i, x.getSubString(1L, (int) x.length())
3301:                                    .getBytes(forcedEncoding));
3302:                        } catch (UnsupportedEncodingException uee) {
3303:                            throw SQLError.createSQLException(
3304:                                    "Unsupported character encoding "
3305:                                            + forcedEncoding,
3306:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3307:                        }
3308:                    }
3309:
3310:                    this .parameterTypes[i - 1 + getParameterIndexOffset()] = Types.CLOB;
3311:                }
3312:            }
3313:
3314:            /**
3315:             * Set a parameter to a java.sql.Date value. The driver converts this to a
3316:             * SQL DATE value when it sends it to the database.
3317:             * 
3318:             * @param parameterIndex
3319:             *            the first parameter is 1...
3320:             * @param x
3321:             *            the parameter value
3322:             * 
3323:             * @exception java.sql.SQLException
3324:             *                if a database access error occurs
3325:             */
3326:            public void setDate(int parameterIndex, java.sql.Date x)
3327:                    throws java.sql.SQLException {
3328:                if (x == null) {
3329:                    setNull(parameterIndex, java.sql.Types.DATE);
3330:                } else {
3331:                    // FIXME: Have instance version of this, problem as it's
3332:                    // not thread-safe :(
3333:                    SimpleDateFormat dateFormatter = new SimpleDateFormat(
3334:                            "''yyyy-MM-dd''", Locale.US); //$NON-NLS-1$
3335:                    setInternal(parameterIndex, dateFormatter.format(x));
3336:
3337:                    this .parameterTypes[parameterIndex - 1
3338:                            + getParameterIndexOffset()] = Types.DATE;
3339:                }
3340:            }
3341:
3342:            /**
3343:             * Set a parameter to a java.sql.Date value. The driver converts this to a
3344:             * SQL DATE value when it sends it to the database.
3345:             * 
3346:             * @param parameterIndex
3347:             *            the first parameter is 1, the second is 2, ...
3348:             * @param x
3349:             *            the parameter value
3350:             * @param cal
3351:             *            the calendar to interpret the date with
3352:             * 
3353:             * @exception SQLException
3354:             *                if a database-access error occurs.
3355:             */
3356:            public void setDate(int parameterIndex, java.sql.Date x,
3357:                    Calendar cal) throws SQLException {
3358:                setDate(parameterIndex, x);
3359:            }
3360:
3361:            /**
3362:             * Set a parameter to a Java double value. The driver converts this to a SQL
3363:             * DOUBLE value when it sends it to the database
3364:             * 
3365:             * @param parameterIndex
3366:             *            the first parameter is 1...
3367:             * @param x
3368:             *            the parameter value
3369:             * 
3370:             * @exception SQLException
3371:             *                if a database access error occurs
3372:             */
3373:            public void setDouble(int parameterIndex, double x)
3374:                    throws SQLException {
3375:
3376:                if (!this .connection.getAllowNanAndInf()
3377:                        && (x == Double.POSITIVE_INFINITY
3378:                                || x == Double.NEGATIVE_INFINITY || Double
3379:                                .isNaN(x))) {
3380:                    throw SQLError
3381:                            .createSQLException(
3382:                                    "'"
3383:                                            + x
3384:                                            + "' is not a valid numeric or approximate numeric value",
3385:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3386:
3387:                }
3388:
3389:                setInternal(parameterIndex, StringUtils
3390:                        .fixDecimalExponent(String.valueOf(x)));
3391:
3392:                this .parameterTypes[parameterIndex - 1
3393:                        + getParameterIndexOffset()] = Types.DOUBLE;
3394:            }
3395:
3396:            /**
3397:             * Set a parameter to a Java float value. The driver converts this to a SQL
3398:             * FLOAT value when it sends it to the database.
3399:             * 
3400:             * @param parameterIndex
3401:             *            the first parameter is 1...
3402:             * @param x
3403:             *            the parameter value
3404:             * 
3405:             * @exception SQLException
3406:             *                if a database access error occurs
3407:             */
3408:            public void setFloat(int parameterIndex, float x)
3409:                    throws SQLException {
3410:                setInternal(parameterIndex, StringUtils
3411:                        .fixDecimalExponent(String.valueOf(x)));
3412:
3413:                this .parameterTypes[parameterIndex - 1
3414:                        + getParameterIndexOffset()] = Types.FLOAT;
3415:            }
3416:
3417:            /**
3418:             * Set a parameter to a Java int value. The driver converts this to a SQL
3419:             * INTEGER value when it sends it to the database.
3420:             * 
3421:             * @param parameterIndex
3422:             *            the first parameter is 1...
3423:             * @param x
3424:             *            the parameter value
3425:             * 
3426:             * @exception SQLException
3427:             *                if a database access error occurs
3428:             */
3429:            public void setInt(int parameterIndex, int x) throws SQLException {
3430:                setInternal(parameterIndex, String.valueOf(x));
3431:
3432:                this .parameterTypes[parameterIndex - 1
3433:                        + getParameterIndexOffset()] = Types.INTEGER;
3434:            }
3435:
3436:            protected final void setInternal(int paramIndex, byte[] val)
3437:                    throws SQLException {
3438:                if (this .isClosed) {
3439:                    throw SQLError.createSQLException(Messages
3440:                            .getString("PreparedStatement.48"), //$NON-NLS-1$
3441:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3442:                }
3443:
3444:                int parameterIndexOffset = getParameterIndexOffset();
3445:
3446:                checkBounds(paramIndex, parameterIndexOffset);
3447:
3448:                this .isStream[paramIndex - 1 + parameterIndexOffset] = false;
3449:                this .isNull[paramIndex - 1 + parameterIndexOffset] = false;
3450:                this .parameterStreams[paramIndex - 1 + parameterIndexOffset] = null;
3451:                this .parameterValues[paramIndex - 1 + parameterIndexOffset] = val;
3452:            }
3453:
3454:            private void checkBounds(int paramIndex, int parameterIndexOffset)
3455:                    throws SQLException {
3456:                if ((paramIndex < 1)) {
3457:                    throw SQLError
3458:                            .createSQLException(
3459:                                    Messages.getString("PreparedStatement.49") //$NON-NLS-1$
3460:                                            + paramIndex
3461:                                            + Messages
3462:                                                    .getString("PreparedStatement.50"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
3463:                } else if (paramIndex > this .parameterCount) {
3464:                    throw SQLError
3465:                            .createSQLException(
3466:                                    Messages.getString("PreparedStatement.51") //$NON-NLS-1$
3467:                                            + paramIndex
3468:                                            + Messages
3469:                                                    .getString("PreparedStatement.52") + (this .parameterValues.length) + Messages.getString("PreparedStatement.53"), //$NON-NLS-1$ //$NON-NLS-2$
3470:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3471:                } else if (parameterIndexOffset == -1 && paramIndex == 1) {
3472:                    throw SQLError
3473:                            .createSQLException(
3474:                                    "Can't set IN parameter for return value of stored function call.",
3475:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3476:                }
3477:            }
3478:
3479:            protected final void setInternal(int paramIndex, String val)
3480:                    throws SQLException {
3481:                checkClosed();
3482:
3483:                byte[] parameterAsBytes = null;
3484:
3485:                if (this .charConverter != null) {
3486:                    parameterAsBytes = this .charConverter.toBytes(val);
3487:                } else {
3488:                    parameterAsBytes = StringUtils.getBytes(val,
3489:                            this .charConverter, this .charEncoding,
3490:                            this .connection.getServerCharacterEncoding(),
3491:                            this .connection.parserKnowsUnicode());
3492:                }
3493:
3494:                setInternal(paramIndex, parameterAsBytes);
3495:            }
3496:
3497:            /**
3498:             * Set a parameter to a Java long value. The driver converts this to a SQL
3499:             * BIGINT value when it sends it to the database.
3500:             * 
3501:             * @param parameterIndex
3502:             *            the first parameter is 1...
3503:             * @param x
3504:             *            the parameter value
3505:             * 
3506:             * @exception SQLException
3507:             *                if a database access error occurs
3508:             */
3509:            public void setLong(int parameterIndex, long x) throws SQLException {
3510:                setInternal(parameterIndex, String.valueOf(x));
3511:
3512:                this .parameterTypes[parameterIndex - 1
3513:                        + getParameterIndexOffset()] = Types.BIGINT;
3514:            }
3515:
3516:            /**
3517:             * Set a parameter to SQL NULL
3518:             * 
3519:             * <p>
3520:             * <B>Note:</B> You must specify the parameters SQL type (although MySQL
3521:             * ignores it)
3522:             * </p>
3523:             * 
3524:             * @param parameterIndex
3525:             *            the first parameter is 1, etc...
3526:             * @param sqlType
3527:             *            the SQL type code defined in java.sql.Types
3528:             * 
3529:             * @exception SQLException
3530:             *                if a database access error occurs
3531:             */
3532:            public void setNull(int parameterIndex, int sqlType)
3533:                    throws SQLException {
3534:                setInternal(parameterIndex, "null"); //$NON-NLS-1$
3535:                this .isNull[parameterIndex - 1] = true;
3536:
3537:                this .parameterTypes[parameterIndex - 1
3538:                        + getParameterIndexOffset()] = Types.NULL;
3539:            }
3540:
3541:            /**
3542:             * Set a parameter to SQL NULL.
3543:             * 
3544:             * <P>
3545:             * <B>Note:</B> You must specify the parameter's SQL type.
3546:             * </p>
3547:             * 
3548:             * @param parameterIndex
3549:             *            the first parameter is 1, the second is 2, ...
3550:             * @param sqlType
3551:             *            SQL type code defined by java.sql.Types
3552:             * @param arg
3553:             *            argument parameters for null
3554:             * 
3555:             * @exception SQLException
3556:             *                if a database-access error occurs.
3557:             */
3558:            public void setNull(int parameterIndex, int sqlType, String arg)
3559:                    throws SQLException {
3560:                setNull(parameterIndex, sqlType);
3561:
3562:                this .parameterTypes[parameterIndex - 1
3563:                        + getParameterIndexOffset()] = Types.NULL;
3564:            }
3565:
3566:            private void setNumericObject(int parameterIndex,
3567:                    Object parameterObj, int targetSqlType, int scale)
3568:                    throws SQLException {
3569:                Number parameterAsNum;
3570:
3571:                if (parameterObj instanceof  Boolean) {
3572:                    parameterAsNum = ((Boolean) parameterObj).booleanValue() ? Constants
3573:                            .integerValueOf(1)
3574:                            : Constants.integerValueOf(0);
3575:                } else if (parameterObj instanceof  String) {
3576:                    switch (targetSqlType) {
3577:                    case Types.BIT:
3578:                        boolean parameterAsBoolean = "true"
3579:                                .equalsIgnoreCase((String) parameterObj);
3580:
3581:                        parameterAsNum = parameterAsBoolean ? Constants
3582:                                .integerValueOf(1) : Constants
3583:                                .integerValueOf(0);
3584:
3585:                        break;
3586:
3587:                    case Types.TINYINT:
3588:                    case Types.SMALLINT:
3589:                    case Types.INTEGER:
3590:                        parameterAsNum = Integer.valueOf((String) parameterObj);
3591:
3592:                        break;
3593:
3594:                    case Types.BIGINT:
3595:                        parameterAsNum = Long.valueOf((String) parameterObj);
3596:
3597:                        break;
3598:
3599:                    case Types.REAL:
3600:                        parameterAsNum = Float.valueOf((String) parameterObj);
3601:
3602:                        break;
3603:
3604:                    case Types.FLOAT:
3605:                    case Types.DOUBLE:
3606:                        parameterAsNum = Double.valueOf((String) parameterObj);
3607:
3608:                        break;
3609:
3610:                    case Types.DECIMAL:
3611:                    case Types.NUMERIC:
3612:                    default:
3613:                        parameterAsNum = new java.math.BigDecimal(
3614:                                (String) parameterObj);
3615:                    }
3616:                } else {
3617:                    parameterAsNum = (Number) parameterObj;
3618:                }
3619:
3620:                switch (targetSqlType) {
3621:                case Types.BIT:
3622:                case Types.TINYINT:
3623:                case Types.SMALLINT:
3624:                case Types.INTEGER:
3625:                    setInt(parameterIndex, parameterAsNum.intValue());
3626:
3627:                    break;
3628:
3629:                case Types.BIGINT:
3630:                    setLong(parameterIndex, parameterAsNum.longValue());
3631:
3632:                    break;
3633:
3634:                case Types.REAL:
3635:                    setFloat(parameterIndex, parameterAsNum.floatValue());
3636:
3637:                    break;
3638:
3639:                case Types.FLOAT:
3640:                case Types.DOUBLE:
3641:                    setDouble(parameterIndex, parameterAsNum.doubleValue());
3642:
3643:                    break;
3644:
3645:                case Types.DECIMAL:
3646:                case Types.NUMERIC:
3647:
3648:                    if (parameterAsNum instanceof  java.math.BigDecimal) {
3649:                        BigDecimal scaledBigDecimal = null;
3650:
3651:                        try {
3652:                            scaledBigDecimal = ((java.math.BigDecimal) parameterAsNum)
3653:                                    .setScale(scale);
3654:                        } catch (ArithmeticException ex) {
3655:                            try {
3656:                                scaledBigDecimal = ((java.math.BigDecimal) parameterAsNum)
3657:                                        .setScale(scale,
3658:                                                BigDecimal.ROUND_HALF_UP);
3659:                            } catch (ArithmeticException arEx) {
3660:                                throw SQLError.createSQLException(
3661:                                        "Can't set scale of '" + scale
3662:                                                + "' for DECIMAL argument '"
3663:                                                + parameterAsNum + "'",
3664:                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3665:                            }
3666:                        }
3667:
3668:                        setBigDecimal(parameterIndex, scaledBigDecimal);
3669:                    } else if (parameterAsNum instanceof  java.math.BigInteger) {
3670:                        setBigDecimal(parameterIndex, new java.math.BigDecimal(
3671:                                (java.math.BigInteger) parameterAsNum, scale));
3672:                    } else {
3673:                        setBigDecimal(parameterIndex, new java.math.BigDecimal(
3674:                                parameterAsNum.doubleValue()));
3675:                    }
3676:
3677:                    break;
3678:                }
3679:            }
3680:
3681:            /**
3682:             * DOCUMENT ME!
3683:             * 
3684:             * @param parameterIndex
3685:             *            DOCUMENT ME!
3686:             * @param parameterObj
3687:             *            DOCUMENT ME!
3688:             * 
3689:             * @throws SQLException
3690:             *             DOCUMENT ME!
3691:             */
3692:            public void setObject(int parameterIndex, Object parameterObj)
3693:                    throws SQLException {
3694:                if (parameterObj == null) {
3695:                    setNull(parameterIndex, java.sql.Types.OTHER);
3696:                } else {
3697:                    if (parameterObj instanceof  Byte) {
3698:                        setInt(parameterIndex, ((Byte) parameterObj).intValue());
3699:                    } else if (parameterObj instanceof  String) {
3700:                        setString(parameterIndex, (String) parameterObj);
3701:                    } else if (parameterObj instanceof  BigDecimal) {
3702:                        setBigDecimal(parameterIndex, (BigDecimal) parameterObj);
3703:                    } else if (parameterObj instanceof  Short) {
3704:                        setShort(parameterIndex, ((Short) parameterObj)
3705:                                .shortValue());
3706:                    } else if (parameterObj instanceof  Integer) {
3707:                        setInt(parameterIndex, ((Integer) parameterObj)
3708:                                .intValue());
3709:                    } else if (parameterObj instanceof  Long) {
3710:                        setLong(parameterIndex, ((Long) parameterObj)
3711:                                .longValue());
3712:                    } else if (parameterObj instanceof  Float) {
3713:                        setFloat(parameterIndex, ((Float) parameterObj)
3714:                                .floatValue());
3715:                    } else if (parameterObj instanceof  Double) {
3716:                        setDouble(parameterIndex, ((Double) parameterObj)
3717:                                .doubleValue());
3718:                    } else if (parameterObj instanceof  byte[]) {
3719:                        setBytes(parameterIndex, (byte[]) parameterObj);
3720:                    } else if (parameterObj instanceof  java.sql.Date) {
3721:                        setDate(parameterIndex, (java.sql.Date) parameterObj);
3722:                    } else if (parameterObj instanceof  Time) {
3723:                        setTime(parameterIndex, (Time) parameterObj);
3724:                    } else if (parameterObj instanceof  Timestamp) {
3725:                        setTimestamp(parameterIndex, (Timestamp) parameterObj);
3726:                    } else if (parameterObj instanceof  Boolean) {
3727:                        setBoolean(parameterIndex, ((Boolean) parameterObj)
3728:                                .booleanValue());
3729:                    } else if (parameterObj instanceof  InputStream) {
3730:                        setBinaryStream(parameterIndex,
3731:                                (InputStream) parameterObj, -1);
3732:                    } else if (parameterObj instanceof  java.sql.Blob) {
3733:                        setBlob(parameterIndex, (java.sql.Blob) parameterObj);
3734:                    } else if (parameterObj instanceof  java.sql.Clob) {
3735:                        setClob(parameterIndex, (java.sql.Clob) parameterObj);
3736:                    } else if (this .connection.getTreatUtilDateAsTimestamp()
3737:                            && parameterObj instanceof  java.util.Date) {
3738:                        setTimestamp(parameterIndex, new Timestamp(
3739:                                ((java.util.Date) parameterObj).getTime()));
3740:                    } else if (parameterObj instanceof  BigInteger) {
3741:                        setString(parameterIndex, parameterObj.toString());
3742:                    } else {
3743:                        setSerializableObject(parameterIndex, parameterObj);
3744:                    }
3745:                }
3746:            }
3747:
3748:            /**
3749:             * DOCUMENT ME!
3750:             * 
3751:             * @param parameterIndex
3752:             *            DOCUMENT ME!
3753:             * @param parameterObj
3754:             *            DOCUMENT ME!
3755:             * @param targetSqlType
3756:             *            DOCUMENT ME!
3757:             * 
3758:             * @throws SQLException
3759:             *             DOCUMENT ME!
3760:             */
3761:            public void setObject(int parameterIndex, Object parameterObj,
3762:                    int targetSqlType) throws SQLException {
3763:                if (!(parameterObj instanceof  BigDecimal)) {
3764:                    setObject(parameterIndex, parameterObj, targetSqlType, 0);
3765:                } else {
3766:                    setObject(parameterIndex, parameterObj, targetSqlType,
3767:                            ((BigDecimal) parameterObj).scale());
3768:                }
3769:            }
3770:
3771:            /**
3772:             * Set the value of a parameter using an object; use the java.lang
3773:             * equivalent objects for integral values.
3774:             * 
3775:             * <P>
3776:             * The given Java object will be converted to the targetSqlType before being
3777:             * sent to the database.
3778:             * </p>
3779:             * 
3780:             * <P>
3781:             * note that this method may be used to pass database-specific abstract data
3782:             * types. This is done by using a Driver-specific Java type and using a
3783:             * targetSqlType of java.sql.Types.OTHER
3784:             * </p>
3785:             * 
3786:             * @param parameterIndex
3787:             *            the first parameter is 1...
3788:             * @param parameterObj
3789:             *            the object containing the input parameter value
3790:             * @param targetSqlType
3791:             *            The SQL type to be send to the database
3792:             * @param scale
3793:             *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3794:             *            this is the number of digits after the decimal. For all other
3795:             *            types this value will be ignored.
3796:             * 
3797:             * @throws SQLException
3798:             *             if a database access error occurs
3799:             */
3800:            public void setObject(int parameterIndex, Object parameterObj,
3801:                    int targetSqlType, int scale) throws SQLException {
3802:                if (parameterObj == null) {
3803:                    setNull(parameterIndex, java.sql.Types.OTHER);
3804:                } else {
3805:                    try {
3806:                        switch (targetSqlType) {
3807:                        case Types.BOOLEAN:
3808:                            /*
3809:                             From Table-B5 in the JDBC-3.0 Spec
3810:                            
3811:                                    T S I B R F D D N B B C V L
3812:                                    I M N I E L O E U I O H A O
3813:                                    N A T G A O U C M T O A R N
3814:                                    Y L E I L A B I E   L R C G
3815:                                    I L G N   T L M R   E   H V
3816:                                    N I E T     E A I   A   A A
3817:                                    T N R         L C   N   R R
3818:                                      T                       C
3819:                                                              H
3820:                                                              A
3821:                                                              R
3822:                            -----------------------------------
3823:                            Boolean x x x x x x x x x x x x x x
3824:                             */
3825:
3826:                            if (parameterObj instanceof  Boolean) {
3827:                                setBoolean(parameterIndex,
3828:                                        ((Boolean) parameterObj).booleanValue());
3829:
3830:                                break;
3831:                            } else if (parameterObj instanceof  String) {
3832:                                setBoolean(
3833:                                        parameterIndex,
3834:                                        "true"
3835:                                                .equalsIgnoreCase((String) parameterObj)
3836:                                                || !"0"
3837:                                                        .equalsIgnoreCase((String) parameterObj));
3838:
3839:                                break;
3840:                            } else if (parameterObj instanceof  Number) {
3841:                                int intValue = ((Number) parameterObj)
3842:                                        .intValue();
3843:
3844:                                setBoolean(parameterIndex, intValue != 0);
3845:
3846:                                break;
3847:                            } else {
3848:                                throw SQLError
3849:                                        .createSQLException(
3850:                                                "No conversion from "
3851:                                                        + parameterObj
3852:                                                                .getClass()
3853:                                                                .getName()
3854:                                                        + " to Types.BOOLEAN possible.",
3855:                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3856:                            }
3857:
3858:                        case Types.BIT:
3859:                        case Types.TINYINT:
3860:                        case Types.SMALLINT:
3861:                        case Types.INTEGER:
3862:                        case Types.BIGINT:
3863:                        case Types.REAL:
3864:                        case Types.FLOAT:
3865:                        case Types.DOUBLE:
3866:                        case Types.DECIMAL:
3867:                        case Types.NUMERIC:
3868:
3869:                            setNumericObject(parameterIndex, parameterObj,
3870:                                    targetSqlType, scale);
3871:
3872:                            break;
3873:
3874:                        case Types.CHAR:
3875:                        case Types.VARCHAR:
3876:                        case Types.LONGVARCHAR:
3877:                            if (parameterObj instanceof  BigDecimal) {
3878:                                setString(
3879:                                        parameterIndex,
3880:                                        (StringUtils
3881:                                                .fixDecimalExponent(StringUtils
3882:                                                        .consistentToString((BigDecimal) parameterObj))));
3883:                            } else {
3884:                                setString(parameterIndex, parameterObj
3885:                                        .toString());
3886:                            }
3887:
3888:                            break;
3889:
3890:                        case Types.CLOB:
3891:
3892:                            if (parameterObj instanceof  java.sql.Clob) {
3893:                                setClob(parameterIndex,
3894:                                        (java.sql.Clob) parameterObj);
3895:                            } else {
3896:                                setString(parameterIndex, parameterObj
3897:                                        .toString());
3898:                            }
3899:
3900:                            break;
3901:
3902:                        case Types.BINARY:
3903:                        case Types.VARBINARY:
3904:                        case Types.LONGVARBINARY:
3905:                        case Types.BLOB:
3906:
3907:                            if (parameterObj instanceof  byte[]) {
3908:                                setBytes(parameterIndex, (byte[]) parameterObj);
3909:                            } else if (parameterObj instanceof  java.sql.Blob) {
3910:                                setBlob(parameterIndex,
3911:                                        (java.sql.Blob) parameterObj);
3912:                            } else {
3913:                                setBytes(parameterIndex, StringUtils.getBytes(
3914:                                        parameterObj.toString(),
3915:                                        this .charConverter, this .charEncoding,
3916:                                        this .connection
3917:                                                .getServerCharacterEncoding(),
3918:                                        this .connection.parserKnowsUnicode()));
3919:                            }
3920:
3921:                            break;
3922:
3923:                        case Types.DATE:
3924:                        case Types.TIMESTAMP:
3925:
3926:                            java.util.Date parameterAsDate;
3927:
3928:                            if (parameterObj instanceof  String) {
3929:                                ParsePosition pp = new ParsePosition(0);
3930:                                java.text.DateFormat sdf = new java.text.SimpleDateFormat(
3931:                                        getDateTimePattern(
3932:                                                (String) parameterObj, false),
3933:                                        Locale.US);
3934:                                parameterAsDate = sdf.parse(
3935:                                        (String) parameterObj, pp);
3936:                            } else {
3937:                                parameterAsDate = (java.util.Date) parameterObj;
3938:                            }
3939:
3940:                            switch (targetSqlType) {
3941:                            case Types.DATE:
3942:
3943:                                if (parameterAsDate instanceof  java.sql.Date) {
3944:                                    setDate(parameterIndex,
3945:                                            (java.sql.Date) parameterAsDate);
3946:                                } else {
3947:                                    setDate(parameterIndex, new java.sql.Date(
3948:                                            parameterAsDate.getTime()));
3949:                                }
3950:
3951:                                break;
3952:
3953:                            case Types.TIMESTAMP:
3954:
3955:                                if (parameterAsDate instanceof  java.sql.Timestamp) {
3956:                                    setTimestamp(
3957:                                            parameterIndex,
3958:                                            (java.sql.Timestamp) parameterAsDate);
3959:                                } else {
3960:                                    setTimestamp(parameterIndex,
3961:                                            new java.sql.Timestamp(
3962:                                                    parameterAsDate.getTime()));
3963:                                }
3964:
3965:                                break;
3966:                            }
3967:
3968:                            break;
3969:
3970:                        case Types.TIME:
3971:
3972:                            if (parameterObj instanceof  String) {
3973:                                java.text.DateFormat sdf = new java.text.SimpleDateFormat(
3974:                                        getDateTimePattern(
3975:                                                (String) parameterObj, true),
3976:                                        Locale.US);
3977:                                setTime(parameterIndex,
3978:                                        new java.sql.Time(sdf.parse(
3979:                                                (String) parameterObj)
3980:                                                .getTime()));
3981:                            } else if (parameterObj instanceof  Timestamp) {
3982:                                Timestamp xT = (Timestamp) parameterObj;
3983:                                setTime(parameterIndex, new java.sql.Time(xT
3984:                                        .getTime()));
3985:                            } else {
3986:                                setTime(parameterIndex,
3987:                                        (java.sql.Time) parameterObj);
3988:                            }
3989:
3990:                            break;
3991:
3992:                        case Types.OTHER:
3993:                            setSerializableObject(parameterIndex, parameterObj);
3994:
3995:                            break;
3996:
3997:                        default:
3998:                            throw SQLError.createSQLException(Messages
3999:                                    .getString("PreparedStatement.16"), //$NON-NLS-1$
4000:                                    SQLError.SQL_STATE_GENERAL_ERROR);
4001:                        }
4002:                    } catch (Exception ex) {
4003:                        if (ex instanceof  SQLException) {
4004:                            throw (SQLException) ex;
4005:                        }
4006:
4007:                        throw SQLError
4008:                                .createSQLException(
4009:                                        Messages
4010:                                                .getString("PreparedStatement.17") //$NON-NLS-1$
4011:                                                + parameterObj.getClass()
4012:                                                        .toString()
4013:                                                + Messages
4014:                                                        .getString("PreparedStatement.18") //$NON-NLS-1$
4015:                                                + ex.getClass().getName()
4016:                                                + Messages
4017:                                                        .getString("PreparedStatement.19") + ex.getMessage(), //$NON-NLS-1$
4018:                                        SQLError.SQL_STATE_GENERAL_ERROR);
4019:                    }
4020:                }
4021:            }
4022:
4023:            protected int setOneBatchedParameterSet(
4024:                    java.sql.PreparedStatement batchedStatement,
4025:                    int batchedParamIndex, Object paramSet) throws SQLException {
4026:                BatchParams paramArg = (BatchParams) paramSet;
4027:
4028:                boolean[] isNullBatch = paramArg.isNull;
4029:                boolean[] isStreamBatch = paramArg.isStream;
4030:
4031:                for (int j = 0; j < isNullBatch.length; j++) {
4032:                    if (isNullBatch[j]) {
4033:                        batchedStatement.setNull(batchedParamIndex++,
4034:                                Types.NULL);
4035:                    } else {
4036:                        if (isStreamBatch[j]) {
4037:                            batchedStatement.setBinaryStream(
4038:                                    batchedParamIndex++,
4039:                                    paramArg.parameterStreams[j],
4040:                                    paramArg.streamLengths[j]);
4041:                        } else {
4042:                            ((com.mysql.jdbc.PreparedStatement) batchedStatement)
4043:                                    .setBytesNoEscapeNoQuotes(
4044:                                            batchedParamIndex++,
4045:                                            paramArg.parameterStrings[j]);
4046:                        }
4047:                    }
4048:                }
4049:
4050:                return batchedParamIndex;
4051:            }
4052:
4053:            /**
4054:             * JDBC 2.0 Set a REF(&lt;structured-type&gt;) parameter.
4055:             * 
4056:             * @param i
4057:             *            the first parameter is 1, the second is 2, ...
4058:             * @param x
4059:             *            an object representing data of an SQL REF Type
4060:             * 
4061:             * @throws SQLException
4062:             *             if a database error occurs
4063:             * @throws NotImplemented
4064:             *             DOCUMENT ME!
4065:             */
4066:            public void setRef(int i, Ref x) throws SQLException {
4067:                throw new NotImplemented();
4068:            }
4069:
4070:            /**
4071:             * Sets the concurrency for result sets generated by this statement
4072:             * 
4073:             * @param concurrencyFlag
4074:             *            DOCUMENT ME!
4075:             */
4076:            void setResultSetConcurrency(int concurrencyFlag) {
4077:                this .resultSetConcurrency = concurrencyFlag;
4078:            }
4079:
4080:            /**
4081:             * Sets the result set type for result sets generated by this statement
4082:             * 
4083:             * @param typeFlag
4084:             *            DOCUMENT ME!
4085:             */
4086:            void setResultSetType(int typeFlag) {
4087:                this .resultSetType = typeFlag;
4088:            }
4089:
4090:            /**
4091:             * DOCUMENT ME!
4092:             * 
4093:             * @param retrieveGeneratedKeys
4094:             */
4095:            protected void setRetrieveGeneratedKeys(
4096:                    boolean retrieveGeneratedKeys) {
4097:                this .retrieveGeneratedKeys = retrieveGeneratedKeys;
4098:            }
4099:
4100:            /**
4101:             * Sets the value for the placeholder as a serialized Java object (used by
4102:             * various forms of setObject()
4103:             * 
4104:             * @param parameterIndex
4105:             *            DOCUMENT ME!
4106:             * @param parameterObj
4107:             *            DOCUMENT ME!
4108:             * 
4109:             * @throws SQLException
4110:             *             DOCUMENT ME!
4111:             */
4112:            private final void setSerializableObject(int parameterIndex,
4113:                    Object parameterObj) throws SQLException {
4114:                try {
4115:                    ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
4116:                    ObjectOutputStream objectOut = new ObjectOutputStream(
4117:                            bytesOut);
4118:                    objectOut.writeObject(parameterObj);
4119:                    objectOut.flush();
4120:                    objectOut.close();
4121:                    bytesOut.flush();
4122:                    bytesOut.close();
4123:
4124:                    byte[] buf = bytesOut.toByteArray();
4125:                    ByteArrayInputStream bytesIn = new ByteArrayInputStream(buf);
4126:                    setBinaryStream(parameterIndex, bytesIn, buf.length);
4127:                    this .parameterTypes[parameterIndex - 1
4128:                            + getParameterIndexOffset()] = Types.JAVA_OBJECT;
4129:                } catch (Exception ex) {
4130:                    throw SQLError.createSQLException(Messages
4131:                            .getString("PreparedStatement.54") //$NON-NLS-1$
4132:                            + ex.getClass().getName(),
4133:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
4134:                }
4135:            }
4136:
4137:            /**
4138:             * Set a parameter to a Java short value. The driver converts this to a SQL
4139:             * SMALLINT value when it sends it to the database.
4140:             * 
4141:             * @param parameterIndex
4142:             *            the first parameter is 1...
4143:             * @param x
4144:             *            the parameter value
4145:             * 
4146:             * @exception SQLException
4147:             *                if a database access error occurs
4148:             */
4149:            public void setShort(int parameterIndex, short x)
4150:                    throws SQLException {
4151:                setInternal(parameterIndex, String.valueOf(x));
4152:
4153:                this .parameterTypes[parameterIndex - 1
4154:                        + getParameterIndexOffset()] = Types.SMALLINT;
4155:            }
4156:
4157:            /**
4158:             * Set a parameter to a Java String value. The driver converts this to a SQL
4159:             * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
4160:             * the driver's limits on VARCHARs) when it sends it to the database.
4161:             * 
4162:             * @param parameterIndex
4163:             *            the first parameter is 1...
4164:             * @param x
4165:             *            the parameter value
4166:             * 
4167:             * @exception SQLException
4168:             *                if a database access error occurs
4169:             */
4170:            public void setString(int parameterIndex, String x)
4171:                    throws SQLException {
4172:                // if the passed string is null, then set this column to null
4173:                if (x == null) {
4174:                    setNull(parameterIndex, Types.CHAR);
4175:                } else {
4176:                    checkClosed();
4177:
4178:                    int stringLength = x.length();
4179:
4180:                    if (this .connection.isNoBackslashEscapesSet()) {
4181:                        // Scan for any nasty chars
4182:
4183:                        boolean needsHexEscape = isEscapeNeededForString(x,
4184:                                stringLength);
4185:
4186:                        if (!needsHexEscape) {
4187:                            byte[] parameterAsBytes = null;
4188:
4189:                            StringBuffer quotedString = new StringBuffer(x
4190:                                    .length() + 2);
4191:                            quotedString.append('\'');
4192:                            quotedString.append(x);
4193:                            quotedString.append('\'');
4194:
4195:                            if (!this .isLoadDataQuery) {
4196:                                parameterAsBytes = StringUtils.getBytes(
4197:                                        quotedString.toString(),
4198:                                        this .charConverter, this .charEncoding,
4199:                                        this .connection
4200:                                                .getServerCharacterEncoding(),
4201:                                        this .connection.parserKnowsUnicode());
4202:                            } else {
4203:                                // Send with platform character encoding
4204:                                parameterAsBytes = quotedString.toString()
4205:                                        .getBytes();
4206:                            }
4207:
4208:                            setInternal(parameterIndex, parameterAsBytes);
4209:                        } else {
4210:                            byte[] parameterAsBytes = null;
4211:
4212:                            if (!this .isLoadDataQuery) {
4213:                                parameterAsBytes = StringUtils.getBytes(x,
4214:                                        this .charConverter, this .charEncoding,
4215:                                        this .connection
4216:                                                .getServerCharacterEncoding(),
4217:                                        this .connection.parserKnowsUnicode());
4218:                            } else {
4219:                                // Send with platform character encoding
4220:                                parameterAsBytes = x.getBytes();
4221:                            }
4222:
4223:                            setBytes(parameterIndex, parameterAsBytes);
4224:                        }
4225:
4226:                        return;
4227:                    }
4228:
4229:                    String parameterAsString = x;
4230:                    boolean needsQuoted = true;
4231:
4232:                    if (this .isLoadDataQuery
4233:                            || isEscapeNeededForString(x, stringLength)) {
4234:                        needsQuoted = false; // saves an allocation later
4235:
4236:                        StringBuffer buf = new StringBuffer(
4237:                                (int) (x.length() * 1.1));
4238:
4239:                        buf.append('\'');
4240:
4241:                        //
4242:                        // Note: buf.append(char) is _faster_ than
4243:                        // appending in blocks, because the block
4244:                        // append requires a System.arraycopy()....
4245:                        // go figure...
4246:                        //
4247:
4248:                        for (int i = 0; i < stringLength; ++i) {
4249:                            char c = x.charAt(i);
4250:
4251:                            switch (c) {
4252:                            case 0: /* Must be escaped for 'mysql' */
4253:                                buf.append('\\');
4254:                                buf.append('0');
4255:
4256:                                break;
4257:
4258:                            case '\n': /* Must be escaped for logs */
4259:                                buf.append('\\');
4260:                                buf.append('n');
4261:
4262:                                break;
4263:
4264:                            case '\r':
4265:                                buf.append('\\');
4266:                                buf.append('r');
4267:
4268:                                break;
4269:
4270:                            case '\\':
4271:                                buf.append('\\');
4272:                                buf.append('\\');
4273:
4274:                                break;
4275:
4276:                            case '\'':
4277:                                buf.append('\\');
4278:                                buf.append('\'');
4279:
4280:                                break;
4281:
4282:                            case '"': /* Better safe than sorry */
4283:                                if (this .usingAnsiMode) {
4284:                                    buf.append('\\');
4285:                                }
4286:
4287:                                buf.append('"');
4288:
4289:                                break;
4290:
4291:                            case '\032': /* This gives problems on Win32 */
4292:                                buf.append('\\');
4293:                                buf.append('Z');
4294:
4295:                                break;
4296:
4297:                            default:
4298:                                buf.append(c);
4299:                            }
4300:                        }
4301:
4302:                        buf.append('\'');
4303:
4304:                        parameterAsString = buf.toString();
4305:                    }
4306:
4307:                    byte[] parameterAsBytes = null;
4308:
4309:                    if (!this .isLoadDataQuery) {
4310:                        if (needsQuoted) {
4311:                            parameterAsBytes = StringUtils.getBytesWrapped(
4312:                                    parameterAsString, '\'', '\'',
4313:                                    this .charConverter, this .charEncoding,
4314:                                    this .connection
4315:                                            .getServerCharacterEncoding(),
4316:                                    this .connection.parserKnowsUnicode());
4317:                        } else {
4318:                            parameterAsBytes = StringUtils.getBytes(
4319:                                    parameterAsString, this .charConverter,
4320:                                    this .charEncoding, this .connection
4321:                                            .getServerCharacterEncoding(),
4322:                                    this .connection.parserKnowsUnicode());
4323:                        }
4324:                    } else {
4325:                        // Send with platform character encoding
4326:                        parameterAsBytes = parameterAsString.getBytes();
4327:                    }
4328:
4329:                    setInternal(parameterIndex, parameterAsBytes);
4330:
4331:                    this .parameterTypes[parameterIndex - 1
4332:                            + getParameterIndexOffset()] = Types.VARCHAR;
4333:                }
4334:            }
4335:
4336:            private boolean isEscapeNeededForString(String x, int stringLength) {
4337:                boolean needsHexEscape = false;
4338:
4339:                for (int i = 0; i < stringLength; ++i) {
4340:                    char c = x.charAt(i);
4341:
4342:                    switch (c) {
4343:                    case 0: /* Must be escaped for 'mysql' */
4344:
4345:                        needsHexEscape = true;
4346:                        break;
4347:
4348:                    case '\n': /* Must be escaped for logs */
4349:                        needsHexEscape = true;
4350:
4351:                        break;
4352:
4353:                    case '\r':
4354:                        needsHexEscape = true;
4355:                        break;
4356:
4357:                    case '\\':
4358:                        needsHexEscape = true;
4359:
4360:                        break;
4361:
4362:                    case '\'':
4363:                        needsHexEscape = true;
4364:
4365:                        break;
4366:
4367:                    case '"': /* Better safe than sorry */
4368:                        needsHexEscape = true;
4369:
4370:                        break;
4371:
4372:                    case '\032': /* This gives problems on Win32 */
4373:                        needsHexEscape = true;
4374:                        break;
4375:                    }
4376:
4377:                    if (needsHexEscape) {
4378:                        break; // no need to scan more
4379:                    }
4380:                }
4381:                return needsHexEscape;
4382:            }
4383:
4384:            /**
4385:             * Set a parameter to a java.sql.Time value. The driver converts this to a
4386:             * SQL TIME value when it sends it to the database.
4387:             * 
4388:             * @param parameterIndex
4389:             *            the first parameter is 1, the second is 2, ...
4390:             * @param x
4391:             *            the parameter value
4392:             * @param cal
4393:             *            the cal specifying the timezone
4394:             * 
4395:             * @throws SQLException
4396:             *             if a database-access error occurs.
4397:             */
4398:            public void setTime(int parameterIndex, java.sql.Time x,
4399:                    Calendar cal) throws SQLException {
4400:                setTimeInternal(parameterIndex, x, cal, cal.getTimeZone(), true);
4401:            }
4402:
4403:            /**
4404:             * Set a parameter to a java.sql.Time value. The driver converts this to a
4405:             * SQL TIME value when it sends it to the database.
4406:             * 
4407:             * @param parameterIndex
4408:             *            the first parameter is 1...));
4409:             * @param x
4410:             *            the parameter value
4411:             * 
4412:             * @throws java.sql.SQLException
4413:             *             if a database access error occurs
4414:             */
4415:            public void setTime(int parameterIndex, Time x)
4416:                    throws java.sql.SQLException {
4417:                setTimeInternal(parameterIndex, x, null, Util
4418:                        .getDefaultTimeZone(), false);
4419:            }
4420:
4421:            /**
4422:             * Set a parameter to a java.sql.Time value. The driver converts this to a
4423:             * SQL TIME value when it sends it to the database, using the given
4424:             * timezone.
4425:             * 
4426:             * @param parameterIndex
4427:             *            the first parameter is 1...));
4428:             * @param x
4429:             *            the parameter value
4430:             * @param tz
4431:             *            the timezone to use
4432:             * 
4433:             * @throws java.sql.SQLException
4434:             *             if a database access error occurs
4435:             */
4436:            private void setTimeInternal(int parameterIndex, Time x,
4437:                    Calendar targetCalendar, TimeZone tz, boolean rollForward)
4438:                    throws java.sql.SQLException {
4439:                if (x == null) {
4440:                    setNull(parameterIndex, java.sql.Types.TIME);
4441:                } else {
4442:                    checkClosed();
4443:
4444:                    Calendar sessionCalendar = getCalendarInstanceForSessionOrNew();
4445:
4446:                    synchronized (sessionCalendar) {
4447:                        x = TimeUtil.changeTimezone(this .connection,
4448:                                sessionCalendar, targetCalendar, x, tz,
4449:                                this .connection.getServerTimezoneTZ(),
4450:                                rollForward);
4451:                    }
4452:
4453:                    setInternal(parameterIndex, "'" + x.toString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
4454:
4455:                    this .parameterTypes[parameterIndex - 1
4456:                            + getParameterIndexOffset()] = Types.TIME;
4457:                }
4458:            }
4459:
4460:            /**
4461:             * Set a parameter to a java.sql.Timestamp value. The driver converts this
4462:             * to a SQL TIMESTAMP value when it sends it to the database.
4463:             * 
4464:             * @param parameterIndex
4465:             *            the first parameter is 1, the second is 2, ...
4466:             * @param x
4467:             *            the parameter value
4468:             * @param cal
4469:             *            the calendar specifying the timezone to use
4470:             * 
4471:             * @throws SQLException
4472:             *             if a database-access error occurs.
4473:             */
4474:            public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
4475:                    Calendar cal) throws SQLException {
4476:                setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(),
4477:                        true);
4478:            }
4479:
4480:            /**
4481:             * Set a parameter to a java.sql.Timestamp value. The driver converts this
4482:             * to a SQL TIMESTAMP value when it sends it to the database.
4483:             * 
4484:             * @param parameterIndex
4485:             *            the first parameter is 1...
4486:             * @param x
4487:             *            the parameter value
4488:             * 
4489:             * @throws java.sql.SQLException
4490:             *             if a database access error occurs
4491:             */
4492:            public void setTimestamp(int parameterIndex, Timestamp x)
4493:                    throws java.sql.SQLException {
4494:                setTimestampInternal(parameterIndex, x, null, Util
4495:                        .getDefaultTimeZone(), false);
4496:            }
4497:
4498:            /**
4499:             * Set a parameter to a java.sql.Timestamp value. The driver converts this
4500:             * to a SQL TIMESTAMP value when it sends it to the database.
4501:             * 
4502:             * @param parameterIndex
4503:             *            the first parameter is 1, the second is 2, ...
4504:             * @param x
4505:             *            the parameter value
4506:             * @param tz
4507:             *            the timezone to use
4508:             * 
4509:             * @throws SQLException
4510:             *             if a database-access error occurs.
4511:             */
4512:            private void setTimestampInternal(int parameterIndex, Timestamp x,
4513:                    Calendar targetCalendar, TimeZone tz, boolean rollForward)
4514:                    throws SQLException {
4515:                if (x == null) {
4516:                    setNull(parameterIndex, java.sql.Types.TIMESTAMP);
4517:                } else {
4518:                    checkClosed();
4519:
4520:                    String timestampString = null;
4521:
4522:                    Calendar sessionCalendar = this .connection
4523:                            .getUseJDBCCompliantTimezoneShift() ? this .connection
4524:                            .getUtcCalendar()
4525:                            : getCalendarInstanceForSessionOrNew();
4526:
4527:                    synchronized (sessionCalendar) {
4528:                        x = TimeUtil.changeTimezone(this .connection,
4529:                                sessionCalendar, targetCalendar, x, tz,
4530:                                this .connection.getServerTimezoneTZ(),
4531:                                rollForward);
4532:                    }
4533:
4534:                    if (this .connection.getUseSSPSCompatibleTimezoneShift()) {
4535:                        doSSPSCompatibleTimezoneShift(parameterIndex, x,
4536:                                sessionCalendar);
4537:                    } else {
4538:
4539:                        if (this .tsdf == null) {
4540:                            this .tsdf = new SimpleDateFormat(
4541:                                    "''yyyy-MM-dd HH:mm:ss''", Locale.US); //$NON-NLS-1$
4542:                        }
4543:
4544:                        timestampString = this .tsdf.format(x);
4545:
4546:                        setInternal(parameterIndex, timestampString); // SimpleDateFormat is not
4547:                        // thread-safe
4548:                    }
4549:
4550:                    this .parameterTypes[parameterIndex - 1
4551:                            + getParameterIndexOffset()] = Types.TIMESTAMP;
4552:                }
4553:            }
4554:
4555:            private void doSSPSCompatibleTimezoneShift(int parameterIndex,
4556:                    Timestamp x, Calendar sessionCalendar) throws SQLException {
4557:                Calendar sessionCalendar2 = (this .connection
4558:                        .getUseJDBCCompliantTimezoneShift()) ? this .connection
4559:                        .getUtcCalendar()
4560:                        : getCalendarInstanceForSessionOrNew();
4561:
4562:                synchronized (sessionCalendar2) {
4563:                    java.util.Date oldTime = sessionCalendar2.getTime();
4564:
4565:                    try {
4566:                        sessionCalendar2.setTime(x);
4567:
4568:                        int year = sessionCalendar2.get(Calendar.YEAR);
4569:                        int month = sessionCalendar2.get(Calendar.MONTH) + 1;
4570:                        int date = sessionCalendar2.get(Calendar.DAY_OF_MONTH);
4571:
4572:                        int hour = sessionCalendar2.get(Calendar.HOUR_OF_DAY);
4573:                        int minute = sessionCalendar2.get(Calendar.MINUTE);
4574:                        int seconds = sessionCalendar2.get(Calendar.SECOND);
4575:
4576:                        StringBuffer tsBuf = new StringBuffer();
4577:
4578:                        tsBuf.append('\'');
4579:                        tsBuf.append(year);
4580:
4581:                        tsBuf.append("-");
4582:
4583:                        if (month < 10) {
4584:                            tsBuf.append('0');
4585:                        }
4586:
4587:                        tsBuf.append(month);
4588:
4589:                        tsBuf.append('-');
4590:
4591:                        if (date < 10) {
4592:                            tsBuf.append('0');
4593:                        }
4594:
4595:                        tsBuf.append(date);
4596:
4597:                        tsBuf.append(' ');
4598:
4599:                        if (hour < 10) {
4600:                            tsBuf.append('0');
4601:                        }
4602:
4603:                        tsBuf.append(hour);
4604:
4605:                        tsBuf.append(':');
4606:
4607:                        if (minute < 10) {
4608:                            tsBuf.append('0');
4609:                        }
4610:
4611:                        tsBuf.append(minute);
4612:
4613:                        tsBuf.append(':');
4614:
4615:                        if (seconds < 10) {
4616:                            tsBuf.append('0');
4617:                        }
4618:
4619:                        tsBuf.append(seconds);
4620:
4621:                        tsBuf.append('\'');
4622:
4623:                        setInternal(parameterIndex, tsBuf.toString());
4624:
4625:                    } finally {
4626:                        sessionCalendar.setTime(oldTime);
4627:                    }
4628:                }
4629:            }
4630:
4631:            /**
4632:             * When a very large Unicode value is input to a LONGVARCHAR parameter, it
4633:             * may be more practical to send it via a java.io.InputStream. JDBC will
4634:             * read the data from the stream as needed, until it reaches end-of-file.
4635:             * The JDBC driver will do any necessary conversion from UNICODE to the
4636:             * database char format.
4637:             * 
4638:             * <P>
4639:             * <B>Note:</B> This stream object can either be a standard Java stream
4640:             * object or your own subclass that implements the standard interface.
4641:             * </p>
4642:             * 
4643:             * @param parameterIndex
4644:             *            the first parameter is 1...
4645:             * @param x
4646:             *            the parameter value
4647:             * @param length
4648:             *            the number of bytes to read from the stream
4649:             * 
4650:             * @throws SQLException
4651:             *             if a database access error occurs
4652:             * 
4653:             * @deprecated
4654:             */
4655:            public void setUnicodeStream(int parameterIndex, InputStream x,
4656:                    int length) throws SQLException {
4657:                if (x == null) {
4658:                    setNull(parameterIndex, java.sql.Types.VARCHAR);
4659:                } else {
4660:                    setBinaryStream(parameterIndex, x, length);
4661:
4662:                    this .parameterTypes[parameterIndex - 1
4663:                            + getParameterIndexOffset()] = Types.CLOB;
4664:                }
4665:            }
4666:
4667:            /**
4668:             * @see PreparedStatement#setURL(int, URL)
4669:             */
4670:            public void setURL(int parameterIndex, URL arg) throws SQLException {
4671:                if (arg != null) {
4672:                    setString(parameterIndex, arg.toString());
4673:
4674:                    this .parameterTypes[parameterIndex - 1
4675:                            + getParameterIndexOffset()] = Types.DATALINK;
4676:                } else {
4677:                    setNull(parameterIndex, Types.CHAR);
4678:                }
4679:            }
4680:
4681:            private final void streamToBytes(Buffer packet, InputStream in,
4682:                    boolean escape, int streamLength, boolean useLength)
4683:                    throws SQLException {
4684:                try {
4685:                    String connectionEncoding = this .connection.getEncoding();
4686:
4687:                    boolean hexEscape = false;
4688:
4689:                    if (this .connection.isNoBackslashEscapesSet()
4690:                            || (this .connection.getUseUnicode()
4691:                                    && connectionEncoding != null
4692:                                    && CharsetMapping
4693:                                            .isMultibyteCharset(connectionEncoding) && !this .connection
4694:                                    .parserKnowsUnicode())) {
4695:                        hexEscape = true;
4696:                    }
4697:
4698:                    if (streamLength == -1) {
4699:                        useLength = false;
4700:                    }
4701:
4702:                    int bc = -1;
4703:
4704:                    if (useLength) {
4705:                        bc = readblock(in, streamConvertBuf, streamLength);
4706:                    } else {
4707:                        bc = readblock(in, streamConvertBuf);
4708:                    }
4709:
4710:                    int lengthLeftToRead = streamLength - bc;
4711:
4712:                    if (hexEscape) {
4713:                        packet.writeStringNoNull("x");
4714:                    } else if (this .connection.getIO().versionMeetsMinimum(4,
4715:                            1, 0)) {
4716:                        packet.writeStringNoNull("_binary");
4717:                    }
4718:
4719:                    if (escape) {
4720:                        packet.writeByte((byte) '\'');
4721:                    }
4722:
4723:                    while (bc > 0) {
4724:                        if (hexEscape) {
4725:                            hexEscapeBlock(streamConvertBuf, packet, bc);
4726:                        } else if (escape) {
4727:                            escapeblockFast(streamConvertBuf, packet, bc);
4728:                        } else {
4729:                            packet.writeBytesNoNull(streamConvertBuf, 0, bc);
4730:                        }
4731:
4732:                        if (useLength) {
4733:                            bc = readblock(in, streamConvertBuf,
4734:                                    lengthLeftToRead);
4735:
4736:                            if (bc > 0) {
4737:                                lengthLeftToRead -= bc;
4738:                            }
4739:                        } else {
4740:                            bc = readblock(in, streamConvertBuf);
4741:                        }
4742:                    }
4743:
4744:                    if (escape) {
4745:                        packet.writeByte((byte) '\'');
4746:                    }
4747:                } finally {
4748:                    if (this .connection.getAutoClosePStmtStreams()) {
4749:                        try {
4750:                            in.close();
4751:                        } catch (IOException ioEx) {
4752:                            ;
4753:                        }
4754:
4755:                        in = null;
4756:                    }
4757:                }
4758:            }
4759:
4760:            private final byte[] streamToBytes(InputStream in, boolean escape,
4761:                    int streamLength, boolean useLength) throws SQLException {
4762:                try {
4763:                    if (streamLength == -1) {
4764:                        useLength = false;
4765:                    }
4766:
4767:                    ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
4768:
4769:                    int bc = -1;
4770:
4771:                    if (useLength) {
4772:                        bc = readblock(in, this .streamConvertBuf, streamLength);
4773:                    } else {
4774:                        bc = readblock(in, this .streamConvertBuf);
4775:                    }
4776:
4777:                    int lengthLeftToRead = streamLength - bc;
4778:
4779:                    if (escape) {
4780:                        if (this .connection.versionMeetsMinimum(4, 1, 0)) {
4781:                            bytesOut.write('_');
4782:                            bytesOut.write('b');
4783:                            bytesOut.write('i');
4784:                            bytesOut.write('n');
4785:                            bytesOut.write('a');
4786:                            bytesOut.write('r');
4787:                            bytesOut.write('y');
4788:                        }
4789:
4790:                        bytesOut.write('\'');
4791:                    }
4792:
4793:                    while (bc > 0) {
4794:                        if (escape) {
4795:                            escapeblockFast(this .streamConvertBuf, bytesOut, bc);
4796:                        } else {
4797:                            bytesOut.write(this .streamConvertBuf, 0, bc);
4798:                        }
4799:
4800:                        if (useLength) {
4801:                            bc = readblock(in, this .streamConvertBuf,
4802:                                    lengthLeftToRead);
4803:
4804:                            if (bc > 0) {
4805:                                lengthLeftToRead -= bc;
4806:                            }
4807:                        } else {
4808:                            bc = readblock(in, this .streamConvertBuf);
4809:                        }
4810:                    }
4811:
4812:                    if (escape) {
4813:                        bytesOut.write('\'');
4814:                    }
4815:
4816:                    return bytesOut.toByteArray();
4817:                } finally {
4818:                    if (this .connection.getAutoClosePStmtStreams()) {
4819:                        try {
4820:                            in.close();
4821:                        } catch (IOException ioEx) {
4822:                            ;
4823:                        }
4824:
4825:                        in = null;
4826:                    }
4827:                }
4828:            }
4829:
4830:            /**
4831:             * Returns this PreparedStatement represented as a string.
4832:             * 
4833:             * @return this PreparedStatement represented as a string.
4834:             */
4835:            public String toString() {
4836:                StringBuffer buf = new StringBuffer();
4837:                buf.append(super .toString());
4838:                buf.append(": "); //$NON-NLS-1$
4839:
4840:                try {
4841:                    buf.append(asSql());
4842:                } catch (SQLException sqlEx) {
4843:                    buf.append("EXCEPTION: " + sqlEx.toString());
4844:                }
4845:
4846:                return buf.toString();
4847:            }
4848:
4849:            public synchronized boolean isClosed() throws SQLException {
4850:                return this .isClosed;
4851:            }
4852:
4853:            /** 
4854:             * For calling stored functions, this will be -1 as we don't really count
4855:             * the first '?' parameter marker, it's only syntax, but JDBC counts it
4856:             * as #1, otherwise it will return 0 
4857:             *
4858:             */
4859:
4860:            protected int getParameterIndexOffset() {
4861:                return 0;
4862:            }
4863:
4864:            public void setAsciiStream(int parameterIndex, InputStream x)
4865:                    throws SQLException {
4866:                setAsciiStream(parameterIndex, x, -1);
4867:            }
4868:
4869:            public void setAsciiStream(int parameterIndex, InputStream x,
4870:                    long length) throws SQLException {
4871:                setAsciiStream(parameterIndex, x, (int) length);
4872:                this .parameterTypes[parameterIndex - 1
4873:                        + getParameterIndexOffset()] = Types.CLOB;
4874:            }
4875:
4876:            public void setBinaryStream(int parameterIndex, InputStream x)
4877:                    throws SQLException {
4878:                setBinaryStream(parameterIndex, x, -1);
4879:            }
4880:
4881:            public void setBinaryStream(int parameterIndex, InputStream x,
4882:                    long length) throws SQLException {
4883:                setBinaryStream(parameterIndex, x, (int) length);
4884:            }
4885:
4886:            public void setBlob(int parameterIndex, InputStream inputStream)
4887:                    throws SQLException {
4888:                setBinaryStream(parameterIndex, inputStream);
4889:            }
4890:
4891:            public void setCharacterStream(int parameterIndex, Reader reader)
4892:                    throws SQLException {
4893:                setCharacterStream(parameterIndex, reader, -1);
4894:            }
4895:
4896:            public void setCharacterStream(int parameterIndex, Reader reader,
4897:                    long length) throws SQLException {
4898:                setCharacterStream(parameterIndex, reader, (int) length);
4899:
4900:            }
4901:
4902:            public void setClob(int parameterIndex, Reader reader)
4903:                    throws SQLException {
4904:                setCharacterStream(parameterIndex, reader);
4905:
4906:            }
4907:
4908:            public void setClob(int parameterIndex, Reader reader, long length)
4909:                    throws SQLException {
4910:                setCharacterStream(parameterIndex, reader, length);
4911:            }
4912:
4913:            public void setNCharacterStream(int parameterIndex, Reader value)
4914:                    throws SQLException {
4915:                setNCharacterStream(parameterIndex, value, -1);
4916:            }
4917:
4918:            /**
4919:             * Set a parameter to a Java String value. The driver converts this to a SQL
4920:             * VARCHAR or LONGVARCHAR value with introducer _utf8 (depending on the 
4921:             * arguments size relative to the driver's limits on VARCHARs) when it sends 
4922:             * it to the database. If charset is set as utf8, this method just call setString.
4923:             * 
4924:             * @param parameterIndex
4925:             *            the first parameter is 1...
4926:             * @param x
4927:             *            the parameter value
4928:             * 
4929:             * @exception SQLException
4930:             *                if a database access error occurs
4931:             */
4932:            public void setNString(int parameterIndex, String x)
4933:                    throws SQLException {
4934:                if (this .charEncoding.equalsIgnoreCase("UTF-8")
4935:                        || this .charEncoding.equalsIgnoreCase("utf8")) {
4936:                    setString(parameterIndex, x);
4937:                    return;
4938:                }
4939:
4940:                // if the passed string is null, then set this column to null
4941:                if (x == null) {
4942:                    setNull(parameterIndex, java.sql.Types.CHAR);
4943:                } else {
4944:                    int stringLength = x.length();
4945:                    // Ignore sql_mode=NO_BACKSLASH_ESCAPES in current implementation.
4946:
4947:                    // Add introducer _utf8 for NATIONAL CHARACTER
4948:                    StringBuffer buf = new StringBuffer(
4949:                            (int) (x.length() * 1.1 + 4));
4950:                    buf.append("_utf8");
4951:                    buf.append('\'');
4952:
4953:                    //
4954:                    // Note: buf.append(char) is _faster_ than
4955:                    // appending in blocks, because the block
4956:                    // append requires a System.arraycopy()....
4957:                    // go figure...
4958:                    //
4959:
4960:                    for (int i = 0; i < stringLength; ++i) {
4961:                        char c = x.charAt(i);
4962:
4963:                        switch (c) {
4964:                        case 0: /* Must be escaped for 'mysql' */
4965:                            buf.append('\\');
4966:                            buf.append('0');
4967:
4968:                            break;
4969:
4970:                        case '\n': /* Must be escaped for logs */
4971:                            buf.append('\\');
4972:                            buf.append('n');
4973:
4974:                            break;
4975:
4976:                        case '\r':
4977:                            buf.append('\\');
4978:                            buf.append('r');
4979:
4980:                            break;
4981:
4982:                        case '\\':
4983:                            buf.append('\\');
4984:                            buf.append('\\');
4985:
4986:                            break;
4987:
4988:                        case '\'':
4989:                            buf.append('\\');
4990:                            buf.append('\'');
4991:
4992:                            break;
4993:
4994:                        case '"': /* Better safe than sorry */
4995:                            if (this .usingAnsiMode) {
4996:                                buf.append('\\');
4997:                            }
4998:
4999:                            buf.append('"');
5000:
5001:                            break;
5002:
5003:                        case '\032': /* This gives problems on Win32 */
5004:                            buf.append('\\');
5005:                            buf.append('Z');
5006:
5007:                            break;
5008:
5009:                        default:
5010:                            buf.append(c);
5011:                        }
5012:                    }
5013:
5014:                    buf.append('\'');
5015:
5016:                    String parameterAsString = buf.toString();
5017:
5018:                    byte[] parameterAsBytes = null;
5019:
5020:                    if (!this .isLoadDataQuery) {
5021:                        parameterAsBytes = StringUtils.getBytes(
5022:                                parameterAsString, this .connection
5023:                                        .getCharsetConverter("UTF-8"), "UTF-8",
5024:                                this .connection.getServerCharacterEncoding(),
5025:                                this .connection.parserKnowsUnicode());
5026:                    } else {
5027:                        // Send with platform character encoding
5028:                        parameterAsBytes = parameterAsString.getBytes();
5029:                    }
5030:
5031:                    setInternal(parameterIndex, parameterAsBytes);
5032:
5033:                    this .parameterTypes[parameterIndex - 1
5034:                            + getParameterIndexOffset()] = -9; /* Types.NVARCHAR */
5035:                }
5036:            }
5037:
5038:            /**
5039:             * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR
5040:             * parameter, it may be more practical to send it via a java.io.Reader. JDBC
5041:             * will read the data from the stream as needed, until it reaches
5042:             * end-of-file. The JDBC driver will do any necessary conversion from
5043:             * UNICODE to the database char format.
5044:             * 
5045:             * <P>
5046:             * <B>Note:</B> This stream object can either be a standard Java stream
5047:             * object or your own subclass that implements the standard interface.
5048:             * </p>
5049:             * 
5050:             * @param parameterIndex
5051:             *            the first parameter is 1, the second is 2, ...
5052:             * @param reader
5053:             *            the java reader which contains the UNICODE data
5054:             * @param length
5055:             *            the number of characters in the stream
5056:             * 
5057:             * @exception SQLException
5058:             *                if a database-access error occurs.
5059:             */
5060:            public void setNCharacterStream(int parameterIndex, Reader reader,
5061:                    long length) throws SQLException {
5062:                try {
5063:                    if (reader == null) {
5064:                        setNull(parameterIndex, java.sql.Types.LONGVARCHAR);
5065:
5066:                    } else {
5067:                        char[] c = null;
5068:                        int len = 0;
5069:
5070:                        boolean useLength = this .connection
5071:                                .getUseStreamLengthsInPrepStmts();
5072:
5073:                        // Ignore "clobCharacterEncoding" because utf8 should be used this time.
5074:
5075:                        if (useLength && (length != -1)) {
5076:                            c = new char[(int) length]; // can't take more than Integer.MAX_VALUE
5077:
5078:                            int numCharsRead = readFully(reader, c,
5079:                                    (int) length); // blocks
5080:                            // until
5081:                            // all
5082:                            // read
5083:                            setNString(parameterIndex, new String(c, 0,
5084:                                    numCharsRead));
5085:
5086:                        } else {
5087:                            c = new char[4096];
5088:
5089:                            StringBuffer buf = new StringBuffer();
5090:
5091:                            while ((len = reader.read(c)) != -1) {
5092:                                buf.append(c, 0, len);
5093:                            }
5094:
5095:                            setNString(parameterIndex, buf.toString());
5096:                        }
5097:
5098:                        this .parameterTypes[parameterIndex - 1
5099:                                + getParameterIndexOffset()] = 2011; /* Types.NCLOB */
5100:                    }
5101:                } catch (java.io.IOException ioEx) {
5102:                    throw SQLError.createSQLException(ioEx.toString(),
5103:                            SQLError.SQL_STATE_GENERAL_ERROR);
5104:                }
5105:            }
5106:
5107:            public void setNClob(int parameterIndex, Reader reader)
5108:                    throws SQLException {
5109:                setNCharacterStream(parameterIndex, reader);
5110:            }
5111:
5112:            /**
5113:             * JDBC 4.0 Set a NCLOB parameter.
5114:             * 
5115:             * @param parameterIndex
5116:             *            the first parameter is 1, the second is 2, ...
5117:             * @param reader
5118:             *            the java reader which contains the UNICODE data
5119:             * @param length
5120:             *            the number of characters in the stream
5121:             * 
5122:             * @throws SQLException
5123:             *             if a database error occurs
5124:             */
5125:            public void setNClob(int parameterIndex, Reader reader, long length)
5126:                    throws SQLException {
5127:                if (reader == null) {
5128:                    setNull(parameterIndex, java.sql.Types.LONGVARCHAR);
5129:                } else {
5130:                    setNCharacterStream(parameterIndex, reader, length);
5131:                }
5132:            }
5133:
5134:            public ParameterBindings getParameterBindings() throws SQLException {
5135:                return new EmulatedPreparedStatementBindings();
5136:            }
5137:
5138:            class EmulatedPreparedStatementBindings implements 
5139:                    ParameterBindings {
5140:
5141:                private ResultSetImpl bindingsAsRs;
5142:                private boolean[] parameterIsNull;
5143:
5144:                public EmulatedPreparedStatementBindings() throws SQLException {
5145:                    List rows = new ArrayList();
5146:                    parameterIsNull = new boolean[parameterCount];
5147:                    System.arraycopy(isNull, 0, this .parameterIsNull, 0,
5148:                            parameterCount);
5149:                    byte[][] rowData = new byte[parameterCount][];
5150:                    Field[] typeMetadata = new Field[parameterCount];
5151:
5152:                    for (int i = 0; i < parameterCount; i++) {
5153:                        rowData[i] = getBytesRepresentation(i);
5154:
5155:                        int charsetIndex = 0;
5156:
5157:                        if (parameterTypes[i] == Types.BINARY
5158:                                || parameterTypes[i] == Types.BLOB) {
5159:                            charsetIndex = 63;
5160:                        } else {
5161:                            String mysqlEncodingName = CharsetMapping
5162:                                    .getMysqlEncodingForJavaEncoding(connection
5163:                                            .getEncoding(), connection);
5164:                            charsetIndex = CharsetMapping
5165:                                    .getCharsetIndexForMysqlEncodingName(mysqlEncodingName);
5166:                        }
5167:
5168:                        Field parameterMetadata = new Field(null, "parameter_"
5169:                                + (i + 1), charsetIndex, parameterTypes[i],
5170:                                rowData[i].length);
5171:                        parameterMetadata.setConnection(connection);
5172:                        typeMetadata[i] = parameterMetadata;
5173:                    }
5174:
5175:                    rows.add(new ByteArrayRow(rowData));
5176:
5177:                    this .bindingsAsRs = new ResultSetImpl(connection
5178:                            .getCatalog(), typeMetadata,
5179:                            new RowDataStatic(rows), connection, null);
5180:                    this .bindingsAsRs.next();
5181:                }
5182:
5183:                public Array getArray(int parameterIndex) throws SQLException {
5184:                    return this .bindingsAsRs.getArray(parameterIndex);
5185:                }
5186:
5187:                public InputStream getAsciiStream(int parameterIndex)
5188:                        throws SQLException {
5189:                    return this .bindingsAsRs.getAsciiStream(parameterIndex);
5190:                }
5191:
5192:                public BigDecimal getBigDecimal(int parameterIndex)
5193:                        throws SQLException {
5194:                    return this .bindingsAsRs.getBigDecimal(parameterIndex);
5195:                }
5196:
5197:                public InputStream getBinaryStream(int parameterIndex)
5198:                        throws SQLException {
5199:                    return this .bindingsAsRs.getBinaryStream(parameterIndex);
5200:                }
5201:
5202:                public java.sql.Blob getBlob(int parameterIndex)
5203:                        throws SQLException {
5204:                    return this .bindingsAsRs.getBlob(parameterIndex);
5205:                }
5206:
5207:                public boolean getBoolean(int parameterIndex)
5208:                        throws SQLException {
5209:                    return this .bindingsAsRs.getBoolean(parameterIndex);
5210:                }
5211:
5212:                public byte getByte(int parameterIndex) throws SQLException {
5213:                    return this .bindingsAsRs.getByte(parameterIndex);
5214:                }
5215:
5216:                public byte[] getBytes(int parameterIndex) throws SQLException {
5217:                    return this .bindingsAsRs.getBytes(parameterIndex);
5218:                }
5219:
5220:                public Reader getCharacterStream(int parameterIndex)
5221:                        throws SQLException {
5222:                    return this .bindingsAsRs.getCharacterStream(parameterIndex);
5223:                }
5224:
5225:                public java.sql.Clob getClob(int parameterIndex)
5226:                        throws SQLException {
5227:                    return this .bindingsAsRs.getClob(parameterIndex);
5228:                }
5229:
5230:                public Date getDate(int parameterIndex) throws SQLException {
5231:                    return this .bindingsAsRs.getDate(parameterIndex);
5232:                }
5233:
5234:                public double getDouble(int parameterIndex) throws SQLException {
5235:                    return this .bindingsAsRs.getDouble(parameterIndex);
5236:                }
5237:
5238:                public float getFloat(int parameterIndex) throws SQLException {
5239:                    return this .bindingsAsRs.getFloat(parameterIndex);
5240:                }
5241:
5242:                public int getInt(int parameterIndex) throws SQLException {
5243:                    return this .bindingsAsRs.getInt(parameterIndex);
5244:                }
5245:
5246:                public long getLong(int parameterIndex) throws SQLException {
5247:                    return this .bindingsAsRs.getLong(parameterIndex);
5248:                }
5249:
5250:                public Reader getNCharacterStream(int parameterIndex)
5251:                        throws SQLException {
5252:                    return this .bindingsAsRs.getCharacterStream(parameterIndex);
5253:                }
5254:
5255:                public Reader getNClob(int parameterIndex) throws SQLException {
5256:                    return this .bindingsAsRs.getCharacterStream(parameterIndex);
5257:                }
5258:
5259:                public Object getObject(int parameterIndex) throws SQLException {
5260:                    checkBounds(parameterIndex, 0);
5261:
5262:                    if (parameterIsNull[parameterIndex - 1]) {
5263:                        return null;
5264:                    }
5265:
5266:                    // we can't rely on the default mapping for JDBC's 
5267:                    // ResultSet.getObject() for numerics, they're not one-to-one with
5268:                    // PreparedStatement.setObject
5269:
5270:                    switch (parameterTypes[parameterIndex - 1]) {
5271:                    case Types.TINYINT:
5272:                        return new Byte(getByte(parameterIndex));
5273:                    case Types.SMALLINT:
5274:                        return new Short(getShort(parameterIndex));
5275:                    case Types.INTEGER:
5276:                        return new Integer(getInt(parameterIndex));
5277:                    case Types.BIGINT:
5278:                        return new Long(getLong(parameterIndex));
5279:                    case Types.FLOAT:
5280:                        return new Float(getFloat(parameterIndex));
5281:                    case Types.DOUBLE:
5282:                        return new Double(getDouble(parameterIndex));
5283:                    default:
5284:                        return this .bindingsAsRs.getObject(parameterIndex);
5285:                    }
5286:                }
5287:
5288:                public Ref getRef(int parameterIndex) throws SQLException {
5289:                    return this .bindingsAsRs.getRef(parameterIndex);
5290:                }
5291:
5292:                public short getShort(int parameterIndex) throws SQLException {
5293:                    return this .bindingsAsRs.getShort(parameterIndex);
5294:                }
5295:
5296:                public String getString(int parameterIndex) throws SQLException {
5297:                    return this .bindingsAsRs.getString(parameterIndex);
5298:                }
5299:
5300:                public Time getTime(int parameterIndex) throws SQLException {
5301:                    return this .bindingsAsRs.getTime(parameterIndex);
5302:                }
5303:
5304:                public Timestamp getTimestamp(int parameterIndex)
5305:                        throws SQLException {
5306:                    return this .bindingsAsRs.getTimestamp(parameterIndex);
5307:                }
5308:
5309:                public URL getURL(int parameterIndex) throws SQLException {
5310:                    return this .bindingsAsRs.getURL(parameterIndex);
5311:                }
5312:
5313:                public boolean isNull(int parameterIndex) throws SQLException {
5314:                    checkBounds(parameterIndex, 0);
5315:
5316:                    return this .parameterIsNull[parameterIndex - 1];
5317:                }
5318:            }
5319:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.