Source Code Cross Referenced for StatementImpl.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 com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
0028:        import com.mysql.jdbc.exceptions.NotYetImplementedException;
0029:        import com.mysql.jdbc.exceptions.MySQLTimeoutException;
0030:        import com.mysql.jdbc.profiler.ProfileEventSink;
0031:        import com.mysql.jdbc.profiler.ProfilerEvent;
0032:        import com.mysql.jdbc.util.LRUCache;
0033:
0034:        import java.io.InputStream;
0035:        import java.sql.BatchUpdateException;
0036:        import java.sql.ResultSet;
0037:        import java.sql.SQLException;
0038:        import java.sql.SQLWarning;
0039:        import java.sql.Types;
0040:
0041:        import java.util.ArrayList;
0042:        import java.util.Calendar;
0043:        import java.util.GregorianCalendar;
0044:        import java.util.Iterator;
0045:        import java.util.List;
0046:        import java.util.Map;
0047:        import java.util.TimerTask;
0048:
0049:        /**
0050:         * A Statement object is used for executing a static SQL statement and obtaining
0051:         * the results produced by it.
0052:         *
0053:         * <p>
0054:         * Only one ResultSet per Statement can be open at any point in time. Therefore,
0055:         * if the reading of one ResultSet is interleaved with the reading of another,
0056:         * each must have been generated by different Statements. All statement execute
0057:         * methods implicitly close a statement's current ResultSet if an open one
0058:         * exists.
0059:         * </p>
0060:         *
0061:         * @author Mark Matthews
0062:         * @version $Id: Statement.java 4624 2005-11-28 14:24:29 -0600 (Mon, 28 Nov
0063:         *          2005) mmatthews $
0064:         *
0065:         * @see java.sql.Statement
0066:         * @see ResultSetInternalMethods
0067:         */
0068:        public class StatementImpl implements  Statement {
0069:            protected static final String PING_MARKER = "/* ping */";
0070:
0071:            /**
0072:             * Thread used to implement query timeouts...Eventually we could be more
0073:             * efficient and have one thread with timers, but this is a straightforward
0074:             * and simple way to implement a feature that isn't used all that often.
0075:             */
0076:            class CancelTask extends TimerTask {
0077:
0078:                long connectionId = 0;
0079:                SQLException caughtWhileCancelling = null;
0080:                StatementImpl toCancel;
0081:
0082:                CancelTask(StatementImpl cancellee) throws SQLException {
0083:                    connectionId = connection.getIO().getThreadId();
0084:                    toCancel = cancellee;
0085:                }
0086:
0087:                public void run() {
0088:
0089:                    Thread cancelThread = new Thread() {
0090:
0091:                        public void run() {
0092:                            Connection cancelConn = null;
0093:                            java.sql.Statement cancelStmt = null;
0094:
0095:                            try {
0096:                                synchronized (cancelTimeoutMutex) {
0097:                                    cancelConn = connection.duplicate();
0098:                                    cancelStmt = cancelConn.createStatement();
0099:                                    cancelStmt.execute("KILL QUERY "
0100:                                            + connectionId);
0101:                                    toCancel.wasCancelled = true;
0102:                                    toCancel.wasCancelledByTimeout = true;
0103:                                }
0104:                            } catch (SQLException sqlEx) {
0105:                                caughtWhileCancelling = sqlEx;
0106:                            } catch (NullPointerException npe) {
0107:                                // Case when connection closed while starting to cancel
0108:                                // We can't easily synchronize this, because then one thread
0109:                                // can't cancel() a running query
0110:
0111:                                // ignore, we shouldn't re-throw this, because the connection's
0112:                                // already closed, so the statement has been timed out.
0113:                            } finally {
0114:                                if (cancelStmt != null) {
0115:                                    try {
0116:                                        cancelStmt.close();
0117:                                    } catch (SQLException sqlEx) {
0118:                                        throw new RuntimeException(sqlEx
0119:                                                .toString());
0120:                                    }
0121:                                }
0122:
0123:                                if (cancelConn != null) {
0124:                                    try {
0125:                                        cancelConn.close();
0126:                                    } catch (SQLException sqlEx) {
0127:                                        throw new RuntimeException(sqlEx
0128:                                                .toString());
0129:                                    }
0130:                                }
0131:                            }
0132:                        }
0133:                    };
0134:
0135:                    cancelThread.start();
0136:                }
0137:            }
0138:
0139:            /** Mutex to prevent race between returning query results and noticing
0140:            that we're timed-out or cancelled. */
0141:
0142:            protected Object cancelTimeoutMutex = new Object();
0143:
0144:            /** Used to generate IDs when profiling. */
0145:            protected static int statementCounter = 1;
0146:
0147:            public final static byte USES_VARIABLES_FALSE = 0;
0148:
0149:            public final static byte USES_VARIABLES_TRUE = 1;
0150:
0151:            public final static byte USES_VARIABLES_UNKNOWN = -1;
0152:
0153:            protected boolean wasCancelled = false;
0154:            protected boolean wasCancelledByTimeout = false;
0155:
0156:            /** Holds batched commands */
0157:            protected List batchedArgs;
0158:
0159:            /** The character converter to use (if available) */
0160:            protected SingleByteCharsetConverter charConverter = null;
0161:
0162:            /** The character encoding to use (if available) */
0163:            protected String charEncoding = null;
0164:
0165:            /** The connection that created us */
0166:            protected ConnectionImpl connection = null;
0167:
0168:            protected long connectionId = 0;
0169:
0170:            /** The catalog in use */
0171:            protected String currentCatalog = null;
0172:
0173:            /** Should we process escape codes? */
0174:            protected boolean doEscapeProcessing = true;
0175:
0176:            /** If we're profiling, where should events go to? */
0177:            protected ProfileEventSink eventSink = null;
0178:
0179:            /** The number of rows to fetch at a time (currently ignored) */
0180:            private int fetchSize = 0;
0181:
0182:            /** Has this statement been closed? */
0183:            protected boolean isClosed = false;
0184:
0185:            /** The auto_increment value for the last insert */
0186:            protected long lastInsertId = -1;
0187:
0188:            /** The max field size for this statement */
0189:            protected int maxFieldSize = MysqlIO.getMaxBuf();
0190:
0191:            /**
0192:             * The maximum number of rows to return for this statement (-1 means _all_
0193:             * rows)
0194:             */
0195:            protected int maxRows = -1;
0196:
0197:            /** Has someone changed this for this statement? */
0198:            protected boolean maxRowsChanged = false;
0199:
0200:            /** List of currently-open ResultSets */
0201:            protected List openResults = new ArrayList();
0202:
0203:            /** Are we in pedantic mode? */
0204:            protected boolean pedantic = false;
0205:
0206:            /**
0207:             * Where this statement was created, only used if profileSql or
0208:             * useUsageAdvisor set to true.
0209:             */
0210:            protected Throwable pointOfOrigin;
0211:
0212:            /** Should we profile? */
0213:            protected boolean profileSQL = false;
0214:
0215:            /** The current results */
0216:            protected ResultSetInternalMethods results = null;
0217:
0218:            /** The concurrency for this result set (updatable or not) */
0219:            protected int resultSetConcurrency = 0;
0220:
0221:            /** The type of this result set (scroll sensitive or in-sensitive) */
0222:            protected int resultSetType = 0;
0223:
0224:            /** Used to identify this statement when profiling. */
0225:            protected int statementId;
0226:
0227:            /** The timeout for a query */
0228:            protected int timeoutInMillis = 0;
0229:
0230:            /** The update count for this statement */
0231:            protected long updateCount = -1;
0232:
0233:            /** Should we use the usage advisor? */
0234:            protected boolean useUsageAdvisor = false;
0235:
0236:            /** The warnings chain. */
0237:            protected SQLWarning warningChain = null;
0238:
0239:            /**
0240:             * Should this statement hold results open over .close() irregardless of
0241:             * connection's setting?
0242:             */
0243:            protected boolean holdResultsOpenOverClose = false;
0244:
0245:            protected ArrayList batchedGeneratedKeys = null;
0246:
0247:            protected boolean retrieveGeneratedKeys = false;
0248:
0249:            protected boolean continueBatchOnError = false;
0250:
0251:            protected PingTarget pingTarget = null;
0252:
0253:            /**
0254:             * Constructor for a Statement.
0255:             *
0256:             * @param c
0257:             *            the Connection instantation that creates us
0258:             * @param catalog
0259:             *            the database name in use when we were created
0260:             *
0261:             * @throws SQLException
0262:             *             if an error occurs.
0263:             */
0264:            public StatementImpl(ConnectionImpl c, String catalog)
0265:                    throws SQLException {
0266:                if ((c == null) || c.isClosed()) {
0267:                    throw SQLError.createSQLException(Messages
0268:                            .getString("Statement.0"), //$NON-NLS-1$
0269:                            SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$ //$NON-NLS-2$
0270:                }
0271:
0272:                this .connection = c;
0273:                this .connectionId = this .connection.getId();
0274:
0275:                this .currentCatalog = catalog;
0276:                this .pedantic = this .connection.getPedantic();
0277:                this .continueBatchOnError = this .connection
0278:                        .getContinueBatchOnError();
0279:
0280:                if (!this .connection.getDontTrackOpenResources()) {
0281:                    this .connection.registerStatement(this );
0282:                }
0283:
0284:                //
0285:                // Adjust, if we know it
0286:                //
0287:
0288:                if (this .connection != null) {
0289:                    this .maxFieldSize = this .connection.getMaxAllowedPacket();
0290:
0291:                    int defaultFetchSize = this .connection
0292:                            .getDefaultFetchSize();
0293:
0294:                    if (defaultFetchSize != 0) {
0295:                        setFetchSize(defaultFetchSize);
0296:                    }
0297:                }
0298:
0299:                if (this .connection.getUseUnicode()) {
0300:                    this .charEncoding = this .connection.getEncoding();
0301:
0302:                    this .charConverter = this .connection
0303:                            .getCharsetConverter(this .charEncoding);
0304:                }
0305:
0306:                boolean profiling = this .connection.getProfileSql()
0307:                        || this .connection.getUseUsageAdvisor();
0308:
0309:                if (this .connection.getAutoGenerateTestcaseScript()
0310:                        || profiling) {
0311:                    this .statementId = statementCounter++;
0312:                }
0313:
0314:                if (profiling) {
0315:                    this .pointOfOrigin = new Throwable();
0316:                    this .profileSQL = this .connection.getProfileSql();
0317:                    this .useUsageAdvisor = this .connection.getUseUsageAdvisor();
0318:                    this .eventSink = ProfileEventSink
0319:                            .getInstance(this .connection);
0320:                }
0321:
0322:                int maxRowsConn = this .connection.getMaxRows();
0323:
0324:                if (maxRowsConn != -1) {
0325:                    setMaxRows(maxRowsConn);
0326:                }
0327:            }
0328:
0329:            /**
0330:             * DOCUMENT ME!
0331:             *
0332:             * @param sql
0333:             *            DOCUMENT ME!
0334:             *
0335:             * @throws SQLException
0336:             *             DOCUMENT ME!
0337:             */
0338:            public synchronized void addBatch(String sql) throws SQLException {
0339:                if (this .batchedArgs == null) {
0340:                    this .batchedArgs = new ArrayList();
0341:                }
0342:
0343:                if (sql != null) {
0344:                    this .batchedArgs.add(sql);
0345:                }
0346:            }
0347:
0348:            /**
0349:             * Cancels this Statement object if both the DBMS and driver support
0350:             * aborting an SQL statement. This method can be used by one thread to
0351:             * cancel a statement that is being executed by another thread.
0352:             */
0353:            public void cancel() throws SQLException {
0354:                if (!this .isClosed && this .connection != null
0355:                        && this .connection.versionMeetsMinimum(5, 0, 0)) {
0356:                    Connection cancelConn = null;
0357:                    java.sql.Statement cancelStmt = null;
0358:
0359:                    try {
0360:                        cancelConn = this .connection.duplicate();
0361:                        cancelStmt = cancelConn.createStatement();
0362:                        cancelStmt.execute("KILL QUERY "
0363:                                + this .connection.getIO().getThreadId());
0364:                        this .wasCancelled = true;
0365:                    } finally {
0366:                        if (cancelStmt != null) {
0367:                            cancelStmt.close();
0368:                        }
0369:
0370:                        if (cancelConn != null) {
0371:                            cancelConn.close();
0372:                        }
0373:                    }
0374:
0375:                }
0376:            }
0377:
0378:            // --------------------------JDBC 2.0-----------------------------
0379:
0380:            /**
0381:             * Checks if closed() has been called, and throws an exception if so
0382:             *
0383:             * @throws SQLException
0384:             *             if this statement has been closed
0385:             */
0386:            protected void checkClosed() throws SQLException {
0387:                if (this .isClosed) {
0388:                    throw SQLError.createSQLException(Messages
0389:                            .getString("Statement.49"), //$NON-NLS-1$
0390:                            SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$
0391:                }
0392:            }
0393:
0394:            /**
0395:             * Checks if the given SQL query with the given first non-ws char is a DML
0396:             * statement. Throws an exception if it is.
0397:             *
0398:             * @param sql
0399:             *            the SQL to check
0400:             * @param firstStatementChar
0401:             *            the UC first non-ws char of the statement
0402:             *
0403:             * @throws SQLException
0404:             *             if the statement contains DML
0405:             */
0406:            protected void checkForDml(String sql, char firstStatementChar)
0407:                    throws SQLException {
0408:                if ((firstStatementChar == 'I') || (firstStatementChar == 'U')
0409:                        || (firstStatementChar == 'D')
0410:                        || (firstStatementChar == 'A')
0411:                        || (firstStatementChar == 'C')) {
0412:                    String noCommentSql = StringUtils.stripComments(sql, "'\"",
0413:                            "'\"", true, false, true, true);
0414:
0415:                    if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql,
0416:                            "INSERT") //$NON-NLS-1$
0417:                            || StringUtils.startsWithIgnoreCaseAndWs(
0418:                                    noCommentSql, "UPDATE") //$NON-NLS-1$
0419:                            || StringUtils.startsWithIgnoreCaseAndWs(
0420:                                    noCommentSql, "DELETE") //$NON-NLS-1$
0421:                            || StringUtils.startsWithIgnoreCaseAndWs(
0422:                                    noCommentSql, "DROP") //$NON-NLS-1$
0423:                            || StringUtils.startsWithIgnoreCaseAndWs(
0424:                                    noCommentSql, "CREATE") //$NON-NLS-1$
0425:                            || StringUtils.startsWithIgnoreCaseAndWs(
0426:                                    noCommentSql, "ALTER")) { //$NON-NLS-1$
0427:                        throw SQLError.createSQLException(Messages
0428:                                .getString("Statement.57"), //$NON-NLS-1$
0429:                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0430:                    }
0431:                }
0432:            }
0433:
0434:            /**
0435:             * Method checkNullOrEmptyQuery.
0436:             *
0437:             * @param sql
0438:             *            the SQL to check
0439:             *
0440:             * @throws SQLException
0441:             *             if query is null or empty.
0442:             */
0443:            protected void checkNullOrEmptyQuery(String sql)
0444:                    throws SQLException {
0445:                if (sql == null) {
0446:                    throw SQLError.createSQLException(Messages
0447:                            .getString("Statement.59"), //$NON-NLS-1$
0448:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
0449:                }
0450:
0451:                if (sql.length() == 0) {
0452:                    throw SQLError.createSQLException(Messages
0453:                            .getString("Statement.61"), //$NON-NLS-1$
0454:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
0455:                }
0456:            }
0457:
0458:            /**
0459:             * JDBC 2.0 Make the set of commands in the current batch empty. This method
0460:             * is optional.
0461:             *
0462:             * @exception SQLException
0463:             *                if a database-access error occurs, or the driver does not
0464:             *                support batch statements
0465:             */
0466:            public synchronized void clearBatch() throws SQLException {
0467:                if (this .batchedArgs != null) {
0468:                    this .batchedArgs.clear();
0469:                }
0470:            }
0471:
0472:            /**
0473:             * After this call, getWarnings returns null until a new warning is reported
0474:             * for this Statement.
0475:             *
0476:             * @exception SQLException
0477:             *                if a database access error occurs (why?)
0478:             */
0479:            public void clearWarnings() throws SQLException {
0480:                this .warningChain = null;
0481:            }
0482:
0483:            /**
0484:             * In many cases, it is desirable to immediately release a Statement's
0485:             * database and JDBC resources instead of waiting for this to happen when it
0486:             * is automatically closed. The close method provides this immediate
0487:             * release.
0488:             *
0489:             * <p>
0490:             * <B>Note:</B> A Statement is automatically closed when it is garbage
0491:             * collected. When a Statement is closed, its current ResultSet, if one
0492:             * exists, is also closed.
0493:             * </p>
0494:             *
0495:             * @exception SQLException
0496:             *                if a database access error occurs
0497:             */
0498:            public void close() throws SQLException {
0499:                realClose(true, true);
0500:            }
0501:
0502:            /**
0503:             * Close any open result sets that have been 'held open'
0504:             */
0505:            protected void closeAllOpenResults() {
0506:                if (this .openResults != null) {
0507:                    for (Iterator iter = this .openResults.iterator(); iter
0508:                            .hasNext();) {
0509:                        ResultSetInternalMethods element = (ResultSetInternalMethods) iter
0510:                                .next();
0511:
0512:                        try {
0513:                            element.realClose(false);
0514:                        } catch (SQLException sqlEx) {
0515:                            AssertionFailedException.shouldNotHappen(sqlEx);
0516:                        }
0517:                    }
0518:
0519:                    this .openResults.clear();
0520:                }
0521:            }
0522:
0523:            /**
0524:             * @param sql
0525:             * @return
0526:             */
0527:            private ResultSetInternalMethods createResultSetUsingServerFetch(
0528:                    String sql) throws SQLException {
0529:                java.sql.PreparedStatement pStmt = this .connection
0530:                        .prepareStatement(sql, this .resultSetType,
0531:                                this .resultSetConcurrency);
0532:
0533:                pStmt.setFetchSize(this .fetchSize);
0534:
0535:                if (this .maxRows > -1) {
0536:                    pStmt.setMaxRows(this .maxRows);
0537:                }
0538:
0539:                pStmt.execute();
0540:
0541:                //
0542:                // Need to be able to get resultset irrespective if we issued DML or
0543:                // not to make this work.
0544:                //
0545:                ResultSetInternalMethods rs = ((com.mysql.jdbc.StatementImpl) pStmt)
0546:                        .getResultSetInternal();
0547:
0548:                rs
0549:                        .setStatementUsedForFetchingRows((com.mysql.jdbc.PreparedStatement) pStmt);
0550:
0551:                this .results = rs;
0552:
0553:                return rs;
0554:            }
0555:
0556:            /**
0557:             * We only stream result sets when they are forward-only, read-only, and the
0558:             * fetch size has been set to Integer.MIN_VALUE
0559:             *
0560:             * @return true if this result set should be streamed row at-a-time, rather
0561:             *         than read all at once.
0562:             */
0563:            protected boolean createStreamingResultSet() {
0564:                return ((this .resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY)
0565:                        && (this .resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this .fetchSize == Integer.MIN_VALUE));
0566:            }
0567:
0568:            private int originalResultSetType = 0;
0569:            private int originalFetchSize = 0;
0570:
0571:            /* (non-Javadoc)
0572:             * @see com.mysql.jdbc.IStatement#enableStreamingResults()
0573:             */
0574:            public void enableStreamingResults() throws SQLException {
0575:                this .originalResultSetType = this .resultSetType;
0576:                this .originalFetchSize = this .fetchSize;
0577:
0578:                setFetchSize(Integer.MIN_VALUE);
0579:                setResultSetType(ResultSet.TYPE_FORWARD_ONLY);
0580:            }
0581:
0582:            public void disableStreamingResults() throws SQLException {
0583:                if (this .fetchSize == Integer.MIN_VALUE
0584:                        && this .resultSetType == ResultSet.TYPE_FORWARD_ONLY) {
0585:                    setFetchSize(this .originalFetchSize);
0586:                    setResultSetType(this .originalResultSetType);
0587:                }
0588:            }
0589:
0590:            /**
0591:             * Execute a SQL statement that may return multiple results. We don't have
0592:             * to worry about this since we do not support multiple ResultSets. You can
0593:             * use getResultSet or getUpdateCount to retrieve the result.
0594:             *
0595:             * @param sql
0596:             *            any SQL statement
0597:             *
0598:             * @return true if the next result is a ResulSet, false if it is an update
0599:             *         count or there are no more results
0600:             *
0601:             * @exception SQLException
0602:             *                if a database access error occurs
0603:             */
0604:            public boolean execute(String sql) throws SQLException {
0605:                checkClosed();
0606:
0607:                ConnectionImpl locallyScopedConn = this .connection;
0608:
0609:                synchronized (locallyScopedConn.getMutex()) {
0610:                    resetCancelledState();
0611:
0612:                    checkNullOrEmptyQuery(sql);
0613:
0614:                    checkClosed();
0615:
0616:                    char firstNonWsChar = StringUtils.firstNonWsCharUc(sql);
0617:
0618:                    boolean isSelect = true;
0619:
0620:                    if (firstNonWsChar != 'S') {
0621:                        isSelect = false;
0622:
0623:                        if (locallyScopedConn.isReadOnly()) {
0624:                            throw SQLError.createSQLException(Messages
0625:                                    .getString("Statement.27") //$NON-NLS-1$
0626:                                    + Messages.getString("Statement.28"), //$NON-NLS-1$
0627:                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0628:                        }
0629:                    }
0630:
0631:                    boolean doStreaming = createStreamingResultSet();
0632:
0633:                    // Adjust net_write_timeout to a higher value if we're
0634:                    // streaming result sets. More often than not, someone runs into
0635:                    // an issue where they blow net_write_timeout when using this
0636:                    // feature, and if they're willing to hold a result set open
0637:                    // for 30 seconds or more, one more round-trip isn't going to hurt
0638:                    //
0639:                    // This is reset by RowDataDynamic.close().
0640:
0641:                    if (doStreaming
0642:                            && this .connection
0643:                                    .getNetTimeoutForStreamingResults() > 0) {
0644:                        executeSimpleNonQuery(
0645:                                locallyScopedConn,
0646:                                "SET net_write_timeout="
0647:                                        + this .connection
0648:                                                .getNetTimeoutForStreamingResults());
0649:                    }
0650:
0651:                    if (this .doEscapeProcessing) {
0652:                        Object escapedSqlResult = EscapeProcessor.escapeSQL(
0653:                                sql, locallyScopedConn
0654:                                        .serverSupportsConvertFn(),
0655:                                locallyScopedConn);
0656:
0657:                        if (escapedSqlResult instanceof  String) {
0658:                            sql = (String) escapedSqlResult;
0659:                        } else {
0660:                            sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
0661:                        }
0662:                    }
0663:
0664:                    if (this .results != null) {
0665:                        if (!locallyScopedConn
0666:                                .getHoldResultsOpenOverStatementClose()) {
0667:                            this .results.realClose(false);
0668:                        }
0669:                    }
0670:
0671:                    if (firstNonWsChar == '/') {
0672:                        if (sql.startsWith(PING_MARKER)) {
0673:                            doPingInstead();
0674:
0675:                            return true;
0676:                        }
0677:                    }
0678:
0679:                    CachedResultSetMetaData cachedMetaData = null;
0680:
0681:                    ResultSetInternalMethods rs = null;
0682:
0683:                    // If there isn't a limit clause in the SQL
0684:                    // then limit the number of rows to return in
0685:                    // an efficient manner. Only do this if
0686:                    // setMaxRows() hasn't been used on any Statements
0687:                    // generated from the current Connection (saves
0688:                    // a query, and network traffic).
0689:
0690:                    this .batchedGeneratedKeys = null;
0691:
0692:                    if (useServerFetch()) {
0693:                        rs = createResultSetUsingServerFetch(sql);
0694:                    } else {
0695:                        CancelTask timeoutTask = null;
0696:
0697:                        String oldCatalog = null;
0698:
0699:                        try {
0700:                            if (locallyScopedConn.getEnableQueryTimeouts()
0701:                                    && this .timeoutInMillis != 0
0702:                                    && locallyScopedConn.versionMeetsMinimum(5,
0703:                                            0, 0)) {
0704:                                timeoutTask = new CancelTask(this );
0705:                                ConnectionImpl.getCancelTimer().schedule(
0706:                                        timeoutTask, this .timeoutInMillis);
0707:                            }
0708:
0709:                            if (!locallyScopedConn.getCatalog().equals(
0710:                                    this .currentCatalog)) {
0711:                                oldCatalog = locallyScopedConn.getCatalog();
0712:                                locallyScopedConn
0713:                                        .setCatalog(this .currentCatalog);
0714:                            }
0715:
0716:                            //
0717:                            // Check if we have cached metadata for this query...
0718:                            //
0719:
0720:                            Field[] cachedFields = null;
0721:
0722:                            if (locallyScopedConn.getCacheResultSetMetadata()) {
0723:                                cachedMetaData = locallyScopedConn
0724:                                        .getCachedMetaData(sql);
0725:
0726:                                if (cachedMetaData != null) {
0727:                                    cachedFields = cachedMetaData.fields;
0728:                                }
0729:                            }
0730:
0731:                            //
0732:                            // Only apply max_rows to selects
0733:                            //
0734:                            if (locallyScopedConn.useMaxRows()) {
0735:                                int rowLimit = -1;
0736:
0737:                                if (isSelect) {
0738:                                    if (StringUtils.indexOfIgnoreCase(sql,
0739:                                            "LIMIT") != -1) { //$NON-NLS-1$
0740:                                        rowLimit = this .maxRows;
0741:                                    } else {
0742:                                        if (this .maxRows <= 0) {
0743:                                            executeSimpleNonQuery(
0744:                                                    locallyScopedConn,
0745:                                                    "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
0746:                                        } else {
0747:                                            executeSimpleNonQuery(
0748:                                                    locallyScopedConn,
0749:                                                    "SET OPTION SQL_SELECT_LIMIT="
0750:                                                            + this .maxRows);
0751:                                        }
0752:                                    }
0753:                                } else {
0754:                                    executeSimpleNonQuery(locallyScopedConn,
0755:                                            "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
0756:                                }
0757:
0758:                                // Finally, execute the query
0759:                                rs = locallyScopedConn.execSQL(this , sql,
0760:                                        rowLimit, null, this .resultSetType,
0761:                                        this .resultSetConcurrency, doStreaming,
0762:                                        this .currentCatalog, cachedFields);
0763:                            } else {
0764:                                rs = locallyScopedConn.execSQL(this , sql, -1,
0765:                                        null, this .resultSetType,
0766:                                        this .resultSetConcurrency, doStreaming,
0767:                                        this .currentCatalog, cachedFields);
0768:                            }
0769:
0770:                            if (timeoutTask != null) {
0771:                                if (timeoutTask.caughtWhileCancelling != null) {
0772:                                    throw timeoutTask.caughtWhileCancelling;
0773:                                }
0774:
0775:                                timeoutTask.cancel();
0776:                                timeoutTask = null;
0777:                            }
0778:
0779:                            synchronized (this .cancelTimeoutMutex) {
0780:                                if (this .wasCancelled) {
0781:                                    SQLException cause = null;
0782:
0783:                                    if (this .wasCancelledByTimeout) {
0784:                                        cause = new MySQLTimeoutException();
0785:                                    } else {
0786:                                        cause = new MySQLStatementCancelledException();
0787:                                    }
0788:
0789:                                    resetCancelledState();
0790:
0791:                                    throw cause;
0792:                                }
0793:                            }
0794:                        } finally {
0795:                            if (timeoutTask != null) {
0796:                                timeoutTask.cancel();
0797:                            }
0798:
0799:                            if (oldCatalog != null) {
0800:                                locallyScopedConn.setCatalog(oldCatalog);
0801:                            }
0802:                        }
0803:                    }
0804:
0805:                    if (rs != null) {
0806:                        this .lastInsertId = rs.getUpdateID();
0807:
0808:                        this .results = rs;
0809:
0810:                        rs.setFirstCharOfQuery(firstNonWsChar);
0811:
0812:                        if (rs.reallyResult()) {
0813:                            if (cachedMetaData != null) {
0814:                                locallyScopedConn
0815:                                        .initializeResultsMetadataFromCache(
0816:                                                sql, cachedMetaData,
0817:                                                this .results);
0818:                            } else {
0819:                                if (this .connection.getCacheResultSetMetadata()) {
0820:                                    locallyScopedConn
0821:                                            .initializeResultsMetadataFromCache(
0822:                                                    sql,
0823:                                                    null /* will be created */,
0824:                                                    this .results);
0825:                                }
0826:                            }
0827:                        }
0828:                    }
0829:
0830:                    return ((rs != null) && rs.reallyResult());
0831:                }
0832:            }
0833:
0834:            protected synchronized void resetCancelledState() {
0835:                if (this .cancelTimeoutMutex == null) {
0836:                    return;
0837:                }
0838:
0839:                synchronized (this .cancelTimeoutMutex) {
0840:                    this .wasCancelled = false;
0841:                    this .wasCancelledByTimeout = false;
0842:                }
0843:            }
0844:
0845:            /**
0846:             * @see StatementImpl#execute(String, int)
0847:             */
0848:            public boolean execute(String sql, int returnGeneratedKeys)
0849:                    throws SQLException {
0850:
0851:                if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) {
0852:                    checkClosed();
0853:
0854:                    ConnectionImpl locallyScopedConn = this .connection;
0855:
0856:                    synchronized (locallyScopedConn.getMutex()) {
0857:                        // If this is a 'REPLACE' query, we need to be able to parse
0858:                        // the 'info' message returned from the server to determine
0859:                        // the actual number of keys generated.
0860:                        boolean readInfoMsgState = this .connection
0861:                                .isReadInfoMsgEnabled();
0862:                        locallyScopedConn.setReadInfoMsgEnabled(true);
0863:
0864:                        try {
0865:                            return execute(sql);
0866:                        } finally {
0867:                            locallyScopedConn
0868:                                    .setReadInfoMsgEnabled(readInfoMsgState);
0869:                        }
0870:                    }
0871:                }
0872:
0873:                return execute(sql);
0874:            }
0875:
0876:            /**
0877:             * @see StatementImpl#execute(String, int[])
0878:             */
0879:            public boolean execute(String sql, int[] generatedKeyIndices)
0880:                    throws SQLException {
0881:                if ((generatedKeyIndices != null)
0882:                        && (generatedKeyIndices.length > 0)) {
0883:                    checkClosed();
0884:
0885:                    ConnectionImpl locallyScopedConn = this .connection;
0886:
0887:                    synchronized (locallyScopedConn.getMutex()) {
0888:                        // If this is a 'REPLACE' query, we need to be able to parse
0889:                        // the 'info' message returned from the server to determine
0890:                        // the actual number of keys generated.
0891:                        boolean readInfoMsgState = locallyScopedConn
0892:                                .isReadInfoMsgEnabled();
0893:                        locallyScopedConn.setReadInfoMsgEnabled(true);
0894:
0895:                        try {
0896:                            return execute(sql);
0897:                        } finally {
0898:                            locallyScopedConn
0899:                                    .setReadInfoMsgEnabled(readInfoMsgState);
0900:                        }
0901:                    }
0902:                }
0903:
0904:                return execute(sql);
0905:            }
0906:
0907:            /**
0908:             * @see StatementImpl#execute(String, String[])
0909:             */
0910:            public boolean execute(String sql, String[] generatedKeyNames)
0911:                    throws SQLException {
0912:                if ((generatedKeyNames != null)
0913:                        && (generatedKeyNames.length > 0)) {
0914:                    checkClosed();
0915:
0916:                    ConnectionImpl locallyScopedConn = this .connection;
0917:
0918:                    synchronized (locallyScopedConn.getMutex()) {
0919:                        // If this is a 'REPLACE' query, we need to be able to parse
0920:                        // the 'info' message returned from the server to determine
0921:                        // the actual number of keys generated.
0922:                        boolean readInfoMsgState = this .connection
0923:                                .isReadInfoMsgEnabled();
0924:                        locallyScopedConn.setReadInfoMsgEnabled(true);
0925:
0926:                        try {
0927:                            return execute(sql);
0928:                        } finally {
0929:                            locallyScopedConn
0930:                                    .setReadInfoMsgEnabled(readInfoMsgState);
0931:                        }
0932:                    }
0933:                }
0934:
0935:                return execute(sql);
0936:            }
0937:
0938:            /**
0939:             * JDBC 2.0 Submit a batch of commands to the database for execution. This
0940:             * method is optional.
0941:             *
0942:             * @return an array of update counts containing one element for each command
0943:             *         in the batch. The array is ordered according to the order in
0944:             *         which commands were inserted into the batch
0945:             *
0946:             * @exception SQLException
0947:             *                if a database-access error occurs, or the driver does not
0948:             *                support batch statements
0949:             * @throws java.sql.BatchUpdateException
0950:             *             DOCUMENT ME!
0951:             */
0952:            public synchronized int[] executeBatch() throws SQLException {
0953:                checkClosed();
0954:
0955:                ConnectionImpl locallyScopedConn = this .connection;
0956:
0957:                if (locallyScopedConn.isReadOnly()) {
0958:                    throw SQLError.createSQLException(Messages
0959:                            .getString("Statement.34") //$NON-NLS-1$
0960:                            + Messages.getString("Statement.35"), //$NON-NLS-1$
0961:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0962:                }
0963:
0964:                if (this .results != null) {
0965:                    if (!locallyScopedConn
0966:                            .getHoldResultsOpenOverStatementClose()) {
0967:                        this .results.realClose(false);
0968:                    }
0969:                }
0970:
0971:                synchronized (locallyScopedConn.getMutex()) {
0972:                    if (this .batchedArgs == null
0973:                            || this .batchedArgs.size() == 0) {
0974:                        return new int[0];
0975:                    }
0976:
0977:                    // we timeout the entire batch, not individual statements
0978:                    int individualStatementTimeout = this .timeoutInMillis;
0979:                    this .timeoutInMillis = 0;
0980:
0981:                    CancelTask timeoutTask = null;
0982:
0983:                    try {
0984:                        resetCancelledState();
0985:
0986:                        this .retrieveGeneratedKeys = true;
0987:
0988:                        int[] updateCounts = null;
0989:
0990:                        if (this .batchedArgs != null) {
0991:                            int nbrCommands = this .batchedArgs.size();
0992:
0993:                            this .batchedGeneratedKeys = new ArrayList(
0994:                                    this .batchedArgs.size());
0995:
0996:                            boolean multiQueriesEnabled = locallyScopedConn
0997:                                    .getAllowMultiQueries();
0998:
0999:                            if (locallyScopedConn.versionMeetsMinimum(4, 1, 1)
1000:                                    && (multiQueriesEnabled || (locallyScopedConn
1001:                                            .getRewriteBatchedStatements() && nbrCommands > 4))) {
1002:                                return executeBatchUsingMultiQueries(
1003:                                        multiQueriesEnabled, nbrCommands,
1004:                                        individualStatementTimeout);
1005:                            }
1006:
1007:                            if (locallyScopedConn.getEnableQueryTimeouts()
1008:                                    && individualStatementTimeout != 0
1009:                                    && locallyScopedConn.versionMeetsMinimum(5,
1010:                                            0, 0)) {
1011:                                timeoutTask = new CancelTask(this );
1012:                                ConnectionImpl.getCancelTimer()
1013:                                        .schedule(timeoutTask,
1014:                                                individualStatementTimeout);
1015:                            }
1016:
1017:                            updateCounts = new int[nbrCommands];
1018:
1019:                            for (int i = 0; i < nbrCommands; i++) {
1020:                                updateCounts[i] = -3;
1021:                            }
1022:
1023:                            SQLException sqlEx = null;
1024:
1025:                            int commandIndex = 0;
1026:
1027:                            for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
1028:                                try {
1029:                                    updateCounts[commandIndex] = executeUpdate(
1030:                                            (String) this .batchedArgs
1031:                                                    .get(commandIndex), true);
1032:                                    getBatchedGeneratedKeys();
1033:                                } catch (SQLException ex) {
1034:                                    updateCounts[commandIndex] = EXECUTE_FAILED;
1035:
1036:                                    if (this .continueBatchOnError
1037:                                            && !(ex instanceof  MySQLTimeoutException)
1038:                                            && !(ex instanceof  MySQLStatementCancelledException)) {
1039:                                        sqlEx = ex;
1040:                                    } else {
1041:                                        int[] newUpdateCounts = new int[commandIndex];
1042:                                        System.arraycopy(updateCounts, 0,
1043:                                                newUpdateCounts, 0,
1044:                                                commandIndex);
1045:
1046:                                        throw new java.sql.BatchUpdateException(
1047:                                                ex.getMessage(), ex
1048:                                                        .getSQLState(), ex
1049:                                                        .getErrorCode(),
1050:                                                newUpdateCounts);
1051:                                    }
1052:                                }
1053:                            }
1054:
1055:                            if (sqlEx != null) {
1056:                                throw new java.sql.BatchUpdateException(sqlEx
1057:                                        .getMessage(), sqlEx.getSQLState(),
1058:                                        sqlEx.getErrorCode(), updateCounts);
1059:                            }
1060:                        }
1061:
1062:                        if (timeoutTask != null) {
1063:                            if (timeoutTask.caughtWhileCancelling != null) {
1064:                                throw timeoutTask.caughtWhileCancelling;
1065:                            }
1066:
1067:                            timeoutTask.cancel();
1068:                            timeoutTask = null;
1069:                        }
1070:
1071:                        return (updateCounts != null) ? updateCounts
1072:                                : new int[0];
1073:                    } finally {
1074:
1075:                        if (timeoutTask != null) {
1076:                            timeoutTask.cancel();
1077:                        }
1078:
1079:                        resetCancelledState();
1080:
1081:                        this .timeoutInMillis = individualStatementTimeout;
1082:                        this .retrieveGeneratedKeys = false;
1083:
1084:                        clearBatch();
1085:                    }
1086:                }
1087:            }
1088:
1089:            /**
1090:             * Rewrites batch into a single query to send to the server. This method
1091:             * will constrain each batch to be shorter than max_allowed_packet on the
1092:             * server.
1093:             *
1094:             * @return update counts in the same manner as executeBatch()
1095:             * @throws SQLException
1096:             */
1097:            private int[] executeBatchUsingMultiQueries(
1098:                    boolean multiQueriesEnabled, int nbrCommands,
1099:                    int individualStatementTimeout) throws SQLException {
1100:
1101:                ConnectionImpl locallyScopedConn = this .connection;
1102:
1103:                if (!multiQueriesEnabled) {
1104:                    locallyScopedConn.getIO().enableMultiQueries();
1105:                }
1106:
1107:                java.sql.Statement batchStmt = null;
1108:
1109:                CancelTask timeoutTask = null;
1110:
1111:                try {
1112:                    int[] updateCounts = new int[nbrCommands];
1113:
1114:                    for (int i = 0; i < nbrCommands; i++) {
1115:                        updateCounts[i] = -3;
1116:                    }
1117:
1118:                    int commandIndex = 0;
1119:
1120:                    StringBuffer queryBuf = new StringBuffer();
1121:
1122:                    batchStmt = locallyScopedConn.createStatement();
1123:
1124:                    if (locallyScopedConn.getEnableQueryTimeouts()
1125:                            && individualStatementTimeout != 0
1126:                            && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
1127:                        timeoutTask = new CancelTask((StatementImpl) batchStmt);
1128:                        ConnectionImpl.getCancelTimer().schedule(timeoutTask,
1129:                                individualStatementTimeout);
1130:                    }
1131:
1132:                    int counter = 0;
1133:
1134:                    int numberOfBytesPerChar = 1;
1135:
1136:                    String connectionEncoding = locallyScopedConn.getEncoding();
1137:
1138:                    if (StringUtils.startsWithIgnoreCase(connectionEncoding,
1139:                            "utf")) {
1140:                        numberOfBytesPerChar = 3;
1141:                    } else if (CharsetMapping
1142:                            .isMultibyteCharset(connectionEncoding)) {
1143:                        numberOfBytesPerChar = 2;
1144:                    }
1145:
1146:                    int escapeAdjust = 1;
1147:
1148:                    if (this .doEscapeProcessing) {
1149:                        escapeAdjust = 2; /* We assume packet _could_ grow by this amount, as we're not
1150:                        			                     sure how big statement will end up after
1151:                        			                     escape processing */
1152:                    }
1153:
1154:                    SQLException sqlEx = null;
1155:
1156:                    int argumentSetsInBatchSoFar = 0;
1157:
1158:                    for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
1159:                        String nextQuery = (String) this .batchedArgs
1160:                                .get(commandIndex);
1161:
1162:                        if (((((queryBuf.length() + nextQuery.length()) * numberOfBytesPerChar) + 1 /* for semicolon */
1163:                        + MysqlIO.HEADER_LENGTH) * escapeAdjust) + 32 > this .connection
1164:                                .getMaxAllowedPacket()) {
1165:                            try {
1166:                                batchStmt.execute(queryBuf.toString());
1167:                            } catch (SQLException ex) {
1168:                                sqlEx = handleExceptionForBatch(commandIndex,
1169:                                        argumentSetsInBatchSoFar, updateCounts,
1170:                                        ex);
1171:                            }
1172:
1173:                            counter = processMultiCountsAndKeys(
1174:                                    (StatementImpl) batchStmt, counter,
1175:                                    updateCounts);
1176:
1177:                            queryBuf = new StringBuffer();
1178:                            argumentSetsInBatchSoFar = 0;
1179:                        }
1180:
1181:                        queryBuf.append(nextQuery);
1182:                        queryBuf.append(";");
1183:                        argumentSetsInBatchSoFar++;
1184:                    }
1185:
1186:                    if (queryBuf.length() > 0) {
1187:                        try {
1188:                            batchStmt.execute(queryBuf.toString());
1189:                        } catch (SQLException ex) {
1190:                            sqlEx = handleExceptionForBatch(commandIndex - 1,
1191:                                    argumentSetsInBatchSoFar, updateCounts, ex);
1192:                        }
1193:
1194:                        counter = processMultiCountsAndKeys(
1195:                                (StatementImpl) batchStmt, counter,
1196:                                updateCounts);
1197:                    }
1198:
1199:                    if (timeoutTask != null) {
1200:                        if (timeoutTask.caughtWhileCancelling != null) {
1201:                            throw timeoutTask.caughtWhileCancelling;
1202:                        }
1203:
1204:                        timeoutTask.cancel();
1205:                        timeoutTask = null;
1206:                    }
1207:
1208:                    if (sqlEx != null) {
1209:                        throw new java.sql.BatchUpdateException(sqlEx
1210:                                .getMessage(), sqlEx.getSQLState(), sqlEx
1211:                                .getErrorCode(), updateCounts);
1212:                    }
1213:
1214:                    return (updateCounts != null) ? updateCounts : new int[0];
1215:                } finally {
1216:                    if (timeoutTask != null) {
1217:                        timeoutTask.cancel();
1218:                    }
1219:
1220:                    resetCancelledState();
1221:
1222:                    try {
1223:                        if (batchStmt != null) {
1224:                            batchStmt.close();
1225:                        }
1226:                    } finally {
1227:                        if (!multiQueriesEnabled) {
1228:                            locallyScopedConn.getIO().disableMultiQueries();
1229:                        }
1230:                    }
1231:                }
1232:            }
1233:
1234:            protected int processMultiCountsAndKeys(
1235:                    StatementImpl batchedStatement, int updateCountCounter,
1236:                    int[] updateCounts) throws SQLException {
1237:                updateCounts[updateCountCounter++] = batchedStatement
1238:                        .getUpdateCount();
1239:
1240:                boolean doGenKeys = this .batchedGeneratedKeys != null;
1241:
1242:                long generatedKeyStart = 0;
1243:                byte[][] row = null;
1244:
1245:                if (doGenKeys) {
1246:                    generatedKeyStart = batchedStatement.getLastInsertID();
1247:
1248:                    row = new byte[1][];
1249:                    row[0] = Long.toString(generatedKeyStart++).getBytes();
1250:                    this .batchedGeneratedKeys.add(new ByteArrayRow(row));
1251:                }
1252:
1253:                while (batchedStatement.getMoreResults()
1254:                        || batchedStatement.getUpdateCount() != -1) {
1255:                    updateCounts[updateCountCounter++] = batchedStatement
1256:                            .getUpdateCount();
1257:
1258:                    if (doGenKeys) {
1259:                        row = new byte[1][];
1260:                        row[0] = Long.toString(generatedKeyStart++).getBytes();
1261:                        this .batchedGeneratedKeys.add(new ByteArrayRow(row));
1262:                    }
1263:                }
1264:
1265:                return updateCountCounter;
1266:            }
1267:
1268:            protected SQLException handleExceptionForBatch(int endOfBatchIndex,
1269:                    int numValuesPerBatch, int[] updateCounts, SQLException ex)
1270:                    throws BatchUpdateException {
1271:                SQLException sqlEx;
1272:
1273:                for (int j = endOfBatchIndex; j > endOfBatchIndex
1274:                        - numValuesPerBatch; j--) {
1275:                    updateCounts[j] = EXECUTE_FAILED;
1276:                }
1277:
1278:                if (this .continueBatchOnError
1279:                        && !(ex instanceof  MySQLTimeoutException)
1280:                        && !(ex instanceof  MySQLStatementCancelledException)) {
1281:                    sqlEx = ex;
1282:                } else {
1283:                    int[] newUpdateCounts = new int[endOfBatchIndex];
1284:                    System.arraycopy(updateCounts, 0, newUpdateCounts, 0,
1285:                            endOfBatchIndex);
1286:
1287:                    throw new java.sql.BatchUpdateException(ex.getMessage(), ex
1288:                            .getSQLState(), ex.getErrorCode(), newUpdateCounts);
1289:                }
1290:
1291:                return sqlEx;
1292:            }
1293:
1294:            /**
1295:             * Execute a SQL statement that retruns a single ResultSet
1296:             *
1297:             * @param sql
1298:             *            typically a static SQL SELECT statement
1299:             *
1300:             * @return a ResulSet that contains the data produced by the query
1301:             *
1302:             * @exception SQLException
1303:             *                if a database access error occurs
1304:             */
1305:            public java.sql.ResultSet executeQuery(String sql)
1306:                    throws SQLException {
1307:                checkClosed();
1308:
1309:                ConnectionImpl locallyScopedConn = this .connection;
1310:
1311:                synchronized (locallyScopedConn.getMutex()) {
1312:                    resetCancelledState();
1313:
1314:                    checkNullOrEmptyQuery(sql);
1315:
1316:                    boolean doStreaming = createStreamingResultSet();
1317:
1318:                    // Adjust net_write_timeout to a higher value if we're
1319:                    // streaming result sets. More often than not, someone runs into
1320:                    // an issue where they blow net_write_timeout when using this
1321:                    // feature, and if they're willing to hold a result set open
1322:                    // for 30 seconds or more, one more round-trip isn't going to hurt
1323:                    //
1324:                    // This is reset by RowDataDynamic.close().
1325:
1326:                    if (doStreaming
1327:                            && this .connection
1328:                                    .getNetTimeoutForStreamingResults() > 0) {
1329:                        executeSimpleNonQuery(
1330:                                locallyScopedConn,
1331:                                "SET net_write_timeout="
1332:                                        + this .connection
1333:                                                .getNetTimeoutForStreamingResults());
1334:                    }
1335:
1336:                    if (this .doEscapeProcessing) {
1337:                        Object escapedSqlResult = EscapeProcessor.escapeSQL(
1338:                                sql, locallyScopedConn
1339:                                        .serverSupportsConvertFn(),
1340:                                this .connection);
1341:
1342:                        if (escapedSqlResult instanceof  String) {
1343:                            sql = (String) escapedSqlResult;
1344:                        } else {
1345:                            sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
1346:                        }
1347:                    }
1348:
1349:                    char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
1350:                            findStartOfStatement(sql));
1351:
1352:                    if (sql.charAt(0) == '/') {
1353:                        if (sql.startsWith(PING_MARKER)) {
1354:                            doPingInstead();
1355:
1356:                            return this .results;
1357:                        }
1358:                    }
1359:
1360:                    checkForDml(sql, firstStatementChar);
1361:
1362:                    if (this .results != null) {
1363:                        if (!locallyScopedConn
1364:                                .getHoldResultsOpenOverStatementClose()) {
1365:                            this .results.realClose(false);
1366:                        }
1367:                    }
1368:
1369:                    CachedResultSetMetaData cachedMetaData = null;
1370:
1371:                    // If there isn't a limit clause in the SQL
1372:                    // then limit the number of rows to return in
1373:                    // an efficient manner. Only do this if
1374:                    // setMaxRows() hasn't been used on any Statements
1375:                    // generated from the current Connection (saves
1376:                    // a query, and network traffic).
1377:
1378:                    if (useServerFetch()) {
1379:                        this .results = createResultSetUsingServerFetch(sql);
1380:
1381:                        return this .results;
1382:                    }
1383:
1384:                    CancelTask timeoutTask = null;
1385:
1386:                    String oldCatalog = null;
1387:
1388:                    try {
1389:                        if (locallyScopedConn.getEnableQueryTimeouts()
1390:                                && this .timeoutInMillis != 0
1391:                                && locallyScopedConn.versionMeetsMinimum(5, 0,
1392:                                        0)) {
1393:                            timeoutTask = new CancelTask(this );
1394:                            ConnectionImpl.getCancelTimer().schedule(
1395:                                    timeoutTask, this .timeoutInMillis);
1396:                        }
1397:
1398:                        if (!locallyScopedConn.getCatalog().equals(
1399:                                this .currentCatalog)) {
1400:                            oldCatalog = locallyScopedConn.getCatalog();
1401:                            locallyScopedConn.setCatalog(this .currentCatalog);
1402:                        }
1403:
1404:                        //
1405:                        // Check if we have cached metadata for this query...
1406:                        //
1407:
1408:                        Field[] cachedFields = null;
1409:
1410:                        if (locallyScopedConn.getCacheResultSetMetadata()) {
1411:                            cachedMetaData = locallyScopedConn
1412:                                    .getCachedMetaData(sql);
1413:
1414:                            if (cachedMetaData != null) {
1415:                                cachedFields = cachedMetaData.fields;
1416:                            }
1417:                        }
1418:
1419:                        if (locallyScopedConn.useMaxRows()) {
1420:                            // We need to execute this all together
1421:                            // So synchronize on the Connection's mutex (because
1422:                            // even queries going through there synchronize
1423:                            // on the connection
1424:                            if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$
1425:                                this .results = locallyScopedConn.execSQL(this ,
1426:                                        sql, this .maxRows, null,
1427:                                        this .resultSetType,
1428:                                        this .resultSetConcurrency, doStreaming,
1429:                                        this .currentCatalog, cachedFields);
1430:                            } else {
1431:                                if (this .maxRows <= 0) {
1432:                                    executeSimpleNonQuery(locallyScopedConn,
1433:                                            "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
1434:                                } else {
1435:                                    executeSimpleNonQuery(locallyScopedConn,
1436:                                            "SET OPTION SQL_SELECT_LIMIT="
1437:                                                    + this .maxRows);
1438:                                }
1439:
1440:                                this .results = locallyScopedConn.execSQL(this ,
1441:                                        sql, -1, null, this .resultSetType,
1442:                                        this .resultSetConcurrency, doStreaming,
1443:                                        this .currentCatalog, cachedFields);
1444:
1445:                                if (oldCatalog != null) {
1446:                                    locallyScopedConn.setCatalog(oldCatalog);
1447:                                }
1448:                            }
1449:                        } else {
1450:                            this .results = locallyScopedConn.execSQL(this , sql,
1451:                                    -1, null, this .resultSetType,
1452:                                    this .resultSetConcurrency, doStreaming,
1453:                                    this .currentCatalog, cachedFields);
1454:                        }
1455:
1456:                        if (timeoutTask != null) {
1457:                            if (timeoutTask.caughtWhileCancelling != null) {
1458:                                throw timeoutTask.caughtWhileCancelling;
1459:                            }
1460:
1461:                            timeoutTask.cancel();
1462:                            timeoutTask = null;
1463:                        }
1464:
1465:                        synchronized (this .cancelTimeoutMutex) {
1466:                            if (this .wasCancelled) {
1467:                                SQLException cause = null;
1468:
1469:                                if (this .wasCancelledByTimeout) {
1470:                                    cause = new MySQLTimeoutException();
1471:                                } else {
1472:                                    cause = new MySQLStatementCancelledException();
1473:                                }
1474:
1475:                                resetCancelledState();
1476:
1477:                                throw cause;
1478:                            }
1479:                        }
1480:                    } finally {
1481:                        if (timeoutTask != null) {
1482:                            timeoutTask.cancel();
1483:                        }
1484:
1485:                        if (oldCatalog != null) {
1486:                            locallyScopedConn.setCatalog(oldCatalog);
1487:                        }
1488:                    }
1489:
1490:                    this .lastInsertId = this .results.getUpdateID();
1491:
1492:                    if (cachedMetaData != null) {
1493:                        locallyScopedConn.initializeResultsMetadataFromCache(
1494:                                sql, cachedMetaData, this .results);
1495:                    } else {
1496:                        if (this .connection.getCacheResultSetMetadata()) {
1497:                            locallyScopedConn
1498:                                    .initializeResultsMetadataFromCache(sql,
1499:                                            null /* will be created */,
1500:                                            this .results);
1501:                        }
1502:                    }
1503:
1504:                    return this .results;
1505:                }
1506:            }
1507:
1508:            protected void doPingInstead() throws SQLException {
1509:                if (this .pingTarget != null) {
1510:                    this .pingTarget.doPing();
1511:                } else {
1512:                    this .connection.ping();
1513:                }
1514:
1515:                ResultSetInternalMethods fakeSelectOneResultSet = generatePingResultSet();
1516:                this .results = fakeSelectOneResultSet;
1517:            }
1518:
1519:            protected ResultSetInternalMethods generatePingResultSet()
1520:                    throws SQLException {
1521:                Field[] fields = { new Field(null, "1", Types.BIGINT, 1) };
1522:                ArrayList rows = new ArrayList();
1523:                byte[] colVal = new byte[] { (byte) '1' };
1524:
1525:                rows.add(new ByteArrayRow(new byte[][] { colVal }));
1526:
1527:                return (ResultSetInternalMethods) DatabaseMetaData
1528:                        .buildResultSet(fields, rows, this .connection);
1529:            }
1530:
1531:            protected void executeSimpleNonQuery(ConnectionImpl c,
1532:                    String nonQuery) throws SQLException {
1533:                c.execSQL(this , nonQuery, -1, null,
1534:                        ResultSet.TYPE_FORWARD_ONLY,
1535:                        ResultSet.CONCUR_READ_ONLY, false, this .currentCatalog,
1536:                        null, false).close();
1537:            }
1538:
1539:            /**
1540:             * Execute a SQL INSERT, UPDATE or DELETE statement. In addition SQL
1541:             * statements that return nothing such as SQL DDL statements can be executed
1542:             * Any IDs generated for AUTO_INCREMENT fields can be retrieved by casting
1543:             * this Statement to org.gjt.mm.mysql.Statement and calling the
1544:             * getLastInsertID() method.
1545:             *
1546:             * @param sql
1547:             *            a SQL statement
1548:             *
1549:             * @return either a row count, or 0 for SQL commands
1550:             *
1551:             * @exception SQLException
1552:             *                if a database access error occurs
1553:             */
1554:            public int executeUpdate(String sql) throws SQLException {
1555:                return executeUpdate(sql, false);
1556:            }
1557:
1558:            protected int executeUpdate(String sql, boolean isBatch)
1559:                    throws SQLException {
1560:                checkClosed();
1561:
1562:                ConnectionImpl locallyScopedConn = this .connection;
1563:
1564:                char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
1565:                        findStartOfStatement(sql));
1566:
1567:                ResultSetInternalMethods rs = null;
1568:
1569:                synchronized (locallyScopedConn.getMutex()) {
1570:                    resetCancelledState();
1571:
1572:                    checkNullOrEmptyQuery(sql);
1573:
1574:                    if (this .doEscapeProcessing) {
1575:                        Object escapedSqlResult = EscapeProcessor.escapeSQL(
1576:                                sql, this .connection.serverSupportsConvertFn(),
1577:                                this .connection);
1578:
1579:                        if (escapedSqlResult instanceof  String) {
1580:                            sql = (String) escapedSqlResult;
1581:                        } else {
1582:                            sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
1583:                        }
1584:                    }
1585:
1586:                    if (locallyScopedConn.isReadOnly()) {
1587:                        throw SQLError.createSQLException(Messages
1588:                                .getString("Statement.42") //$NON-NLS-1$
1589:                                + Messages.getString("Statement.43"), //$NON-NLS-1$
1590:                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1591:                    }
1592:
1593:                    if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$
1594:                        throw SQLError.createSQLException(Messages
1595:                                .getString("Statement.46"), //$NON-NLS-1$
1596:                                "01S03"); //$NON-NLS-1$
1597:                    }
1598:
1599:                    if (this .results != null) {
1600:                        if (!locallyScopedConn
1601:                                .getHoldResultsOpenOverStatementClose()) {
1602:                            this .results.realClose(false);
1603:                        }
1604:                    }
1605:
1606:                    // The checking and changing of catalogs
1607:                    // must happen in sequence, so synchronize
1608:                    // on the same mutex that _conn is using
1609:
1610:                    CancelTask timeoutTask = null;
1611:
1612:                    String oldCatalog = null;
1613:
1614:                    try {
1615:                        if (locallyScopedConn.getEnableQueryTimeouts()
1616:                                && this .timeoutInMillis != 0
1617:                                && locallyScopedConn.versionMeetsMinimum(5, 0,
1618:                                        0)) {
1619:                            timeoutTask = new CancelTask(this );
1620:                            ConnectionImpl.getCancelTimer().schedule(
1621:                                    timeoutTask, this .timeoutInMillis);
1622:                        }
1623:
1624:                        if (!locallyScopedConn.getCatalog().equals(
1625:                                this .currentCatalog)) {
1626:                            oldCatalog = locallyScopedConn.getCatalog();
1627:                            locallyScopedConn.setCatalog(this .currentCatalog);
1628:                        }
1629:
1630:                        //
1631:                        // Only apply max_rows to selects
1632:                        //
1633:                        if (locallyScopedConn.useMaxRows()) {
1634:                            executeSimpleNonQuery(locallyScopedConn,
1635:                                    "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
1636:                        }
1637:
1638:                        rs = locallyScopedConn.execSQL(this , sql, -1, null,
1639:                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
1640:                                java.sql.ResultSet.CONCUR_READ_ONLY, false,
1641:                                this .currentCatalog,
1642:                                null /* force read of field info on DML */,
1643:                                isBatch);
1644:
1645:                        if (timeoutTask != null) {
1646:                            if (timeoutTask.caughtWhileCancelling != null) {
1647:                                throw timeoutTask.caughtWhileCancelling;
1648:                            }
1649:
1650:                            timeoutTask.cancel();
1651:                            timeoutTask = null;
1652:                        }
1653:
1654:                        synchronized (this .cancelTimeoutMutex) {
1655:                            if (this .wasCancelled) {
1656:                                SQLException cause = null;
1657:
1658:                                if (this .wasCancelledByTimeout) {
1659:                                    cause = new MySQLTimeoutException();
1660:                                } else {
1661:                                    cause = new MySQLStatementCancelledException();
1662:                                }
1663:
1664:                                resetCancelledState();
1665:
1666:                                throw cause;
1667:                            }
1668:                        }
1669:                    } finally {
1670:                        if (timeoutTask != null) {
1671:                            timeoutTask.cancel();
1672:                        }
1673:
1674:                        if (oldCatalog != null) {
1675:                            locallyScopedConn.setCatalog(oldCatalog);
1676:                        }
1677:                    }
1678:                }
1679:
1680:                this .results = rs;
1681:
1682:                rs.setFirstCharOfQuery(firstStatementChar);
1683:
1684:                this .updateCount = rs.getUpdateCount();
1685:
1686:                int truncatedUpdateCount = 0;
1687:
1688:                if (this .updateCount > Integer.MAX_VALUE) {
1689:                    truncatedUpdateCount = Integer.MAX_VALUE;
1690:                } else {
1691:                    truncatedUpdateCount = (int) this .updateCount;
1692:                }
1693:
1694:                this .lastInsertId = rs.getUpdateID();
1695:
1696:                return truncatedUpdateCount;
1697:            }
1698:
1699:            /**
1700:             * @see StatementImpl#executeUpdate(String, int)
1701:             */
1702:            public int executeUpdate(String sql, int returnGeneratedKeys)
1703:                    throws SQLException {
1704:                if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) {
1705:                    checkClosed();
1706:
1707:                    ConnectionImpl locallyScopedConn = this .connection;
1708:
1709:                    synchronized (locallyScopedConn.getMutex()) {
1710:                        // If this is a 'REPLACE' query, we need to be able to parse
1711:                        // the 'info' message returned from the server to determine
1712:                        // the actual number of keys generated.
1713:                        boolean readInfoMsgState = locallyScopedConn
1714:                                .isReadInfoMsgEnabled();
1715:                        locallyScopedConn.setReadInfoMsgEnabled(true);
1716:
1717:                        try {
1718:                            return executeUpdate(sql);
1719:                        } finally {
1720:                            locallyScopedConn
1721:                                    .setReadInfoMsgEnabled(readInfoMsgState);
1722:                        }
1723:                    }
1724:                }
1725:
1726:                return executeUpdate(sql);
1727:            }
1728:
1729:            /**
1730:             * @see StatementImpl#executeUpdate(String, int[])
1731:             */
1732:            public int executeUpdate(String sql, int[] generatedKeyIndices)
1733:                    throws SQLException {
1734:                if ((generatedKeyIndices != null)
1735:                        && (generatedKeyIndices.length > 0)) {
1736:                    checkClosed();
1737:
1738:                    ConnectionImpl locallyScopedConn = this .connection;
1739:
1740:                    synchronized (locallyScopedConn.getMutex()) {
1741:                        // If this is a 'REPLACE' query, we need to be able to parse
1742:                        // the 'info' message returned from the server to determine
1743:                        // the actual number of keys generated.
1744:                        boolean readInfoMsgState = locallyScopedConn
1745:                                .isReadInfoMsgEnabled();
1746:                        locallyScopedConn.setReadInfoMsgEnabled(true);
1747:
1748:                        try {
1749:                            return executeUpdate(sql);
1750:                        } finally {
1751:                            locallyScopedConn
1752:                                    .setReadInfoMsgEnabled(readInfoMsgState);
1753:                        }
1754:                    }
1755:                }
1756:
1757:                return executeUpdate(sql);
1758:            }
1759:
1760:            /**
1761:             * @see StatementImpl#executeUpdate(String, String[])
1762:             */
1763:            public int executeUpdate(String sql, String[] generatedKeyNames)
1764:                    throws SQLException {
1765:                if ((generatedKeyNames != null)
1766:                        && (generatedKeyNames.length > 0)) {
1767:                    checkClosed();
1768:
1769:                    ConnectionImpl locallyScopedConn = this .connection;
1770:
1771:                    synchronized (locallyScopedConn.getMutex()) {
1772:                        // If this is a 'REPLACE' query, we need to be able to parse
1773:                        // the 'info' message returned from the server to determine
1774:                        // the actual number of keys generated.
1775:                        boolean readInfoMsgState = this .connection
1776:                                .isReadInfoMsgEnabled();
1777:                        locallyScopedConn.setReadInfoMsgEnabled(true);
1778:
1779:                        try {
1780:                            return executeUpdate(sql);
1781:                        } finally {
1782:                            locallyScopedConn
1783:                                    .setReadInfoMsgEnabled(readInfoMsgState);
1784:                        }
1785:                    }
1786:                }
1787:
1788:                return executeUpdate(sql);
1789:            }
1790:
1791:            /**
1792:             * Optimization to only use one calendar per-session, or calculate it for
1793:             * each call, depending on user configuration
1794:             */
1795:            protected Calendar getCalendarInstanceForSessionOrNew() {
1796:                if (this .connection != null) {
1797:                    return this .connection.getCalendarInstanceForSessionOrNew();
1798:                } else {
1799:                    // punt, no connection around
1800:                    return new GregorianCalendar();
1801:                }
1802:            }
1803:
1804:            /**
1805:             * JDBC 2.0 Return the Connection that produced the Statement.
1806:             *
1807:             * @return the Connection that produced the Statement
1808:             *
1809:             * @throws SQLException
1810:             *             if an error occurs
1811:             */
1812:            public java.sql.Connection getConnection() throws SQLException {
1813:                return this .connection;
1814:            }
1815:
1816:            /**
1817:             * JDBC 2.0 Determine the fetch direction.
1818:             *
1819:             * @return the default fetch direction
1820:             *
1821:             * @exception SQLException
1822:             *                if a database-access error occurs
1823:             */
1824:            public int getFetchDirection() throws SQLException {
1825:                return java.sql.ResultSet.FETCH_FORWARD;
1826:            }
1827:
1828:            /**
1829:             * JDBC 2.0 Determine the default fetch size.
1830:             *
1831:             * @return the number of rows to fetch at a time
1832:             *
1833:             * @throws SQLException
1834:             *             if an error occurs
1835:             */
1836:            public int getFetchSize() throws SQLException {
1837:                return this .fetchSize;
1838:            }
1839:
1840:            /**
1841:             * DOCUMENT ME!
1842:             *
1843:             * @return DOCUMENT ME!
1844:             *
1845:             * @throws SQLException
1846:             *             DOCUMENT ME!
1847:             */
1848:            public synchronized java.sql.ResultSet getGeneratedKeys()
1849:                    throws SQLException {
1850:                if (this .batchedGeneratedKeys == null) {
1851:                    return getGeneratedKeysInternal();
1852:                }
1853:
1854:                Field[] fields = new Field[1];
1855:                fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$
1856:                fields[0].setConnection(this .connection);
1857:
1858:                return com.mysql.jdbc.ResultSetImpl.getInstance(
1859:                        this .currentCatalog, fields, new RowDataStatic(
1860:                                this .batchedGeneratedKeys), this .connection,
1861:                        this , false);
1862:            }
1863:
1864:            /*
1865:             * Needed because there's no concept of super.super to get to this
1866:             * implementation from ServerPreparedStatement when dealing with batched
1867:             * updates.
1868:             */
1869:            protected java.sql.ResultSet getGeneratedKeysInternal()
1870:                    throws SQLException {
1871:                Field[] fields = new Field[1];
1872:                fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$
1873:                fields[0].setConnection(this .connection);
1874:
1875:                ArrayList rowSet = new ArrayList();
1876:
1877:                long beginAt = getLastInsertID();
1878:                int numKeys = getUpdateCount();
1879:
1880:                if (this .results != null) {
1881:                    String serverInfo = this .results.getServerInfo();
1882:
1883:                    //
1884:                    // Only parse server info messages for 'REPLACE'
1885:                    // queries
1886:                    //
1887:                    if ((numKeys > 0)
1888:                            && (this .results.getFirstCharOfQuery() == 'R')
1889:                            && (serverInfo != null)
1890:                            && (serverInfo.length() > 0)) {
1891:                        numKeys = getRecordCountFromInfo(serverInfo);
1892:                    }
1893:
1894:                    if ((beginAt > 0) && (numKeys > 0)) {
1895:                        for (int i = 0; i < numKeys; i++) {
1896:                            byte[][] row = new byte[1][];
1897:                            row[0] = Long.toString(beginAt++).getBytes();
1898:                            rowSet.add(new ByteArrayRow(row));
1899:                        }
1900:                    }
1901:                }
1902:
1903:                return com.mysql.jdbc.ResultSetImpl.getInstance(
1904:                        this .currentCatalog, fields, new RowDataStatic(rowSet),
1905:                        this .connection, this , false);
1906:            }
1907:
1908:            /**
1909:             * Returns the id used when profiling
1910:             *
1911:             * @return the id used when profiling.
1912:             */
1913:            protected int getId() {
1914:                return this .statementId;
1915:            }
1916:
1917:            /**
1918:             * getLastInsertID returns the value of the auto_incremented key after an
1919:             * executeQuery() or excute() call.
1920:             *
1921:             * <p>
1922:             * This gets around the un-threadsafe behavior of "select LAST_INSERT_ID()"
1923:             * which is tied to the Connection that created this Statement, and
1924:             * therefore could have had many INSERTS performed before one gets a chance
1925:             * to call "select LAST_INSERT_ID()".
1926:             * </p>
1927:             *
1928:             * @return the last update ID.
1929:             */
1930:            public long getLastInsertID() {
1931:                return this .lastInsertId;
1932:            }
1933:
1934:            /**
1935:             * getLongUpdateCount returns the current result as an update count, if the
1936:             * result is a ResultSet or there are no more results, -1 is returned. It
1937:             * should only be called once per result.
1938:             *
1939:             * <p>
1940:             * This method returns longs as MySQL server versions newer than 3.22.4
1941:             * return 64-bit values for update counts
1942:             * </p>
1943:             *
1944:             * @return the current update count.
1945:             */
1946:            public long getLongUpdateCount() {
1947:                if (this .results == null) {
1948:                    return -1;
1949:                }
1950:
1951:                if (this .results.reallyResult()) {
1952:                    return -1;
1953:                }
1954:
1955:                return this .updateCount;
1956:            }
1957:
1958:            /**
1959:             * The maxFieldSize limit (in bytes) is the maximum amount of data returned
1960:             * for any column value; it only applies to BINARY, VARBINARY,
1961:             * LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR columns. If the limit is
1962:             * exceeded, the excess data is silently discarded.
1963:             *
1964:             * @return the current max column size limit; zero means unlimited
1965:             *
1966:             * @exception SQLException
1967:             *                if a database access error occurs
1968:             */
1969:            public int getMaxFieldSize() throws SQLException {
1970:                return this .maxFieldSize;
1971:            }
1972:
1973:            /**
1974:             * The maxRows limit is set to limit the number of rows that any ResultSet
1975:             * can contain. If the limit is exceeded, the excess rows are silently
1976:             * dropped.
1977:             *
1978:             * @return the current maximum row limit; zero means unlimited
1979:             *
1980:             * @exception SQLException
1981:             *                if a database access error occurs
1982:             */
1983:            public int getMaxRows() throws SQLException {
1984:                if (this .maxRows <= 0) {
1985:                    return 0;
1986:                }
1987:
1988:                return this .maxRows;
1989:            }
1990:
1991:            /**
1992:             * getMoreResults moves to a Statement's next result. If it returns true,
1993:             * this result is a ResulSet.
1994:             *
1995:             * @return true if the next ResultSet is valid
1996:             *
1997:             * @exception SQLException
1998:             *                if a database access error occurs
1999:             */
2000:            public boolean getMoreResults() throws SQLException {
2001:                return getMoreResults(CLOSE_CURRENT_RESULT);
2002:            }
2003:
2004:            /**
2005:             * @see StatementImpl#getMoreResults(int)
2006:             */
2007:            public boolean getMoreResults(int current) throws SQLException {
2008:
2009:                if (this .results == null) {
2010:                    return false;
2011:                }
2012:
2013:                ResultSetInternalMethods nextResultSet = this .results
2014:                        .getNextResultSet();
2015:
2016:                switch (current) {
2017:                case java.sql.Statement.CLOSE_CURRENT_RESULT:
2018:
2019:                    if (this .results != null) {
2020:                        this .results.close();
2021:                        this .results.clearNextResult();
2022:                    }
2023:
2024:                    break;
2025:
2026:                case java.sql.Statement.CLOSE_ALL_RESULTS:
2027:
2028:                    if (this .results != null) {
2029:                        this .results.close();
2030:                        this .results.clearNextResult();
2031:                    }
2032:
2033:                    closeAllOpenResults();
2034:
2035:                    break;
2036:
2037:                case java.sql.Statement.KEEP_CURRENT_RESULT:
2038:                    if (!this .connection.getDontTrackOpenResources()) {
2039:                        this .openResults.add(this .results);
2040:                    }
2041:
2042:                    this .results.clearNextResult(); // nobody besides us should
2043:                    // ever need this value...
2044:                    break;
2045:
2046:                default:
2047:                    throw SQLError.createSQLException(Messages
2048:                            .getString("Statement.19"), //$NON-NLS-1$
2049:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2050:                }
2051:
2052:                this .results = nextResultSet;
2053:
2054:                if (this .results == null) {
2055:                    this .updateCount = -1;
2056:                    this .lastInsertId = -1;
2057:                } else if (this .results.reallyResult()) {
2058:                    this .updateCount = -1;
2059:                    this .lastInsertId = -1;
2060:                } else {
2061:                    this .updateCount = this .results.getUpdateCount();
2062:                    this .lastInsertId = this .results.getUpdateID();
2063:                }
2064:
2065:                return ((this .results != null) && this .results.reallyResult()) ? true
2066:                        : false;
2067:            }
2068:
2069:            /**
2070:             * The queryTimeout limit is the number of seconds the driver will wait for
2071:             * a Statement to execute. If the limit is exceeded, a SQLException is
2072:             * thrown.
2073:             *
2074:             * @return the current query timeout limit in seconds; 0 = unlimited
2075:             *
2076:             * @exception SQLException
2077:             *                if a database access error occurs
2078:             */
2079:            public int getQueryTimeout() throws SQLException {
2080:                return this .timeoutInMillis / 1000;
2081:            }
2082:
2083:            /**
2084:             * Parses actual record count from 'info' message
2085:             *
2086:             * @param serverInfo
2087:             *            DOCUMENT ME!
2088:             *
2089:             * @return DOCUMENT ME!
2090:             */
2091:            private int getRecordCountFromInfo(String serverInfo) {
2092:                StringBuffer recordsBuf = new StringBuffer();
2093:                int recordsCount = 0;
2094:                int duplicatesCount = 0;
2095:
2096:                char c = (char) 0;
2097:
2098:                int length = serverInfo.length();
2099:                int i = 0;
2100:
2101:                for (; i < length; i++) {
2102:                    c = serverInfo.charAt(i);
2103:
2104:                    if (Character.isDigit(c)) {
2105:                        break;
2106:                    }
2107:                }
2108:
2109:                recordsBuf.append(c);
2110:                i++;
2111:
2112:                for (; i < length; i++) {
2113:                    c = serverInfo.charAt(i);
2114:
2115:                    if (!Character.isDigit(c)) {
2116:                        break;
2117:                    }
2118:
2119:                    recordsBuf.append(c);
2120:                }
2121:
2122:                recordsCount = Integer.parseInt(recordsBuf.toString());
2123:
2124:                StringBuffer duplicatesBuf = new StringBuffer();
2125:
2126:                for (; i < length; i++) {
2127:                    c = serverInfo.charAt(i);
2128:
2129:                    if (Character.isDigit(c)) {
2130:                        break;
2131:                    }
2132:                }
2133:
2134:                duplicatesBuf.append(c);
2135:                i++;
2136:
2137:                for (; i < length; i++) {
2138:                    c = serverInfo.charAt(i);
2139:
2140:                    if (!Character.isDigit(c)) {
2141:                        break;
2142:                    }
2143:
2144:                    duplicatesBuf.append(c);
2145:                }
2146:
2147:                duplicatesCount = Integer.parseInt(duplicatesBuf.toString());
2148:
2149:                return recordsCount - duplicatesCount;
2150:            }
2151:
2152:            /**
2153:             * getResultSet returns the current result as a ResultSet. It should only be
2154:             * called once per result.
2155:             *
2156:             * @return the current result set; null if there are no more
2157:             *
2158:             * @exception SQLException
2159:             *                if a database access error occurs (why?)
2160:             */
2161:            public java.sql.ResultSet getResultSet() throws SQLException {
2162:                return ((this .results != null) && this .results.reallyResult()) ? (java.sql.ResultSet) this .results
2163:                        : null;
2164:            }
2165:
2166:            /**
2167:             * JDBC 2.0 Determine the result set concurrency.
2168:             *
2169:             * @return CONCUR_UPDATABLE or CONCUR_READONLY
2170:             *
2171:             * @throws SQLException
2172:             *             if an error occurs
2173:             */
2174:            public int getResultSetConcurrency() throws SQLException {
2175:                return this .resultSetConcurrency;
2176:            }
2177:
2178:            /**
2179:             * @see StatementImpl#getResultSetHoldability()
2180:             */
2181:            public int getResultSetHoldability() throws SQLException {
2182:                return java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
2183:            }
2184:
2185:            protected ResultSetInternalMethods getResultSetInternal() {
2186:                return this .results;
2187:            }
2188:
2189:            /**
2190:             * JDBC 2.0 Determine the result set type.
2191:             *
2192:             * @return the ResultSet type (SCROLL_SENSITIVE or SCROLL_INSENSITIVE)
2193:             *
2194:             * @throws SQLException
2195:             *             if an error occurs.
2196:             */
2197:            public int getResultSetType() throws SQLException {
2198:                return this .resultSetType;
2199:            }
2200:
2201:            /**
2202:             * getUpdateCount returns the current result as an update count, if the
2203:             * result is a ResultSet or there are no more results, -1 is returned. It
2204:             * should only be called once per result.
2205:             *
2206:             * @return the current result as an update count.
2207:             *
2208:             * @exception SQLException
2209:             *                if a database access error occurs
2210:             */
2211:            public int getUpdateCount() throws SQLException {
2212:                if (this .results == null) {
2213:                    return -1;
2214:                }
2215:
2216:                if (this .results.reallyResult()) {
2217:                    return -1;
2218:                }
2219:
2220:                int truncatedUpdateCount = 0;
2221:
2222:                if (this .results.getUpdateCount() > Integer.MAX_VALUE) {
2223:                    truncatedUpdateCount = Integer.MAX_VALUE;
2224:                } else {
2225:                    truncatedUpdateCount = (int) this .results.getUpdateCount();
2226:                }
2227:
2228:                return truncatedUpdateCount;
2229:            }
2230:
2231:            /**
2232:             * The first warning reported by calls on this Statement is returned. A
2233:             * Statement's execute methods clear its java.sql.SQLWarning chain.
2234:             * Subsequent Statement warnings will be chained to this
2235:             * java.sql.SQLWarning.
2236:             *
2237:             * <p>
2238:             * The Warning chain is automatically cleared each time a statement is
2239:             * (re)executed.
2240:             * </p>
2241:             *
2242:             * <p>
2243:             * <B>Note:</B> If you are processing a ResultSet then any warnings
2244:             * associated with ResultSet reads will be chained on the ResultSet object.
2245:             * </p>
2246:             *
2247:             * @return the first java.sql.SQLWarning or null
2248:             *
2249:             * @exception SQLException
2250:             *                if a database access error occurs
2251:             */
2252:            public java.sql.SQLWarning getWarnings() throws SQLException {
2253:                checkClosed();
2254:
2255:                if (this .connection != null && !this .connection.isClosed()
2256:                        && this .connection.versionMeetsMinimum(4, 1, 0)) {
2257:                    SQLWarning pendingWarningsFromServer = SQLError
2258:                            .convertShowWarningsToSQLWarnings(this .connection);
2259:
2260:                    if (this .warningChain != null) {
2261:                        this .warningChain
2262:                                .setNextWarning(pendingWarningsFromServer);
2263:                    } else {
2264:                        this .warningChain = pendingWarningsFromServer;
2265:                    }
2266:
2267:                    return this .warningChain;
2268:                }
2269:
2270:                return this .warningChain;
2271:            }
2272:
2273:            /**
2274:             * Closes this statement, and frees resources.
2275:             *
2276:             * @param calledExplicitly
2277:             *            was this called from close()?
2278:             *
2279:             * @throws SQLException
2280:             *             if an error occurs
2281:             */
2282:            protected void realClose(boolean calledExplicitly,
2283:                    boolean closeOpenResults) throws SQLException {
2284:                if (this .isClosed) {
2285:                    return;
2286:                }
2287:
2288:                if (this .useUsageAdvisor) {
2289:                    if (!calledExplicitly) {
2290:                        String message = Messages.getString("Statement.63") //$NON-NLS-1$
2291:                                + Messages.getString("Statement.64"); //$NON-NLS-1$
2292:
2293:                        this .eventSink.consumeEvent(new ProfilerEvent(
2294:                                ProfilerEvent.TYPE_WARN,
2295:                                "", //$NON-NLS-1$
2296:                                this .currentCatalog, this .connectionId, this 
2297:                                        .getId(), -1, System
2298:                                        .currentTimeMillis(), 0,
2299:                                Constants.MILLIS_I18N, null,
2300:                                this .pointOfOrigin, message));
2301:                    }
2302:                }
2303:
2304:                if (this .results != null) {
2305:                    if (closeOpenResults) {
2306:                        closeOpenResults = !this .holdResultsOpenOverClose;
2307:                    }
2308:
2309:                    if (closeOpenResults
2310:                            && this .connection != null
2311:                            && !this .connection
2312:                                    .getHoldResultsOpenOverStatementClose()) {
2313:                        try {
2314:                            this .results.close();
2315:                        } catch (Exception ex) {
2316:                            ;
2317:                        }
2318:
2319:                        this .closeAllOpenResults();
2320:                    }
2321:                }
2322:
2323:                if (this .connection != null) {
2324:                    if (this .maxRowsChanged) {
2325:                        this .connection.unsetMaxRows(this );
2326:                    }
2327:
2328:                    if (!this .connection.getDontTrackOpenResources()) {
2329:                        this .connection.unregisterStatement(this );
2330:                    }
2331:                }
2332:
2333:                this .isClosed = true;
2334:
2335:                this .results = null;
2336:                this .connection = null;
2337:                this .warningChain = null;
2338:                this .openResults = null;
2339:                this .batchedGeneratedKeys = null;
2340:                this .cancelTimeoutMutex = null;
2341:                this .localInfileInputStream = null;
2342:                this .pingTarget = null;
2343:            }
2344:
2345:            /**
2346:             * setCursorName defines the SQL cursor name that will be used by subsequent
2347:             * execute methods. This name can then be used in SQL positioned
2348:             * update/delete statements to identify the current row in the ResultSet
2349:             * generated by this statement. If a database doesn't support positioned
2350:             * update/delete, this method is a no-op.
2351:             *
2352:             * <p>
2353:             * <b>Note:</b> This MySQL driver does not support cursors.
2354:             * </p>
2355:             *
2356:             * @param name
2357:             *            the new cursor name
2358:             *
2359:             * @exception SQLException
2360:             *                if a database access error occurs
2361:             */
2362:            public void setCursorName(String name) throws SQLException {
2363:                // No-op
2364:            }
2365:
2366:            /**
2367:             * If escape scanning is on (the default), the driver will do escape
2368:             * substitution before sending the SQL to the database.
2369:             *
2370:             * @param enable
2371:             *            true to enable; false to disable
2372:             *
2373:             * @exception SQLException
2374:             *                if a database access error occurs
2375:             */
2376:            public void setEscapeProcessing(boolean enable) throws SQLException {
2377:                this .doEscapeProcessing = enable;
2378:            }
2379:
2380:            /**
2381:             * JDBC 2.0 Give a hint as to the direction in which the rows in a result
2382:             * set will be processed. The hint applies only to result sets created using
2383:             * this Statement object. The default value is ResultSet.FETCH_FORWARD.
2384:             *
2385:             * @param direction
2386:             *            the initial direction for processing rows
2387:             *
2388:             * @exception SQLException
2389:             *                if a database-access error occurs or direction is not one
2390:             *                of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
2391:             *                ResultSet.FETCH_UNKNOWN
2392:             */
2393:            public void setFetchDirection(int direction) throws SQLException {
2394:                switch (direction) {
2395:                case java.sql.ResultSet.FETCH_FORWARD:
2396:                case java.sql.ResultSet.FETCH_REVERSE:
2397:                case java.sql.ResultSet.FETCH_UNKNOWN:
2398:                    break;
2399:
2400:                default:
2401:                    throw SQLError.createSQLException(Messages
2402:                            .getString("Statement.5"), //$NON-NLS-1$
2403:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2404:                }
2405:            }
2406:
2407:            /**
2408:             * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
2409:             * be fetched from the database when more rows are needed. The number of
2410:             * rows specified only affects result sets created using this statement. If
2411:             * the value specified is zero, then the hint is ignored. The default value
2412:             * is zero.
2413:             *
2414:             * @param rows
2415:             *            the number of rows to fetch
2416:             *
2417:             * @exception SQLException
2418:             *                if a database-access error occurs, or the condition 0
2419:             *                &lt;= rows &lt;= this.getMaxRows() is not satisfied.
2420:             */
2421:            public void setFetchSize(int rows) throws SQLException {
2422:                if (((rows < 0) && (rows != Integer.MIN_VALUE))
2423:                        || ((this .maxRows != 0) && (this .maxRows != -1) && (rows > this 
2424:                                .getMaxRows()))) {
2425:                    throw SQLError.createSQLException(Messages
2426:                            .getString("Statement.7"), //$NON-NLS-1$
2427:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
2428:                }
2429:
2430:                this .fetchSize = rows;
2431:            }
2432:
2433:            protected void setHoldResultsOpenOverClose(
2434:                    boolean holdResultsOpenOverClose) {
2435:                this .holdResultsOpenOverClose = holdResultsOpenOverClose;
2436:            }
2437:
2438:            /**
2439:             * Sets the maxFieldSize
2440:             *
2441:             * @param max
2442:             *            the new max column size limit; zero means unlimited
2443:             *
2444:             * @exception SQLException
2445:             *                if size exceeds buffer size
2446:             */
2447:            public void setMaxFieldSize(int max) throws SQLException {
2448:                if (max < 0) {
2449:                    throw SQLError.createSQLException(Messages
2450:                            .getString("Statement.11"), //$NON-NLS-1$
2451:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2452:                }
2453:
2454:                int maxBuf = (this .connection != null) ? this .connection
2455:                        .getMaxAllowedPacket() : MysqlIO.getMaxBuf();
2456:
2457:                if (max > maxBuf) {
2458:                    throw SQLError.createSQLException(Messages.getString(
2459:                            "Statement.13", //$NON-NLS-1$
2460:                            new Object[] { Constants.longValueOf(maxBuf) }), //$NON-NLS-1$
2461:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2462:                }
2463:
2464:                this .maxFieldSize = max;
2465:            }
2466:
2467:            /**
2468:             * Set the maximum number of rows
2469:             *
2470:             * @param max
2471:             *            the new max rows limit; zero means unlimited
2472:             *
2473:             * @exception SQLException
2474:             *                if a database access error occurs
2475:             *
2476:             * @see getMaxRows
2477:             */
2478:            public void setMaxRows(int max) throws SQLException {
2479:                if ((max > MysqlDefs.MAX_ROWS) || (max < 0)) {
2480:                    throw SQLError
2481:                            .createSQLException(
2482:                                    Messages.getString("Statement.15") + max //$NON-NLS-1$
2483:                                            + " > " //$NON-NLS-1$ //$NON-NLS-2$
2484:                                            + MysqlDefs.MAX_ROWS + ".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
2485:                }
2486:
2487:                if (max == 0) {
2488:                    max = -1;
2489:                }
2490:
2491:                this .maxRows = max;
2492:                this .maxRowsChanged = true;
2493:
2494:                if (this .maxRows == -1) {
2495:                    this .connection.unsetMaxRows(this );
2496:                    this .maxRowsChanged = false;
2497:                } else {
2498:                    // Most people don't use setMaxRows()
2499:                    // so don't penalize them
2500:                    // with the extra query it takes
2501:                    // to do it efficiently unless we need
2502:                    // to.
2503:                    this .connection.maxRowsChanged(this );
2504:                }
2505:            }
2506:
2507:            /**
2508:             * Sets the queryTimeout limit
2509:             *
2510:             * @param seconds -
2511:             *            the new query timeout limit in seconds
2512:             *
2513:             * @exception SQLException
2514:             *                if a database access error occurs
2515:             */
2516:            public void setQueryTimeout(int seconds) throws SQLException {
2517:                if (seconds < 0) {
2518:                    throw SQLError.createSQLException(Messages
2519:                            .getString("Statement.21"), //$NON-NLS-1$
2520:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2521:                }
2522:
2523:                this .timeoutInMillis = seconds * 1000;
2524:            }
2525:
2526:            /**
2527:             * Sets the concurrency for result sets generated by this statement
2528:             *
2529:             * @param concurrencyFlag
2530:             *            DOCUMENT ME!
2531:             */
2532:            void setResultSetConcurrency(int concurrencyFlag) {
2533:                this .resultSetConcurrency = concurrencyFlag;
2534:            }
2535:
2536:            /**
2537:             * Sets the result set type for result sets generated by this statement
2538:             *
2539:             * @param typeFlag
2540:             *            DOCUMENT ME!
2541:             */
2542:            void setResultSetType(int typeFlag) {
2543:                this .resultSetType = typeFlag;
2544:            }
2545:
2546:            protected void getBatchedGeneratedKeys(
2547:                    java.sql.Statement batchedStatement) throws SQLException {
2548:                if (this .retrieveGeneratedKeys) {
2549:                    java.sql.ResultSet rs = null;
2550:
2551:                    try {
2552:                        rs = batchedStatement.getGeneratedKeys();
2553:
2554:                        while (rs.next()) {
2555:                            this .batchedGeneratedKeys.add(new ByteArrayRow(
2556:                                    new byte[][] { rs.getBytes(1) }));
2557:                        }
2558:                    } finally {
2559:                        if (rs != null) {
2560:                            rs.close();
2561:                        }
2562:                    }
2563:                }
2564:            }
2565:
2566:            protected void getBatchedGeneratedKeys() throws SQLException {
2567:                if (this .retrieveGeneratedKeys) {
2568:                    java.sql.ResultSet rs = null;
2569:
2570:                    try {
2571:                        rs = getGeneratedKeysInternal();
2572:
2573:                        while (rs.next()) {
2574:                            this .batchedGeneratedKeys.add(new ByteArrayRow(
2575:                                    new byte[][] { rs.getBytes(1) }));
2576:                        }
2577:                    } finally {
2578:                        if (rs != null) {
2579:                            rs.close();
2580:                        }
2581:                    }
2582:                }
2583:            }
2584:
2585:            /**
2586:             * @return
2587:             */
2588:            private boolean useServerFetch() throws SQLException {
2589:
2590:                return this .connection.isCursorFetchEnabled()
2591:                        && this .fetchSize > 0
2592:                        && this .resultSetConcurrency == ResultSet.CONCUR_READ_ONLY
2593:                        && this .resultSetType == ResultSet.TYPE_FORWARD_ONLY;
2594:            }
2595:
2596:            public synchronized boolean isClosed() throws SQLException {
2597:                return this .isClosed;
2598:            }
2599:
2600:            private boolean isPoolable = true;
2601:
2602:            public boolean isPoolable() throws SQLException {
2603:                return this .isPoolable;
2604:            }
2605:
2606:            public void setPoolable(boolean poolable) throws SQLException {
2607:                this .isPoolable = poolable;
2608:            }
2609:
2610:            /**
2611:             * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
2612:             * for an object that does. Returns false otherwise. If this implements the interface then return true,
2613:             * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
2614:             * object. If this does not implement the interface and is not a wrapper, return false.
2615:             * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
2616:             * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
2617:             * returns true then calling <code>unwrap</code> with the same argument should succeed.
2618:             *
2619:             * @param interfaces a Class defining an interface.
2620:             * @return true if this implements the interface or directly or indirectly wraps an object that does.
2621:             * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
2622:             * for an object with the given interface.
2623:             * @since 1.6
2624:             */
2625:            public boolean isWrapperFor(Class iface) throws SQLException {
2626:                checkClosed();
2627:
2628:                // This works for classes that aren't actually wrapping
2629:                // anything
2630:                return iface.isInstance(this );
2631:            }
2632:
2633:            /**
2634:             * Returns an object that implements the given interface to allow access to non-standard methods,
2635:             * or standard methods not exposed by the proxy.
2636:             * The result may be either the object found to implement the interface or a proxy for that object.
2637:             * If the receiver implements the interface then that is the object. If the receiver is a wrapper
2638:             * and the wrapped object implements the interface then that is the object. Otherwise the object is
2639:             *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
2640:             * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
2641:             *
2642:             * @param iface A Class defining an interface that the result must implement.
2643:             * @return an object that implements the interface. May be a proxy for the actual implementing object.
2644:             * @throws java.sql.SQLException If no object found that implements the interface
2645:             * @since 1.6
2646:             */
2647:            public Object unwrap(Class iface) throws java.sql.SQLException {
2648:                try {
2649:                    // This works for classes that aren't actually wrapping
2650:                    // anything
2651:                    return Util.cast(iface, this );
2652:                } catch (ClassCastException cce) {
2653:                    throw SQLError.createSQLException("Unable to unwrap to "
2654:                            + iface.toString(),
2655:                            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2656:                }
2657:            }
2658:
2659:            protected int findStartOfStatement(String sql) {
2660:                int statementStartPos = 0;
2661:
2662:                if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
2663:                    statementStartPos = sql.indexOf("*/");
2664:
2665:                    if (statementStartPos == -1) {
2666:                        statementStartPos = 0;
2667:                    } else {
2668:                        statementStartPos += 2;
2669:                    }
2670:                } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "--")
2671:                        || StringUtils.startsWithIgnoreCaseAndWs(sql, "#")) {
2672:                    statementStartPos = sql.indexOf('\n');
2673:
2674:                    if (statementStartPos == -1) {
2675:                        statementStartPos = sql.indexOf('\r');
2676:
2677:                        if (statementStartPos == -1) {
2678:                            statementStartPos = 0;
2679:                        }
2680:                    }
2681:                }
2682:
2683:                return statementStartPos;
2684:            }
2685:
2686:            private InputStream localInfileInputStream;
2687:
2688:            public synchronized InputStream getLocalInfileInputStream() {
2689:                return this .localInfileInputStream;
2690:            }
2691:
2692:            public synchronized void setLocalInfileInputStream(
2693:                    InputStream stream) {
2694:                this .localInfileInputStream = stream;
2695:            }
2696:
2697:            public synchronized void setPingTarget(PingTarget pingTarget) {
2698:                this.pingTarget = pingTarget;
2699:            }
2700:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.