EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.impl.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [EmbedStatement.java]

nameclass, %method, %block, %line, %
EmbedStatement.java100% (1/1)100% (55/55)90%  (1156/1278)90%  (339.4/375)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EmbedStatement100% (1/1)100% (55/55)90%  (1156/1278)90%  (339.4/375)
EmbedStatement (EmbedConnection, boolean, int, int, int): void 100% (1/1)100% (41/41)100% (13/13)
addBatch (String): void 100% (1/1)82%  (23/28)94%  (6.6/7)
addWarning (SQLWarning): void 100% (1/1)71%  (10/14)80%  (4/5)
cancel (): void 100% (1/1)100% (3/3)100% (1/1)
checkExecStatus (): void 100% (1/1)100% (7/7)100% (3/3)
checkIfInMiddleOfBatch (): void 100% (1/1)100% (8/8)100% (3/3)
checkRequiresCallableStatement (Activation): void 100% (1/1)90%  (18/20)78%  (7/9)
checkStatus (): void 100% (1/1)100% (9/9)100% (3/3)
clearBatch (): void 100% (1/1)74%  (14/19)94%  (4.7/5)
clearResultSets (): void 100% (1/1)71%  (57/80)66%  (21/32)
clearWarnings (): void 100% (1/1)100% (6/6)100% (3/3)
close (): void 100% (1/1)86%  (32/37)99%  (11.8/12)
closeActions (): void 100% (1/1)100% (1/1)100% (1/1)
execute (String): boolean 100% (1/1)100% (9/9)100% (1/1)
execute (String, String []): boolean 100% (1/1)100% (3/3)100% (1/1)
execute (String, boolean, boolean, int, int [], String []): boolean 100% (1/1)100% (79/79)100% (20/20)
execute (String, int []): boolean 100% (1/1)100% (3/3)100% (1/1)
execute (String, int): boolean 100% (1/1)100% (9/9)100% (1/1)
executeBatch (): int [] 100% (1/1)85%  (97/114)86%  (24.9/29)
executeBatchElement (Object): boolean 100% (1/1)100% (10/10)100% (1/1)
executeQuery (String): ResultSet 100% (1/1)88%  (15/17)75%  (3/4)
executeStatement (Activation, boolean, boolean): boolean 100% (1/1)93%  (191/206)92%  (51.8/56)
executeUpdate (String): int 100% (1/1)100% (12/12)100% (2/2)
executeUpdate (String, String []): int 100% (1/1)100% (3/3)100% (1/1)
executeUpdate (String, int []): int 100% (1/1)100% (3/3)100% (1/1)
executeUpdate (String, int): int 100% (1/1)100% (12/12)100% (2/2)
getConnection (): Connection 100% (1/1)100% (16/16)100% (5/5)
getExecuteHoldable (): boolean 100% (1/1)100% (21/21)100% (5/5)
getFetchDirection (): int 100% (1/1)100% (5/5)100% (2/2)
getFetchSize (): int 100% (1/1)100% (5/5)100% (2/2)
getGeneratedKeys (): ResultSet 100% (1/1)100% (17/17)100% (4/4)
getMaxFieldSize (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxRows (): int 100% (1/1)100% (5/5)100% (2/2)
getMoreResults (): boolean 100% (1/1)100% (4/4)100% (1/1)
getMoreResults (int): boolean 100% (1/1)74%  (105/142)76%  (28.8/38)
getParameterValueSet (): ParameterValueSet 100% (1/1)100% (3/3)100% (1/1)
getQueryTimeout (): int 100% (1/1)100% (2/2)100% (1/1)
getResultSet (): ResultSet 100% (1/1)100% (5/5)100% (2/2)
getResultSetConcurrency (): int 100% (1/1)100% (5/5)100% (2/2)
getResultSetHoldability (): int 100% (1/1)100% (5/5)100% (2/2)
getResultSetType (): int 100% (1/1)100% (5/5)100% (2/2)
getSQLText (): String 100% (1/1)100% (3/3)100% (1/1)
getUpdateCount (): int 100% (1/1)100% (5/5)100% (2/2)
getWarnings (): SQLWarning 100% (1/1)100% (5/5)100% (2/2)
processDynamicResults (ResultSet [][], int): boolean 100% (1/1)98%  (107/109)94%  (30/32)
resultSetClosing (EmbedResultSet): void 100% (1/1)100% (37/37)100% (14/14)
setApplicationStatement (EngineStatement): void 100% (1/1)100% (4/4)100% (2/2)
setCursorName (String): void 100% (1/1)100% (6/6)100% (3/3)
setEscapeProcessing (boolean): void 100% (1/1)100% (3/3)100% (2/2)
setFetchDirection (int): void 100% (1/1)100% (24/24)100% (5/5)
setFetchSize (int): void 100% (1/1)100% (25/25)100% (6/6)
setMaxFieldSize (int): void 100% (1/1)100% (16/16)100% (5/5)
setMaxRows (int): void 100% (1/1)100% (16/16)100% (5/5)
setQueryTimeout (int): void 100% (1/1)100% (6/6)100% (3/3)
transferBatch (EmbedStatement): void 100% (1/1)76%  (16/21)95%  (4.8/5)

1/*
2 
3   Derby - Class org.apache.derby.impl.jdbc.EmbedStatement
4 
5   Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.impl.jdbc;
22 
23import org.apache.derby.iapi.reference.JDBC20Translation;
24import org.apache.derby.iapi.reference.JDBC30Translation;
25import org.apache.derby.iapi.reference.SQLState;
26 
27import org.apache.derby.iapi.services.sanity.SanityManager;
28 
29import org.apache.derby.iapi.sql.Activation;
30import org.apache.derby.iapi.sql.PreparedStatement;
31import org.apache.derby.iapi.sql.ResultSet;
32import org.apache.derby.iapi.sql.ParameterValueSet;
33import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
34import org.apache.derby.iapi.error.StandardException;
35import org.apache.derby.iapi.jdbc.EngineStatement;
36 
37import java.sql.SQLException;
38import java.sql.SQLWarning;
39import java.util.Vector;
40 
41/*
42 We would import these, but have name-overlap
43import java.sql.Statement;
44import java.sql.ResultSet;
45*/
46 
47/**
48 *
49 * EmbedStatement is a local JDBC statement.
50 *
51   <P><B>Supports</B>
52   <UL>
53   <LI> JSR169 - no subsetting for java.sql.Statement
54   <LI> JDBC 2.0
55   <LI> JDBC 3.0 - no new dependencies on new JDBC 3.0 or JDK 1.4 classes,
56        new methods can safely be added into implementation.
57   </UL>
58 
59 * @author ames
60 */
61public class EmbedStatement extends ConnectionChild
62    implements EngineStatement {
63 
64        private final java.sql.Connection applicationConnection;
65    
66    /**
67     * Statement reference the application is using to execute
68     * this Statement. Normally set to this, but if this was
69     * created by a Connection from an XAConnection then this
70     * will be a reference to the BrokeredStatement.
71     *
72     * Making it protected to allow access from EmbedPreparedStatement40
73     * to be used for StatementEvents
74     *
75     */
76    protected EngineStatement applicationStatement;
77 
78        int updateCount = -1;
79        java.sql.ResultSet results;
80        //for jdbc3.0 feature, where you can get a resultset of rows inserted
81        //for auto generated columns after an insert
82        private java.sql.ResultSet autoGeneratedKeysResultSet;
83        private String cursorName;
84 
85        private final boolean forMetaData;
86        final int resultSetType;
87        private final int resultSetConcurrency;
88        private final int resultSetHoldability;
89        final LanguageConnectionContext lcc;
90 
91        private SQLWarning warnings;
92        String SQLText;
93 
94    private int fetchSize = 1;
95    private int fetchDirection = JDBC20Translation.FETCH_FORWARD;
96    int MaxFieldSize;
97    private int timeoutSeconds;
98 
99        //the state of this statement, set to false when close() is called
100        private boolean active = true;
101 
102    //in case of batch update, save the individual statements in the batch in this vector
103         //this is only used by JDBC 2.0
104         Vector batchStatements;
105        
106        // The maximum # of rows to return per result set.
107        // (0 means no limit.)
108        int maxRows;
109 
110        private ParameterValueSet pvs;
111 
112        // An EmbedStatement is NOT poolable by default. The constructor for
113        // PreparedStatement overrides this.
114        protected boolean isPoolable = false;
115 
116        //
117        // constructor
118        //
119        public EmbedStatement (EmbedConnection connection, boolean forMetaData,
120                                                          int resultSetType, int resultSetConcurrency, int resultSetHoldability)
121        {
122            super(connection);
123                this.forMetaData = forMetaData;
124                this.resultSetType = resultSetType;
125                this.resultSetConcurrency = resultSetConcurrency;
126                this.resultSetHoldability = resultSetHoldability;
127 
128                lcc = getEmbedConnection().getLanguageConnection();
129                applicationConnection = getEmbedConnection().getApplicationConnection();
130        applicationStatement = this;
131 
132        // By default, no statements time out.
133        // Timeout is set explicitly with setQueryTimeout().
134        timeoutSeconds = 0;
135        }
136 
137        //
138        // java.sql.Statement interface
139        // the comments are those from the JDBC interface,
140        // so we know what we're supposed to to.
141 
142        /**
143     * Execute a SQL statement that returns a single ResultSet.
144     *
145     * @param sql                                        typically this is a static SQL SELECT statement
146         * @return a ResultSet that contains the data produced by the
147     * query; never null
148         * @exception SQLException thrown on failure.
149     */
150        public java.sql.ResultSet executeQuery(String sql)
151                throws SQLException
152        {
153                execute(sql, true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
154 
155                if (SanityManager.DEBUG) {
156                        if (results == null)
157                                SanityManager.THROWASSERT("no results returned on executeQuery()");
158                }
159 
160                return results;
161        }
162 
163    /**
164     * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
165     * SQL statements that return nothing such as SQL DDL statements
166     * can be executed.
167     *
168     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
169     * statement that returns nothing
170     * @return either the row count for INSERT, UPDATE or DELETE; or 0
171     * for SQL statements that return nothing
172         * @exception SQLException thrown on failure.
173     */
174        public int executeUpdate(String sql) throws SQLException
175        {
176                execute(sql, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);
177                return updateCount;
178        }
179 
180    /**
181     * JDBC 3.0
182     *
183     * Execute the given SQL statement and signals the driver with the given flag
184     * about whether the auto-generated keys produced by this Statement object
185     * should be made available for retrieval.
186     *
187     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
188     * statement that returns nothing
189     * @param autoGeneratedKeys - a flag indicating whether auto-generated keys
190     * should be made available for retrieval; one of the following constants:
191     * Statement.RETURN_GENERATED_KEYS Statement.NO_GENERATED_KEYS
192     * @return either the row count for INSERT, UPDATE or DELETE; or 0
193     * for SQL statements that return nothing
194     * @exception SQLException if a database access error occurs
195     */
196        public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
197        {
198                execute(sql, false, true, autoGeneratedKeys, null, null);
199                return updateCount;
200        }
201 
202    /**
203     * JDBC 3.0
204     *
205     * Executes the given SQL statement and signals the driver that the
206     * auto-generated keys indicated in the given array should be made
207     * available for retrieval. The driver will ignore the array if the SQL
208     * statement is not an INSERT statement
209     *
210     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
211     * statement that returns nothing
212     * @param columnIndexes - an array of column indexes indicating the
213     * columns that should be returned from the inserted row
214     * @return either the row count for INSERT, UPDATE or DELETE; or 0
215     * for SQL statements that return nothing
216     * @exception SQLException if a database access error occurs
217     */
218        public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
219        {
220                 throw Util.notImplemented("executeUpdate(String, int[])");
221        }
222 
223    /**
224     * JDBC 3.0
225     *
226     * Executes the given SQL statement and signals the driver that the
227     * auto-generated keys indicated in the given array should be made
228     * available for retrieval. The driver will ignore the array if the SQL
229     * statement is not an INSERT statement
230     *
231     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
232     * statement that returns nothing
233     * @param columnNames - an array of the names of the columns
234     * that should be returned from the inserted row
235     * @return either the row count for INSERT, UPDATE or DELETE; or 0
236     * for SQL statements that return nothing
237     * @exception SQLException if a database access error occurs
238     */
239        public int executeUpdate(String sql, String[] columnNames) throws SQLException
240        {
241                 throw Util.notImplemented("executeUpdate(String, String[])");
242        }
243 
244        final void checkIfInMiddleOfBatch() throws SQLException {
245                /* If batchStatements is not null then we are in the middle
246                 * of a batch. That's an invalid state. We need to finish the
247                 * batch either by clearing the batch or executing the batch.
248                 * executeUpdate is not allowed inside the batch.
249                 */
250                if (batchStatements != null)
251                  throw newSQLException(SQLState.MIDDLE_OF_BATCH);
252        }
253 
254    /**
255     * Tell whether this statment has been closed or not.
256     *
257     * @return <code>true</code> is closed, <code>false</code> otherwise.
258     * @exception SQLException if a database access error occurs.
259     */
260    public boolean isClosed() throws SQLException {
261        // If active, verify state by consulting parent connection.
262        if (active) {
263            try {
264                checkExecStatus();
265            } catch (SQLException sqle) {
266            }
267        }
268        return !active;
269    }
270 
271    /**
272     * In many cases, it is desirable to immediately release a
273     * Statements's database and JDBC resources instead of waiting for
274     * this to happen when it is automatically closed; the close
275     * method provides this immediate release.
276     *
277     * <P><B>Note:</B> A Statement is automatically closed when it is
278     * garbage collected. When a Statement is closed its current
279     * ResultSet, if one exists, is also closed.
280         * @exception SQLException thrown on failure.
281     */
282        public final void close() throws SQLException {
283 
284                /* The close() method is the only method
285                 * that is allowed to be called on a closed
286                 * Statement, as per Jon Ellis.
287                 */
288                if (!active)
289                {
290                        return;
291                }
292 
293          synchronized (getConnectionSynchronization()) {
294 
295                  closeActions();
296                  
297                  //we first set the status
298                  active = false;
299 
300                  //first, clear the resutl set
301                  clearResultSets();
302                  
303                  //next, release other resource
304                  cursorName = null;
305                  warnings = null;
306                  SQLText = null;
307                  batchStatements = null;
308          }
309        }
310 
311        // allow sub-classes to execute additional close
312        // logic while holding the synchronization.
313        void closeActions() throws SQLException {
314        }
315 
316    //----------------------------------------------------------------------
317 
318    /**
319     * The maxFieldSize limit (in bytes) is the maximum amount of data
320     * returned for any column value; it only applies to BINARY,
321     * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR
322     * columns.  If the limit is exceeded, the excess data is silently
323     * discarded.
324     *
325     * @return the current max column size limit; zero means unlimited
326         * @exception SQLException thrown on failure.
327     */
328        public int getMaxFieldSize() throws SQLException {
329                checkStatus();
330 
331        return MaxFieldSize;
332        }
333 
334    /**
335     * The maxFieldSize limit (in bytes) is set to limit the size of
336     * data that can be returned for any column value; it only applies
337     * to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and
338     * LONGVARCHAR fields.  If the limit is exceeded, the excess data
339     * is silently discarded.
340     *
341     * @param max the new max column size limit; zero means unlimited
342         * @exception SQLException thrown on failure.
343     */
344        public void setMaxFieldSize(int max) throws SQLException {
345                checkStatus();
346 
347                if (max < 0)
348                {
349                        throw newSQLException(SQLState.INVALID_MAXFIELD_SIZE, new Integer(max));
350                }
351        this.MaxFieldSize = max;
352        }
353 
354    /**
355     * The maxRows limit is the maximum number of rows that a
356     * ResultSet can contain.  If the limit is exceeded, the excess
357     * rows are silently dropped.
358     *
359     * @return the current max row limit; zero means unlimited
360         * @exception SQLException thrown on failure.
361     */
362        public int getMaxRows() throws SQLException 
363        {
364                checkStatus();
365                return maxRows;
366        }
367 
368    /**
369     * The maxRows limit is set to limit the number of rows that any
370     * ResultSet can contain.  If the limit is exceeded, the excess
371     * rows are silently dropped.
372     *
373     * @param max the new max rows limit; zero means unlimited
374         * @exception SQLException thrown on failure.
375     */
376        public void setMaxRows(int max) throws SQLException        
377        {
378                checkStatus();
379                if (max < 0)
380                {
381                        throw newSQLException(SQLState.INVALID_MAX_ROWS_VALUE, new Integer(max));
382                }
383                this.maxRows = max;
384        }
385 
386    /**
387     * If escape scanning is on (the default) the driver will do
388     * escape substitution before sending the SQL to the database.
389     *
390     * @param enable true to enable; false to disable
391         * @exception SQLException thrown on failure.
392     */
393        public void setEscapeProcessing(boolean enable) throws SQLException        {
394                checkStatus();
395        // Nothing to do in our server , just ignore it.
396 
397        }
398 
399    /**
400     * The queryTimeout limit is the number of seconds the driver will
401     * wait for a Statement to execute. If the limit is exceeded a
402     * SQLException is thrown.
403     *
404     * @return the current query timeout limit in seconds; zero means unlimited
405         * @exception SQLException thrown on failure.
406     */
407        public final int getQueryTimeout() throws SQLException {
408        checkStatus();
409        return timeoutSeconds;
410        }
411 
412    /**
413     * The queryTimeout limit is the number of seconds the driver will
414     * wait for a Statement to execute. If the limit is exceeded a
415     * SQLException is thrown.
416     *
417     * @param seconds the new query timeout limit in seconds; zero means unlimited
418         * @exception SQLException thrown on failure.
419     */
420        public final void setQueryTimeout(int seconds) throws SQLException {
421                checkStatus();
422        if (seconds < 0) {
423            throw newSQLException(SQLState.INVALID_QUERYTIMEOUT_VALUE,
424                                  new Integer(seconds));
425        }
426        timeoutSeconds = seconds;
427        }
428 
429    /**
430     * Cancel can be used by one thread to cancel a statement that
431     * is being executed by another thread.
432         * @exception SQLException thrown on failure.
433     */
434        public void cancel() throws SQLException {
435                throw Util.notImplemented("cancel");
436        }
437 
438    /**
439     * The first warning reported by calls on this Statement is
440     * returned.  A Statment's execute methods clear its SQLWarning
441     * chain. Subsequent Statement warnings will be chained to this
442     * SQLWarning.
443     *
444     * <p>The warning chain is automatically cleared each time
445     * a statement is (re)executed.
446     *
447     * <P><B>Note:</B> If you are processing a ResultSet then any
448     * warnings associated with ResultSet reads will be chained on the
449     * ResultSet object.
450     *
451     * @return the first SQLWarning or null
452         * @exception SQLException thrown on failure.
453     */
454        public SQLWarning getWarnings() throws SQLException        {
455                checkStatus();
456                return warnings;
457        }
458 
459    /**
460     * After this call getWarnings returns null until a new warning is
461     * reported for this Statement.
462         * @exception SQLException thrown on failure.
463     */
464        public void clearWarnings() throws SQLException        {
465                checkStatus();
466                warnings = null;
467        }
468 
469    /**
470     * setCursorName defines the SQL cursor name that will be used by
471     * subsequent Statement execute methods. This name can then be
472     * used in SQL positioned update/delete statements to identify the
473     * current row in the ResultSet generated by this statement.  If
474     * the database doesn't support positioned update/delete, this
475     * method is a noop.
476     *
477     * <P><B>Note:</B> By definition, positioned update/delete
478     * execution must be done by a different Statement than the one
479     * which generated the ResultSet being used for positioning. Also,
480     * cursor names must be unique within a Connection.
481     *
482     * @param name the new cursor name.
483     */
484        public void setCursorName(String name) throws SQLException {
485                checkStatus();
486                cursorName = name;
487        }
488 
489    //----------------------- Multiple Results --------------------------
490 
491    /**
492     * Execute a SQL statement that may return multiple results.
493     * Under some (uncommon) situations a single SQL statement may return
494     * multiple result sets and/or update counts.  Normally you can ignore
495     * this, unless you're executing a stored procedure that you know may
496     * return multiple results, or unless you're dynamically executing an
497     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"
498     * and "getUpdateCount" methods let you navigate through multiple results.
499     *
500     * The "execute" method executes a SQL statement and indicates the
501     * form of the first result.  You can then use getResultSet or
502     * getUpdateCount to retrieve the result, and getMoreResults to
503     * move to any subsequent result(s).
504     *
505     * @param sql                                        any SQL statement
506         *
507     * @return true if the first result is a ResultSet; false if it is an integer
508     * @see #getResultSet
509     * @see #getUpdateCount
510     * @see #getMoreResults
511         * @exception SQLException thrown on failure
512     */
513        public boolean execute(String sql)
514                throws SQLException
515        {
516                return execute(sql, false, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
517        }
518        
519    /**
520     * Execute a SQL statement that may return multiple results.
521     * Under some (uncommon) situations a single SQL statement may return
522     * multiple result sets and/or update counts.  Normally you can ignore
523     * this, unless you're executing a stored procedure that you know may
524     * return multiple results, or unless you're dynamically executing an
525     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"
526     * and "getUpdateCount" methods let you navigate through multiple results.
527     *
528     * The "execute" method executes a SQL statement and indicates the
529     * form of the first result.  You can then use getResultSet or
530     * getUpdateCount to retrieve the result, and getMoreResults to
531     * move to any subsequent result(s).
532     *
533     * @param sql                                        any SQL statement
534         * @param executeQuery                        caller is executeQuery()
535         * @param executeUpdate                        caller is executeUpdate()
536     * @param autoGeneratedKeys
537     * @param columnIndexes
538     * @param columnNames
539         *
540     * @return true if the first result is a ResultSet; false if it is an integer
541     * @see #getResultSet
542     * @see #getUpdateCount
543     * @see #getMoreResults
544         * @exception SQLException thrown on failure
545     */
546        private boolean execute(String sql, boolean executeQuery, boolean executeUpdate,
547                int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException
548        {
549          synchronized (getConnectionSynchronization()) {
550 
551                checkExecStatus();
552                if (sql == null) {
553                        throw newSQLException(SQLState.NULL_SQL_TEXT);
554                }
555                checkIfInMiddleOfBatch();
556                clearResultSets(); // release the last statement executed, if any.
557 
558        setupContextStack(); // make sure there's context
559 
560 
561                // try to remember the SQL statement in case anybody asks for it
562                SQLText = sql;                
563 
564                try {
565                        Activation activation;
566                        try {
567                                PreparedStatement preparedStatement = lcc.prepareInternalStatement
568                                    (lcc.getDefaultSchema(), sql, resultSetConcurrency==JDBC20Translation.CONCUR_READ_ONLY, false);
569                                activation =
570                                        preparedStatement.getActivation(lcc, resultSetType == JDBC20Translation.TYPE_SCROLL_INSENSITIVE);
571                                checkRequiresCallableStatement(activation);
572                         } catch (Throwable t) {
573                                throw handleException(t);
574                         }
575 
576 
577                        // this is for a Statement execution
578                        activation.setSingleExecution();
579 
580                        //bug 4838 - save the auto-generated key information in activation. keeping this
581                        //information in lcc will not work work it can be tampered by a nested trasaction
582                        if (autoGeneratedKeys == JDBC30Translation.RETURN_GENERATED_KEYS)
583                                activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);
584                        return executeStatement(activation, executeQuery, executeUpdate);
585                } finally {
586                    restoreContextStack();
587                }
588          }
589        }
590 
591    /**
592     * JDBC 3.0
593     *
594     * Executes the given SQL statement, which may return multiple
595     * results, and signals the driver that any auto-generated keys
596     * should be made available for retrieval. The driver will ignore
597     * this signal if the SQL statement is not an INSERT statement.
598     *
599     * @param sql any SQL statement
600     * @param autoGeneratedKeys - a constant indicating whether
601     * auto-generated keys should be made available for retrieval using
602     * the method getGeneratedKeys; one of the following constants:
603     * Statement.RETURN_GENERATED_KEYS or Statement.NO_GENERATED_KEYS
604     * @return rue if the first result is a ResultSet object; false if
605     * it is an update count or there are no results
606     * @exception SQLException if a database access error occurs
607     */
608        public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
609        {
610                return execute(sql, false, false, autoGeneratedKeys, null, null);
611        }
612 
613    /**
614     * JDBC 3.0
615     *
616     * Executes the given SQL statement, which may return multiple
617     * results, and signals the driver that the auto-generated keys
618     * indicated in the given array should be made available for retrieval.
619     * This array contains the indexes of the columns in the target table
620     * that contain the auto-generated keys that should be made available.
621     * The driver will ignore the array if the given SQL statement is not an
622     * INSERT statement.
623     *
624     * @param sql any SQL statement
625     * @param columnIndexes - an array of the indexes of the columns in the
626     * inserted row that should be made available for retrieval by a call to
627     * the method getGeneratedKeys
628     * @return rue if the first result is a ResultSet object; false if
629     * it is an update count or there are no results
630     * @exception SQLException if a database access error occurs
631     */
632        public boolean execute(String sql, int[] columnIndexes) throws SQLException
633        {
634                 throw Util.notImplemented("execute(String, int[])");
635        }
636 
637    /**
638     * JDBC 3.0
639     *
640     * Executes the given SQL statement, which may return multiple
641     * results, and signals the driver that the auto-generated keys
642     * indicated in the given array should be made available for retrieval.
643     * This array contains the names of the columns in the target table
644     * that contain the auto-generated keys that should be made available.
645     * The driver will ignore the array if the given SQL statement is not an
646     * INSERT statement.
647     *
648     * @param sql any SQL statement
649     * @param columnNames - an array of the names of the columns in the
650     * inserted row that should be made available for retrieval by a call to
651     * the method getGeneratedKeys
652     * @return rue if the first result is a ResultSet object; false if
653     * it is an update count or there are no results
654     * @exception SQLException if a database access error occurs
655     */
656        public boolean execute(String sql, String[] columnNames) throws SQLException
657        {
658                 throw Util.notImplemented("execute(String, String[])");
659        }
660 
661    /**
662     *  getResultSet returns the current result as a ResultSet.  It
663     *  should only be called once per result.
664     *
665     * @return the current result as a ResultSet; null if the result
666     * is an update count or there are no more results or the statement
667         * was closed.
668     * @see #execute
669     */
670        public final java.sql.ResultSet getResultSet() throws SQLException  {
671                checkStatus();
672 
673                return results;
674        }
675 
676    /**
677     *  getUpdateCount returns the current result as an update count;
678     *  if the result is a ResultSet or there are no more results -1
679     *  is returned.  It should only be called once per result.
680     *
681     * <P>The only way to tell for sure that the result is an update
682     *  count is to first test to see if it is a ResultSet. If it is
683     *  not a ResultSet it is either an update count or there are no
684     *  more results.
685     *
686     * @return the current result as an update count; -1 if it is a
687     * ResultSet or there are no more results
688     * @see #execute
689     */
690        public final int getUpdateCount()        throws SQLException  {
691                checkStatus();
692                return updateCount;
693        }
694 
695    /**
696     * getMoreResults moves to a Statement's next result.  It returns true if
697     * this result is a ResultSet.  getMoreResults also implicitly
698     * closes any current ResultSet obtained with getResultSet.
699     *
700     * There are no more results when (!getMoreResults() &&
701     * (getUpdateCount() == -1)
702     *
703     * @return true if the next result is a ResultSet; false if it is
704     * an update count or there are no more results
705     * @see #execute
706         * @exception SQLException thrown on failure.
707     */
708        public final boolean getMoreResults() throws SQLException        {
709                return getMoreResults(JDBC30Translation.CLOSE_ALL_RESULTS);
710        }
711 
712        /////////////////////////////////////////////////////////////////////////
713        //
714        //        JDBC 2.0 methods that are implemented here because EmbedPreparedStatement
715        //  and EmbedCallableStatement in Local20 need access to them, and those
716        //        classes extend their peer classes in Local, instead of EmbedStatement
717        //        in Local20
718        //
719        //  We do the same of JDBC 3.0 methods.
720        /////////////////////////////////////////////////////////////////////////
721 
722    /**
723     * JDBC 2.0
724     *
725     * Determine the result set type.
726     *
727     * @exception SQLException Feature not implemented for now.
728     */
729    public final int getResultSetType()
730                throws SQLException 
731        {
732                checkStatus();
733                return resultSetType;
734        }
735 
736 
737    /**
738     * JDBC 2.0
739     *
740     * Give a hint as to the direction in which the rows in a result set
741     * will be processed. The hint applies only to result sets created
742     * using this Statement object.  The default value is 
743     * ResultSet.FETCH_FORWARD.
744     *
745     * @param direction the initial direction for processing rows
746     * @exception SQLException if a database-access error occurs or direction
747     * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
748     * ResultSet.FETCH_UNKNOWN
749     */
750    public void setFetchDirection(int direction) throws SQLException {
751                
752                checkStatus();
753                /* fetch direction is meaningless to us. we just save
754                 * it off if it is valid  and return the current value if asked.
755                 */
756                if (direction == JDBC20Translation.FETCH_FORWARD || 
757                    direction == JDBC20Translation.FETCH_REVERSE ||
758                    direction == JDBC20Translation.FETCH_UNKNOWN )
759                {
760                    fetchDirection = direction;
761                }else
762                    throw newSQLException(SQLState.INVALID_FETCH_DIRECTION, 
763                                   new Integer(direction));
764        }
765 
766    /**
767     * JDBC 2.0
768     *
769     * Determine the fetch direction.
770     *
771     * @return the default fetch direction
772     * @exception SQLException if a database-access error occurs
773     */
774    public int getFetchDirection() throws SQLException {
775                checkStatus();
776                return fetchDirection;
777        }
778 
779 
780    /**
781     * JDBC 2.0
782     *
783     * Give the JDBC driver a hint as to the number of rows that should
784     * be fetched from the database when more rows are needed.  The number 
785     * of rows specified only affects result sets created using this 
786     * statement. If the value specified is zero, then the hint is ignored.
787     * The default value is zero.
788     *
789     * @param rows the number of rows to fetch
790     * @exception SQLException if a database-access error occurs, or the
791     * condition 0 <= rows <= this.getMaxRows() is not satisfied.
792     */
793    public void setFetchSize(int rows) throws SQLException {
794                checkStatus();
795        if (rows < 0  || (this.getMaxRows() != 0 && 
796                             rows > this.getMaxRows()))
797        {
798                throw newSQLException(SQLState.INVALID_ST_FETCH_SIZE, new Integer(rows));
799        }else if ( rows > 0 ) // ignore the call if the value is zero
800            fetchSize = rows;
801        }
802  
803    /**
804     * JDBC 2.0
805     *
806     * Determine the default fetch size.
807     * @exception SQLException if a database-access error occurs
808     *
809     */
810    public int getFetchSize() throws SQLException {
811                checkStatus();
812                return fetchSize;
813        }
814 
815    /**
816     * JDBC 2.0
817     *
818     * Determine the result set concurrency.
819     *
820     * @exception SQLException Feature not implemented for now.
821     */
822    public int getResultSetConcurrency() throws SQLException {
823                checkStatus();
824                return resultSetConcurrency;
825        }
826 
827    /**
828     * JDBC 3.0
829     *
830     * Retrieves the result set holdability for ResultSet objects
831     * generated by this Statement object.
832     *
833     * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or
834     * ResultSet.CLOSE_CURSORS_AT_COMMIT
835     * @exception SQLException Feature not implemented for now.
836     */
837    public final int getResultSetHoldability() throws SQLException {
838                checkStatus();
839                return resultSetHoldability;
840        }
841 
842    /**
843     * JDBC 2.0
844     *
845     * Adds a SQL command to the current batch of commmands for the statement.
846     * This method is optional.
847     *
848     * @param sql typically this is a static SQL INSERT or UPDATE statement
849     * @exception SQLException if a database-access error occurs, or the
850     * driver does not support batch statements
851     */
852    public void addBatch( String sql ) throws SQLException {
853                checkStatus();
854            synchronized (getConnectionSynchronization()) {
855                  if (batchStatements == null)
856                          batchStatements = new Vector();
857        batchStatements.addElement(sql);
858                  }
859        }
860 
861    /**
862     * JDBC 2.0
863     *
864     * Make the set of commands in the current batch empty.
865     * This method is optional.
866     *
867     * @exception SQLException if a database-access error occurs, or the
868     * driver does not support batch statements
869     */
870    public final void clearBatch() throws SQLException {
871                checkStatus();
872            synchronized (getConnectionSynchronization()) {
873        batchStatements = null;
874                  }
875        }
876 
877    /**
878     * JDBC 2.0
879     * 
880     * Submit a batch of commands to the database for execution.
881     * This method is optional.
882         *
883         * Moving jdbc2.0 batch related code in this class because
884         * callableStatement in jdbc 20 needs this code too and it doesn't derive
885         * from prepared statement in jdbc 20 in our implementation. 
886         * BatchUpdateException is the only new class from jdbc 20 which is being
887         * referenced here and in order to avoid any jdk11x problems, using
888         * reflection code to make an instance of that class. 
889     *
890     * @return an array of update counts containing one element for each
891     * command in the batch.  The array is ordered according
892     * to the order in which commands were inserted into the batch
893     * @exception SQLException if a database-access error occurs, or the
894     * driver does not support batch statements
895     */
896    public int[] executeBatch() throws SQLException {
897                checkExecStatus();
898                synchronized (getConnectionSynchronization()) 
899                {
900                        setupContextStack();
901                        int i = 0;
902                        // As per the jdbc 2.0 specs, close the statement object's current resultset
903                        // if one is open.
904                        // Are there results?
905                        // outside of the lower try/finally since results will
906                        // setup and restore themselves.
907                        clearResultSets();
908 
909                        Vector stmts = batchStatements;
910                        batchStatements = null;
911                        int size;
912                        if (stmts == null)
913                                size = 0;
914                        else
915                                size = stmts.size();
916 
917                        int[] returnUpdateCountForBatch = new int[size];
918 
919                        SQLException sqle;
920                        try {
921                                for (; i< size; i++) 
922                                {
923                                        if (executeBatchElement(stmts.elementAt(i)))
924                                                throw newSQLException(SQLState.RESULTSET_RETURN_NOT_ALLOWED);
925                                        returnUpdateCountForBatch[i] = getUpdateCount();
926                                }
927                                return returnUpdateCountForBatch;
928                        }
929                        catch (StandardException se) {
930 
931                                sqle = handleException(se);
932                        }
933                        catch (SQLException sqle2) 
934                        {
935                                sqle = sqle2;
936                        }
937                        finally 
938                        {
939                                restoreContextStack();
940                        }
941 
942                        int successfulUpdateCount[] = new int[i];
943                        for (int j=0; j<i; j++)
944                        {
945                                successfulUpdateCount[j] = returnUpdateCountForBatch[j];
946                        }
947 
948                        SQLException batch =
949                        new java.sql.BatchUpdateException(sqle.getMessage(), sqle.getSQLState(),
950                                                                        sqle.getErrorCode(), successfulUpdateCount);
951 
952                        batch.setNextException(sqle);
953                        throw batch;
954      }
955        }
956 
957        /**
958                Execute a single element of the batch. Overridden by EmbedPreparedStatement
959        */
960        boolean executeBatchElement(Object batchElement) throws SQLException, StandardException {
961                return execute((String)batchElement, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);
962        }
963 
964    /**
965     * JDBC 2.0
966     *
967     * Return the Connection that produced the Statement.
968     *
969     * @exception SQLException Exception if it cannot find the connection
970     * associated to this statement.
971     */
972    public final java.sql.Connection getConnection()  throws SQLException {
973                checkStatus();
974 
975            java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();
976                if ((appConn != applicationConnection) || (appConn == null)) {
977 
978                        throw Util.noCurrentConnection();
979        }
980                return appConn;
981    }
982 
983    /**
984     * JDBC 3.0
985     *
986     * Moves to this Statement obect's next result, deals with any current ResultSet
987     * object(s) according to the instructions specified by the given flag, and
988     * returns true if the next result is a ResultSet object
989     *
990     * @param current - one of the following Statement constants indicating what
991     * should happen to current ResultSet objects obtained using the method
992     * getResultSetCLOSE_CURRENT_RESULT, KEEP_CURRENT_RESULT, or CLOSE_ALL_RESULTS
993     * @return true if the next result is a ResultSet; false if it is
994     * an update count or there are no more results
995     * @see #execute
996     * @exception SQLException thrown on failure.
997     */
998        public final boolean getMoreResults(int current) throws SQLException        {
999                checkExecStatus();
1000 
1001                synchronized (getConnectionSynchronization()) {
1002                        if (dynamicResults == null) {
1003                                // we only have the one resultset, so this is
1004                                // simply a close for us.
1005                                clearResultSets();
1006                                return false;
1007                        }
1008 
1009                        int startingClose;
1010                        switch (current) {
1011                        default:
1012                        case JDBC30Translation.CLOSE_ALL_RESULTS:
1013                                startingClose = 0;
1014                                break;
1015                        case JDBC30Translation.CLOSE_CURRENT_RESULT:
1016                                // just close the current result set.
1017                                startingClose = currentDynamicResultSet;
1018                                break;
1019                        case JDBC30Translation.KEEP_CURRENT_RESULT:
1020                                // make the close loop a no-op.
1021                                startingClose = dynamicResults.length;
1022                                break;
1023                        }
1024 
1025                        // Close loop.
1026                        SQLException se = null;
1027                        for (int i = startingClose; i <= currentDynamicResultSet && i < dynamicResults.length; i++) {
1028                                EmbedResultSet lrs = dynamicResults[i];
1029                                if (lrs == null)
1030                                        continue;
1031 
1032 
1033                                try {
1034                                        lrs.close();
1035                                } catch (SQLException sqle) {
1036                                        if (se == null)
1037                                                se = sqle;
1038                                        else
1039                                                se.setNextException(sqle);
1040                                } finally {
1041                                        dynamicResults[i] = null;
1042                                }
1043                        }
1044 
1045                        if (se != null) {
1046                                // leave positioned on the current result set (?)
1047                                throw se;
1048                        }
1049 
1050                        updateCount = -1;
1051 
1052                        while (++currentDynamicResultSet < dynamicResults.length) {
1053 
1054                                EmbedResultSet lrs = dynamicResults[currentDynamicResultSet];
1055                                if (lrs != null) {
1056                                        if (lrs.isClosed) {
1057                                                dynamicResults[currentDynamicResultSet] = null;
1058                                                continue;
1059                                        }
1060 
1061                                        results = lrs;
1062 
1063                                        return true;
1064                                }
1065                        }
1066 
1067                        results = null;
1068                        return false;
1069                }
1070        }
1071 
1072    /**
1073     * JDBC 3.0
1074     *
1075     * Retrieves any auto-generated keys created as a result of executing this
1076     * Statement object. If this Statement is a non-insert statement,
1077     * a null ResultSet object is returned.
1078     *
1079     * @return a ResultSet object containing the auto-generated key(s) generated by
1080     * the execution of this Statement object
1081     * @exception SQLException if a database access error occurs
1082     */
1083        public final java.sql.ResultSet getGeneratedKeys() throws SQLException        {
1084                checkStatus();
1085                if (autoGeneratedKeysResultSet == null)
1086                        return null;
1087                else {
1088                        execute("VALUES IDENTITY_VAL_LOCAL()", true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
1089                        return results;
1090                }
1091        }
1092 
1093        /////////////////////////////////////////////////////////////////////////
1094        //
1095        //        Implementation specific methods        
1096        //
1097        /////////////////////////////////////////////////////////////////////////
1098 
1099        /**
1100                Execute the current statement.
1101            @exception SQLException thrown on failure.
1102        */
1103        boolean executeStatement(Activation a,
1104                     boolean executeQuery, boolean executeUpdate)
1105                     throws SQLException {
1106 
1107                // we don't differentiate the update from the resultset case.
1108                // so, there could be a result set.
1109 
1110                // note: the statement interface will paste together
1111                // an activation and make sure the prepared statement
1112                // is still valid, so it is preferrable, for now,
1113                // to creating our own activation and stuffing it in
1114                // the prepared statement.
1115 
1116                synchronized (getConnectionSynchronization()) {
1117                        setupContextStack(); // make sure there's context
1118                        boolean retval;
1119 
1120                        pvs = a.getParameterValueSet();
1121 
1122                        try {
1123                                // The following is from the javadoc for java.sql.Statement
1124                                // Only one ResultSet per Statement can be open at any point in time.
1125                                // Therefore, if the reading of one ResultSet is interleaved with the
1126                                // reading of another, each must have been generated by different Statements.
1127                                // All statement execute methods implicitly close a
1128                                // statment's current ResultSet if an open one exists. 
1129                                if (results != null) {
1130                                        results.close();
1131                                        results = null;
1132                                }
1133 
1134                                clearWarnings();
1135 
1136                                if (! forMetaData) {
1137                                        commitIfNeeded(); // commit the last statement if needed
1138                                        needCommit();
1139                                } else {
1140 
1141 
1142                                if (lcc.getActivationCount() > 1) {
1143                                       // we do not want to commit here as there seems to be other
1144                                          // statements/resultSets currently opened for this connection.
1145                                        } else {
1146                                                commitIfNeeded(); // we can legitimately commit
1147                                                needCommit();
1148                                        }
1149                                }
1150 
1151                                // if this was a prepared statement, this just
1152                                // gets it for us, it won't recompile unless it is invalid.
1153                                PreparedStatement ps = a.getPreparedStatement();
1154                                ps.rePrepare(lcc);
1155                                addWarning(ps.getCompileTimeWarnings());
1156 
1157 
1158                                /*
1159                                ** WARNING WARNING
1160                                **
1161                                ** Any state set in the activation before execution *must* be copied
1162                                ** to the new activation in GenericActivationHolder.execute() when
1163                                ** the statement has been recompiled. State such as
1164                                ** singleExecution, cursorName, holdability, maxRows.
1165                                */
1166 
1167                                if (cursorName != null)
1168                                {
1169                                        a.setCursorName(cursorName);
1170                                }
1171                
1172                boolean executeHoldable = getExecuteHoldable();
1173 
1174                                a.setResultSetHoldability(executeHoldable);
1175 
1176                                //reset the activation to clear warnings
1177                                //and clear existing result sets in case this has been cached
1178                                a.reset();
1179                                a.setMaxRows(maxRows);
1180                long timeoutMillis = (long)timeoutSeconds * 1000L;
1181                ResultSet resultsToWrap = ps.execute(a,
1182                                                     false,
1183                                                     timeoutMillis);
1184                                addWarning(a.getWarnings());
1185 
1186 
1187                                if (resultsToWrap.returnsRows()) {
1188 
1189                    // The statement returns rows, so calling it with
1190                    // executeUpdate() is not allowed.
1191                    if (executeUpdate) {
1192                        throw StandardException.newException(
1193                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
1194                    }
1195 
1196                                        EmbedResultSet lresults = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap, forMetaData, this, ps.isAtomic());
1197                                        results = lresults;
1198 
1199 
1200                                        // Set up the finalization of the ResultSet to
1201                                        // mark the activation as unused. It will be
1202                                        // closed sometime later by the connection
1203                                        // outside of finalization.
1204                                        if (a.isSingleExecution())
1205                                                lresults.finalizeActivation = a;
1206 
1207                                        updateCount = -1;
1208                                        retval = true;
1209                                }
1210                                else {
1211 
1212                                        // Only applipable for an insert statement, which does not return rows.
1213                                        //the auto-generated keys resultset will be null if used for non-insert statement
1214                                        if (a.getAutoGeneratedKeysResultsetMode() && (resultsToWrap.getAutoGeneratedKeysResultset() != null))
1215                                        {
1216                                                resultsToWrap.getAutoGeneratedKeysResultset().open();
1217                                                autoGeneratedKeysResultSet = factory.newEmbedResultSet(getEmbedConnection(),
1218                                                        resultsToWrap.getAutoGeneratedKeysResultset(), false, this, ps.isAtomic());
1219                                        }
1220 
1221                                        updateCount = resultsToWrap.modifiedRowCount();
1222 
1223                                        resultsToWrap.finish();        // Don't need the result set any more
1224                                        results = null; // note that we have none.
1225 
1226                    int dynamicResultCount = 0;
1227                                        if (a.getDynamicResults() != null) {
1228                        dynamicResultCount =
1229                            processDynamicResults(a.getDynamicResults(),
1230                                                  a.getMaxDynamicResults());
1231                                        }
1232 
1233                    // executeQuery() is not allowed if the statement
1234                    // doesn't return exactly one ResultSet.
1235                    if (executeQuery && dynamicResultCount != 1) {
1236                        throw StandardException.newException(
1237                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_QUERY);
1238                    }
1239 
1240                    // executeUpdate() is not allowed if the statement
1241                    // returns ResultSets.
1242                    if (executeUpdate && dynamicResultCount > 0) {
1243                        throw StandardException.newException(
1244                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
1245                    }
1246                                        
1247                    if (dynamicResultCount == 0) {
1248                                                if (a.isSingleExecution()) {
1249                                                        a.close();
1250                                                }
1251 
1252                                                if (!forMetaData)
1253                                                        commitIfNeeded();
1254                                                else {
1255 
1256                                                        if (lcc.getActivationCount() > 1) {
1257                                                          // we do not want to commit here as there seems to be other
1258                                                          // statements/resultSets currently opened for this connection.
1259                                                        } else {
1260                                                                commitIfNeeded(); // we can legitimately commit
1261                                                        }
1262                                                }
1263                                        }
1264 
1265                    retval = (dynamicResultCount > 0);
1266                                }
1267                } catch (Throwable t) {
1268                                if (a.isSingleExecution()) {
1269                                        try { a.close(); } catch (Throwable tt) {;}
1270                                }
1271                        throw handleException(t);
1272                        } finally {
1273                            restoreContextStack();
1274                        }
1275                        return retval;
1276                }
1277        }
1278 
1279    /**
1280     * Add a SQLWarning to this Statement object.
1281     * If the Statement already has a SQLWarning then it
1282     * is added to the end of the chain.
1283     * 
1284     * @see #getWarnings()
1285     */
1286        final void addWarning(SQLWarning sw)
1287        {
1288                if (sw != null) {
1289                        if (warnings == null)
1290                                warnings = sw;
1291                        else
1292                                warnings.setNextException(sw);
1293                }
1294        }
1295 
1296 
1297        /* package */
1298        public String getSQLText()
1299        {
1300                // no need to synchronize - accessing a reference is atomic
1301                // synchronized (getConnectionSynchronization()) 
1302                return SQLText;
1303        }
1304 
1305        public ParameterValueSet getParameterValueSet()
1306        {
1307                return pvs;
1308        }
1309 
1310        /**
1311     * Throw an exception if this Statement has been closed explictly
1312     * or it has noticed it has been closed implicitly.
1313     * JDBC specifications require nearly all methods throw a SQLException
1314     * if the Statement has been closed, thus most methods call this
1315     * method or checkExecStatus first.
1316     * 
1317     * @exception SQLException Thrown if the statement is marked as closed.
1318     * 
1319     * @see #checkExecStatus()
1320         */
1321    final void checkStatus() throws SQLException {
1322 
1323                if (!active)
1324                        throw newSQLException(SQLState.ALREADY_CLOSED, "Statement");
1325        }
1326 
1327        /**
1328                A heavier weight version of checkStatus() that ensures the application's Connection
1329                object is still open. This is to stop errors or unexpected behaviour when a [Prepared]Statement
1330                object is used after the application has been closed. In particular to ensure that
1331                a Statement obtained from a PooledConnection cannot be used after the application has closed
1332                its connection (as the underlying Connection is still active).
1333                To avoid this heavier weight check on every method of [Prepared]Statement it is only used
1334                on those methods that would end up using the database's connection to read or modify data.
1335                E.g. execute*(), but not setXXX, etc.
1336        <BR>
1337        If this Statement's Connection is closed an exception will
1338        be thrown and the active field will be set to false,
1339        completely marking the Statement as closed.
1340        <BR>
1341        If the Statement is not currently connected to an active
1342        transaction, i.e. a suspended global transaction, then
1343        this method will throw a SQLException but the Statement
1344        will remain open. The Statement is open but unable to
1345        process any new requests until its global transaction
1346        is resumed.
1347        <BR>
1348        Upon return from the method, with or without a SQLException
1349        the field active will correctly represent the open state of
1350        the Statement.
1351        
1352        @exception SQLException Thrown if the statement is marked as closed
1353        or the Statement's transaction is suspended.
1354        
1355        @see #checkStatus()
1356        */
1357        final void checkExecStatus() throws SQLException {
1358                // getConnection() checks if the Statement is closed
1359                if (!getConnection().isClosed())
1360                        return;
1361        
1362        // Now this connection is closed for all
1363        // future use.
1364        active = false;
1365                
1366                throw Util.noCurrentConnection();
1367        }
1368 
1369        /**
1370                Close and clear all result sets associated with this statement
1371                from the last execution.
1372        */
1373        void clearResultSets() throws SQLException {
1374 
1375                SQLException sqle = null;
1376 
1377                try {
1378                        // Are there results?
1379                        // outside of the lower try/finally since results will
1380                        // setup and restore themselves.
1381                        if (results != null) {
1382                                results.close();
1383                                results = null;
1384                        }
1385                } catch (SQLException s1) {
1386                        sqle = s1;
1387                }
1388 
1389                try {
1390                        if (autoGeneratedKeysResultSet != null) {
1391                                autoGeneratedKeysResultSet.close();
1392                                autoGeneratedKeysResultSet = null;
1393                        }
1394                } catch (SQLException sauto) {
1395                        if (sqle == null)
1396                                sqle = sauto;
1397                        else
1398                                sqle.setNextException(sauto);
1399                }
1400 
1401                // close all the dynamic result sets.
1402                if (dynamicResults != null) {
1403                        for (int i = 0; i < dynamicResults.length; i++) {
1404                                EmbedResultSet lrs = dynamicResults[i];
1405                                if (lrs == null)
1406                                        continue;
1407 
1408                                try {
1409                                        lrs.close();
1410                                } catch (SQLException sdynamic) {
1411                                        if (sqle == null)
1412                                                sqle = sdynamic;
1413                                        else
1414                                                sqle.setNextException(sdynamic);
1415                                }
1416                        }
1417                        dynamicResults = null;
1418                }
1419 
1420                /*
1421                          We don't reset statement to null because PreparedStatement
1422                          relies on it being there for subsequent (post-close) execution
1423                          requests.  There is no close method on database statement objects.
1424                */
1425 
1426                updateCount = -1; // reset field
1427 
1428                if (sqle != null)
1429                        throw sqle;
1430         }  
1431        
1432        /**
1433                Check to see if a statement requires to be executed via a callable statement.
1434        */
1435        void checkRequiresCallableStatement(Activation activation) throws SQLException {
1436 
1437                ParameterValueSet pvs = activation.getParameterValueSet();
1438 
1439                if (pvs == null)
1440                        return;
1441 
1442                if (pvs.checkNoDeclaredOutputParameters()) {
1443                        try {
1444                                activation.close();
1445                        } catch (StandardException se) {
1446                        }
1447                        throw newSQLException(SQLState.REQUIRES_CALLABLE_STATEMENT, SQLText);
1448                }
1449        }
1450 
1451        /**
1452                Transfer my batch of Statements to a newly created Statement.
1453        */
1454        public void transferBatch(EmbedStatement other) throws SQLException {
1455                
1456                synchronized (getConnectionSynchronization()) {
1457                        other.batchStatements = batchStatements;
1458                        batchStatements = null;
1459                }
1460        }
1461    
1462    /**
1463     * Set the application statement for this Statement.
1464    */
1465    public final void setApplicationStatement(EngineStatement s) {
1466        this.applicationStatement = s;
1467    }
1468 
1469        private EmbedResultSet[] dynamicResults;
1470        private int currentDynamicResultSet;
1471 
1472    /**
1473     * Go through a holder of dynamic result sets, remove those that
1474     * should not be returned, and sort the result sets according to
1475     * their creation.
1476     *
1477     * @param holder a holder of dynamic result sets
1478     * @param maxDynamicResultSets the maximum number of result sets
1479     * to be returned
1480     * @return the actual number of result sets
1481     * @exception SQLException if an error occurs
1482     */
1483    private int processDynamicResults(java.sql.ResultSet[][] holder,
1484                                      int maxDynamicResultSets)
1485        throws SQLException
1486    {
1487 
1488                EmbedResultSet[] sorted = new EmbedResultSet[holder.length];
1489 
1490                int actualCount = 0;
1491                for (int i = 0; i < holder.length; i++) {
1492 
1493                        java.sql.ResultSet[] param = holder[i];
1494 
1495                        if (param[0] == null)
1496                                continue;
1497 
1498                        java.sql.ResultSet rs = param[0];
1499                        param[0] = null;
1500 
1501                        // ignore non-cloudscape result sets or results sets from another connection
1502                        if (!(rs instanceof EmbedResultSet))
1503                                continue;
1504 
1505                        EmbedResultSet lrs = (EmbedResultSet) rs;
1506 
1507                        if (lrs.getEmbedConnection().rootConnection != getEmbedConnection().rootConnection)
1508                                continue;
1509 
1510                        // ignore closed result sets.
1511                        if (lrs.isClosed)
1512                                continue;
1513 
1514                        lrs.setDynamicResultSet(this);
1515                        sorted[actualCount++] = lrs;
1516                }
1517 
1518                if (actualCount != 0) {
1519 
1520                        // results are defined to be ordered according to their creation
1521                        if (actualCount != 1) {
1522                                java.util.Arrays.sort(sorted, 0, actualCount);
1523                        }
1524 
1525                        dynamicResults = sorted;
1526 
1527                        if (actualCount > maxDynamicResultSets) {
1528                                addWarning(StandardException.newWarning(SQLState.LANG_TOO_MANY_DYNAMIC_RESULTS_RETURNED));
1529 
1530                                for (int i = maxDynamicResultSets; i < actualCount; i++) {
1531                                        sorted[i].close();
1532                                        sorted[i] = null;
1533                                }
1534 
1535                                actualCount = maxDynamicResultSets;
1536                        }
1537 
1538 
1539                        updateCount = -1;
1540                        results = sorted[0];
1541                        currentDynamicResultSet = 0;
1542 
1543                        // 0100C is not returned for procedures written in Java, from the SQL2003 spec.
1544                        // getWarnings(StandardException.newWarning(SQLState.LANG_DYNAMIC_RESULTS_RETURNED));
1545                }
1546 
1547 
1548                return actualCount;
1549        }
1550 
1551        /**
1552                Callback on the statement when one of its result sets is closed.
1553                This allows the statement to control when it completes and hence
1554                when it commits in auto commit mode.
1555 
1556        Must have connection synchronization and setupContextStack(), this
1557        is required for the call to commitIfNeeded().
1558        */
1559        void resultSetClosing(EmbedResultSet closingLRS) throws SQLException {
1560 
1561                // If the Connection is not in auto commit then this statement completion
1562                // cannot cause a commit.
1563                if (!getEmbedConnection().autoCommit)
1564                        return;
1565 
1566                // If we have dynamic results, see if there is another result set open.
1567                // If so, then no commit. The last result set to close will close the statement.
1568                if (dynamicResults != null) {
1569                        for (int i = 0; i < dynamicResults.length; i++) {
1570                                EmbedResultSet lrs = dynamicResults[i];
1571                                if (lrs == null)
1572                                        continue;
1573                                if (lrs.isClosed)
1574                                        continue;
1575                                if (lrs == closingLRS)
1576                                        continue;
1577 
1578                                // at least one still open so no commit now.
1579                                return;
1580                        }
1581                }
1582 
1583                // new Throwable("COMMIT ON " + SQLText).printStackTrace(System.out);
1584 
1585        // beetle 5383.  Force a commit in autocommit always.  Before this
1586        // change if client in autocommit opened a result set, did a commit,
1587        // then next then close a commit would not be forced on the close.
1588                commitIfAutoCommit();
1589        }
1590    
1591    /**
1592     * Get the execute time holdability for the Statement.
1593     * When in a global transaction holdabilty defaults to false.
1594     * @throws SQLException Error from getResultSetHoldability.
1595     */
1596    private boolean getExecuteHoldable() throws SQLException
1597    {
1598        if (resultSetHoldability  == JDBC30Translation.CLOSE_CURSORS_AT_COMMIT)
1599            return false;
1600        
1601        // Simple non-XA case
1602        if (applicationStatement == this)
1603            return true;
1604        
1605        return applicationStatement.getResultSetHoldability() ==
1606            JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
1607    }
1608 
1609        /**
1610         * Returns the value of the EmbedStatement's poolable hint,
1611         * indicating whether pooling is requested.
1612         *
1613         * @return The value of the poolable hint.
1614         * @throws SQLException if the Statement has been closed.
1615         */
1616 
1617        public boolean isPoolable() throws SQLException {
1618                // Assert the statement is still active (not closed)
1619                checkStatus();
1620 
1621                return isPoolable;
1622        }                
1623 
1624        /**
1625         * Requests that an EmbedStatement be pooled or not.
1626         *
1627         * @param poolable requests that the EmbedStatement be pooled if true
1628         * and not be pooled if false.
1629         * @throws SQLException if the EmbedStatement has been closed.
1630         */
1631     
1632        public void setPoolable(boolean poolable) throws SQLException {
1633                // Assert the statement is still active (not closed)
1634                checkStatus();
1635 
1636                isPoolable = poolable;
1637        }
1638}
1639 

[all classes][org.apache.derby.impl.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov