Source Code Cross Referenced for Statement.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » client » am » 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 DBMS » db derby 10.2 » org.apache.derby.client.am 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.client.am.Statement
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to You under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:        package org.apache.derby.client.am;
0022:
0023:        import java.sql.SQLException;
0024:
0025:        import org.apache.derby.shared.common.reference.JDBC30Translation;
0026:        import org.apache.derby.shared.common.reference.SQLState;
0027:
0028:        public class Statement implements  java.sql.Statement,
0029:                StatementCallbackInterface {
0030:
0031:            // JDBC 3 constant indicating that the current ResultSet object
0032:            // should be closed when calling getMoreResults.
0033:            // Constant value matches that defined by JDBC 3 java.sql.Statement.CLOSE_CURRENT_RESULT
0034:            public final static int CLOSE_CURRENT_RESULT = 1;
0035:
0036:            // JDBC 3 constant indicating that the current ResultSet object
0037:            // should not be closed when calling getMoreResults.
0038:            // Constant value matches that defined by JDBC 3 java.sql.Statement.KEEP_CURRENT_RESULT
0039:            public final static int KEEP_CURRENT_RESULT = 2;
0040:
0041:            // JDBC 3 constant indicating that all ResultSet objects that
0042:            // have previously been kept open should be closed when calling getMoreResults.
0043:            // Constant value matches that defined by JDBC 3 java.sql.Statement.CLOSE_ALL_RESULTS
0044:            public final static int CLOSE_ALL_RESULTS = 3;
0045:
0046:            //---------------------navigational members-----------------------------------
0047:
0048:            public MaterialStatement materialStatement_ = null;
0049:
0050:            public Connection connection_;
0051:            public Section section_;
0052:            public Agent agent_;
0053:
0054:            public ResultSet resultSet_ = null;
0055:
0056:            // Use -1, if there is no update count returned, ie. when result set is returned. 0 is a valid update count for DDL.
0057:            int updateCount_ = -1;
0058:            int returnValueFromProcedure_;
0059:
0060:            // Enumeration of the flavors of statement execute call used.
0061:            static final int executeQueryMethod__ = 1;
0062:            static final int executeUpdateMethod__ = 2;
0063:            static final int executeMethod__ = 3;
0064:
0065:            // sqlMode_ will be moved to PS as soon as we remove the hack reference in completeExecute()
0066:            // Enumerated in Statement: S.sqlIsQuery__, S.sqlIsCall__, S.sqlIsUpdate__
0067:            // Determines whether sql_ starts with SELECT/VALUES, CALL, or other (assumed to be an update).
0068:            protected int sqlMode_ = 0;
0069:            // Enum for sqlMode_:
0070:            static final int isQuery__ = 0x1; // sql starts with SELECT.... or VALUES...
0071:            static final int isCall__ = 0x2; // sql starts with CALL ...
0072:            static final int isUpdate__ = 0x4; // All other sql is categorized as a update DML or DDL.
0073:
0074:            // sqlUpdateMode_ is only set when the sqlMode_ == isUpdate__
0075:            public int sqlUpdateMode_ = 0;
0076:            // Enum for sqlUpdateMode_:
0077:            public final static int isCommitSql__ = 0x1;
0078:            public final static int isRollbackSql__ = 0x2;
0079:            final static int isPositionedUpdateDeleteSql__ = 0x10;
0080:            final static int isInsertSql__ = 0x20; // used to recognize "insert" for auto-generated keys
0081:            final static int isDeleteSql__ = 0x40; // used to recognize "delete" for parsing cursorname
0082:            final static int isUpdateSql__ = 0x80; // used to recognize "update" for parsing cursorname
0083:
0084:            public ColumnMetaData resultSetMetaData_; // type information for output sqlda
0085:
0086:            // these two are used during parsing of literals for call statement.
0087:            // please add a comment desribing what why you can't reuse inputs_ and parameterMetaData_
0088:            // members for the literal inputs
0089:
0090:            // Caching the Cursor object for reuse.
0091:            public Cursor cachedCursor_ = null;
0092:            public Cursor cachedSingletonRowData_ = null;
0093:            public boolean isPreparedStatement_ = false;
0094:            public boolean isCallableStatement_ = false; // we can get rid of this member once we define polymorphic reset() on S/PS/CS
0095:
0096:            //---------------------navigational cheat-links-------------------------------
0097:            // Cheat-links are for convenience only, and are not part of the conceptual model.
0098:            // Warning:
0099:            //   Cheat-links should only be defined for invariant state data.
0100:            //   That is, state data that is set by the constructor and never changes.
0101:
0102:            // Alias for connection_.databaseMetaData
0103:            public DatabaseMetaData databaseMetaData_;
0104:
0105:            //-----------------------------state------------------------------------------
0106:
0107:            // Jdbc 1 positioned updates are implemented via
0108:            // sql scan for "...where current of <users-cursor-name>",
0109:            // the addition of mappings from cursor names to query sections,
0110:            // and the subtitution of <users-cursor-name> with <canned-cursor-name> in the pass-thru sql string
0111:            // "...where current of <canned-cursor-name>" when user-defined cursor names are used.
0112:            // Both "canned" cursor names (from our jdbc package set) and user-defined cursor names are mapped.
0113:            // Statement.cursorName_ is initialized to null until the cursor name is requested or set.
0114:            // s.setCursorName()) adds a user-defined name, but it is not
0115:            // added to the cursor map until execution time (DERBY-1036);
0116:            // When requested (rs.getCursorName()), if the cursor name is still null,
0117:            // then is given the canned cursor name as defined by our jdbc package set.
0118:            // Still need to consider how positioned updates should interact with multiple result sets from a stored.
0119:            String cursorName_ = null;
0120:
0121:            // This means the client-side jdbc statement object is open.
0122:            // This value is set to true when the statement object is constructed, and will not change
0123:            // until statement.close() is called either directly or via connection.close(), finalizer, or other methods.
0124:            boolean openOnClient_ = true;
0125:            // This means a DERBY server-side section for this statement is in the prepared state.
0126:            // A client-side jdbc statement may remain open across commits (openOnClient=true),
0127:            // but the server-side DERBY section moves to an unprepared state (openOnServer=false) across commits,
0128:            // requiring an implicit re-prepare "under the covers" by the driver.
0129:            // Unprepared jdbc query statements still have prepared sections on the server.
0130:            // This openOnServer_ only has implications for preparedstatement
0131:            boolean openOnServer_ = false;
0132:
0133:            //private int indexOfCurrentResultSet_ = -1;
0134:            protected int indexOfCurrentResultSet_ = -1;
0135:            ResultSet[] resultSetList_ = null; // array of ResultSet objects
0136:
0137:            protected final static String TIMEOUT_STATEMENT = "SET STATEMENT_TIMEOUT ";
0138:            protected java.util.ArrayList timeoutArrayList = new java.util.ArrayList(
0139:                    1);
0140:            protected boolean doWriteTimeout = false;
0141:            int timeout_ = 0; // for query timeout in seconds
0142:            int maxRows_ = 0;
0143:            int maxFieldSize_ = 0; // zero means that there is no limit to the size of a column.
0144:            boolean escapedProcedureCallWithResult_ = false;
0145:
0146:            // When this is false we skip autocommit for this PreparedStatement.
0147:            // This is needed when the PreparedStatement object is used internally by
0148:            // the driver and a commit is not desired, e.g., Blob/Clob API calls
0149:            public boolean isAutoCommittableStatement_ = true;
0150:
0151:            // The user has no control over the statement that owns a catalog query, and has no ability to close that statement.
0152:            // We need a special member variable on our internal catalog query statements so that
0153:            // when the catalog query is closed, the result set will know to close it's owning statement.
0154:            boolean isCatalogQuery_ = false;
0155:
0156:            // This collection is used for two different purposes:
0157:            //   For statement batching it contains the batched SQL strings.
0158:            //   For prepared statement batching it contains the batched input rows.
0159:            java.util.ArrayList batch_ = new java.util.ArrayList();
0160:
0161:            // Scrollable cursor attributes
0162:            public int resultSetType_ = java.sql.ResultSet.TYPE_FORWARD_ONLY;
0163:            public int resultSetConcurrency_ = java.sql.ResultSet.CONCUR_READ_ONLY;
0164:            public int resultSetHoldability_;
0165:            // This is ignored by the driver if this is zero.
0166:            // For the net forward-only result set, if fetchSize is unset, we let the server return however many rows will fit in a query block.
0167:            // For the net scrollable result set, then we use a default of 64 rows.
0168:            public int fetchSize_ = 0;
0169:            public int fetchDirection_ = java.sql.ResultSet.FETCH_FORWARD;
0170:
0171:            // Conceptually this doesn't belong in Statement, but belongs in PreparedStatement,
0172:            // since Statement doesn't know about params, so we're just putting it here perhaps temporarily,
0173:            // Used for callable statement OUT paramters.
0174:            public Cursor singletonRowData_ = null;
0175:
0176:            // number of invisible result sets returned from a stored procedure.
0177:            public int numInvisibleRS_ = 0;
0178:
0179:            // This is a cache of the attributes to be sent on prepare.
0180:            // Think about caching the entire prepare DDM string for the re-prepares
0181:            public String cursorAttributesToSendOnPrepare_ = null;
0182:
0183:            // The following members are for the exclusive use of prepared statements that require auto-generated keys to be returned
0184:            public PreparedStatement preparedStatementForAutoGeneratedKeys_;
0185:            public ResultSet generatedKeysResultSet_;
0186:            public String[] generatedKeysColumnNames_;
0187:            public int autoGeneratedKeys_ = java.sql.Statement.NO_GENERATED_KEYS;
0188:
0189:            // This flag makes sure that only one copy of this statement
0190:            // will be in connection_.commitListeners_.
0191:
0192:            private SqlWarning warnings_ = null;
0193:
0194:            // A Statement is NOT poolable by default. The constructor for
0195:            // PreparedStatement overrides this.
0196:            protected boolean isPoolable = false;
0197:
0198:            //---------------------constructors/finalizer/accessors--------------------
0199:
0200:            private Statement() throws SqlException {
0201:                initStatement();
0202:            }
0203:
0204:            private void resetStatement() throws SqlException {
0205:                initStatement();
0206:            }
0207:
0208:            private void initStatement() throws SqlException {
0209:                materialStatement_ = null;
0210:                connection_ = null;
0211:                agent_ = null;
0212:                databaseMetaData_ = null;
0213:                resultSetType_ = java.sql.ResultSet.TYPE_FORWARD_ONLY;
0214:                resultSetConcurrency_ = java.sql.ResultSet.CONCUR_READ_ONLY;
0215:                resultSetHoldability_ = 0;
0216:                cursorAttributesToSendOnPrepare_ = null;
0217:                if (timeoutArrayList.size() == 0) {
0218:                    timeoutArrayList.add(null); // Make sure the list's length is 1
0219:                }
0220:
0221:                initResetStatement();
0222:            }
0223:
0224:            private void initResetStatement() throws SqlException {
0225:                initResetPreparedStatement();
0226:
0227:                //section_ = null; // don't set section to null because write piggyback command require a section
0228:                if (section_ != null) {
0229:                    section_.free();
0230:                }
0231:                sqlMode_ = 0;
0232:                sqlUpdateMode_ = 0;
0233:                resultSetMetaData_ = null;
0234:            }
0235:
0236:            protected void initResetPreparedStatement() {
0237:                warnings_ = null;
0238:                //section_ = null;
0239:                resultSet_ = null;
0240:                updateCount_ = -1;
0241:                returnValueFromProcedure_ = 0;
0242:                cursorName_ = null;
0243:                openOnClient_ = true;
0244:                openOnServer_ = false;
0245:                indexOfCurrentResultSet_ = -1;
0246:                resultSetList_ = null;
0247:                timeout_ = 0;
0248:                doWriteTimeout = false;
0249:                maxRows_ = 0;
0250:                maxFieldSize_ = 0;
0251:                escapedProcedureCallWithResult_ = false;
0252:                isCatalogQuery_ = false;
0253:                isAutoCommittableStatement_ = true;
0254:
0255:                if (batch_ == null) {
0256:                    batch_ = new java.util.ArrayList();
0257:                } else {
0258:                    batch_.clear();
0259:                }
0260:                fetchSize_ = 0;
0261:                fetchDirection_ = java.sql.ResultSet.FETCH_FORWARD;
0262:                singletonRowData_ = null;
0263:                numInvisibleRS_ = 0;
0264:                preparedStatementForAutoGeneratedKeys_ = null;
0265:                generatedKeysResultSet_ = null;
0266:                generatedKeysColumnNames_ = null;
0267:                autoGeneratedKeys_ = java.sql.Statement.NO_GENERATED_KEYS;
0268:
0269:                // these members were not initialized
0270:                isPreparedStatement_ = false;
0271:            }
0272:
0273:            // If a dataSource is passed into resetClientConnection(), then we will assume
0274:            // properties on the dataSource may have changed, and we will need to go through
0275:            // the open-statement list on the connection and do a full reset on all statements,
0276:            // including preparedStatement's and callableStatement's.  This is because property
0277:            // change may influence the section we allocate for the preparedStatement, and
0278:            // also the cursor attributes, i.e. setCursorSensitivity().
0279:            // If no dataSource is passed into resetClientConnection(), then we will do the
0280:            // minimum reset required for preparedStatement's and callableStatement's.
0281:            public void reset(boolean fullReset) throws SqlException {
0282:                if (fullReset) {
0283:                    connection_.resetStatement(this );
0284:                } else {
0285:                    initResetStatement();
0286:                    materialStatement_.reset_();
0287:                }
0288:            }
0289:
0290:            public Statement(Agent agent, Connection connection)
0291:                    throws SqlException {
0292:                this ();
0293:                initStatement(agent, connection);
0294:            }
0295:
0296:            public void resetStatement(Agent agent, Connection connection)
0297:                    throws SqlException {
0298:                resetStatement();
0299:                initStatement(agent, connection);
0300:            }
0301:
0302:            private void initStatement(Agent agent, Connection connection) {
0303:                agent_ = agent;
0304:                connection_ = connection;
0305:                databaseMetaData_ = connection.databaseMetaData_;
0306:            }
0307:
0308:            // For jdbc 2 statements with scroll attributes
0309:            public Statement(Agent agent, Connection connection, int type,
0310:                    int concurrency, int holdability, int autoGeneratedKeys,
0311:                    String[] columnNames) throws SqlException {
0312:                this (agent, connection);
0313:                initStatement(type, concurrency, holdability,
0314:                        autoGeneratedKeys, columnNames);
0315:            }
0316:
0317:            public void resetStatement(Agent agent, Connection connection,
0318:                    int type, int concurrency, int holdability,
0319:                    int autoGeneratedKeys, String[] columnNames)
0320:                    throws SqlException {
0321:                resetStatement(agent, connection);
0322:                initStatement(type, concurrency, holdability,
0323:                        autoGeneratedKeys, columnNames);
0324:            }
0325:
0326:            private void initStatement(int type, int concurrency,
0327:                    int holdability, int autoGeneratedKeys, String[] columnNames)
0328:                    throws SqlException {
0329:                switch (type) {
0330:                case java.sql.ResultSet.TYPE_FORWARD_ONLY:
0331:                case java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE:
0332:                case java.sql.ResultSet.TYPE_SCROLL_SENSITIVE:
0333:                    resultSetType_ = type;
0334:                    break;
0335:                default:
0336:                    throw new SqlException(
0337:                            agent_.logWriter_,
0338:                            new ClientMessageId(SQLState.INVALID_API_PARAMETER),
0339:                            new Integer(type), "type", "createStatement()");
0340:                }
0341:
0342:                switch (concurrency) {
0343:                case java.sql.ResultSet.CONCUR_READ_ONLY:
0344:                case java.sql.ResultSet.CONCUR_UPDATABLE:
0345:                    resultSetConcurrency_ = concurrency;
0346:                    break;
0347:                default:
0348:                    throw new SqlException(
0349:                            agent_.logWriter_,
0350:                            new ClientMessageId(SQLState.INVALID_API_PARAMETER),
0351:                            new Integer(concurrency), "concurrency",
0352:                            "createStatement()");
0353:                }
0354:
0355:                switch (holdability) {
0356:                case JDBC30Translation.CLOSE_CURSORS_AT_COMMIT:
0357:                case JDBC30Translation.HOLD_CURSORS_OVER_COMMIT:
0358:                    resultSetHoldability_ = holdability;
0359:                    break;
0360:                default:
0361:                    throw new SqlException(
0362:                            agent_.logWriter_,
0363:                            new ClientMessageId(SQLState.INVALID_API_PARAMETER),
0364:                            new Integer(holdability), "holdability",
0365:                            "createStatement()");
0366:                }
0367:
0368:                switch (autoGeneratedKeys) {
0369:                case java.sql.Statement.NO_GENERATED_KEYS:
0370:                case java.sql.Statement.RETURN_GENERATED_KEYS:
0371:                    autoGeneratedKeys_ = autoGeneratedKeys;
0372:                    break;
0373:                default:
0374:                    throw new SqlException(
0375:                            agent_.logWriter_,
0376:                            new ClientMessageId(SQLState.INVALID_API_PARAMETER),
0377:                            new Integer(autoGeneratedKeys),
0378:                            "autoGeneratedKeys", "createStatement");
0379:                }
0380:
0381:                generatedKeysColumnNames_ = columnNames;
0382:            }
0383:
0384:            /* (non-Javadoc)
0385:             * @see java.lang.Object#finalize()
0386:             * 
0387:             * This method cleans up client-side resources by calling markClosed().
0388:             * It is different from close() method, which also does clean up on server.
0389:             * Changes done as part of DERBY-210. 
0390:             */
0391:            protected void finalize() throws java.lang.Throwable {
0392:                if (agent_.loggingEnabled()) {
0393:                    agent_.logWriter_.traceEntry(this , "finalize");
0394:                }
0395:                if (openOnClient_) {
0396:                    markClosed();
0397:                }
0398:                super .finalize();
0399:            }
0400:
0401:            /*
0402:             * Accessor to state variable warnings_
0403:             */
0404:            protected SqlWarning getSqlWarnings() {
0405:                return warnings_;
0406:            }
0407:
0408:            // ---------------------------jdbc 1------------------------------------------
0409:
0410:            public java.sql.ResultSet executeQuery(String sql)
0411:                    throws SQLException {
0412:                try {
0413:                    synchronized (connection_) {
0414:                        if (agent_.loggingEnabled()) {
0415:                            agent_.logWriter_.traceEntry(this , "executeQuery",
0416:                                    sql);
0417:                        }
0418:                        ResultSet resultSet = executeQueryX(sql);
0419:                        if (agent_.loggingEnabled()) {
0420:                            agent_.logWriter_.traceExit(this , "executeQuery",
0421:                                    resultSet);
0422:                        }
0423:                        return resultSet;
0424:                    }
0425:                } catch (SqlException se) {
0426:                    throw se.getSQLException();
0427:                }
0428:
0429:            }
0430:
0431:            private ResultSet executeQueryX(String sql) throws SqlException {
0432:                flowExecute(executeQueryMethod__, sql);
0433:                return resultSet_;
0434:            }
0435:
0436:            public int executeUpdate(String sql) throws SQLException {
0437:                try {
0438:                    synchronized (connection_) {
0439:                        if (agent_.loggingEnabled()) {
0440:                            agent_.logWriter_.traceEntry(this , "executeUpdate",
0441:                                    sql);
0442:                        }
0443:                        int updateValue = executeUpdateX(sql);
0444:                        if (agent_.loggingEnabled()) {
0445:                            agent_.logWriter_.traceExit(this , "executeUpdate",
0446:                                    updateValue);
0447:                        }
0448:                        return updateValue;
0449:                    }
0450:                } catch (SqlException se) {
0451:                    throw se.getSQLException();
0452:                }
0453:            }
0454:
0455:            private int executeUpdateX(String sql) throws SqlException {
0456:                flowExecute(executeUpdateMethod__, sql);
0457:                return updateCount_;
0458:            }
0459:
0460:            /**
0461:             * Returns false unless <code>iface</code> is implemented 
0462:             * 
0463:             * @param  iface                  a Class defining an interface.
0464:             * @return true                   if this implements the interface or 
0465:             *                                directly or indirectly wraps an object 
0466:             *                                that does.
0467:             * @throws java.sql.SQLException  if an error occurs while determining 
0468:             *                                whether this is a wrapper for an object 
0469:             *                                with the given interface.
0470:             */
0471:            public boolean isWrapperFor(Class iface) throws SQLException {
0472:                try {
0473:                    checkForClosedStatement();
0474:                } catch (SqlException se) {
0475:                    throw se.getSQLException();
0476:                }
0477:                return iface.isInstance(this );
0478:            }
0479:
0480:            /**
0481:             * Tell whether the statement has been closed or not.
0482:             *
0483:             * @return <code>true</code> if closed, <code>false</code> otherwise.
0484:             * @exception SQLException if a database access error occurs (according to
0485:             *                         spec). Never thrown by this implementation. 
0486:             */
0487:            public boolean isClosed() throws SQLException {
0488:                if (agent_.loggingEnabled()) {
0489:                    agent_.logWriter_.traceEntry(this , "isClosed",
0490:                            !openOnClient_);
0491:                }
0492:                if (agent_.loggingEnabled()) {
0493:                    agent_.logWriter_.traceExit(this , "isClosed",
0494:                            !openOnClient_);
0495:                }
0496:                return !openOnClient_;
0497:            }
0498:
0499:            // The server holds statement resources until transaction end.
0500:            public void close() throws SQLException {
0501:                try {
0502:                    synchronized (connection_) {
0503:                        if (agent_.loggingEnabled()) {
0504:                            agent_.logWriter_.traceEntry(this , "close");
0505:                        }
0506:                        closeX();
0507:                    }
0508:                } catch (SqlException se) {
0509:                    throw se.getSQLException();
0510:                }
0511:            }
0512:
0513:            /**
0514:             * An untraced version of <code>close</code>. This method cleans up 
0515:             * client-side resources and also sends commands to network server to 
0516:             * perform clean up. This should not be called in the finalizer. 
0517:             * Difference between <code>finalize</code> and <code>close</code> is
0518:             * that close method does these things additionally (Changes done as 
0519:             * part of DERBY-210):
0520:             * 1) Sends commands to the server to close the result sets.
0521:             * 2) Sends commands to the server to close the result sets of the 
0522:             * generated keys query.
0523:             * 3) Sends a commit if autocommit is on and it is appropriate.
0524:             * 4) Explicitly removes the statement from connection_.openStatements_ 
0525:             * and CommitAndRollbackListeners_ by passing true to markClosed.  
0526:             * 
0527:             * We may need to do 1) in finalizer too. This is being tracked in 
0528:             * DERBY-1021
0529:             * 
0530:             * @throws SqlException
0531:             */
0532:            public void closeX() throws SqlException {
0533:                if (!openOnClient_) {
0534:                    return;
0535:                }
0536:                // Regardless of whether or not this statement is in the prepared state,
0537:                // we need to close any open cursors for this statement on the server.
0538:                int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
0539:                        : resultSetList_.length;
0540:                boolean willTickleServer = willTickleServer(
0541:                        numberOfResultSetsToClose, true);
0542:                try {
0543:                    if (willTickleServer) {
0544:                        flowClose();
0545:                    } else {
0546:                        flowCloseOutsideUOW();
0547:                    }
0548:                } finally {
0549:                    markClosed(true);
0550:                }
0551:            }
0552:
0553:            /**
0554:             * Returns the value of the poolable hint, indicating whether
0555:             * pooling is requested.
0556:             *
0557:             * @return The value of the poolable hint.
0558:             * @throws SQLException if the Statement has been closed.
0559:             */
0560:            public boolean isPoolable() throws SQLException {
0561:                try {
0562:                    synchronized (connection_) {
0563:                        if (agent_.loggingEnabled()) {
0564:                            agent_.logWriter_.traceEntry(this , "isPoolable");
0565:                        }
0566:                        // Assert the statement has not been closed
0567:                        checkForClosedStatement();
0568:
0569:                        return isPoolable;
0570:                    }
0571:                } catch (SqlException se) {
0572:                    throw se.getSQLException();
0573:                }
0574:            }
0575:
0576:            /**
0577:             * Requests that a Statement be pooled or not.
0578:             *
0579:             * @param poolable requests that the Statement be pooled if true 
0580:             * and not be pooled if false.
0581:             * @throws SQLException if the Statement has been closed.
0582:             */
0583:            public void setPoolable(boolean poolable) throws SQLException {
0584:                try {
0585:                    synchronized (connection_) {
0586:                        if (agent_.loggingEnabled()) {
0587:                            agent_.logWriter_.traceEntry(this , "setPoolable",
0588:                                    poolable);
0589:                        }
0590:                        // Assert the statement has not been closed
0591:                        checkForClosedStatement();
0592:
0593:                        isPoolable = poolable;
0594:                    }
0595:                } catch (SqlException se) {
0596:                    throw se.getSQLException();
0597:                }
0598:            }
0599:
0600:            public int getMaxFieldSize() throws SQLException {
0601:                try {
0602:                    if (agent_.loggingEnabled()) {
0603:                        agent_.logWriter_.traceEntry(this , "getMaxFieldSize");
0604:                    }
0605:                    checkForClosedStatement();
0606:                    return maxFieldSize_;
0607:                } catch (SqlException se) {
0608:                    throw se.getSQLException();
0609:                }
0610:            }
0611:
0612:            public void setMaxFieldSize(int max) throws SQLException {
0613:                try {
0614:                    synchronized (connection_) {
0615:                        if (agent_.loggingEnabled()) {
0616:                            agent_.logWriter_.traceEntry(this ,
0617:                                    "setMaxFieldSize", max);
0618:                        }
0619:                        checkForClosedStatement();
0620:                        if (max < 0) {
0621:                            throw new SqlException(agent_.logWriter_,
0622:                                    new ClientMessageId(
0623:                                            SQLState.INVALID_MAXFIELD_SIZE),
0624:                                    new Integer(max));
0625:                        }
0626:                        maxFieldSize_ = max;
0627:                    }
0628:                } catch (SqlException se) {
0629:                    throw se.getSQLException();
0630:                }
0631:            }
0632:
0633:            public int getMaxRows() throws SQLException {
0634:                try {
0635:                    checkForClosedStatement();
0636:                    if (agent_.loggingEnabled()) {
0637:                        agent_.logWriter_.traceExit(this , "getMaxRows",
0638:                                maxRows_);
0639:                    }
0640:                    return maxRows_;
0641:                } catch (SqlException se) {
0642:                    throw se.getSQLException();
0643:                }
0644:            }
0645:
0646:            public void setMaxRows(int maxRows) throws SQLException {
0647:                try {
0648:                    synchronized (connection_) {
0649:                        if (agent_.loggingEnabled()) {
0650:                            agent_.logWriter_.traceEntry(this , "setMaxRows",
0651:                                    maxRows);
0652:                        }
0653:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0654:                        if (maxRows < 0) {
0655:                            throw new SqlException(agent_.logWriter_,
0656:                                    new ClientMessageId(
0657:                                            SQLState.INVALID_MAX_ROWS_VALUE),
0658:                                    new Integer(maxRows));
0659:                        }
0660:                        maxRows_ = maxRows;
0661:                    }
0662:                } catch (SqlException se) {
0663:                    throw se.getSQLException();
0664:                }
0665:            }
0666:
0667:            public void setEscapeProcessing(boolean enable) throws SQLException {
0668:                try {
0669:                    synchronized (connection_) {
0670:                        if (agent_.loggingEnabled()) {
0671:                            agent_.logWriter_.traceEntry(this ,
0672:                                    "setEscapeProcessing", enable);
0673:                        }
0674:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0675:                    }
0676:                } catch (SqlException se) {
0677:                    throw se.getSQLException();
0678:                }
0679:            }
0680:
0681:            public int getQueryTimeout() throws SQLException {
0682:                try {
0683:                    checkForClosedStatement();
0684:                    if (agent_.loggingEnabled()) {
0685:                        agent_.logWriter_.traceExit(this , "getQueryTimeout",
0686:                                timeout_);
0687:                    }
0688:                    return timeout_;
0689:                } catch (SqlException se) {
0690:                    throw se.getSQLException();
0691:                }
0692:            }
0693:
0694:            public void setQueryTimeout(int seconds) throws SQLException {
0695:                try {
0696:                    synchronized (connection_) {
0697:                        if (agent_.loggingEnabled()) {
0698:                            agent_.logWriter_.traceEntry(this ,
0699:                                    "setQueryTimeout", seconds);
0700:                        }
0701:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0702:                        if (seconds < 0) {
0703:                            throw new SqlException(
0704:                                    agent_.logWriter_,
0705:                                    new ClientMessageId(
0706:                                            SQLState.INVALID_QUERYTIMEOUT_VALUE),
0707:                                    new Integer(seconds));
0708:                        }
0709:                        if (seconds != timeout_) {
0710:                            timeout_ = seconds;
0711:                            doWriteTimeout = true;
0712:                        }
0713:                    }
0714:                } catch (SqlException se) {
0715:                    throw se.getSQLException();
0716:                }
0717:            }
0718:
0719:            public void cancel() throws SQLException {
0720:                try {
0721:                    if (agent_.loggingEnabled()) {
0722:                        agent_.logWriter_.traceEntry(this , "cancel");
0723:                    }
0724:                    checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0725:                    throw new SqlException(agent_.logWriter_,
0726:                            new ClientMessageId(
0727:                                    SQLState.CANCEL_NOT_SUPPORTED_BY_SERVER));
0728:                } catch (SqlException se) {
0729:                    throw se.getSQLException();
0730:                }
0731:            }
0732:
0733:            public java.sql.SQLWarning getWarnings() throws SQLException {
0734:                if (agent_.loggingEnabled()) {
0735:                    agent_.logWriter_.traceExit(this , "getWarnings", warnings_);
0736:                }
0737:                try {
0738:                    checkForClosedStatement();
0739:                } catch (SqlException se) {
0740:                    throw se.getSQLException();
0741:                }
0742:                return warnings_ == null ? null : warnings_.getSQLWarning();
0743:            }
0744:
0745:            public void clearWarnings() throws SQLException {
0746:                synchronized (connection_) {
0747:                    if (agent_.loggingEnabled()) {
0748:                        agent_.logWriter_.traceEntry(this , "clearWarnings");
0749:                    }
0750:                    try {
0751:                        checkForClosedStatement();
0752:                    } catch (SqlException se) {
0753:                        throw se.getSQLException();
0754:                    }
0755:                    clearWarningsX();
0756:                }
0757:            }
0758:
0759:            // An untraced version of clearWarnings()
0760:            public void clearWarningsX() {
0761:                warnings_ = null;
0762:            }
0763:
0764:            // Dnc statements are already associated with a unique cursor name as defined
0765:            // by our canned dnc package set.
0766:            // ResultSet.getCursorName() should be used to
0767:            // obtain the for update cursor name to use when executing a positioned update statement.
0768:            // See Jdbc 3 spec section 14.2.4.4.
0769:            public void setCursorName(String name) throws SQLException {
0770:                try {
0771:                    synchronized (connection_) {
0772:                        if (agent_.loggingEnabled()) {
0773:                            agent_.logWriter_.traceEntry(this , "setCursorName",
0774:                                    name);
0775:                        }
0776:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0777:                        if (name == null || name.equals("")) {
0778:                            throw new SqlException(agent_.logWriter_,
0779:                                    new ClientMessageId(
0780:                                            SQLState.CURSOR_INVALID_NAME), name);
0781:                        }
0782:
0783:                        // Invalid to set the cursor name if there are ResultSet's open on the Statement.
0784:                        if (resultSet_ != null && resultSet_.openOnClient_) {
0785:                            throw new SqlException(
0786:                                    agent_.logWriter_,
0787:                                    new ClientMessageId(
0788:                                            SQLState.LANG_CANT_INVALIDATE_OPEN_RESULT_SET),
0789:                                    "setCursorName()", "Statement");
0790:                        }
0791:
0792:                        // DERBY-1036: Duplicate cursor names not allowed, check
0793:                        // deferred till execute time. 
0794:
0795:                        cursorName_ = name;
0796:                    }
0797:                } catch (SqlException se) {
0798:                    throw se.getSQLException();
0799:                }
0800:            }
0801:
0802:            //----------------------- Multiple Results --------------------------
0803:
0804:            public boolean execute(String sql) throws SQLException {
0805:                try {
0806:                    synchronized (connection_) {
0807:                        if (agent_.loggingEnabled()) {
0808:                            agent_.logWriter_.traceEntry(this , "execute", sql);
0809:                        }
0810:                        boolean b = executeX(sql);
0811:                        if (agent_.loggingEnabled()) {
0812:                            agent_.logWriter_.traceExit(this , "execute", b);
0813:                        }
0814:                        return b;
0815:                    }
0816:                } catch (SqlException se) {
0817:                    throw se.getSQLException();
0818:                }
0819:            }
0820:
0821:            boolean executeX(String sql) throws SqlException {
0822:                flowExecute(executeMethod__, sql);
0823:                return resultSet_ != null;
0824:            }
0825:
0826:            public java.sql.ResultSet getResultSet() throws SQLException {
0827:                try {
0828:                    synchronized (connection_) {
0829:                        if (agent_.loggingEnabled()) {
0830:                            agent_.logWriter_.traceEntry(this , "getResultSet");
0831:                        }
0832:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0833:                        if (agent_.loggingEnabled()) {
0834:                            agent_.logWriter_.traceExit(this , "getResultSet",
0835:                                    resultSet_);
0836:                        }
0837:                        return resultSet_;
0838:                    }
0839:                } catch (SqlException se) {
0840:                    throw se.getSQLException();
0841:                }
0842:            }
0843:
0844:            public int getUpdateCount() throws SQLException {
0845:                try {
0846:                    synchronized (connection_) {
0847:                        if (agent_.loggingEnabled()) {
0848:                            agent_.logWriter_
0849:                                    .traceEntry(this , "getUpdateCount");
0850:                        }
0851:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0852:                        if (agent_.loggingEnabled()) {
0853:                            agent_.logWriter_.traceExit(this , "getUpdateCount",
0854:                                    updateCount_);
0855:                        }
0856:                        return updateCount_;
0857:                    }
0858:                } catch (SqlException se) {
0859:                    throw se.getSQLException();
0860:                }
0861:            }
0862:
0863:            public boolean getMoreResults() throws SQLException {
0864:                try {
0865:                    synchronized (connection_) {
0866:                        if (agent_.loggingEnabled()) {
0867:                            agent_.logWriter_
0868:                                    .traceEntry(this , "getMoreResults");
0869:                        }
0870:                        boolean resultIsResultSet = getMoreResultsX(CLOSE_ALL_RESULTS);
0871:                        if (agent_.loggingEnabled()) {
0872:                            agent_.logWriter_.traceExit(this , "getMoreResults",
0873:                                    resultIsResultSet);
0874:                        }
0875:                        return resultIsResultSet;
0876:                    }
0877:                } catch (SqlException se) {
0878:                    throw se.getSQLException();
0879:                }
0880:            }
0881:
0882:            //--------------------------JDBC 2.0-----------------------------
0883:
0884:            public void setFetchDirection(int direction) throws SQLException {
0885:                try {
0886:                    synchronized (connection_) {
0887:                        if (agent_.loggingEnabled()) {
0888:                            agent_.logWriter_.traceEntry(this ,
0889:                                    "setFetchDirection", direction);
0890:                        }
0891:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0892:                        switch (direction) {
0893:                        case java.sql.ResultSet.FETCH_FORWARD:
0894:                        case java.sql.ResultSet.FETCH_REVERSE:
0895:                        case java.sql.ResultSet.FETCH_UNKNOWN:
0896:                            fetchDirection_ = direction;
0897:                            break;
0898:                        default:
0899:                            throw new SqlException(agent_.logWriter_,
0900:                                    new ClientMessageId(
0901:                                            SQLState.INVALID_FETCH_DIRECTION),
0902:                                    new Integer(direction));
0903:                        }
0904:                    }
0905:                } catch (SqlException se) {
0906:                    throw se.getSQLException();
0907:                }
0908:            }
0909:
0910:            public int getFetchDirection() throws SQLException {
0911:                try {
0912:                    checkForClosedStatement();
0913:                    if (agent_.loggingEnabled()) {
0914:                        agent_.logWriter_.traceExit(this , "getFetchDirection",
0915:                                fetchDirection_);
0916:                    }
0917:                    return fetchDirection_;
0918:                } catch (SqlException se) {
0919:                    throw se.getSQLException();
0920:                }
0921:            }
0922:
0923:            public void setFetchSize(int rows) throws SQLException {
0924:                try {
0925:                    synchronized (connection_) {
0926:                        if (agent_.loggingEnabled()) {
0927:                            agent_.logWriter_.traceEntry(this , "setFetchSize",
0928:                                    rows);
0929:                        }
0930:                        checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
0931:
0932:                        if (rows < 0 || (maxRows_ != 0 && rows > maxRows_)) {
0933:                            throw new SqlException(agent_.logWriter_,
0934:                                    new ClientMessageId(
0935:                                            SQLState.INVALID_ST_FETCH_SIZE),
0936:                                    new Integer(rows)).getSQLException();
0937:                        }
0938:                        fetchSize_ = rows;
0939:                    }
0940:                } catch (SqlException se) {
0941:                    throw se.getSQLException();
0942:                }
0943:            }
0944:
0945:            public int getFetchSize() throws SQLException {
0946:                try {
0947:                    checkForClosedStatement();
0948:                    if (agent_.loggingEnabled()) {
0949:                        agent_.logWriter_.traceExit(this , "getFetchSize",
0950:                                fetchSize_);
0951:                    }
0952:                    return fetchSize_;
0953:                } catch (SqlException se) {
0954:                    throw se.getSQLException();
0955:                }
0956:            }
0957:
0958:            public int getResultSetConcurrency() throws SQLException {
0959:                try {
0960:                    checkForClosedStatement();
0961:                    if (agent_.loggingEnabled()) {
0962:                        agent_.logWriter_.traceExit(this ,
0963:                                "getResultSetConcurrency",
0964:                                resultSetConcurrency_);
0965:                    }
0966:                    return resultSetConcurrency_;
0967:                } catch (SqlException se) {
0968:                    throw se.getSQLException();
0969:                }
0970:            }
0971:
0972:            public int getResultSetType() throws SQLException {
0973:                try {
0974:                    checkForClosedStatement();
0975:                    if (agent_.loggingEnabled()) {
0976:                        agent_.logWriter_.traceExit(this , "getResultSetType",
0977:                                resultSetType_);
0978:                    }
0979:                    return resultSetType_;
0980:                } catch (SqlException se) {
0981:                    throw se.getSQLException();
0982:                }
0983:            }
0984:
0985:            public void addBatch(String sql) throws SQLException {
0986:                try {
0987:                    synchronized (connection_) {
0988:                        if (agent_.loggingEnabled()) {
0989:                            agent_.logWriter_.traceEntry(this , "addBatch", sql);
0990:                        }
0991:                        checkForClosedStatement();
0992:                        sql = connection_.nativeSQLX(sql);
0993:                        batch_.add(sql);
0994:                    }
0995:                } catch (SqlException se) {
0996:                    throw se.getSQLException();
0997:                }
0998:            }
0999:
1000:            public void clearBatch() throws SQLException {
1001:                try {
1002:                    synchronized (connection_) {
1003:                        if (agent_.loggingEnabled()) {
1004:                            agent_.logWriter_.traceEntry(this , "clearBatch");
1005:                        }
1006:                        checkForClosedStatement();
1007:                        batch_.clear();
1008:                    }
1009:                } catch (SqlException se) {
1010:                    throw se.getSQLException();
1011:                }
1012:            }
1013:
1014:            public int[] executeBatch() throws SQLException,
1015:                    BatchUpdateException {
1016:                try {
1017:                    synchronized (connection_) {
1018:                        if (agent_.loggingEnabled()) {
1019:                            agent_.logWriter_.traceEntry(this , "executeBatch");
1020:                        }
1021:                        int[] updateCounts = executeBatchX();
1022:                        if (agent_.loggingEnabled()) {
1023:                            agent_.logWriter_.traceExit(this , "executeBatch",
1024:                                    updateCounts);
1025:                        }
1026:                        return updateCounts;
1027:                    }
1028:                } catch (SqlException se) {
1029:                    throw se.getSQLException();
1030:                }
1031:            }
1032:
1033:            private int[] executeBatchX() throws SqlException,
1034:                    BatchUpdateException {
1035:                checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
1036:                clearWarningsX(); // Per jdbc spec 0.7, and getWarnings() javadoc
1037:                resultSetList_ = null;
1038:                // Initialize all the updateCounts to indicate failure
1039:                // This is done to account for "chain-breaking" errors where we cannot
1040:                // read any more replies
1041:                int[] updateCounts = new int[batch_.size()];
1042:                for (int i = 0; i < batch_.size(); i++) {
1043:                    updateCounts[i] = -3;
1044:                }
1045:                flowExecuteBatch(updateCounts);
1046:                return updateCounts;
1047:            }
1048:
1049:            public java.sql.Connection getConnection() throws SQLException {
1050:                try {
1051:                    checkForClosedStatement();
1052:                    if (agent_.loggingEnabled()) {
1053:                        agent_.logWriter_.traceExit(this , "getConnection",
1054:                                connection_);
1055:                    }
1056:                    return connection_;
1057:                } catch (SqlException se) {
1058:                    throw se.getSQLException();
1059:                }
1060:            }
1061:
1062:            //--------------------------JDBC 3.0-----------------------------
1063:
1064:            public boolean getMoreResults(int current) throws SQLException {
1065:                try {
1066:                    synchronized (connection_) {
1067:                        if (agent_.loggingEnabled()) {
1068:                            agent_.logWriter_.traceEntry(this ,
1069:                                    "getMoreResults", current);
1070:                        }
1071:                        boolean resultIsResultSet = getMoreResultsX(current);
1072:                        if (agent_.loggingEnabled()) {
1073:                            agent_.logWriter_.traceExit(this , "getMoreResults",
1074:                                    resultIsResultSet);
1075:                        }
1076:                        return resultIsResultSet;
1077:                    }
1078:                } catch (SqlException se) {
1079:                    throw se.getSQLException();
1080:                }
1081:            }
1082:
1083:            private boolean getMoreResultsX(int current) throws SqlException {
1084:                checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
1085:                boolean resultIsResultSet;
1086:                updateCount_ = -1;
1087:                if (resultSetList_ == null) {
1088:                    if (resultSet_ != null) {
1089:                        if (current != KEEP_CURRENT_RESULT) {
1090:                            resultSet_.closeX();
1091:                        }
1092:                        resultSet_ = null;
1093:                    }
1094:                    resultIsResultSet = false;
1095:                } else {
1096:                    if (numInvisibleRS_ == 0 && current == CLOSE_CURRENT_RESULT
1097:                            && resultSetList_[indexOfCurrentResultSet_] != null) {
1098:                        resultSetList_[indexOfCurrentResultSet_].closeX();
1099:                    }
1100:                    resultIsResultSet = indexOfCurrentResultSet_ + 1 < resultSetList_.length;
1101:                }
1102:                if ((current == CLOSE_ALL_RESULTS) && (numInvisibleRS_ == 0)) {
1103:                    int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
1104:                            : indexOfCurrentResultSet_ + 1;
1105:                    boolean willTickleServer = willTickleServer(
1106:                            numberOfResultSetsToClose, false);
1107:                    if (willTickleServer) {
1108:                        flowCloseRetrievedResultSets();
1109:                    } else {
1110:                        flowCloseRetrievedResultSetsOutsideUOW();
1111:                    }
1112:                }
1113:                if (resultIsResultSet) {
1114:                    resultSet_ = resultSetList_[++indexOfCurrentResultSet_];
1115:                } else {
1116:                    resultSet_ = null;
1117:                }
1118:
1119:                return resultIsResultSet;
1120:            }
1121:
1122:            public java.sql.ResultSet getGeneratedKeys() throws SQLException {
1123:                try {
1124:                    if (agent_.loggingEnabled()) {
1125:                        agent_.logWriter_.traceEntry(this , "getGeneratedKeys");
1126:                    }
1127:                    checkForClosedStatement();
1128:                    if (agent_.loggingEnabled()) {
1129:                        agent_.logWriter_.traceExit(this , "getGeneratedKeys",
1130:                                generatedKeysResultSet_);
1131:                    }
1132:                    return generatedKeysResultSet_;
1133:                } catch (SqlException se) {
1134:                    throw se.getSQLException();
1135:                }
1136:            }
1137:
1138:            public int executeUpdate(String sql, int autoGeneratedKeys)
1139:                    throws SQLException {
1140:                try {
1141:                    synchronized (connection_) {
1142:                        if (agent_.loggingEnabled()) {
1143:                            agent_.logWriter_.traceEntry(this , "executeUpdate",
1144:                                    sql, autoGeneratedKeys);
1145:                        }
1146:                        autoGeneratedKeys_ = autoGeneratedKeys;
1147:                        int updateValue = executeUpdateX(sql);
1148:                        if (agent_.loggingEnabled()) {
1149:                            agent_.logWriter_.traceExit(this , "executeUpdate",
1150:                                    updateValue);
1151:                        }
1152:                        return updateValue;
1153:                    }
1154:                } catch (SqlException se) {
1155:                    throw se.getSQLException();
1156:                }
1157:            }
1158:
1159:            public int executeUpdate(String sql, int columnIndexes[])
1160:                    throws SQLException {
1161:                try {
1162:                    if (agent_.loggingEnabled()) {
1163:                        agent_.logWriter_.traceEntry(this , "executeUpdate",
1164:                                sql, columnIndexes);
1165:                    }
1166:                    checkForClosedStatement();
1167:                    throw new SqlException(agent_.logWriter_,
1168:                            new ClientMessageId(SQLState.NOT_IMPLEMENTED),
1169:                            "executeUpdate(String, int[])");
1170:                } catch (SqlException se) {
1171:                    throw se.getSQLException();
1172:                }
1173:            }
1174:
1175:            public int executeUpdate(String sql, String columnNames[])
1176:                    throws SQLException {
1177:                try {
1178:                    synchronized (connection_) {
1179:                        if (agent_.loggingEnabled()) {
1180:                            agent_.logWriter_.traceEntry(this , "executeUpdate",
1181:                                    sql, columnNames);
1182:                        }
1183:                        generatedKeysColumnNames_ = columnNames;
1184:                        int updateValue = executeUpdateX(sql);
1185:                        if (agent_.loggingEnabled()) {
1186:                            agent_.logWriter_.traceExit(this , "executeUpdate",
1187:                                    updateValue);
1188:                        }
1189:                        return updateValue;
1190:                    }
1191:                } catch (SqlException se) {
1192:                    throw se.getSQLException();
1193:                }
1194:            }
1195:
1196:            public boolean execute(String sql, int autoGeneratedKeys)
1197:                    throws SQLException {
1198:                try {
1199:                    synchronized (connection_) {
1200:                        if (agent_.loggingEnabled()) {
1201:                            agent_.logWriter_.traceEntry(this , "execute", sql,
1202:                                    autoGeneratedKeys);
1203:                        }
1204:                        autoGeneratedKeys_ = autoGeneratedKeys;
1205:                        boolean b = executeX(sql);
1206:                        if (agent_.loggingEnabled()) {
1207:                            agent_.logWriter_.traceExit(this , "execute", b);
1208:                        }
1209:                        return b;
1210:                    }
1211:                } catch (SqlException se) {
1212:                    throw se.getSQLException();
1213:                }
1214:            }
1215:
1216:            public boolean execute(String sql, int columnIndexes[])
1217:                    throws SQLException {
1218:                try {
1219:                    if (agent_.loggingEnabled()) {
1220:                        agent_.logWriter_.traceEntry(this , "execute", sql,
1221:                                columnIndexes);
1222:                    }
1223:                    checkForClosedStatement();
1224:                    throw new SqlException(agent_.logWriter_,
1225:                            new ClientMessageId(SQLState.NOT_IMPLEMENTED),
1226:                            "execute(String, int[])");
1227:                } catch (SqlException se) {
1228:                    throw se.getSQLException();
1229:                }
1230:            }
1231:
1232:            public boolean execute(String sql, String columnNames[])
1233:                    throws SQLException {
1234:                try {
1235:                    synchronized (connection_) {
1236:                        if (agent_.loggingEnabled()) {
1237:                            agent_.logWriter_.traceEntry(this , "execute", sql,
1238:                                    columnNames);
1239:                        }
1240:                        generatedKeysColumnNames_ = columnNames;
1241:                        boolean b = executeX(sql);
1242:                        if (agent_.loggingEnabled()) {
1243:                            agent_.logWriter_.traceExit(this , "execute", b);
1244:                        }
1245:                        return b;
1246:                    }
1247:                } catch (SqlException se) {
1248:                    throw se.getSQLException();
1249:                }
1250:            }
1251:
1252:            public int getResultSetHoldability() throws SQLException {
1253:                try {
1254:                    if (agent_.loggingEnabled()) {
1255:                        agent_.logWriter_.traceEntry(this ,
1256:                                "getResultSetHoldability");
1257:                    }
1258:                    checkForClosedStatement();
1259:                    return resultSetHoldability_;
1260:                } catch (SqlException se) {
1261:                    throw se.getSQLException();
1262:                }
1263:            }
1264:
1265:            // ----------------------- box car and callback methods ---------------------
1266:            // All callbacks must be client-side only operations.
1267:            // Use of MaterialStatement interface is necessary to avoid multiple inheritance problem in Java.
1268:            public void writeSetSpecialRegister(java.util.ArrayList sqlsttList)
1269:                    throws SqlException {
1270:                materialStatement_.writeSetSpecialRegister_(sqlsttList);
1271:            }
1272:
1273:            public void readSetSpecialRegister() throws SqlException {
1274:                materialStatement_.readSetSpecialRegister_();
1275:            }
1276:
1277:            public void writeExecuteImmediate(String sql, Section section)
1278:                    throws SqlException {
1279:                materialStatement_.writeExecuteImmediate_(sql, section);
1280:            }
1281:
1282:            public void readExecuteImmediate() throws SqlException {
1283:                materialStatement_.readExecuteImmediate_();
1284:            }
1285:
1286:            public void completeExecuteImmediate(Sqlca sqlca) {
1287:                int sqlcode = completeSqlca(sqlca);
1288:                if (sqlcode < 0) {
1289:                    return;
1290:                }
1291:                if (sqlca != null) {
1292:                    updateCount_ = sqlca.getUpdateCount();
1293:                }
1294:            }
1295:
1296:            public void readExecuteImmediateForBatch(String sql)
1297:                    throws SqlException {
1298:                materialStatement_.readExecuteImmediateForBatch_(sql);
1299:            }
1300:
1301:            public void writePrepareDescribeOutput(String sql, Section section)
1302:                    throws SqlException {
1303:                materialStatement_.writePrepareDescribeOutput_(sql, section);
1304:            }
1305:
1306:            public void readPrepareDescribeOutput() throws SqlException {
1307:                materialStatement_.readPrepareDescribeOutput_();
1308:            }
1309:
1310:            public void completePrepareDescribeOutput(
1311:                    ColumnMetaData resultSetMetaData, Sqlca sqlca) {
1312:                completePrepare(sqlca);
1313:                resultSetMetaData_ = resultSetMetaData;
1314:                if (agent_.loggingEnabled()) {
1315:                    agent_.logWriter_.traceResultSetMetaData(this ,
1316:                            resultSetMetaData_);
1317:                }
1318:            }
1319:
1320:            // Used for re-prepares across commit only
1321:            public void writePrepare(String sql, Section section)
1322:                    throws SqlException {
1323:                materialStatement_.writePrepare_(sql, section);
1324:            }
1325:
1326:            public void readPrepare() throws SqlException {
1327:                materialStatement_.readPrepare_();
1328:            }
1329:
1330:            public void completePrepare(Sqlca sqlca) {
1331:                int sqlcode = completeSqlca(sqlca);
1332:                if (sqlcode < 0) {
1333:                    return;
1334:                }
1335:                markPrepared();
1336:            }
1337:
1338:            public void writeOpenQuery(Section section, int fetchSize,
1339:                    int resultSetType) throws SqlException {
1340:                materialStatement_.writeOpenQuery_(section, fetchSize,
1341:                        resultSetType);
1342:            }
1343:
1344:            public void readOpenQuery() throws SqlException {
1345:                materialStatement_.readOpenQuery_();
1346:            }
1347:
1348:            public void completeOpenQuery(Sqlca sqlca, ResultSet resultSet) {
1349:                completeSqlca(sqlca);
1350:                resultSet_ = resultSet;
1351:                // For NET, resultSet_ == null when open query fails and receives OPNQFLRM.
1352:                // Then, in NetStatementReply.parseOpenQueryFailure(), completeOpenQuery() is
1353:                // invoked with resultSet explicitly set to null.
1354:                if (resultSet == null) {
1355:                    return;
1356:                }
1357:                resultSet.resultSetMetaData_ = resultSetMetaData_;
1358:                resultSet.resultSetMetaData_.resultSetConcurrency_ = resultSet.resultSetConcurrency_;
1359:
1360:                // only cache the Cursor object for a PreparedStatement and if a Cursor object is
1361:                // not already cached.
1362:                if (cachedCursor_ == null && isPreparedStatement_) {
1363:                    cachedCursor_ = resultSet_.cursor_;
1364:                }
1365:
1366:                // The following two assignments should have already happened via prepareEvent(),
1367:                // but are included here for safety for the time being.
1368:                if (sqlca != null && sqlca.getSqlCode() < 0) {
1369:                    return;
1370:                }
1371:                openOnServer_ = true;
1372:                resultSet.cursor_.rowsRead_ = 0;
1373:
1374:                // Set fetchSize_ to the default(64) if not set by the user if the resultset is scrollable.
1375:                // This fetchSize_ is used to check for a complete rowset when rowsets are parsed.
1376:                // For scrollable cursors when the fetchSize_ is not set, (fetchSize_ == 0), a default
1377:                // fetchSize of 64 is sent on behalf of the application, so we need to update the fetchSize_
1378:                // here to 64.
1379:                if (resultSet_.fetchSize_ == 0
1380:                        && (resultSet_.resultSetType_ == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE || resultSet_.resultSetType_ == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE)) {
1381:                    resultSet_
1382:                            .setFetchSize_(org.apache.derby.client.am.Configuration.defaultFetchSize);
1383:                }
1384:            }
1385:
1386:            public void completeExecuteCallOpenQuery(Sqlca sqlca,
1387:                    ResultSet resultSet, ColumnMetaData resultSetMetaData,
1388:                    Section generatedSection) {
1389:                resultSet.completeSqlca(sqlca);
1390:                // For CallableStatements we can't just clobber the resultSet_ here, must use setResultSetEvent() separately
1391:                resultSet.resultSetMetaData_ = resultSetMetaData;
1392:
1393:                // The following two assignments should have already happened via prepareEvent(),
1394:                // but are included here for safety for the time being.
1395:                if (sqlca != null && sqlca.getSqlCode() < 0) {
1396:                    return;
1397:                }
1398:                openOnServer_ = true;
1399:                resultSet.cursor_.rowsRead_ = 0;
1400:
1401:                resultSet.generatedSection_ = generatedSection;
1402:
1403:                // We are always sending the default fetchSize of 64 if not set for stored procedure calls.
1404:                // This is different from the "normal" cursor case for forward_only cursors, where if
1405:                // fetchSize_ is not set, we do not send any default value.  Here since we always send
1406:                // the fetchSize_, we need to set it to what we sent.
1407:                if (resultSet.fetchSize_ == 0) {
1408:                    resultSet.fetchSize_ = org.apache.derby.client.am.Configuration.defaultFetchSize;
1409:                }
1410:            }
1411:
1412:            public void writeExecuteCall(boolean outputExpected,
1413:                    String procedureName, Section section,
1414:                    int fetchSize,
1415:                    boolean suppressResultSets, // for batch updates == true
1416:                    int resultSetType, ColumnMetaData parameterMetaData,
1417:                    Object[] inputs) throws SqlException {
1418:                materialStatement_.writeExecuteCall_(outputExpected,
1419:                        procedureName, section, fetchSize, suppressResultSets,
1420:                        resultSetType, parameterMetaData, inputs);
1421:            }
1422:
1423:            public void readExecuteCall() throws SqlException {
1424:                materialStatement_.readExecuteCall_();
1425:            }
1426:
1427:            public void completeExecuteCall(Sqlca sqlca,
1428:                    Cursor singletonParams, ResultSet[] resultSets) {
1429:                completeExecuteCall(sqlca, singletonParams);
1430:                resultSetList_ = resultSets;
1431:                if (resultSets != null) {
1432:                    resultSet_ = resultSets[0];
1433:                }
1434:                indexOfCurrentResultSet_ = 0;
1435:            }
1436:
1437:            public void completeExecuteCall(Sqlca sqlca, Cursor singletonParams) // no result sets returned
1438:            {
1439:                completeExecute(sqlca);
1440:                //if ((sqlca != null) && ((sqlca.getSqlCode() < 0) || (sqlca.getSqlCode() == 100)))
1441:                if (sqlca != null && sqlca.getSqlCode() < 0) {
1442:                    singletonRowData_ = null;
1443:                } else {
1444:                    singletonRowData_ = singletonParams;
1445:                    if (cachedSingletonRowData_ == null && isPreparedStatement_) {
1446:                        cachedSingletonRowData_ = singletonRowData_;
1447:                    }
1448:                }
1449:            }
1450:
1451:            // Callback for CALLS, and PreparedStatement updates.
1452:            public void completeExecute(Sqlca sqlca) {
1453:                if (sqlca == null) {
1454:                    return;
1455:                }
1456:
1457:                int sqlcode = sqlca.getSqlCode();
1458:                if (sqlcode < 0) {
1459:                    agent_.accumulateReadException(new SqlException(
1460:                            agent_.logWriter_, sqlca));
1461:                    returnValueFromProcedure_ = sqlcode;
1462:                } else {
1463:                    updateCount_ = sqlca.getUpdateCount();
1464:                    // sometime for call statement, protocol will return updateCount_, we will always set that to 0
1465:                    // sqlMode_ is not set for statements, only for prepared statements
1466:                    if (sqlMode_ == isCall__) {
1467:                        updateCount_ = -1;
1468:                        returnValueFromProcedure_ = sqlca.getSqlErrd()[0]; ////what is this for??
1469:                    }
1470:                    // Sqlcode 466 indicates a call statement has issued and result sets returned.
1471:                    // This is a good place to set some state variable to indicate result sets are open
1472:                    // for call, so that when autocommit is true, commit will not be issued until the
1473:                    // result sets are closed.
1474:                    // Currently, commit is not issued even there is no result set.
1475:                    // do not externalize sqlcode +100
1476:                    if (sqlcode > 0 && sqlcode != 466 && sqlcode != 100) {
1477:                        accumulateWarning(new SqlWarning(agent_.logWriter_,
1478:                                sqlca));
1479:                    }
1480:                }
1481:            }
1482:
1483:            public void setUpdateCount(int updateCount) {
1484:                updateCount_ = updateCount;
1485:            }
1486:
1487:            private boolean willTickleServer(int number,
1488:                    boolean allowAutoCommits) throws SqlException {
1489:                boolean requiresAutocommit = false;
1490:                if (resultSetList_ != null) {
1491:                    for (int i = 0; i < number; i++) {
1492:                        if (resultSetList_[i] != null) {
1493:                            if (resultSetList_[i].openOnServer_) {
1494:                                return true; // for the writeClose flow
1495:                            }
1496:                            if (!resultSetList_[i].autoCommitted_
1497:                                    && allowAutoCommits) {
1498:                                requiresAutocommit = true; // for the commit flow
1499:                            }
1500:                        }
1501:                    }
1502:                } else if (generatedKeysResultSet_ != null
1503:                        && generatedKeysResultSet_.openOnServer_) {
1504:                    generatedKeysResultSet_.writeClose();
1505:                } else if (resultSet_ != null) {
1506:                    if (resultSet_.openOnServer_) {
1507:                        return true; // for the writeClose flow
1508:                    }
1509:                    if (!resultSet_.autoCommitted_ && allowAutoCommits) {
1510:                        requiresAutocommit = true;
1511:                    }
1512:                }
1513:                if (connection_.autoCommit_ && requiresAutocommit) { // for the auto-commit;
1514:                    if (connection_.isXAConnection_) {
1515:                        return (connection_.getXAState() == Connection.XA_T0_NOT_ASSOCIATED);
1516:                    } else {
1517:                        return true;
1518:                    }
1519:                }
1520:                return false;
1521:            }
1522:
1523:            private void flowClose() throws SqlException {
1524:                agent_.beginWriteChain(this );
1525:                writeClose(true); // true means permit auto-commits
1526:                agent_.flow(this );
1527:                readClose(true); // true means permit auto-commits
1528:                agent_.endReadChain();
1529:            }
1530:
1531:            private void flowCloseOutsideUOW() throws SqlException {
1532:                agent_.beginWriteChainOutsideUOW();
1533:                writeClose(true); // true means permit auto-commits
1534:                agent_.flowOutsideUOW();
1535:                readClose(true); // true means permit auto-commits
1536:                agent_.endReadChain();
1537:            }
1538:
1539:            final void writeClose(boolean allowAutoCommits) throws SqlException {
1540:                writeCloseResultSets(allowAutoCommits);
1541:            }
1542:
1543:            final void readClose(boolean allowAutoCommits) throws SqlException {
1544:                readCloseResultSets(allowAutoCommits);
1545:            }
1546:
1547:            boolean writeCloseResultSets(boolean allowAutoCommits)
1548:                    throws SqlException {
1549:                int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
1550:                        : resultSetList_.length;
1551:                return writeCloseResultSets(numberOfResultSetsToClose,
1552:                        allowAutoCommits);
1553:            }
1554:
1555:            // The connection close processing passes allowAutoCommits=false because if we drove an
1556:            // autocommits after each statement close, then when we issue close requests on non-held cursors
1557:            // the server would complain that the non-held cursor was already closed from the previous statement's auto-commit.
1558:            // So the solution is to never autocommit statements during connection close processing.
1559:            //
1560:            // Here's the operative explanation:
1561:            // Given a sequence of open statements S1, S2, .... a logic problem is occuring after S1 close-query
1562:            // drives an auto-commit, and S2 close-query is driven against a non-held cursor.
1563:            // The first auto-commit driven by S1 triggers a callback that closes S2's non-held cursor,
1564:            // and so the subsequent S2 close-query request generates an error from the server saying
1565:            // that the cursor is already closed.
1566:            //
1567:            // This is fixed by passing a flag to our statement close processing that prevents
1568:            // driving additional auto-commits after each statement close.
1569:            // Connectino close drives its own final auto-commit.
1570:            //
1571:            boolean writeCloseResultSets(int number, boolean allowAutoCommits)
1572:                    throws SqlException {
1573:                boolean requiresAutocommit = false;
1574:                if (resultSetList_ != null) {
1575:                    for (int i = 0; i < number; i++) {
1576:                        if (resultSetList_[i] != null) {
1577:                            if (resultSetList_[i].openOnServer_) {
1578:                                resultSetList_[i].writeClose();
1579:                            }
1580:                            if (!resultSetList_[i].autoCommitted_
1581:                                    && allowAutoCommits) {
1582:                                requiresAutocommit = true;
1583:                            }
1584:                        }
1585:                    }
1586:                } else if (generatedKeysResultSet_ != null
1587:                        && generatedKeysResultSet_.openOnServer_) {
1588:                    generatedKeysResultSet_.writeClose();
1589:                } else if (resultSet_ != null) {
1590:                    if (resultSet_.openOnServer_) {
1591:                        resultSet_.writeClose();
1592:                    }
1593:                    if (!resultSet_.autoCommitted_ && allowAutoCommits) {
1594:                        requiresAutocommit = true;
1595:                    }
1596:                }
1597:                if (connection_.autoCommit_ && requiresAutocommit
1598:                        && isAutoCommittableStatement_) {
1599:                    connection_.writeAutoCommit();
1600:                    if (connection_.isXAConnection_) {
1601:                        return (connection_.getXAState() == Connection.XA_T0_NOT_ASSOCIATED);
1602:                    } else {
1603:                        return true;
1604:                    }
1605:                }
1606:                return false;
1607:            }
1608:
1609:            // Helper method for S.flowCloseResultSets() and PS.flowExecute()
1610:            void readCloseResultSets(boolean allowAutoCommits)
1611:                    throws SqlException {
1612:                int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
1613:                        : resultSetList_.length;
1614:                readCloseResultSets(numberOfResultSetsToClose, allowAutoCommits);
1615:            }
1616:
1617:            void readCloseResultSets(int number, boolean allowAutoCommits)
1618:                    throws SqlException {
1619:                boolean requiredAutocommit = false;
1620:                if (resultSetList_ != null) {
1621:                    for (int i = 0; i < number; i++) {
1622:                        if (resultSetList_[i] != null) {
1623:                            if (resultSetList_[i].openOnServer_) {
1624:                                resultSetList_[i].readClose();
1625:                            } else {
1626:                                resultSetList_[i].markClosed();
1627:                            }
1628:                            if (!resultSetList_[i].autoCommitted_
1629:                                    && allowAutoCommits) {
1630:                                requiredAutocommit = true;
1631:                            }
1632:                        }
1633:                    }
1634:                } else if (generatedKeysResultSet_ != null) {
1635:                    if (generatedKeysResultSet_.openOnServer_) {
1636:                        generatedKeysResultSet_.readClose();
1637:                    } else {
1638:                        generatedKeysResultSet_.markClosed();
1639:                    }
1640:                } else if (resultSet_ != null) {
1641:                    if (resultSet_.openOnServer_) {
1642:                        resultSet_.readClose();
1643:                    } else {
1644:                        resultSet_.markClosed();
1645:                    }
1646:                    if (!resultSet_.autoCommitted_ && allowAutoCommits) {
1647:                        requiredAutocommit = true;
1648:                    }
1649:                }
1650:                // we only commit when auto commit is turned on and at least one result set needed closing on server.
1651:                if (connection_.autoCommit_ && requiredAutocommit
1652:                        && isAutoCommittableStatement_) {
1653:                    connection_.readAutoCommit();
1654:                }
1655:            }
1656:
1657:            private void flowCloseRetrievedResultSets() throws SqlException {
1658:                int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
1659:                        : indexOfCurrentResultSet_ + 1;
1660:                agent_.beginWriteChain(this );
1661:                // Need to refactor the ResultSet.readClose() path to check if we are the
1662:                // last result set closed in a set of multiple result sets of the owning statement,
1663:                // if so, we need to flow the auto-commit (but only then).
1664:                // currently, the code to do this is only in the closeX() path, which isn't called here
1665:                writeCloseResultSets(numberOfResultSetsToClose, false);
1666:                agent_.flow(this );
1667:                readCloseResultSets(numberOfResultSetsToClose, false); // true means permit auto-commits
1668:                agent_.endReadChain();
1669:            }
1670:
1671:            private void flowCloseRetrievedResultSetsOutsideUOW()
1672:                    throws SqlException {
1673:                int numberOfResultSetsToClose = (resultSetList_ == null) ? 0
1674:                        : indexOfCurrentResultSet_ + 1;
1675:                agent_.beginWriteChainOutsideUOW();
1676:                // Need to refactor the ResultSet.readClose() path to check if we are the
1677:                // last result set closed in a set of multiple result sets of the owning statement,
1678:                // if so, we need to flow the auto-commit (but only then).
1679:                // currently, the code to do this is only in the closeX() path, which isn't called here
1680:                writeCloseResultSets(numberOfResultSetsToClose, false);
1681:                agent_.flowOutsideUOW();
1682:                readCloseResultSets(numberOfResultSetsToClose, false); // true means permit auto-commits
1683:                agent_.endReadChain();
1684:            }
1685:
1686:            public int completeSqlca(Sqlca sqlca) {
1687:                if (sqlca == null) {
1688:                    return 0;
1689:                }
1690:                int sqlcode = sqlca.getSqlCode();
1691:                if (sqlcode < 0) {
1692:                    connection_.agent_
1693:                            .accumulateReadException(new SqlException(
1694:                                    agent_.logWriter_, sqlca));
1695:                } else if (sqlcode > 0) {
1696:                    accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca));
1697:                }
1698:                return sqlcode;
1699:            }
1700:
1701:            public void completeExecuteSetStatement(Sqlca sqlca) {
1702:            }
1703:
1704:            void markClosedOnServer() {
1705:                if (section_ != null) {
1706:                    section_.free();
1707:                    section_ = null;
1708:                }
1709:                openOnServer_ = false;
1710:                // if an error occurs during the middle of the reset, before the statement
1711:                // has a chance to reset its materialStatement_, and Agent.disconnectEvent() is called,
1712:                // then the materialStatement_ here can be null.
1713:                if (materialStatement_ != null) {
1714:                    materialStatement_.markClosedOnServer_();
1715:                }
1716:            }
1717:
1718:            /**
1719:             * This method cleans up client-side resources held by this Statement. 
1720:             * The Statement will not be removed from the open statements list and 
1721:             * PreparedStatement will also not be removed from the commit and rollback 
1722:             * listeners list in <code>org.apache.derby.client.am.Connection</code>.
1723:             * 
1724:             * This method is called from:
1725:             * 1. finalize() - For the finaizer to be called, the Statement 
1726:             * should not have any references and so it should have been already 
1727:             * removed from the lists.  
1728:             * 
1729:             * 2. <code>org.apache.derby.client.am.Connection#markStatementsClosed</code> 
1730:             * This method explicitly removes the Statement from open statements list.
1731:             *  
1732:             * 3. To close positioned update statements - These statements are not
1733:             * added to the list of open statements.
1734:             */
1735:            void markClosed() {
1736:                markClosed(false);
1737:            }
1738:
1739:            /**
1740:             * This method cleans up client-side resources held by this Statement. 
1741:             * If removeListener is true, the Statement is removed from open statements
1742:             * list and PreparedStatement is also removed from commit and rollback 
1743:             * listeners list. This is called from the close methods.
1744:             * 
1745:             * @param removeListener if true the Statement will be removed
1746:             * from the open statements list and PreparedStatement will also be removed
1747:             * from commit and rollback listeners list in 
1748:             * <code>org.apache.derby.client.am.Connection</code>.
1749:             */
1750:            void markClosed(boolean removeListener) {
1751:                openOnClient_ = false;
1752:                markResultSetsClosed();
1753:                // in case a cursorName was set on the Statement but the Statement was
1754:                // never used to execute a query, the cursorName will not be removed
1755:                // when the resultSets are mark closed, so we need to remove the
1756:                // cursorName form the cache.
1757:                removeClientCursorNameFromCache();
1758:                markPreparedStatementForAutoGeneratedKeysClosed();
1759:                markClosedOnServer();
1760:
1761:                // mark close ResultSetMetaData
1762:                if (resultSetMetaData_ != null) {
1763:                    resultSetMetaData_.markClosed();
1764:                    resultSetMetaData_ = null;
1765:                }
1766:
1767:                if (removeListener)
1768:                    connection_.openStatements_.remove(this );
1769:            }
1770:
1771:            void markPreparedStatementForAutoGeneratedKeysClosed() {
1772:                if (preparedStatementForAutoGeneratedKeys_ != null) {
1773:                    preparedStatementForAutoGeneratedKeys_.markClosed();
1774:                }
1775:            }
1776:
1777:            /**
1778:             * Mark all ResultSets associated with this statement as
1779:             * closed. The ResultSets will not be removed from the commit and
1780:             * rollback listeners list in
1781:             * <code>org.apache.derby.client.am.Connection</code>.
1782:             */
1783:            void markResultSetsClosed() {
1784:                markResultSetsClosed(false);
1785:            }
1786:
1787:            /**
1788:             * Mark all ResultSets associated with this statement as
1789:             * closed.
1790:             *
1791:             * @param removeListener if true the ResultSets will be removed
1792:             * from the commit and rollback listeners list in
1793:             * <code>org.apache.derby.client.am.Connection</code>.
1794:             */
1795:            void markResultSetsClosed(boolean removeListener) {
1796:                if (resultSetList_ != null) {
1797:                    for (int i = 0; i < resultSetList_.length; i++) {
1798:                        if (resultSetList_[i] != null) {
1799:                            resultSetList_[i].markClosed(removeListener);
1800:                        }
1801:                        resultSetList_[i] = null;
1802:                    }
1803:                }
1804:                if (generatedKeysResultSet_ != null) {
1805:                    generatedKeysResultSet_.markClosed(removeListener);
1806:                }
1807:                if (resultSet_ != null) {
1808:                    resultSet_.markClosed(removeListener);
1809:                }
1810:                resultSet_ = null;
1811:                resultSetList_ = null;
1812:                generatedKeysResultSet_ = null;
1813:            }
1814:
1815:            private void flowExecute(int executeType, String sql)
1816:                    throws SqlException {
1817:                checkForClosedStatement(); // Per jdbc spec (see java.sql.Statement.close() javadoc)
1818:                checkAutoGeneratedKeysParameters();
1819:                clearWarningsX(); // Per jdbc spec 0.7, and getWarnings() javadoc
1820:
1821:                sql = escape(sql);
1822:                parseSqlAndSetSqlModes(sql);
1823:                if (sqlMode_ == isUpdate__) {
1824:                    updateCount_ = 0;
1825:                } else {
1826:                    updateCount_ = -1;
1827:                }
1828:
1829:                checkForAppropriateSqlMode(executeType, sqlMode_);
1830:
1831:                // DERBY-1036: Moved check till execute time to comply with embedded
1832:                // behavior. Since we check here and not in setCursorName, several
1833:                // statements can have the same cursor name as long as their result
1834:                // sets are not simultaneously open.
1835:
1836:                if (sqlMode_ == isQuery__) {
1837:                    checkForDuplicateCursorName();
1838:                }
1839:
1840:                boolean timeoutSent = false;
1841:
1842:                agent_.beginWriteChain(this );
1843:                boolean piggybackedAutoCommit = writeCloseResultSets(true); // true means permit auto-commits
1844:
1845:                ResultSet scrollableRS = null;
1846:                Section newSection = null;
1847:                boolean repositionedCursor = false;
1848:
1849:                // DERBY-1692: Statement objects need to send the timeout value for
1850:                // each execution since the server will create a new statement
1851:                // object each time. Since the server forgets the timeout value,
1852:                // doWriteTimeout should not be reset, and it is OK not to send the
1853:                // timeout value when it is zero.
1854:                if (doWriteTimeout && (timeout_ > 0)) {
1855:                    timeoutArrayList.set(0, TIMEOUT_STATEMENT + timeout_);
1856:                    writeSetSpecialRegister(timeoutArrayList);
1857:                    timeoutSent = true;
1858:                }
1859:                switch (sqlMode_) {
1860:                case isQuery__:
1861:                    newSection = agent_.sectionManager_
1862:                            .getDynamicSection(resultSetHoldability_);
1863:
1864:                    writePrepareDescribeOutput(sql, newSection);
1865:                    writeOpenQuery(newSection, fetchSize_, resultSetType_);
1866:                    break;
1867:                case isUpdate__:
1868:                    String cursorName = null;
1869:                    if (sqlUpdateMode_ == isDeleteSql__
1870:                            || sqlUpdateMode_ == isUpdateSql__) {
1871:                        String[] sqlAndCursorName = extractCursorNameFromWhereCurrentOf(sql);
1872:                        if (sqlAndCursorName != null) {
1873:                            cursorName = sqlAndCursorName[0];
1874:                            sql = sqlAndCursorName[1];
1875:                        }
1876:                    }
1877:                    if (cursorName != null) {
1878:                        newSection = agent_.sectionManager_
1879:                                .getPositionedUpdateSection(cursorName, true); // true means get an execute immediate section
1880:                        if (newSection == null) {
1881:                            throw new SqlException(agent_.logWriter_,
1882:                                    new ClientMessageId(
1883:                                            SQLState.CURSOR_INVALID_NAME),
1884:                                    cursorName);
1885:                        }
1886:                        scrollableRS = agent_.sectionManager_
1887:                                .getPositionedUpdateResultSet(cursorName);
1888:                        // do not need to reposition for rowset cursors
1889:                        if (scrollableRS != null
1890:                                && !scrollableRS.isRowsetCursor_) {
1891:                            repositionedCursor = scrollableRS
1892:                                    .repositionScrollableResultSetBeforeJDBC1PositionedUpdateDelete();
1893:                            if (!repositionedCursor) {
1894:                                scrollableRS = null;
1895:                            }
1896:                        }
1897:
1898:                        // if client's cursor name is set, and the cursor name in the positioned update
1899:                        // string is the same as the client's cursor name, replace client's cursor name
1900:                        // with the server's cursor name.
1901:                        if (newSection.getClientCursorName() != null
1902:                                && cursorName.compareTo(newSection
1903:                                        .getClientCursorName()) == 0) {
1904:                            // substitute cusor name in pass thru sql string
1905:                            sql = substituteClientCursorNameWithServerCursorName(
1906:                                    sql, newSection);
1907:                        }
1908:                        writeExecuteImmediate(sql, newSection);
1909:                    }
1910:                    // if sql is an insert and columnNames is not null, and
1911:                    // then transform the insert statement into an
1912:                    // select from insert statement.
1913:                    // else chain an "select from identity_val_local()" to the insert statement
1914:                    else if (sqlUpdateMode_ == isInsertSql__
1915:                            && generatedKeysColumnNames_ != null) {
1916:                        newSection = agent_.sectionManager_
1917:                                .getDynamicSection(resultSetHoldability_);
1918:                        writePrepareDescribeOutput(
1919:                                constructSelectFromInsertSQL(sql), newSection);
1920:                        writeOpenQuery(newSection, fetchSize_, resultSetType_);
1921:                    } else {
1922:                        newSection = agent_.sectionManager_
1923:                                .getDynamicSection(resultSetHoldability_);
1924:
1925:                        writeExecuteImmediate(sql, newSection);
1926:                        if (sqlUpdateMode_ == isInsertSql__
1927:                                && autoGeneratedKeys_ == RETURN_GENERATED_KEYS) {
1928:                            prepareAutoGeneratedKeysStatement();
1929:                            writeOpenQuery(
1930:                                    preparedStatementForAutoGeneratedKeys_.section_,
1931:                                    preparedStatementForAutoGeneratedKeys_.fetchSize_,
1932:                                    preparedStatementForAutoGeneratedKeys_.resultSetType_);
1933:                        }
1934:                    }
1935:
1936:                    // maybe duplicate a commit here if the sql is a "commit"
1937:                    if (connection_.autoCommit_) {
1938:                        connection_.writeAutoCommit();
1939:                    }
1940:                    break;
1941:                case isCall__:
1942:                    newSection = writeExecuteCall(sql, false);
1943:
1944:                    break;
1945:                }
1946:
1947:                agent_.flow(this );
1948:
1949:                readCloseResultSets(true); // true means permit auto-commits
1950:
1951:                if (timeoutSent) {
1952:                    readSetSpecialRegister(); // Read response to the EXCSQLSET
1953:                }
1954:
1955:                // turn inUnitOfWork_ flag back on and add statement
1956:                // back on commitListeners_ list if they were off
1957:                // by an autocommit chained to a close cursor.
1958:                if (piggybackedAutoCommit) {
1959:                    connection_.completeTransactionStart();
1960:                }
1961:
1962:                markResultSetsClosed(true); // true means remove from list of commit and rollback listeners
1963:                markClosedOnServer();
1964:                section_ = newSection;
1965:
1966:                switch (sqlMode_) {
1967:                case isQuery__:
1968:                    // parse out the reply to a chained prepare and open request
1969:                    readPrepareDescribeOutput();
1970:                    // This establishes statement.resultSet
1971:                    readOpenQuery();
1972:
1973:                    // resultSet_ is null if open query failed.
1974:                    // check for null resultSet_ before using it.
1975:                    // the first rowset comes back on OPEN for static non-rowset cursors.
1976:                    // no row is returned on open for rowset cursors.
1977:                    if (resultSet_ != null) {
1978:                        resultSet_.parseScrollableRowset();
1979:
1980:                        // DERBY-1183: If we set it up it earlier, the entry in
1981:                        // clientCursorNameCache_ gets wiped out by the closing of
1982:                        // result sets happening during readCloseResultSets above
1983:                        // because ResultSet#markClosed calls
1984:                        // Statement#removeClientCursorNameFromCache.
1985:                        setupCursorNameCacheAndMappings();
1986:                    }
1987:
1988:                    break;
1989:
1990:                case isUpdate__:
1991:
1992:                    // do not need to reposition for rowset cursors.
1993:                    if (scrollableRS != null && !scrollableRS.isRowsetCursor_) {
1994:                        scrollableRS.readPositioningFetch_();
1995:                    }
1996:
1997:                    if (sqlUpdateMode_ == isInsertSql__
1998:                            && generatedKeysColumnNames_ != null) {
1999:                        readPrepareDescribeOutput();
2000:                        readOpenQuery();
2001:                        if (resultSet_ != null) {
2002:                            generatedKeysResultSet_ = resultSet_;
2003:                            resultSet_ = null;
2004:                            updateCount_ = 1;
2005:                        }
2006:                    } else {
2007:                        readExecuteImmediate();
2008:
2009:                        if (sqlUpdateMode_ == isInsertSql__
2010:                                && autoGeneratedKeys_ == RETURN_GENERATED_KEYS) {
2011:                            readPrepareAutoGeneratedKeysStatement();
2012:                            preparedStatementForAutoGeneratedKeys_
2013:                                    .readOpenQuery();
2014:                            generatedKeysResultSet_ = preparedStatementForAutoGeneratedKeys_.resultSet_;
2015:                            preparedStatementForAutoGeneratedKeys_.resultSet_ = null;
2016:                        }
2017:                    }
2018:
2019:                    if (connection_.autoCommit_) {
2020:                        connection_.readAutoCommit();
2021:                    }
2022:                    break;
2023:
2024:                case isCall__:
2025:                    readPrepare();
2026:                    readExecuteCall();
2027:                    break;
2028:
2029:                }
2030:
2031:                // in the case the stored procedure call is uncatalogued, we need to catch that
2032:                // kind exception and changed the call from dynamic to static
2033:                agent_.endReadChain();
2034:
2035:                //  If we hear from Sun that we can just set a warning for this, then move this code to the ResultSet constructor.
2036:                // Throw an exception if holdability returned by the server is different from requested.
2037:                if (resultSet_ != null
2038:                        && resultSet_.resultSetHoldability_ != resultSetHoldability_
2039:                        && sqlMode_ != isCall__) {
2040:                    throw new SqlException(
2041:                            agent_.logWriter_,
2042:                            new ClientMessageId(
2043:                                    SQLState.UNABLE_TO_OPEN_RS_WITH_REQUESTED_HOLDABILITY),
2044:                            new Integer(resultSetHoldability_));
2045:                }
2046:
2047:                // In the case of executing a call to a stored procedure.
2048:                if (sqlMode_ == isCall__) {
2049:                    parseStorProcReturnedScrollableRowset();
2050:                    checkForStoredProcResultSetCount(executeType);
2051:                    // When there is no result sets back, we will commit immediately when autocommit is true.
2052:                    if (connection_.autoCommit_ && resultSet_ == null
2053:                            && resultSetList_ == null) {
2054:                        connection_.flowAutoCommit();
2055:                    }
2056:                }
2057:
2058:                // The JDBC spec says that executeUpdate() should return 0
2059:                // when no row count is returned.
2060:                if (executeType == executeUpdateMethod__ && updateCount_ < 0) {
2061:                    updateCount_ = 0;
2062:                }
2063:            }
2064:
2065:            void flowExecuteBatch(int[] updateCounts) throws SqlException,
2066:                    BatchUpdateException {
2067:                SqlException chainBreaker = null;
2068:                boolean isCallCataloguedBestGuess = true;
2069:                agent_.beginBatchedWriteChain(this );
2070:                for (int i = 0; i < batch_.size(); i++) {
2071:                    boolean flowSQL = true;
2072:                    String sql = (String) batch_.get(i);
2073:                    parseSqlAndSetSqlModes(sql);
2074:                    try {
2075:                        checkForInvalidBatchedSql(sql);
2076:                    } catch (SqlException e) {
2077:                        flowSQL = false;
2078:                    }
2079:
2080:                    // if you have a length mismatch for a lob flow, then we need to return a -3
2081:                    // need to trap the exceptions coming back from writeExecuteImmediate and continue on with a -3
2082:                    // net will need to be able to reset the send buffer
2083:                    if (flowSQL) {
2084:                        if (section_ != null) {
2085:                            section_.free();
2086:                        }
2087:                        if (sqlMode_ != isCall__) {
2088:                            section_ = agent_.sectionManager_
2089:                                    .getDynamicSection(resultSetHoldability_);
2090:                            writeExecuteImmediate(sql, section_);
2091:                        } else {
2092:                            section_ = writeExecuteCall(sql, true);
2093:                        }
2094:                    }
2095:                }
2096:
2097:                if (connection_.autoCommit_) {
2098:                    connection_.writeAutoCommit();
2099:                }
2100:
2101:                agent_.flowBatch(this , batch_.size());
2102:
2103:                try {
2104:                    for (int i = 0; i < batch_.size(); i++) {
2105:                        agent_.setBatchedExceptionLabelIndex(i);
2106:                        SqlException invalidSQLCaughtByClient = null;
2107:                        String sql = (String) batch_.get(i);
2108:                        parseSqlAndSetSqlModes(sql);
2109:                        try {
2110:                            checkForInvalidBatchedSql(sql);
2111:                        } catch (SqlException e) {
2112:                            invalidSQLCaughtByClient = e;
2113:                        }
2114:                        if (invalidSQLCaughtByClient == null) {
2115:                            updateCount_ = -1;
2116:                            if (sqlMode_ != isCall__) {
2117:                                readExecuteImmediateForBatch(sql);
2118:                            } else {
2119:                                if (isCallCataloguedBestGuess) {
2120:                                    readPrepare();
2121:                                }
2122:                                readExecuteCall();
2123:                            }
2124:                        } else {
2125:                            agent_
2126:                                    .accumulateReadException(invalidSQLCaughtByClient);
2127:                            updateCount_ = java.sql.Statement.EXECUTE_FAILED;
2128:                            invalidSQLCaughtByClient = null;
2129:                        }
2130:
2131:                        updateCounts[i] = updateCount_;
2132:
2133:                        // DERBY doesn't return an update count for DDL statements, so we need to
2134:                        // remap our initial value of -1 (represents invalid update count) to a
2135:                        // valid update count of zero.
2136:                        if (updateCounts[i] == -1) {
2137:                            updateCounts[i] = 0;
2138:                        }
2139:                    }
2140:                    agent_.disableBatchedExceptionTracking(); // to prvent the following readCommit() from getting a batch label
2141:                    if (connection_.autoCommit_) {
2142:                        connection_.readAutoCommit(); // this could throw a chainbreaker too
2143:                    }
2144:                }
2145:                // for chain-breaking exception only, all read() methods do their own accumulation
2146:                // this catches the entire accumulated chain, we need to be careful not to
2147:                // reaccumulate it on the agent since the batch labels will be overwritten if
2148:                // batch exception tracking is enabled.
2149:                catch (SqlException e) {
2150:                    chainBreaker = e;
2151:                    chainBreaker.setNextException(new SqlException(
2152:                            agent_.logWriter_, new ClientMessageId(
2153:                                    SQLState.BATCH_CHAIN_BREAKING_EXCEPTION)));
2154:                }
2155:                // We need to clear the batch before any exception is thrown from agent_.endBatchedReadChain().
2156:                batch_.clear();
2157:                agent_.endBatchedReadChain(updateCounts, chainBreaker);
2158:            }
2159:
2160:            private Section writeExecuteCall(String sql, boolean isBatch)
2161:                    throws SqlException {
2162:                Section newSection = null;
2163:
2164:                newSection = agent_.sectionManager_
2165:                        .getDynamicSection(resultSetHoldability_);
2166:                // this code is beneficial only if there is literal in the sql call statement
2167:                writePrepare(sql, newSection);
2168:                writeExecuteCall(false, // no out parameters, outputExpected = false
2169:                        null, // sql is prepared, procedureName = null
2170:                        newSection, fetchSize_, isBatch, // do not suppress ResultSets for regular CALLs
2171:                        resultSetType_, null, // no parameters, parameterMetaData = null
2172:                        null); // no parameters, inputs = null
2173:
2174:                return newSection;
2175:            }
2176:
2177:            //------------------material layer event callbacks follow---------------------
2178:            // All callbacks are client-side only operations
2179:
2180:            public void listenToUnitOfWork() {
2181:            } // do nothing for now.
2182:
2183:            public void completeLocalCommit(java.util.Iterator listenerIterator) {
2184:            } // do nothing for now.
2185:
2186:            public void completeLocalRollback(
2187:                    java.util.Iterator listenerIterator) {
2188:            } // do nothing for now.
2189:
2190:            // This method will not work if e is chained.
2191:            // It is assumed that e is a single warning and is not chained.
2192:            public void accumulateWarning(SqlWarning e) {
2193:                if (warnings_ == null) {
2194:                    warnings_ = e;
2195:                } else {
2196:                    warnings_.setNextWarning(e);
2197:                }
2198:            }
2199:
2200:            private void markPrepared() {
2201:                //openOnClient_ = true;
2202:                openOnServer_ = true;
2203:                listenToUnitOfWork();
2204:            }
2205:
2206:            //-------------------------------helper methods-------------------------------
2207:
2208:            /**
2209:             * Returns the name of the java.sql interface implemented by this class.
2210:             * @return name of java.sql interface
2211:             */
2212:            protected String getJdbcStatementInterfaceName() {
2213:                return "java.sql.Statement";
2214:            }
2215:
2216:            // Should investigate if it can be optimized..  if we can avoid this parsing..
2217:            //
2218:            void parseSqlAndSetSqlModes(String sql) throws SqlException {
2219:                String delims = "\t\n\r\f=? (";
2220:                java.util.StringTokenizer tokenizer = null;
2221:                String firstToken = null;
2222:
2223:                // See if the statement starts with a comment; if so, move
2224:                // past the comment and get the first token of the actual
2225:                // statement to be executed.  Note: must use "startsWith"
2226:                // when looking for the comment delimiters instead of
2227:                // "equals" because there may not be whitespace between the
2228:                // the delimiter and the comment itself, ex "--my comment".
2229:                if (sql.trim().startsWith("--")) {
2230:
2231:                    // Read each line of the statement until we find a
2232:                    // line that is NOT a comment.
2233:                    int lastEndLine = -1;
2234:                    String endline = "\n\r\f";
2235:                    tokenizer = new java.util.StringTokenizer(sql, endline,
2236:                            true);
2237:                    while (tokenizer.hasMoreTokens()) {
2238:                        firstToken = tokenizer.nextToken();
2239:                        if (endline.indexOf(firstToken) != -1)
2240:                            // this is some sort of newline ("\n", "\r", or "\f").
2241:                            lastEndLine = sql.indexOf(firstToken,
2242:                                    lastEndLine + 1);
2243:                        else if (!firstToken.trim().startsWith("--"))
2244:                            break;
2245:                    }
2246:
2247:                    if (firstToken.startsWith("--")) {
2248:                        // entire statement was just one or more comments; pass it as
2249:                        // a query to the server and let the server deal with it.
2250:                        sqlMode_ = isQuery__;
2251:                        return;
2252:                    } else {
2253:                        // we have a non-comment line; get a tokenizer for the
2254:                        // statement beginning at the start of this line.
2255:                        tokenizer = new java.util.StringTokenizer(sql
2256:                                .substring(lastEndLine + 1), delims);
2257:                    }
2258:
2259:                } else {
2260:                    // there aren't any leading comments, so just get the first token
2261:                    // in the SQL statement.
2262:                    tokenizer = new java.util.StringTokenizer(sql, delims);
2263:                }
2264:
2265:                if (!tokenizer.hasMoreTokens()) {
2266:                    throw new SqlException(
2267:                            agent_.logWriter_,
2268:                            new ClientMessageId(SQLState.NO_TOKENS_IN_SQL_TEXT),
2269:                            sql);
2270:                }
2271:
2272:                sqlUpdateMode_ = 0;
2273:                firstToken = tokenizer.nextToken();
2274:
2275:                if (firstToken.equalsIgnoreCase("select") || // captures <subselect> production
2276:                        firstToken.equalsIgnoreCase("values")) // captures <values-clause> production
2277:                {
2278:                    sqlMode_ = isQuery__;
2279:                } else if (firstToken.equalsIgnoreCase("call")) // captures CALL...and ?=CALL...
2280:                {
2281:                    sqlMode_ = isCall__;
2282:                } else {
2283:                    parseUpdateSql(firstToken);
2284:                }
2285:            }
2286:
2287:            private void parseUpdateSql(String firstToken) throws SqlException {
2288:                sqlMode_ = isUpdate__;
2289:                if (firstToken.equalsIgnoreCase("insert")) {
2290:                    sqlUpdateMode_ = isInsertSql__;
2291:                }
2292:                if (firstToken.equalsIgnoreCase("delete")) {
2293:                    sqlUpdateMode_ = isDeleteSql__;
2294:                }
2295:                if (firstToken.equalsIgnoreCase("update")) {
2296:                    sqlUpdateMode_ = isUpdateSql__;
2297:                }
2298:            }
2299:
2300:            // the sql is assumed to start with CALL... or ?=CALL...
2301:            String getProcedureName(String sql) throws SqlException {
2302:                java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
2303:                        sql, "\t\n\r\f= (?");
2304:                if (!tokenizer.hasMoreTokens()) {
2305:                    throw new SqlException(
2306:                            agent_.logWriter_,
2307:                            new ClientMessageId(SQLState.NO_TOKENS_IN_SQL_TEXT),
2308:                            sql);
2309:                }
2310:                String firstToken = tokenizer.nextToken();
2311:                if (!firstToken.equalsIgnoreCase("call")) {
2312:                    throw new SqlException(agent_.logWriter_,
2313:                            new ClientMessageId(
2314:                                    SQLState.LANG_INVALID_CALL_STATEMENT));
2315:                }
2316:                if (!tokenizer.hasMoreTokens()) {
2317:                    throw new SqlException(agent_.logWriter_,
2318:                            new ClientMessageId(
2319:                                    SQLState.LANG_INVALID_CALL_STATEMENT));
2320:                }
2321:                return tokenizer.nextToken();
2322:            }
2323:
2324:            // Try to enforce the use of this method later.
2325:            public static String upperCaseProcedureName(String procedureName)
2326:                    throws SqlException {
2327:                // upper case the parts of a 3-part procedure name unless the part is in a double quotes
2328:
2329:                // Loop thru every character, if we're in double quotes just echo it,
2330:                // if we're not in double quotes, upper case it.
2331:                char[] charArray = null;
2332:                if (procedureName.indexOf("\"") == -1) {
2333:                    return procedureName.toUpperCase();
2334:                } else {
2335:                    charArray = procedureName.toCharArray();
2336:                    boolean inStringLiteral = false;
2337:                    for (int i = 0; i < charArray.length; i++) {
2338:                        if (charArray[i] == '"') {
2339:                            inStringLiteral = !inStringLiteral;
2340:                        } else if (!inStringLiteral && charArray[i] != '.') {
2341:                            charArray[i] = Character.toUpperCase(charArray[i]);
2342:                        }
2343:                    }
2344:                }
2345:                return new String(charArray);
2346:            }
2347:
2348:            void checkForAppropriateSqlMode(int executeType, int sqlMode)
2349:                    throws SqlException {
2350:                if (executeType == executeQueryMethod__
2351:                        && sqlMode == isUpdate__) {
2352:                    throw new SqlException(agent_.logWriter_,
2353:                            new ClientMessageId(
2354:                                    SQLState.CANT_USE_EXEC_QUERY_FOR_UPDATE));
2355:                }
2356:                if (executeType == executeUpdateMethod__
2357:                        && sqlMode == isQuery__) {
2358:                    throw new SqlException(
2359:                            agent_.logWriter_,
2360:                            new ClientMessageId(
2361:                                    SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE));
2362:                }
2363:            }
2364:
2365:            /**
2366:             * Checks that the number of result sets returned by the statement
2367:             * is consistent with the executed type. <code>executeQuery()</code>
2368:             * should return exactly one result set and <code>executeUpdate()</code>
2369:             * none. Raises an exception if the result set count does not match the
2370:             * execute type.
2371:             *
2372:             * @param executeType one of <code>executeQueryMethod__</code>,
2373:             * <code>executeUpdateMethod__</code> and <code>executeMethod__</code>
2374:             * @exception SqlException if the number of result sets does not
2375:             *                         match the execute type
2376:             */
2377:            private void checkResultSetCount(int executeType)
2378:                    throws SqlException {
2379:                switch (executeType) {
2380:                case executeQueryMethod__:
2381:                    // We'll just rely on finalizers to close the dangling result sets.
2382:                    if (resultSetList_ != null && resultSetList_.length > 1) {
2383:                        throw new SqlException(
2384:                                agent_.logWriter_,
2385:                                new ClientMessageId(
2386:                                        SQLState.MULTIPLE_RESULTS_ON_EXECUTE_QUERY),
2387:                                getJdbcStatementInterfaceName(),
2388:                                getJdbcStatementInterfaceName());
2389:                    }
2390:                    if (resultSet_ == null || resultSetList_.length == 0) {
2391:                        ClientMessageId messageId = new ClientMessageId(
2392:                                SQLState.USE_EXECUTE_UPDATE_WITH_NO_RESULTS);
2393:                        throw new SqlException(agent_.logWriter_, messageId,
2394:                                getJdbcStatementInterfaceName(),
2395:                                getJdbcStatementInterfaceName());
2396:                    }
2397:                    break;
2398:                case executeUpdateMethod__:
2399:                    // We'll just rely on finalizers to close the dangling result sets.
2400:                    if (resultSet_ != null && resultSetList_.length > 0) {
2401:                        ClientMessageId messageId = new ClientMessageId(
2402:                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
2403:                        throw new SqlException(agent_.logWriter_, messageId);
2404:                    }
2405:                    break;
2406:                }
2407:            }
2408:
2409:            /**
2410:             * Checks that a stored procedure returns the correct number of
2411:             * result sets given its execute type. If the number is incorrect,
2412:             * make sure the transaction is rolled back when auto commit is
2413:             * enabled.
2414:             *
2415:             * @param executeType one of <code>executeQueryMethod__</code>,
2416:             * <code>executeUpdateMethod__</code> and <code>executeMethod__</code>
2417:             * @exception SqlException if the number of result sets does not
2418:             *                         match the execute type
2419:             * @see #checkResultSetCount(int)
2420:             */
2421:            protected final void checkForStoredProcResultSetCount(
2422:                    int executeType) throws SqlException {
2423:                try {
2424:                    checkResultSetCount(executeType);
2425:                } catch (SqlException se) {
2426:                    if (connection_.autoCommit_) {
2427:                        connection_.flowRollback();
2428:                    }
2429:                    throw se;
2430:                }
2431:            }
2432:
2433:            void checkForClosedStatement() throws SqlException {
2434:                // For some odd reason, there was a JVM hotspot error with Sun's 1.4 JDK
2435:                // when the code was written like this:
2436:                // agent_checkForDeferredExceptions();
2437:                // if (!openOnClient_)
2438:                //   throw new SqlException (agent_.logWriter_, "Invalid operation: statement closed");
2439:                //
2440:                if (this .connection_ == null || this .connection_.isClosed())
2441:                    throw new SqlException(agent_.logWriter_,
2442:                            new ClientMessageId(SQLState.NO_CURRENT_CONNECTION));
2443:
2444:                if (!openOnClient_) {
2445:                    agent_.checkForDeferredExceptions();
2446:                    throw new SqlException(agent_.logWriter_,
2447:                            new ClientMessageId(SQLState.ALREADY_CLOSED),
2448:                            "Statement");
2449:                } else {
2450:                    agent_.checkForDeferredExceptions();
2451:                }
2452:            }
2453:
2454:            // precondition: parseSqlAndSetSqlModes() must be called on the supplied sql string before invoking this method
2455:            void checkForInvalidBatchedSql(String sql) throws SqlException {
2456:                if (sql == null) {
2457:                    throw new SqlException(agent_.logWriter_,
2458:                            new ClientMessageId(SQLState.NULL_SQL_TEXT));
2459:                }
2460:
2461:                if (sqlMode_ != isCall__
2462:                        && !(sqlMode_ == isUpdate__ && (sqlUpdateMode_ == isInsertSql__
2463:                                || sqlUpdateMode_ == isDeleteSql__
2464:                                || sqlUpdateMode_ == isUpdateSql__ || sqlUpdateMode_ == 0)))// For any undefined pass thru statement like drop create
2465:                {
2466:                    throw new SqlException(agent_.logWriter_,
2467:                            new ClientMessageId(
2468:                                    SQLState.LANG_INVALID_SQL_IN_BATCH), sql);
2469:                }
2470:            }
2471:
2472:            // Two open result sets can not have the same cursor name. 
2473:            protected void checkForDuplicateCursorName() throws SqlException {
2474:                if (cursorName_ != null
2475:                        && (connection_.clientCursorNameCache_
2476:                                .containsKey(cursorName_))) {
2477:                    throw new SqlException(
2478:                            agent_.logWriter_,
2479:                            new ClientMessageId(SQLState.CURSOR_DUPLICATE_NAME),
2480:                            cursorName_);
2481:                }
2482:            }
2483:
2484:            // Set up information to be able to handle cursor names:
2485:            // canned or user named (via setCursorName).
2486:            protected void setupCursorNameCacheAndMappings() {
2487:                if (cursorName_ != null) {
2488:                    // The user has set a cursor name for this statement.
2489:                    // This means we must subtitute the <users-cursor-name>
2490:                    // with the <canned-cursor-name> in the pass-thru sql
2491:                    // string "...where current of <canned-cursor-name>"
2492:                    // whenever the result set produced by this statement
2493:                    // is referenced in a positioned update/delete statement.
2494:                    agent_.sectionManager_.mapCursorNameToQuerySection(
2495:                            cursorName_, section_);
2496:                    section_.setClientCursorName(cursorName_);
2497:
2498:                    // Update cache to avoid duplicates of user set cursor name.
2499:                    connection_.clientCursorNameCache_.put(cursorName_,
2500:                            cursorName_);
2501:                } else {
2502:                    // canned cursor name
2503:                    agent_.sectionManager_.mapCursorNameToQuerySection(section_
2504:                            .getServerCursorName(), section_);
2505:                }
2506:
2507:                // If client's cursor name is set, map the client's cursor name to the
2508:                // result set, else map the server's cursor name to the result set.
2509:                mapCursorNameToResultSet();
2510:            }
2511:
2512:            String[] extractCursorNameFromWhereCurrentOf(String sql) {
2513:                String lowerSql = sql.toLowerCase();
2514:                int currentIndex = lowerSql.lastIndexOf("current");
2515:                if (currentIndex != -1) {
2516:                    int whereIndex = lowerSql.lastIndexOf("where");
2517:                    if (whereIndex != -1) {
2518:                        String[] whereCurrentOf = { "where", "current", "of" };
2519:                        java.util.StringTokenizer st = new java.util.StringTokenizer(
2520:                                sql.substring(whereIndex));
2521:                        while (st.hasMoreTokens()) {
2522:                            if (st.nextToken().equalsIgnoreCase(
2523:                                    whereCurrentOf[0])
2524:                                    && st.nextToken().equalsIgnoreCase(
2525:                                            whereCurrentOf[1])
2526:                                    && st.nextToken().equalsIgnoreCase(
2527:                                            whereCurrentOf[2])) {
2528:                                String cursorName = st.nextToken();
2529:                                String oldCursorName = cursorName;
2530:                                int originalCursorNameLength = cursorName
2531:                                        .length();
2532:                                int index = sql.lastIndexOf(cursorName);
2533:                                if (cursorName.charAt(0) == '\"'
2534:                                        && cursorName.charAt(cursorName
2535:                                                .length() - 1) == '\"') {
2536:                                    cursorName = cursorName.substring(1,
2537:                                            cursorName.length() - 1);
2538:                                } else {
2539:                                    cursorName = cursorName.toUpperCase();
2540:                                }
2541:                                // we cannot assume "where current of cursorName" is always the end of the sql string
2542:                                // with rowset cursors, it can be "where current of cursorName for row X of rowset"
2543:                                if (sql.length() > index
2544:                                        + originalCursorNameLength) {
2545:                                    sql = sql.substring(0, index)
2546:                                            + cursorName
2547:                                            + sql.substring(index
2548:                                                    + oldCursorName.length(),
2549:                                                    sql.length());
2550:                                } else {
2551:                                    sql = sql.substring(0, index) + cursorName;
2552:                                }
2553:                                return new String[] { cursorName, sql }; // delimited name, so just extract the name.
2554:                            }
2555:                        }
2556:                    }
2557:                }
2558:                return null;
2559:            }
2560:
2561:            // Substitute the client cursor name in the SQL string with the server's cursor name.
2562:            // Only called on positioned update statements.
2563:            protected String substituteClientCursorNameWithServerCursorName(
2564:                    String sql, Section section) throws SqlException {
2565:                String clientCursorName = section.getClientCursorName();
2566:                int index = sql.lastIndexOf(clientCursorName);
2567:                if (sql.length() > index + clientCursorName.length()) {
2568:                    return sql.substring(0, index)
2569:                            + section.getServerCursorNameForPositionedUpdate()
2570:                            + sql.substring(index + clientCursorName.length(),
2571:                                    sql.length());
2572:                } else {
2573:                    return sql.substring(0, index)
2574:                            + section.getServerCursorNameForPositionedUpdate();
2575:                }
2576:            }
2577:
2578:            public ConnectionCallbackInterface getConnectionCallbackInterface() {
2579:                return connection_;
2580:            }
2581:
2582:            // This was being called only on positioned update statements. When working 
2583:            // on DERBY-210, it was found that result sets of all statements (not just
2584:            // positioned update statements) get added to the table. So, this is called
2585:            // for all statements. Otherwise, this will cause memory leaks when statements
2586:            // are not explicitly closed in the application. 
2587:            void resetCursorNameAndRemoveFromWhereCurrentOfMappings() {
2588:                // Remove client/server cursorName -> ResultSet mapping from the hashtable.
2589:                // If Statement.close() is called before ResultSet.close(), then statement_.section is null.
2590:                if (section_ != null) {
2591:                    agent_.sectionManager_.removeCursorNameToResultSetMapping(
2592:                            cursorName_, section_
2593:                                    .getServerCursorNameForPositionedUpdate());
2594:
2595:                    // remove resultset mapping for other cursors (other than positioned
2596:                    // update statements) - DERBY-210
2597:                    agent_.sectionManager_.removeCursorNameToResultSetMapping(
2598:                            cursorName_, section_.getServerCursorName());
2599:
2600:                    // Remove client and server cursorName -> QuerySection mapping from the hashtable
2601:                    // if one exists
2602:                    agent_.sectionManager_
2603:                            .removeCursorNameToQuerySectionMapping(
2604:                                    cursorName_,
2605:                                    section_
2606:                                            .getServerCursorNameForPositionedUpdate());
2607:                }
2608:
2609:                // client cursor name will be set to null when it is removed from the
2610:                // clientCursorNameCache.
2611:                //cursorName_ = null;
2612:            }
2613:
2614:            void mapCursorNameToResultSet() {
2615:                if (cursorName_ != null) {
2616:                    agent_.sectionManager_.mapCursorNameToResultSet(
2617:                            cursorName_, resultSet_);
2618:                } else {
2619:                    agent_.sectionManager_.mapCursorNameToResultSet(section_
2620:                            .getServerCursorName(), resultSet_);
2621:                }
2622:            }
2623:
2624:            void parseStorProcReturnedScrollableRowset() throws SqlException {
2625:                if (resultSetList_ != null) {
2626:                    for (int i = 0; i < resultSetList_.length; i++) {
2627:                        if (resultSetList_[i].scrollable_
2628:                                && resultSetList_[i].cursor_
2629:                                        .dataBufferHasUnprocessedData()) {
2630:                            resultSetList_[i].parseScrollableRowset();
2631:                            if (resultSetList_[i].rowCountIsUnknown()) {
2632:                                resultSetList_[i].getRowCount();
2633:                            }
2634:                        }
2635:                    }
2636:                }
2637:            }
2638:
2639:            String escape(String sql) throws SqlException {
2640:                String nativeSQL = sql;
2641:
2642:                nativeSQL = connection_.nativeSQLX(sql);
2643:                return nativeSQL;
2644:            }
2645:
2646:            // Called by statement constructor only for jdbc 2 statements with scroll attributes.
2647:            // This method is not in the StatementRequest class because it is not building into
2648:            // the request buffer directly, it is building into a cache to be written into the request
2649:            // buffer at prepare-time.
2650:            String cacheCursorAttributesToSendOnPrepare() throws SqlException {
2651:                StringBuffer cursorAttributes = new StringBuffer();
2652:                if (resultSetType_ == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE) {
2653:                    // append "SENSITIVE STATIC SCROLL"
2654:                    cursorAttributes
2655:                            .append(Configuration.cursorAttribute_SensitiveStatic);
2656:                } else if (resultSetType_ == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
2657:                    // if "insensitve, updatable" cursor is asked, then server sends back error
2658:                    // and we will pass that error back to the user.
2659:                    // we will not try to catch any errors/warnings here.
2660:                    // append "INSENSITIVE SCROLL"
2661:                    cursorAttributes
2662:                            .append(Configuration.cursorAttribute_Insensitive);
2663:                }
2664:
2665:                // Default is read-only, forward-only.  No attribute needs to be sent.
2666:                if (resultSetConcurrency_ == java.sql.ResultSet.CONCUR_UPDATABLE) {
2667:                    cursorAttributes
2668:                            .append(Configuration.cursorAttribute_ForUpdate); // FOR UPDATE
2669:                }
2670:
2671:                if ((resultSetHoldability_ == java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT)) {
2672:                    cursorAttributes
2673:                            .append(Configuration.cursorAttribute_WithHold); // WITH HOLD
2674:                }
2675:
2676:                return (cursorAttributes == null || cursorAttributes.toString()
2677:                        .equals("")) ? null : cursorAttributes.toString();
2678:            }
2679:
2680:            protected String constructSelectFromInsertSQL(String sql) {
2681:                String temp = "select ";
2682:                int numOfColumns = generatedKeysColumnNames_.length;
2683:
2684:                for (int i = 0; i < numOfColumns; i++) {
2685:                    temp += generatedKeysColumnNames_[i];
2686:                    if ((i + 1) < numOfColumns) {
2687:                        temp += ",";
2688:                    }
2689:                }
2690:                temp += (" from final table (" + sql + ")");
2691:                return temp;
2692:            }
2693:
2694:            void getPreparedStatementForAutoGeneratedKeys() throws SqlException {
2695:                if (preparedStatementForAutoGeneratedKeys_ == null) {
2696:                    String s = "select IDENTITY_VAL_LOCAL() from SYSIBM.SYSDUMMY1";
2697:                    preparedStatementForAutoGeneratedKeys_ = connection_
2698:                            .newPreparedStatement_(
2699:                                    s,
2700:                                    java.sql.ResultSet.TYPE_FORWARD_ONLY,
2701:                                    java.sql.ResultSet.CONCUR_READ_ONLY,
2702:                                    java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT,
2703:                                    java.sql.Statement.NO_GENERATED_KEYS, null);
2704:                    // need a special case for Derby, since the attribute has to go through the wire.
2705:                    // This same special casing for Derby is already in place in method PS.cacheCursorAttributesToSendOnPrepare() as called by prepareStatementX().
2706:                    //  We need to figure how some way to get code reuse here, ie. to consolidate to just one special casing rather than two?
2707:                    // Maybe just call prepareStatementX() or use some special purpose prepare method like the ones in Connection.
2708:                    // Something more abstract so that we don't have to special case the WITH HOLD thing twice.
2709:                    StringBuffer cursorAttributes = new StringBuffer();
2710:                    cursorAttributes
2711:                            .append(Configuration.cursorAttribute_WithHold);
2712:                    preparedStatementForAutoGeneratedKeys_.cursorAttributesToSendOnPrepare_ = cursorAttributes
2713:                            .toString();
2714:                }
2715:            }
2716:
2717:            void prepareAutoGeneratedKeysStatement() throws SqlException {
2718:                getPreparedStatementForAutoGeneratedKeys();
2719:                if (!preparedStatementForAutoGeneratedKeys_.openOnServer_) {
2720:                    preparedStatementForAutoGeneratedKeys_.materialPreparedStatement_
2721:                            .writePrepareDescribeOutput_(
2722:                                    preparedStatementForAutoGeneratedKeys_.sql_,
2723:                                    preparedStatementForAutoGeneratedKeys_.section_);
2724:                }
2725:            }
2726:
2727:            void readPrepareAutoGeneratedKeysStatement() throws SqlException {
2728:                if (!preparedStatementForAutoGeneratedKeys_.openOnServer_) {
2729:                    preparedStatementForAutoGeneratedKeys_.materialPreparedStatement_
2730:                            .readPrepareDescribeOutput_();
2731:                }
2732:            }
2733:
2734:            void checkAutoGeneratedKeysParameters() throws SqlException {
2735:                if (autoGeneratedKeys_ != java.sql.Statement.NO_GENERATED_KEYS
2736:                        && autoGeneratedKeys_ != java.sql.Statement.RETURN_GENERATED_KEYS) {
2737:                    throw new SqlException(
2738:                            agent_.logWriter_,
2739:                            new ClientMessageId(SQLState.INVALID_API_PARAMETER),
2740:                            new Integer(autoGeneratedKeys_),
2741:                            "autoGeneratedKeys",
2742:                            "Statement.execute()/executeQuery()");
2743:                }
2744:
2745:                if (generatedKeysColumnNames_ != null) {
2746:                    throw new SqlException(agent_.logWriter_,
2747:                            new ClientMessageId(SQLState.NOT_IMPLEMENTED),
2748:                            "Connection.prepareStatement(String sql, String[] columnNames)");
2749:                }
2750:            }
2751:
2752:            public ColumnMetaData getGuessedResultSetMetaData() {
2753:                return resultSetMetaData_;
2754:            }
2755:
2756:            public boolean isQueryMode() {
2757:                if (this .sqlMode_ == this .isQuery__) {
2758:                    return true;
2759:                } else {
2760:                    return false;
2761:                }
2762:            }
2763:
2764:            protected void removeClientCursorNameFromCache() {
2765:                if (cursorName_ != null
2766:                        && connection_.clientCursorNameCache_
2767:                                .containsKey(cursorName_)) {
2768:                    connection_.clientCursorNameCache_.remove(cursorName_);
2769:                }
2770:            }
2771:
2772:            /**
2773:             * Convenience method for resultSetCommitting(ResultSet, boolean)
2774:             * 
2775:             * @see Statement#resultSetCommitting(ResultSet, boolean)
2776:             * @param closingRS The ResultSet to be closed
2777:             * @throws SqlException
2778:             */
2779:            public void resultSetCommitting(ResultSet closingRS)
2780:                    throws SqlException {
2781:                resultSetCommitting(closingRS, false);
2782:            }
2783:
2784:            /**
2785:             * Method that checks to see if any other ResultSets are open. If not
2786:             * proceeds with the autocommit.
2787:             * 
2788:             * @param closingRS The ResultSet to be closed
2789:             * @param writeChain A Boolean indicating whether this method
2790:             * is part of a chain of write from client to Server
2791:             * @throws SqlException
2792:             */
2793:            public boolean resultSetCommitting(ResultSet closingRS,
2794:                    boolean writeChain) throws SqlException {
2795:
2796:                // If the Connection is not in auto commit then this statement completion
2797:                // cannot cause a commit.
2798:                if (!connection_.autoCommit_ || closingRS.autoCommitted_)
2799:                    return false;
2800:
2801:                // If we have multiple results, see if there is another result set open.
2802:                // If so, then no commit. The last result set to close will close the statement.
2803:                if (resultSetList_ != null) {
2804:                    for (int i = 0; i < resultSetList_.length; i++) {
2805:                        ResultSet crs = resultSetList_[i];
2806:                        if (crs == null)
2807:                            continue;
2808:                        if (!crs.openOnClient_)
2809:                            continue;
2810:                        if (crs == closingRS)
2811:                            continue;
2812:
2813:                        // at least one still open so no commit now.
2814:                        return false;
2815:                    }
2816:                }
2817:
2818:                if (writeChain) {
2819:                    connection_.writeAutoCommit();
2820:                    return true;
2821:                } else {
2822:                    if (connection_.flowAutoCommit()) {
2823:                        markAutoCommitted();
2824:                        return true;
2825:                    }
2826:                    return false;
2827:                }
2828:            }
2829:
2830:            /**
2831:             * Mark all ResultSets associated with this statement as auto-committed.   
2832:             */
2833:            public void markAutoCommitted() {
2834:                if (resultSetList_ != null) {
2835:                    for (int i = 0; i < resultSetList_.length; i++)
2836:                        if (resultSetList_[i] != null) {
2837:                            resultSetList_[i].markAutoCommitted();
2838:                        }
2839:                } else if (resultSet_ != null) {
2840:                    resultSet_.markAutoCommitted();
2841:                }
2842:            }
2843:
2844:            protected SQLException jdbc3FeatureNotSupported(
2845:                    boolean checkStatement) throws SQLException {
2846:                try {
2847:                    if (checkStatement)
2848:                        checkForClosedStatement();
2849:
2850:                    throw new SqlException(agent_.logWriter_,
2851:                            new ClientMessageId(
2852:                                    SQLState.JDBC_METHOD_NOT_IMPLEMENTED));
2853:                } catch (SqlException se) {
2854:                    throw se.getSQLException();
2855:                }
2856:            }
2857:
2858:            protected SQLException jdbc3FeatureNotSupported()
2859:                    throws SQLException {
2860:                return jdbc3FeatureNotSupported(true);
2861:            }
2862:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.