Source Code Cross Referenced for JtdsStatement.java in  » Database-JDBC-Connection-Pool » jTDS » net » sourceforge » jtds » 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 » jTDS » net.sourceforge.jtds.jdbc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // jTDS JDBC Driver for Microsoft SQL Server and Sybase
0002:        // Copyright (C) 2004 The jTDS Project
0003:        //
0004:        // This library is free software; you can redistribute it and/or
0005:        // modify it under the terms of the GNU Lesser General Public
0006:        // License as published by the Free Software Foundation; either
0007:        // version 2.1 of the License, or (at your option) any later version.
0008:        //
0009:        // This library is distributed in the hope that it will be useful,
0010:        // but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:        // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012:        // Lesser General Public License for more details.
0013:        //
0014:        // You should have received a copy of the GNU Lesser General Public
0015:        // License along with this library; if not, write to the Free Software
0016:        // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:        //
0018:        package net.sourceforge.jtds.jdbc;
0019:
0020:        import java.sql.BatchUpdateException;
0021:        import java.sql.Connection;
0022:        import java.sql.ResultSet;
0023:        import java.sql.SQLException;
0024:        import java.sql.SQLWarning;
0025:        import java.sql.Types;
0026:        import java.util.ArrayList;
0027:        import java.util.LinkedList;
0028:
0029:        /**
0030:         * jTDS implementation of the java.sql.Statement interface.<p>
0031:         * NB. As allowed by the JDBC standard and like most other drivers,
0032:         * this implementation only allows one open result set at a time.
0033:         * <p>
0034:         * Implementation notes:
0035:         * <p>
0036:         * I experimented with allowing multiple open result sets as supported
0037:         * by the origianal jTDS but rejected this approach for the following
0038:         * reasons:
0039:         * <ol>
0040:         * <li>It is more difficult to ensure that there are no memory leaks and that
0041:         *     cursors are closed if multiple open sets are allowed.
0042:         * <li>The use of one result set allows cursor and non cursor result sets to
0043:         *     be derived from exeuteQuery() or execute() and getResultSet() in the
0044:         *     same way that other drivers do.
0045:         * </ol>
0046:         * In the event of an IO failure the setClosed() method forces this statement
0047:         * and associated result set to close preventing the propogation of errors.
0048:         * This class includes a finalize method which increases the chances of the
0049:         * statement being closed tidly in a pooled environment where the user has
0050:         * forgotten to explicitly close the statement before it goes out of scope.
0051:         *
0052:         * @see java.sql.Statement
0053:         * @see java.sql.Connection#createStatement()
0054:         * @see java.sql.ResultSet
0055:         *
0056:         * @author Mike Hutchinson
0057:         * @version $Id: JtdsStatement.java,v 1.64 2007/07/12 21:03:23 bheineman Exp $
0058:         */
0059:        public class JtdsStatement implements  java.sql.Statement {
0060:            /*
0061:             * Constants used for backwards compatibility with JDK 1.3
0062:             */
0063:            static final int RETURN_GENERATED_KEYS = 1;
0064:            static final int NO_GENERATED_KEYS = 2;
0065:            static final int CLOSE_CURRENT_RESULT = 1;
0066:            static final int KEEP_CURRENT_RESULT = 2;
0067:            static final int CLOSE_ALL_RESULTS = 3;
0068:            static final int BOOLEAN = 16;
0069:            static final int DATALINK = 70;
0070:            static final Integer SUCCESS_NO_INFO = new Integer(-2);
0071:            static final Integer EXECUTE_FAILED = new Integer(-3);
0072:            static final int DEFAULT_FETCH_SIZE = 100;
0073:
0074:            /** The connection owning this statement object. */
0075:            protected ConnectionJDBC2 connection;
0076:            /** The TDS object used for server access. */
0077:            protected TdsCore tds;
0078:            /** The read query timeout in seconds */
0079:            protected int queryTimeout;
0080:            /** The current <code>ResultSet</code>. */
0081:            protected JtdsResultSet currentResult;
0082:            /** The current update count. */
0083:            private int updateCount = -1;
0084:            /** The fetch direction for result sets. */
0085:            protected int fetchDirection = ResultSet.FETCH_FORWARD;
0086:            /** The type of result sets created by this statement. */
0087:            protected int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
0088:            /** The concurrency of result sets created by this statement. */
0089:            protected int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
0090:            /** The fetch size (default 100, only used by cursor
0091:             * <code>ResultSet</code>s).
0092:             */
0093:            protected int fetchSize = DEFAULT_FETCH_SIZE;
0094:            /** The cursor name to be used for positioned updates. */
0095:            protected String cursorName;
0096:            /** True if this statement is closed. */
0097:            protected boolean closed;
0098:            /** The maximum field size (not used at present). */
0099:            protected int maxFieldSize;
0100:            /** The maximum number of rows to return (not used at present). */
0101:            protected int maxRows;
0102:            /** True if SQL statements should be preprocessed. */
0103:            protected boolean escapeProcessing = true;
0104:            /** SQL Diagnostic exceptions and warnings. */
0105:            protected final SQLDiagnostic messages;
0106:            /** Batched SQL Statement array. */
0107:            protected ArrayList batchValues;
0108:            /** Dummy result set for getGeneratedKeys. */
0109:            protected JtdsResultSet genKeyResultSet;
0110:            /**
0111:             * List of queued results (update counts, possibly followed by a
0112:             * <code>ResultSet</code>).
0113:             */
0114:            protected final LinkedList resultQueue = new LinkedList();
0115:            /** List of open result sets. */
0116:            protected ArrayList openResultSets;
0117:            /** The cached column meta data. */
0118:            protected ColInfo[] colMetaData;
0119:
0120:            /**
0121:             * Construct a new Statement object.
0122:             *
0123:             * @param connection The parent connection.
0124:             * @param resultSetType The result set type for example TYPE_FORWARD_ONLY.
0125:             * @param resultSetConcurrency The concurrency for example CONCUR_READ_ONLY.
0126:             */
0127:            JtdsStatement(ConnectionJDBC2 connection, int resultSetType,
0128:                    int resultSetConcurrency) throws SQLException {
0129:                //
0130:                // This is a good point to do common validation of the result set type
0131:                //
0132:                if (resultSetType < ResultSet.TYPE_FORWARD_ONLY
0133:                        || resultSetType > ResultSet.TYPE_SCROLL_SENSITIVE + 1) {
0134:                    String method;
0135:                    if (this  instanceof  JtdsCallableStatement) {
0136:                        method = "prepareCall";
0137:                    } else if (this  instanceof  JtdsPreparedStatement) {
0138:                        method = "prepareStatement";
0139:                    } else {
0140:                        method = "createStatement";
0141:                    }
0142:                    throw new SQLException(Messages.get(
0143:                            "error.generic.badparam", "resultSetType", method),
0144:                            "HY092");
0145:                }
0146:                //
0147:                // Ditto for the result set concurrency
0148:                //
0149:                if (resultSetConcurrency < ResultSet.CONCUR_READ_ONLY
0150:                        || resultSetConcurrency > ResultSet.CONCUR_UPDATABLE + 2) {
0151:                    String method;
0152:                    if (this  instanceof  JtdsCallableStatement) {
0153:                        method = "prepareCall";
0154:                    } else if (this  instanceof  JtdsPreparedStatement) {
0155:                        method = "prepareStatement";
0156:                    } else {
0157:                        method = "createStatement";
0158:                    }
0159:                    throw new SQLException(Messages.get(
0160:                            "error.generic.badparam", "resultSetConcurrency",
0161:                            method), "HY092");
0162:                }
0163:
0164:                this .connection = connection;
0165:                this .resultSetType = resultSetType;
0166:                this .resultSetConcurrency = resultSetConcurrency;
0167:
0168:                this .tds = connection.getCachedTds();
0169:                if (this .tds == null) {
0170:                    this .messages = new SQLDiagnostic(connection
0171:                            .getServerType());
0172:                    this .tds = new TdsCore(this .connection, messages);
0173:                } else {
0174:                    this .messages = tds.getMessages();
0175:                }
0176:            }
0177:
0178:            /**
0179:             * Called when this object goes out of scope to close any
0180:             * <code>ResultSet</code> object and this statement.
0181:             */
0182:            protected void finalize() throws Throwable {
0183:                super .finalize();
0184:                try {
0185:                    close();
0186:                } catch (SQLException e) {
0187:                    // Ignore errors
0188:                }
0189:            }
0190:
0191:            /**
0192:             * Get the Statement's TDS object.
0193:             *
0194:             * @return The TDS support as a <code>TdsCore</core> Object.
0195:             */
0196:            TdsCore getTds() {
0197:                return tds;
0198:            }
0199:
0200:            /**
0201:             * Get the statement's warnings list.
0202:             *
0203:             * @return The warnings list as a <code>SQLDiagnostic</code>.
0204:             */
0205:            SQLDiagnostic getMessages() {
0206:                return messages;
0207:            }
0208:
0209:            /**
0210:             * Check that this statement is still open.
0211:             *
0212:             * @throws SQLException if statement closed.
0213:             */
0214:            protected void checkOpen() throws SQLException {
0215:                if (closed || connection == null || connection.isClosed()) {
0216:                    throw new SQLException(Messages.get("error.generic.closed",
0217:                            "Statement"), "HY010");
0218:                }
0219:            }
0220:
0221:            /**
0222:             * Check that the exception is caused by the failure to open a
0223:             * cursor and not by a more serious SQL error.
0224:             *
0225:             * @param e the exception returned by the cursor class
0226:             * @throws SQLException if exception is not due to a cursor error
0227:             */
0228:            protected void checkCursorException(SQLException e)
0229:                    throws SQLException {
0230:                if (connection == null || connection.isClosed()
0231:                        || "HYT00".equals(e.getSQLState())
0232:                        || "HY008".equals(e.getSQLState())) {
0233:                    // Serious error or timeout so return exception to caller
0234:                    throw e;
0235:                }
0236:                if (connection.getServerType() == Driver.SYBASE) {
0237:                    // Allow retry for Sybase
0238:                    return;
0239:                }
0240:                //
0241:                // Check cursor specific errors and ranges for SQL Server
0242:                //
0243:                int error = e.getErrorCode();
0244:                if (error >= 16900 && error <= 16999) {
0245:                    // Errors in this range are all related to the cursor API.
0246:                    // This is true for all versions of SQL Server.
0247:                    return;
0248:                }
0249:                if (error == 6819) {
0250:                    // A FOR XML clause was found
0251:                    return;
0252:                }
0253:                if (error == 8654) {
0254:                    // A inrow textptr exists
0255:                    return;
0256:                }
0257:                if (error == 8162) {
0258:                    // Formal parameter '%.*ls' was defined as OUTPUT but the actual
0259:                    // parameter not declared OUTPUT. This happens when trying to
0260:                    // execute a stored procedure with output parameters via a cursor.
0261:                    return;
0262:                }
0263:                //
0264:                // More serious error we should rethrow the error and
0265:                // not allow the driver to re-execute sql.
0266:                //
0267:                throw e;
0268:            }
0269:
0270:            /**
0271:             * Report that user tried to call a method which has not been implemented.
0272:             *
0273:             * @param method The method name to report in the error message.
0274:             * @throws SQLException
0275:             */
0276:            static void notImplemented(String method) throws SQLException {
0277:                throw new SQLException(Messages.get("error.generic.notimp",
0278:                        method), "HYC00");
0279:            }
0280:
0281:            /**
0282:             * Close current result set (if any).
0283:             */
0284:            void closeCurrentResultSet() throws SQLException {
0285:                try {
0286:                    if (currentResult != null) {
0287:                        currentResult.close();
0288:                    }
0289:                    //        } catch (SQLException e) {
0290:                    // Ignore
0291:                } finally {
0292:                    currentResult = null;
0293:                }
0294:            }
0295:
0296:            /**
0297:             * Close all result sets.
0298:             */
0299:            void closeAllResultSets() throws SQLException {
0300:                try {
0301:                    if (openResultSets != null) {
0302:                        for (int i = 0; i < openResultSets.size(); i++) {
0303:                            JtdsResultSet rs = (JtdsResultSet) openResultSets
0304:                                    .get(i);
0305:                            if (rs != null) {
0306:                                rs.close();
0307:                            }
0308:                        }
0309:                    }
0310:                    closeCurrentResultSet();
0311:                } finally {
0312:                    openResultSets = null;
0313:                }
0314:            }
0315:
0316:            /**
0317:             * Add an SQLWarning object to the statment warnings list.
0318:             *
0319:             * @param w The SQLWarning to add.
0320:             */
0321:            void addWarning(SQLWarning w) {
0322:                messages.addWarning(w);
0323:            }
0324:
0325:            /**
0326:             * Execute the SQL batch on a MS server.
0327:             *
0328:             * @param size the total size of the batch
0329:             * @param executeSize the maximum number of statements to send in one request
0330:             * @param counts the returned update counts
0331:             * @return chained exceptions linked to a <code>SQLException</code>
0332:             * @throws SQLException if a serious error occurs during execution
0333:             */
0334:            protected SQLException executeMSBatch(int size, int executeSize,
0335:                    ArrayList counts) throws SQLException {
0336:                SQLException sqlEx = null;
0337:                for (int i = 0; i < size;) {
0338:                    Object value = batchValues.get(i);
0339:                    ++i;
0340:                    // Execute batch now if max size reached or end of batch
0341:                    boolean executeNow = (i % executeSize == 0) || i == size;
0342:
0343:                    tds.startBatch();
0344:                    tds.executeSQL((String) value, null, null, false, 0, -1,
0345:                            -1, executeNow);
0346:
0347:                    // If the batch has been sent, process the results
0348:                    if (executeNow) {
0349:                        sqlEx = tds.getBatchCounts(counts, sqlEx);
0350:
0351:                        // If a serious error then we stop execution now as count
0352:                        // is too small.
0353:                        if (sqlEx != null && counts.size() != i) {
0354:                            break;
0355:                        }
0356:                    }
0357:                }
0358:                return sqlEx;
0359:            }
0360:
0361:            /**
0362:             * Execute the SQL batch on a Sybase server.
0363:             * <p/>
0364:             * Sybase needs to have the SQL concatenated into one TDS language packet. This method will be overriden for
0365:             * <code>PreparedStatements</code>.
0366:             *
0367:             * @param size the total size of the batch
0368:             * @param executeSize the maximum number of statements to send in one request
0369:             * @param counts the returned update counts
0370:             * @return chained exceptions linked to a <code>SQLException</code>
0371:             * @throws SQLException if a serious error occurs during execution
0372:             */
0373:            protected SQLException executeSybaseBatch(int size,
0374:                    int executeSize, ArrayList counts) throws SQLException {
0375:                StringBuffer sql = new StringBuffer(size * 32); // Make buffer reasonable size
0376:                SQLException sqlEx = null;
0377:
0378:                for (int i = 0; i < size;) {
0379:                    Object value = batchValues.get(i);
0380:                    ++i;
0381:                    // Execute batch now if max size reached or end of batch
0382:                    boolean executeNow = (i % executeSize == 0) || i == size;
0383:
0384:                    sql.append((String) value).append(' ');
0385:
0386:                    if (executeNow) {
0387:                        tds.executeSQL(sql.toString(), null, null, false, 0,
0388:                                -1, -1, true);
0389:                        sql.setLength(0);
0390:                        // If the batch has been sent, process the results
0391:                        sqlEx = tds.getBatchCounts(counts, sqlEx);
0392:
0393:                        // If a serious error or a server error then we stop
0394:                        // execution now as count is too small.
0395:                        if (sqlEx != null && counts.size() != i) {
0396:                            break;
0397:                        }
0398:                    }
0399:                }
0400:                return sqlEx;
0401:            }
0402:
0403:            /**
0404:             * Executes SQL to obtain a result set.
0405:             *
0406:             * @param sql       the SQL statement to execute
0407:             * @param spName    optional stored procedure name
0408:             * @param params    optional parameters
0409:             * @param useCursor whether a cursor should be created for the SQL
0410:             * @return the result set generated by the query
0411:             */
0412:            protected ResultSet executeSQLQuery(String sql, String spName,
0413:                    ParamInfo[] params, boolean useCursor) throws SQLException {
0414:                String warningMessage = null;
0415:
0416:                //
0417:                // Try to open a cursor result set if required
0418:                //
0419:                if (useCursor) {
0420:                    try {
0421:                        if (connection.getServerType() == Driver.SQLSERVER) {
0422:                            currentResult = new MSCursorResultSet(this , sql,
0423:                                    spName, params, resultSetType,
0424:                                    resultSetConcurrency);
0425:
0426:                            return currentResult;
0427:                        } else {
0428:                            // Use client side cursor for Sybase
0429:                            currentResult = new CachedResultSet(this , sql,
0430:                                    spName, params, resultSetType,
0431:                                    resultSetConcurrency);
0432:
0433:                            return currentResult;
0434:                        }
0435:                    } catch (SQLException e) {
0436:                        checkCursorException(e);
0437:                        warningMessage = '[' + e.getSQLState() + "] "
0438:                                + e.getMessage();
0439:                    }
0440:                }
0441:
0442:                //
0443:                // Could not open a cursor (or was not requested) so try a direct select
0444:                //
0445:                if (spName != null && connection.getUseMetadataCache()
0446:                        && connection.getPrepareSql() == TdsCore.PREPARE
0447:                        && colMetaData != null
0448:                        && connection.getServerType() == Driver.SQLSERVER) {
0449:                    // There is cached meta data available for this
0450:                    // prepared statement
0451:                    tds.setColumns(colMetaData);
0452:                    tds.executeSQL(sql, spName, params, true, queryTimeout,
0453:                            maxRows, maxFieldSize, true);
0454:                } else {
0455:                    tds.executeSQL(sql, spName, params, false, queryTimeout,
0456:                            maxRows, maxFieldSize, true);
0457:                }
0458:
0459:                // Update warning chain if cursor was downgraded before processing results
0460:                if (warningMessage != null) {
0461:                    addWarning(new SQLWarning(Messages.get(
0462:                            "warning.cursordowngraded", warningMessage),
0463:                            "01000"));
0464:                }
0465:
0466:                // Ignore update counts preceding the result set. All drivers seem to
0467:                // do this.
0468:                while (!tds.getMoreResults() && !tds.isEndOfResponse())
0469:                    ;
0470:
0471:                // check for server side errors
0472:                messages.checkErrors();
0473:
0474:                if (tds.isResultSet()) {
0475:                    currentResult = new JtdsResultSet(this ,
0476:                            ResultSet.TYPE_FORWARD_ONLY,
0477:                            ResultSet.CONCUR_READ_ONLY, tds.getColumns());
0478:                } else {
0479:                    throw new SQLException(Messages
0480:                            .get("error.statement.noresult"), "24000");
0481:                }
0482:
0483:                return currentResult;
0484:            }
0485:
0486:            /**
0487:             * Executes any type of SQL.
0488:             *
0489:             * @param sql        the SQL statement to execute
0490:             * @param spName     optional stored procedure name
0491:             * @param params     optional parameters
0492:             * @param returnKeys whether the statement returns generated keys
0493:             * @param update     whether the caller is {@link #executeUpdate}
0494:             * @param useCursor  whether the requested result set type or concurrency
0495:             *                   or connection properties request usage of a cursor
0496:             * @return <code>true</code> if the first result is a result set
0497:             * @throws SQLException if an error condition occurs
0498:             */
0499:            protected boolean executeSQL(String sql, String spName,
0500:                    ParamInfo[] params, boolean returnKeys, boolean update,
0501:                    boolean useCursor) throws SQLException {
0502:                String warningMessage = null;
0503:
0504:                //
0505:                // For SQL Server, try to open a cursor result set if required
0506:                // (and possible).
0507:                //
0508:                if (connection.getServerType() == Driver.SQLSERVER && !update
0509:                        && useCursor) {
0510:                    try {
0511:                        currentResult = new MSCursorResultSet(this , sql,
0512:                                spName, params, resultSetType,
0513:                                resultSetConcurrency);
0514:
0515:                        return true;
0516:                    } catch (SQLException e) {
0517:                        checkCursorException(e);
0518:                        warningMessage = '[' + e.getSQLState() + "] "
0519:                                + e.getMessage();
0520:                    }
0521:                }
0522:
0523:                //
0524:                // We are talking to a Sybase server or we could not open a cursor
0525:                // or we did not have a SELECT so just execute the SQL normally.
0526:                //
0527:                tds.executeSQL(sql, spName, params, false, queryTimeout,
0528:                        maxRows, maxFieldSize, true);
0529:
0530:                if (warningMessage != null) {
0531:                    // Update warning chain if cursor was downgraded
0532:                    addWarning(new SQLWarning(Messages.get(
0533:                            "warning.cursordowngraded", warningMessage),
0534:                            "01000"));
0535:                }
0536:
0537:                if (processResults(returnKeys, update)) {
0538:                    Object nextResult = resultQueue.removeFirst();
0539:
0540:                    // Next result is an update count
0541:                    if (nextResult instanceof  Integer) {
0542:                        updateCount = ((Integer) nextResult).intValue();
0543:                        return false;
0544:                    }
0545:
0546:                    // Next result is a ResultSet. Set currentResult and remove it.
0547:                    currentResult = (JtdsResultSet) nextResult;
0548:                    return true;
0549:                } else {
0550:                    return false;
0551:                }
0552:            }
0553:
0554:            /**
0555:             * Queue up update counts into {@link #resultQueue} until the end of the
0556:             * response is reached or a <code>ResultSet</code> is encountered. Calling
0557:             * <code>processResults</code> while a <code>ResultSet</code> is open will
0558:             * not close it, but will consume all remaining rows.
0559:             *
0560:             * @param returnKeys <code>true</code> if a generated keys
0561:             *                   <code>ResultSet</code> is expected
0562:             * @param update     <code>true</code> if the method is called from within
0563:             *                   <code>executeUpdate</code>
0564:             * @return           <code>true</code> if there are any results,
0565:             *                   <code>false</code> otherwise
0566:             * @throws SQLException if an error condition occurs
0567:             */
0568:            private boolean processResults(boolean returnKeys, boolean update)
0569:                    throws SQLException {
0570:                if (!resultQueue.isEmpty()) {
0571:                    throw new IllegalStateException(
0572:                            "There should be no queued results.");
0573:                }
0574:
0575:                while (!tds.isEndOfResponse()) {
0576:                    if (!tds.getMoreResults()) {
0577:                        if (tds.isUpdateCount()) {
0578:                            if (update && connection.getLastUpdateCount()) {
0579:                                resultQueue.clear();
0580:                            }
0581:                            resultQueue.addLast(new Integer(tds
0582:                                    .getUpdateCount()));
0583:                        }
0584:                    } else {
0585:                        if (returnKeys) {
0586:                            // This had better be the generated key
0587:                            // FIXME We could use SELECT @@IDENTITY AS jTDS_SOMETHING and check the column name to make sure
0588:                            if (tds.getNextRow()) {
0589:                                genKeyResultSet = new CachedResultSet(this , tds
0590:                                        .getColumns(), tds.getRowData());
0591:                            }
0592:                        } else {
0593:                            if (update && resultQueue.isEmpty()) {
0594:                                // Throw exception but queue up any previous ones
0595:                                SQLException ex = new SQLException(Messages
0596:                                        .get("error.statement.nocount"),
0597:                                        "07000");
0598:                                ex.setNextException(messages.exceptions);
0599:                                throw ex;
0600:                            }
0601:
0602:                            resultQueue.add(new JtdsResultSet(this ,
0603:                                    ResultSet.TYPE_FORWARD_ONLY,
0604:                                    ResultSet.CONCUR_READ_ONLY, tds
0605:                                            .getColumns()));
0606:                            break;
0607:                        }
0608:                    }
0609:                }
0610:
0611:                // Check for server side errors
0612:                getMessages().checkErrors();
0613:
0614:                return !resultQueue.isEmpty();
0615:            }
0616:
0617:            /**
0618:             * Cache as many results as possible (up to the first
0619:             * <code>ResultSet</code>). Called by <code>ResultSet</code>s when the
0620:             * end is reached.
0621:             */
0622:            protected void cacheResults() throws SQLException {
0623:                // Cache results
0624:                processResults(false, false);
0625:            }
0626:
0627:            /**
0628:             * Initialize the <code>Statement</code>, by cleaning up all queued and
0629:             * unprocessed results. Called by all execute methods.
0630:             *
0631:             * @throws SQLException if an error occurs
0632:             */
0633:            protected void initialize() throws SQLException {
0634:                updateCount = -1;
0635:                resultQueue.clear();
0636:                genKeyResultSet = null;
0637:                tds.clearResponseQueue();
0638:                // FIXME Should old exceptions found now be thrown instead of lost?
0639:                messages.exceptions = null;
0640:                messages.clearWarnings();
0641:                closeAllResultSets();
0642:            }
0643:
0644:            /**
0645:             * Implements the common functionality for plain statement {@link #execute}
0646:             * and {#link #executeUpdate}: basic checks, cleaning up of previous
0647:             * results, setting up and executing the query and loading the first
0648:             * results.
0649:             *
0650:             * @param sql    an SQL <code>INSERT</code>, <code>UPDATE</code> or
0651:             *               <code>DELETE</code> statement or an SQL statement that
0652:             *               returns nothing, such as an SQL DDL statement
0653:             * @param autoGeneratedKeys a flag indicating whether auto-generated keys
0654:             *               should be made available for retrieval
0655:             * @param update boolean flag indicating whether the caller is
0656:             *               {@link #executeUpdate} -- in this case an exception is
0657:             *               thrown if the first result is not an update count and no
0658:             *               cursor is created (direct execution)
0659:             * @return <code>true</code> if the first result is a
0660:             *         <code>ResultSet</code>, <code>false</code> if it's an update
0661:             *         count
0662:             * @see #execute
0663:             * @see #executeUpdate
0664:             */
0665:            private boolean executeImpl(String sql, int autoGeneratedKeys,
0666:                    boolean update) throws SQLException {
0667:                initialize();
0668:
0669:                if (sql == null || sql.length() == 0) {
0670:                    throw new SQLException(Messages.get("error.generic.nosql"),
0671:                            "HY000");
0672:                }
0673:
0674:                boolean returnKeys;
0675:                String sqlWord = "";
0676:                if (escapeProcessing) {
0677:                    String tmp[] = SQLParser
0678:                            .parse(sql, null, connection, false);
0679:
0680:                    if (tmp[1].length() != 0) {
0681:                        throw new SQLException(Messages
0682:                                .get("error.statement.badsql"), "07000");
0683:                    }
0684:
0685:                    sql = tmp[0];
0686:                    sqlWord = tmp[2];
0687:                } else {
0688:                    // Escape processing turned off so
0689:                    // see if we can extract "insert" from start of statement
0690:                    sql = sql.trim();
0691:                    if (sql.length() > 5) {
0692:                        sqlWord = sql.substring(0, 6).toLowerCase();
0693:                    }
0694:                }
0695:
0696:                if (autoGeneratedKeys == RETURN_GENERATED_KEYS) {
0697:                    returnKeys = "insert".equals(sqlWord);
0698:                } else if (autoGeneratedKeys == NO_GENERATED_KEYS) {
0699:                    returnKeys = false;
0700:                } else {
0701:                    throw new SQLException(Messages.get(
0702:                            "error.generic.badoption", Integer
0703:                                    .toString(autoGeneratedKeys),
0704:                            "autoGeneratedKeys"), "HY092");
0705:                }
0706:
0707:                if (returnKeys) {
0708:                    if (connection.getServerType() == Driver.SQLSERVER
0709:                            && connection.getDatabaseMajorVersion() >= 8) {
0710:                        sql += " SELECT SCOPE_IDENTITY() AS ID";
0711:                    } else {
0712:                        sql += " SELECT @@IDENTITY AS ID";
0713:                    }
0714:                }
0715:
0716:                return executeSQL(sql, null, null, returnKeys, update, !update
0717:                        && useCursor(returnKeys, sqlWord));
0718:            }
0719:
0720:            /**
0721:             * Determines whether a cursor should be used based on the requested result
0722:             * set type and concurrency, whether a cursor name has been set, the
0723:             * <code>useCursors</code> connection property has been set, the first
0724:             * word in the SQL query is either SELECT or EXEC/EXECUTE and no generated
0725:             * keys are returned.
0726:             *
0727:             * @param returnKeys indicates whether keys will be returned by the query
0728:             * @param sqlWord    the first word in the SQL query; can be
0729:             *                   <code>null</code> if the caller is
0730:             *                   {@link #executeQuery}
0731:             * @return <code>true</code> if a cursor should be used, <code>false</code>
0732:             *         if not
0733:             */
0734:            protected boolean useCursor(boolean returnKeys, String sqlWord) {
0735:                return (resultSetType != ResultSet.TYPE_FORWARD_ONLY
0736:                        || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY
0737:                        || connection.getUseCursors() || cursorName != null)
0738:                        && !returnKeys
0739:                        && (sqlWord == null || "select".equals(sqlWord) || sqlWord
0740:                                .startsWith("exec"));
0741:            }
0742:
0743:            /**
0744:             * Retrieve the default fetch size for this statement.
0745:             *
0746:             * @return the default fetch size for a new <code>ResultSet</code>
0747:             */
0748:            int getDefaultFetchSize() {
0749:                return (0 < this .maxRows && this .maxRows < DEFAULT_FETCH_SIZE) ? this .maxRows
0750:                        : DEFAULT_FETCH_SIZE;
0751:            }
0752:
0753:            // ------------------ java.sql.Statement methods ----------------------
0754:
0755:            public int getFetchDirection() throws SQLException {
0756:                checkOpen();
0757:
0758:                return this .fetchDirection;
0759:            }
0760:
0761:            public int getFetchSize() throws SQLException {
0762:                checkOpen();
0763:
0764:                return this .fetchSize;
0765:            }
0766:
0767:            public int getMaxFieldSize() throws SQLException {
0768:                checkOpen();
0769:
0770:                return this .maxFieldSize;
0771:            }
0772:
0773:            public int getMaxRows() throws SQLException {
0774:                checkOpen();
0775:
0776:                return this .maxRows;
0777:            }
0778:
0779:            public int getQueryTimeout() throws SQLException {
0780:                checkOpen();
0781:
0782:                return this .queryTimeout;
0783:            }
0784:
0785:            public int getResultSetConcurrency() throws SQLException {
0786:                checkOpen();
0787:
0788:                return this .resultSetConcurrency;
0789:            }
0790:
0791:            public int getResultSetHoldability() throws SQLException {
0792:                checkOpen();
0793:
0794:                return JtdsResultSet.HOLD_CURSORS_OVER_COMMIT;
0795:            }
0796:
0797:            public int getResultSetType() throws SQLException {
0798:                checkOpen();
0799:
0800:                return resultSetType;
0801:            }
0802:
0803:            public int getUpdateCount() throws SQLException {
0804:                checkOpen();
0805:
0806:                return updateCount;
0807:            }
0808:
0809:            public void cancel() throws SQLException {
0810:                checkOpen();
0811:
0812:                if (tds != null) {
0813:                    tds.cancel(false);
0814:                }
0815:            }
0816:
0817:            public void clearBatch() throws SQLException {
0818:                checkOpen();
0819:
0820:                if (batchValues != null) {
0821:                    batchValues.clear();
0822:                }
0823:            }
0824:
0825:            public void clearWarnings() throws SQLException {
0826:                checkOpen();
0827:
0828:                messages.clearWarnings();
0829:            }
0830:
0831:            public void close() throws SQLException {
0832:                if (!closed) {
0833:                    SQLException closeEx = null;
0834:                    try {
0835:                        closeAllResultSets();
0836:                    } catch (SQLException ex) {
0837:                        if (!"HYT00".equals(ex.getSQLState())
0838:                                && !"HY008".equals(ex.getSQLState())) {
0839:                            // Only throw exceptions not caused by cancels or timeouts
0840:                            closeEx = ex;
0841:                        }
0842:                    } finally {
0843:                        SQLException releaseEx = null;
0844:                        try {
0845:                            if (!connection.isClosed()) {
0846:                                connection.releaseTds(tds);
0847:                            }
0848:                            // Check for server side errors
0849:                            tds.getMessages().checkErrors();
0850:                        } catch (SQLException ex) {
0851:                            // Remember any exception thrown
0852:                            releaseEx = ex;
0853:                            // Queue up any result set close exceptions
0854:                            if (closeEx != null) {
0855:                                releaseEx.setNextException(closeEx);
0856:                            }
0857:                        } finally {
0858:                            // Clean up everything
0859:                            closed = true;
0860:                            tds = null;
0861:                            connection.removeStatement(this );
0862:                            connection = null;
0863:
0864:                            // Re-throw any caught exception
0865:                            if (releaseEx != null) {
0866:                                throw releaseEx;
0867:                            }
0868:                        }
0869:                    }
0870:                    // Throw any exception caught during result set close
0871:                    if (closeEx != null) {
0872:                        throw closeEx;
0873:                    }
0874:                }
0875:            }
0876:
0877:            public boolean getMoreResults() throws SQLException {
0878:                checkOpen();
0879:
0880:                return getMoreResults(CLOSE_ALL_RESULTS);
0881:            }
0882:
0883:            /**
0884:             * Execute batch of SQL Statements.
0885:             * <p/>
0886:             * The JDBC3 standard says that the behaviour of this method must be
0887:             * consistent for any DBMS. As Sybase (and to a lesser extent SQL Server)
0888:             * will sometimes continue after a batch execution error, the only way to
0889:             * comply with the standard is to always return an array of update counts
0890:             * the same size as the batch list. Slots in the array beyond the last
0891:             * executed statement are set to <code>EXECUTE_FAILED</code>.
0892:             *
0893:             * @return update counts as an <code>int[]</code>
0894:             */
0895:            public int[] executeBatch() throws SQLException,
0896:                    BatchUpdateException {
0897:                checkOpen();
0898:                initialize();
0899:
0900:                if (batchValues == null || batchValues.size() == 0) {
0901:                    return new int[0];
0902:                }
0903:
0904:                int size = batchValues.size();
0905:                int executeSize = connection.getBatchSize();
0906:                executeSize = (executeSize == 0) ? Integer.MAX_VALUE
0907:                        : executeSize;
0908:                SQLException sqlEx;
0909:                ArrayList counts = new ArrayList(size);
0910:
0911:                try {
0912:                    // Lock the connection, making sure the batch executes atomically. This is especially important in the
0913:                    // case of prepared statement batches (where we don't want the prepares rolled back before being executed)
0914:                    // but should also provide some level of sanity in the general case.
0915:                    synchronized (connection) {
0916:                        if (connection.getServerType() == Driver.SYBASE
0917:                                && connection.getTdsVersion() == Driver.TDS50) {
0918:                            sqlEx = executeSybaseBatch(size, executeSize,
0919:                                    counts);
0920:                        } else {
0921:                            sqlEx = executeMSBatch(size, executeSize, counts);
0922:                        }
0923:                    }
0924:
0925:                    // Ensure array is the same size as the original statement list
0926:                    int updateCounts[] = new int[size];
0927:                    // Copy the update counts into the int array
0928:                    int results = counts.size();
0929:                    for (int i = 0; i < results; i++) {
0930:                        updateCounts[i] = ((Integer) counts.get(i)).intValue();
0931:                    }
0932:                    // Pad any remaining slots with EXECUTE_FAILED
0933:                    for (int i = results; i < updateCounts.length; i++) {
0934:                        updateCounts[i] = EXECUTE_FAILED.intValue();
0935:                    }
0936:
0937:                    // See if we should return an exception
0938:                    if (sqlEx != null) {
0939:                        BatchUpdateException batchEx = new BatchUpdateException(
0940:                                sqlEx.getMessage(), sqlEx.getSQLState(), sqlEx
0941:                                        .getErrorCode(), updateCounts);
0942:                        // Chain any other exceptions
0943:                        batchEx.setNextException(sqlEx.getNextException());
0944:                        throw batchEx;
0945:                    }
0946:                    return updateCounts;
0947:                } catch (BatchUpdateException ex) {
0948:                    // If it's a BatchUpdateException let it go
0949:                    throw ex;
0950:                } catch (SQLException ex) {
0951:                    // An SQLException can only occur while sending the batch
0952:                    // (getBatchCounts() doesn't throw SQLExceptions), so we have to
0953:                    // end the batch and return the partial results
0954:                    // FIXME What should we send here to flush out the batch?
0955:                    // Come to think of it, is there any circumstance under which this
0956:                    // could actually happen without the connection getting closed?
0957:                    // No counts will have been returned either as last packet will not
0958:                    // have been sent.
0959:                    throw new BatchUpdateException(ex.getMessage(), ex
0960:                            .getSQLState(), ex.getErrorCode(), new int[0]);
0961:                } finally {
0962:                    clearBatch();
0963:                }
0964:            }
0965:
0966:            public void setFetchDirection(int direction) throws SQLException {
0967:                checkOpen();
0968:                switch (direction) {
0969:                case ResultSet.FETCH_UNKNOWN:
0970:                case ResultSet.FETCH_REVERSE:
0971:                case ResultSet.FETCH_FORWARD:
0972:                    this .fetchDirection = direction;
0973:                    break;
0974:
0975:                default:
0976:                    throw new SQLException(Messages.get(
0977:                            "error.generic.badoption", Integer
0978:                                    .toString(direction), "direction"), "24000");
0979:                }
0980:            }
0981:
0982:            public void setFetchSize(int rows) throws SQLException {
0983:                checkOpen();
0984:
0985:                if (rows < 0) {
0986:                    throw new SQLException(Messages.get(
0987:                            "error.generic.optltzero", "setFetchSize"), "HY092");
0988:                } else if (maxRows > 0 && rows > maxRows) {
0989:                    throw new SQLException(Messages
0990:                            .get("error.statement.gtmaxrows"), "HY092");
0991:                }
0992:                if (rows == 0) {
0993:                    rows = getDefaultFetchSize();
0994:                }
0995:                this .fetchSize = rows;
0996:            }
0997:
0998:            public void setMaxFieldSize(int max) throws SQLException {
0999:                checkOpen();
1000:
1001:                if (max < 0) {
1002:                    throw new SQLException(Messages.get(
1003:                            "error.generic.optltzero", "setMaxFieldSize"),
1004:                            "HY092");
1005:                }
1006:
1007:                maxFieldSize = max;
1008:            }
1009:
1010:            public void setMaxRows(int max) throws SQLException {
1011:                checkOpen();
1012:
1013:                if (max < 0) {
1014:                    throw new SQLException(Messages.get(
1015:                            "error.generic.optltzero", "setMaxRows"), "HY092");
1016:                }
1017:                if (max > 0 && max < this .fetchSize) {
1018:                    // Just for consistency with setFetchSize()
1019:                    this .fetchSize = max;
1020:                }
1021:                this .maxRows = max;
1022:            }
1023:
1024:            public void setQueryTimeout(int seconds) throws SQLException {
1025:                checkOpen();
1026:
1027:                if (seconds < 0) {
1028:                    throw new SQLException(Messages.get(
1029:                            "error.generic.optltzero", "setQueryTimeout"),
1030:                            "HY092");
1031:                }
1032:
1033:                this .queryTimeout = seconds;
1034:            }
1035:
1036:            public boolean getMoreResults(int current) throws SQLException {
1037:                checkOpen();
1038:
1039:                switch (current) {
1040:                case CLOSE_ALL_RESULTS:
1041:                    updateCount = -1;
1042:                    closeAllResultSets();
1043:                    break;
1044:                case CLOSE_CURRENT_RESULT:
1045:                    updateCount = -1;
1046:                    closeCurrentResultSet();
1047:                    break;
1048:                case KEEP_CURRENT_RESULT:
1049:                    updateCount = -1;
1050:                    // If there is an open result set it is transferred to
1051:                    // the list of open result sets. For JtdsResultSet
1052:                    // result sets we cache the remaining data. For CachedResultSet
1053:                    // result sets the data is already cached.
1054:                    if (openResultSets == null) {
1055:                        openResultSets = new ArrayList();
1056:                    }
1057:                    if (currentResult instanceof  MSCursorResultSet
1058:                            || currentResult instanceof  CachedResultSet) {
1059:                        // NB. Due to restrictions on the way API cursors are
1060:                        // created, MSCursorResultSet can never be followed by
1061:                        // any other result sets, update counts or return variables.
1062:                        openResultSets.add(currentResult);
1063:                    } else if (currentResult != null) {
1064:                        currentResult.cacheResultSetRows();
1065:                        openResultSets.add(currentResult);
1066:                    }
1067:                    currentResult = null;
1068:                    break;
1069:                default:
1070:                    throw new SQLException(Messages.get(
1071:                            "error.generic.badoption", Integer
1072:                                    .toString(current), "current"), "HY092");
1073:                }
1074:
1075:                // Check for server side errors
1076:                messages.checkErrors();
1077:
1078:                // Dequeue any results
1079:                if (!resultQueue.isEmpty() || processResults(false, false)) {
1080:                    Object nextResult = resultQueue.removeFirst();
1081:
1082:                    // Next result is an update count
1083:                    if (nextResult instanceof  Integer) {
1084:                        updateCount = ((Integer) nextResult).intValue();
1085:                        return false;
1086:                    }
1087:
1088:                    // Next result is a ResultSet. Set currentResult and remove it.
1089:                    currentResult = (JtdsResultSet) nextResult;
1090:                    return true;
1091:                } else {
1092:                    return false;
1093:                }
1094:            }
1095:
1096:            public void setEscapeProcessing(boolean enable) throws SQLException {
1097:                checkOpen();
1098:
1099:                this .escapeProcessing = enable;
1100:            }
1101:
1102:            public int executeUpdate(String sql) throws SQLException {
1103:                return executeUpdate(sql, NO_GENERATED_KEYS);
1104:            }
1105:
1106:            public void addBatch(String sql) throws SQLException {
1107:                checkOpen();
1108:
1109:                if (sql == null) {
1110:                    throw new NullPointerException();
1111:                }
1112:
1113:                if (batchValues == null) {
1114:                    batchValues = new ArrayList();
1115:                }
1116:
1117:                if (escapeProcessing) {
1118:                    String tmp[] = SQLParser
1119:                            .parse(sql, null, connection, false);
1120:
1121:                    if (tmp[1].length() != 0) {
1122:                        throw new SQLException(Messages
1123:                                .get("error.statement.badsql"), "07000");
1124:                    }
1125:
1126:                    sql = tmp[0];
1127:                }
1128:
1129:                batchValues.add(sql);
1130:            }
1131:
1132:            public void setCursorName(String name) throws SQLException {
1133:                checkOpen();
1134:                this .cursorName = name;
1135:                if (name != null) {
1136:                    // Reset statement type to JDBC 1 default.
1137:                    this .resultSetType = ResultSet.TYPE_FORWARD_ONLY;
1138:                    this .fetchSize = 1; // Needed for positioned updates
1139:                }
1140:            }
1141:
1142:            public boolean execute(String sql) throws SQLException {
1143:                checkOpen();
1144:
1145:                return executeImpl(sql, NO_GENERATED_KEYS, false);
1146:            }
1147:
1148:            public int executeUpdate(String sql, int autoGeneratedKeys)
1149:                    throws SQLException {
1150:                checkOpen();
1151:
1152:                executeImpl(sql, autoGeneratedKeys, true);
1153:
1154:                int res = getUpdateCount();
1155:                return res == -1 ? 0 : res;
1156:            }
1157:
1158:            public boolean execute(String sql, int autoGeneratedKeys)
1159:                    throws SQLException {
1160:                checkOpen();
1161:
1162:                return executeImpl(sql, autoGeneratedKeys, false);
1163:            }
1164:
1165:            public int executeUpdate(String sql, int[] columnIndexes)
1166:                    throws SQLException {
1167:                checkOpen();
1168:
1169:                if (columnIndexes == null) {
1170:                    throw new SQLException(Messages.get(
1171:                            "error.generic.nullparam", "executeUpdate"),
1172:                            "HY092");
1173:                } else if (columnIndexes.length != 1) {
1174:                    throw new SQLException(Messages.get(
1175:                            "error.generic.needcolindex", "executeUpdate"),
1176:                            "HY092");
1177:                }
1178:
1179:                return executeUpdate(sql, RETURN_GENERATED_KEYS);
1180:            }
1181:
1182:            public boolean execute(String sql, int[] columnIndexes)
1183:                    throws SQLException {
1184:                checkOpen();
1185:
1186:                if (columnIndexes == null) {
1187:                    throw new SQLException(Messages.get(
1188:                            "error.generic.nullparam", "execute"), "HY092");
1189:                } else if (columnIndexes.length != 1) {
1190:                    throw new SQLException(Messages.get(
1191:                            "error.generic.needcolindex", "execute"), "HY092");
1192:                }
1193:
1194:                return executeImpl(sql, RETURN_GENERATED_KEYS, false);
1195:            }
1196:
1197:            public Connection getConnection() throws SQLException {
1198:                checkOpen();
1199:
1200:                return this .connection;
1201:            }
1202:
1203:            public ResultSet getGeneratedKeys() throws SQLException {
1204:                checkOpen();
1205:
1206:                if (genKeyResultSet == null) {
1207:                    String colNames[] = { "ID" };
1208:                    int colTypes[] = { Types.INTEGER };
1209:                    //
1210:                    // Return an empty result set
1211:                    //
1212:                    CachedResultSet rs = new CachedResultSet(this , colNames,
1213:                            colTypes);
1214:                    rs.setConcurrency(ResultSet.CONCUR_READ_ONLY);
1215:                    genKeyResultSet = rs;
1216:                }
1217:
1218:                return genKeyResultSet;
1219:            }
1220:
1221:            public ResultSet getResultSet() throws SQLException {
1222:                checkOpen();
1223:                //
1224:                if (currentResult instanceof  MSCursorResultSet
1225:                        || currentResult instanceof  CachedResultSet) {
1226:                    return currentResult;
1227:                }
1228:                //
1229:                // See if we are returning a forward read only resultset
1230:                //
1231:                if (currentResult == null
1232:                        || (resultSetType == ResultSet.TYPE_FORWARD_ONLY && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY)) {
1233:                    return currentResult;
1234:                }
1235:                //
1236:                // OK Now create a CachedResultSet based on the existng result set.
1237:                //
1238:                currentResult = new CachedResultSet(currentResult, true);
1239:
1240:                return currentResult;
1241:            }
1242:
1243:            public SQLWarning getWarnings() throws SQLException {
1244:                checkOpen();
1245:
1246:                return messages.getWarnings();
1247:            }
1248:
1249:            public int executeUpdate(String sql, String[] columnNames)
1250:                    throws SQLException {
1251:                checkOpen();
1252:
1253:                if (columnNames == null) {
1254:                    throw new SQLException(Messages.get(
1255:                            "error.generic.nullparam", "executeUpdate"),
1256:                            "HY092");
1257:                } else if (columnNames.length != 1) {
1258:                    throw new SQLException(Messages.get(
1259:                            "error.generic.needcolname", "executeUpdate"),
1260:                            "HY092");
1261:                }
1262:
1263:                return executeUpdate(sql, RETURN_GENERATED_KEYS);
1264:            }
1265:
1266:            public boolean execute(String sql, String[] columnNames)
1267:                    throws SQLException {
1268:                checkOpen();
1269:
1270:                if (columnNames == null) {
1271:                    throw new SQLException(Messages.get(
1272:                            "error.generic.nullparam", "execute"), "HY092");
1273:                } else if (columnNames.length != 1) {
1274:                    throw new SQLException(Messages.get(
1275:                            "error.generic.needcolname", "execute"), "HY092");
1276:                }
1277:
1278:                return executeImpl(sql, RETURN_GENERATED_KEYS, false);
1279:            }
1280:
1281:            public ResultSet executeQuery(String sql) throws SQLException {
1282:                checkOpen();
1283:                initialize();
1284:
1285:                if (sql == null || sql.length() == 0) {
1286:                    throw new SQLException(Messages.get("error.generic.nosql"),
1287:                            "HY000");
1288:                }
1289:                if (escapeProcessing) {
1290:                    String tmp[] = SQLParser
1291:                            .parse(sql, null, connection, false);
1292:
1293:                    if (tmp[1].length() != 0) {
1294:                        throw new SQLException(Messages
1295:                                .get("error.statement.badsql"), "07000");
1296:                    }
1297:
1298:                    sql = tmp[0];
1299:                }
1300:
1301:                return this .executeSQLQuery(sql, null, null, useCursor(false,
1302:                        null));
1303:            }
1304:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.