KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > jdbc > EmbedStatement


1 /*
2
3    Derby - Class org.apache.derby.impl.jdbc.EmbedStatement
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.jdbc;
23
24 import org.apache.derby.iapi.reference.JDBC20Translation;
25 import org.apache.derby.iapi.reference.JDBC30Translation;
26 import org.apache.derby.iapi.reference.SQLState;
27
28 import org.apache.derby.iapi.services.sanity.SanityManager;
29
30 import org.apache.derby.iapi.sql.Activation;
31 import org.apache.derby.iapi.sql.PreparedStatement;
32 import org.apache.derby.iapi.sql.ResultSet;
33 import org.apache.derby.iapi.sql.ParameterValueSet;
34 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
35 import org.apache.derby.iapi.error.StandardException;
36 import org.apache.derby.iapi.jdbc.EngineStatement;
37
38 import java.sql.SQLException JavaDoc;
39 import java.sql.SQLWarning JavaDoc;
40 import java.util.Vector JavaDoc;
41
42 /*
43  We would import these, but have name-overlap
44 import java.sql.Statement;
45 import java.sql.ResultSet;
46 */

47
48 /**
49  *
50  * EmbedStatement is a local JDBC statement.
51  *
52    <P><B>Supports</B>
53    <UL>
54    <LI> JSR169 - no subsetting for java.sql.Statement
55    <LI> JDBC 2.0
56    <LI> JDBC 3.0 - no new dependencies on new JDBC 3.0 or JDK 1.4 classes,
57         new methods can safely be added into implementation.
58    </UL>
59
60  * @author ames
61  */

62 public class EmbedStatement extends ConnectionChild
63     implements EngineStatement {
64
65     private final java.sql.Connection JavaDoc applicationConnection;
66     
67     /**
68      * Statement reference the application is using to execute
69      * this Statement. Normally set to this, but if this was
70      * created by a Connection from an XAConnection then this
71      * will be a reference to the BrokeredStatement.
72      *
73      * Making it protected to allow access from EmbedPreparedStatement40
74      * to be used for StatementEvents
75      *
76      */

77     protected EngineStatement applicationStatement;
78
79     int updateCount = -1;
80     java.sql.ResultSet JavaDoc results;
81     //for jdbc3.0 feature, where you can get a resultset of rows inserted
82
//for auto generated columns after an insert
83
private java.sql.ResultSet JavaDoc autoGeneratedKeysResultSet;
84     private String JavaDoc cursorName;
85
86     private final boolean forMetaData;
87     final int resultSetType;
88     private final int resultSetConcurrency;
89     private final int resultSetHoldability;
90     final LanguageConnectionContext lcc;
91
92     private SQLWarning JavaDoc warnings;
93     String JavaDoc SQLText;
94
95     private int fetchSize = 1;
96     private int fetchDirection = JDBC20Translation.FETCH_FORWARD;
97     int MaxFieldSize;
98     private int timeoutSeconds;
99
100     //the state of this statement, set to false when close() is called
101
private boolean active = true;
102
103     //in case of batch update, save the individual statements in the batch in this vector
104
//this is only used by JDBC 2.0
105
Vector JavaDoc batchStatements;
106     
107     // The maximum # of rows to return per result set.
108
// (0 means no limit.)
109
int maxRows;
110
111     private ParameterValueSet pvs;
112
113     // An EmbedStatement is NOT poolable by default. The constructor for
114
// PreparedStatement overrides this.
115
protected boolean isPoolable = false;
116
117     //
118
// constructor
119
//
120
public EmbedStatement (EmbedConnection connection, boolean forMetaData,
121                               int resultSetType, int resultSetConcurrency, int resultSetHoldability)
122     {
123         super(connection);
124         this.forMetaData = forMetaData;
125         this.resultSetType = resultSetType;
126         this.resultSetConcurrency = resultSetConcurrency;
127         this.resultSetHoldability = resultSetHoldability;
128
129         lcc = getEmbedConnection().getLanguageConnection();
130         applicationConnection = getEmbedConnection().getApplicationConnection();
131         applicationStatement = this;
132
133         // By default, no statements time out.
134
// Timeout is set explicitly with setQueryTimeout().
135
timeoutSeconds = 0;
136     }
137
138     //
139
// java.sql.Statement interface
140
// the comments are those from the JDBC interface,
141
// so we know what we're supposed to to.
142

143     /**
144      * Execute a SQL statement that returns a single ResultSet.
145      *
146      * @param sql typically this is a static SQL SELECT statement
147      * @return a ResultSet that contains the data produced by the
148      * query; never null
149      * @exception SQLException thrown on failure.
150      */

151     public java.sql.ResultSet JavaDoc executeQuery(String JavaDoc sql)
152         throws SQLException JavaDoc
153     {
154         execute(sql, true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
155
156         if (SanityManager.DEBUG) {
157             if (results == null)
158                 SanityManager.THROWASSERT("no results returned on executeQuery()");
159         }
160
161         return results;
162     }
163
164     /**
165      * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
166      * SQL statements that return nothing such as SQL DDL statements
167      * can be executed.
168      *
169      * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
170      * statement that returns nothing
171      * @return either the row count for INSERT, UPDATE or DELETE; or 0
172      * for SQL statements that return nothing
173      * @exception SQLException thrown on failure.
174      */

175     public int executeUpdate(String JavaDoc sql) throws SQLException JavaDoc
176     {
177         execute(sql, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);
178         return updateCount;
179     }
180
181     /**
182      * JDBC 3.0
183      *
184      * Execute the given SQL statement and signals the driver with the given flag
185      * about whether the auto-generated keys produced by this Statement object
186      * should be made available for retrieval.
187      *
188      * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
189      * statement that returns nothing
190      * @param autoGeneratedKeys - a flag indicating whether auto-generated keys
191      * should be made available for retrieval; one of the following constants:
192      * Statement.RETURN_GENERATED_KEYS Statement.NO_GENERATED_KEYS
193      * @return either the row count for INSERT, UPDATE or DELETE; or 0
194      * for SQL statements that return nothing
195      * @exception SQLException if a database access error occurs
196      */

197     public int executeUpdate(String JavaDoc sql, int autoGeneratedKeys) throws SQLException JavaDoc
198     {
199         execute(sql, false, true, autoGeneratedKeys, null, null);
200         return updateCount;
201     }
202
203     /**
204      * JDBC 3.0
205      *
206      * Executes the given SQL statement and signals the driver that the
207      * auto-generated keys indicated in the given array should be made
208      * available for retrieval. The driver will ignore the array if the SQL
209      * statement is not an INSERT statement
210      *
211      * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
212      * statement that returns nothing
213      * @param columnIndexes - an array of column indexes indicating the
214      * columns that should be returned from the inserted row
215      * @return either the row count for INSERT, UPDATE or DELETE; or 0
216      * for SQL statements that return nothing
217      * @exception SQLException if a database access error occurs
218      */

219     public int executeUpdate(String JavaDoc sql, int[] columnIndexes) throws SQLException JavaDoc
220     {
221         throw Util.notImplemented("executeUpdate(String, int[])");
222     }
223
224     /**
225      * JDBC 3.0
226      *
227      * Executes the given SQL statement and signals the driver that the
228      * auto-generated keys indicated in the given array should be made
229      * available for retrieval. The driver will ignore the array if the SQL
230      * statement is not an INSERT statement
231      *
232      * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
233      * statement that returns nothing
234      * @param columnNames - an array of the names of the columns
235      * that should be returned from the inserted row
236      * @return either the row count for INSERT, UPDATE or DELETE; or 0
237      * for SQL statements that return nothing
238      * @exception SQLException if a database access error occurs
239      */

240     public int executeUpdate(String JavaDoc sql, String JavaDoc[] columnNames) throws SQLException JavaDoc
241     {
242         throw Util.notImplemented("executeUpdate(String, String[])");
243     }
244
245     final void checkIfInMiddleOfBatch() throws SQLException JavaDoc {
246         /* If batchStatements is not null then we are in the middle
247          * of a batch. That's an invalid state. We need to finish the
248          * batch either by clearing the batch or executing the batch.
249          * executeUpdate is not allowed inside the batch.
250          */

251         if (batchStatements != null)
252         throw newSQLException(SQLState.MIDDLE_OF_BATCH);
253     }
254
255     /**
256      * Tell whether this statment has been closed or not.
257      *
258      * @return <code>true</code> is closed, <code>false</code> otherwise.
259      * @exception SQLException if a database access error occurs.
260      */

261     public boolean isClosed() throws SQLException JavaDoc {
262         // If active, verify state by consulting parent connection.
263
if (active) {
264             try {
265                 checkExecStatus();
266             } catch (SQLException JavaDoc sqle) {
267             }
268         }
269         return !active;
270     }
271
272     /**
273      * In many cases, it is desirable to immediately release a
274      * Statements's database and JDBC resources instead of waiting for
275      * this to happen when it is automatically closed; the close
276      * method provides this immediate release.
277      *
278      * <P><B>Note:</B> A Statement is automatically closed when it is
279      * garbage collected. When a Statement is closed its current
280      * ResultSet, if one exists, is also closed.
281      * @exception SQLException thrown on failure.
282      */

283     public final void close() throws SQLException JavaDoc {
284
285         /* The close() method is the only method
286          * that is allowed to be called on a closed
287          * Statement, as per Jon Ellis.
288          */

289         if (!active)
290         {
291             return;
292         }
293
294       synchronized (getConnectionSynchronization()) {
295
296           closeActions();
297           
298           //we first set the status
299
active = false;
300
301           //first, clear the resutl set
302
clearResultSets();
303           
304           //next, release other resource
305
cursorName = null;
306           warnings = null;
307           SQLText = null;
308           batchStatements = null;
309       }
310     }
311
312     // allow sub-classes to execute additional close
313
// logic while holding the synchronization.
314
void closeActions() throws SQLException JavaDoc {
315     }
316
317     //----------------------------------------------------------------------
318

319     /**
320      * The maxFieldSize limit (in bytes) is the maximum amount of data
321      * returned for any column value; it only applies to BINARY,
322      * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR
323      * columns. If the limit is exceeded, the excess data is silently
324      * discarded.
325      *
326      * @return the current max column size limit; zero means unlimited
327      * @exception SQLException thrown on failure.
328      */

329     public int getMaxFieldSize() throws SQLException JavaDoc {
330         checkStatus();
331
332         return MaxFieldSize;
333     }
334
335     /**
336      * The maxFieldSize limit (in bytes) is set to limit the size of
337      * data that can be returned for any column value; it only applies
338      * to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and
339      * LONGVARCHAR fields. If the limit is exceeded, the excess data
340      * is silently discarded.
341      *
342      * @param max the new max column size limit; zero means unlimited
343      * @exception SQLException thrown on failure.
344      */

345     public void setMaxFieldSize(int max) throws SQLException JavaDoc {
346         checkStatus();
347
348         if (max < 0)
349         {
350             throw newSQLException(SQLState.INVALID_MAXFIELD_SIZE, new Integer JavaDoc(max));
351         }
352         this.MaxFieldSize = max;
353     }
354
355     /**
356      * The maxRows limit is the maximum number of rows that a
357      * ResultSet can contain. If the limit is exceeded, the excess
358      * rows are silently dropped.
359      *
360      * @return the current max row limit; zero means unlimited
361      * @exception SQLException thrown on failure.
362      */

363     public int getMaxRows() throws SQLException JavaDoc
364     {
365         checkStatus();
366         return maxRows;
367     }
368
369     /**
370      * The maxRows limit is set to limit the number of rows that any
371      * ResultSet can contain. If the limit is exceeded, the excess
372      * rows are silently dropped.
373      *
374      * @param max the new max rows limit; zero means unlimited
375      * @exception SQLException thrown on failure.
376      */

377     public void setMaxRows(int max) throws SQLException JavaDoc
378     {
379         checkStatus();
380         if (max < 0)
381         {
382             throw newSQLException(SQLState.INVALID_MAX_ROWS_VALUE, new Integer JavaDoc(max));
383         }
384         this.maxRows = max;
385     }
386
387     /**
388      * If escape scanning is on (the default) the driver will do
389      * escape substitution before sending the SQL to the database.
390      *
391      * @param enable true to enable; false to disable
392      * @exception SQLException thrown on failure.
393      */

394     public void setEscapeProcessing(boolean enable) throws SQLException JavaDoc {
395         checkStatus();
396         // Nothing to do in our server , just ignore it.
397

398     }
399
400     /**
401      * The queryTimeout limit is the number of seconds the driver will
402      * wait for a Statement to execute. If the limit is exceeded a
403      * SQLException is thrown.
404      *
405      * @return the current query timeout limit in seconds; zero means unlimited
406      * @exception SQLException thrown on failure.
407      */

408     public final int getQueryTimeout() throws SQLException JavaDoc {
409         checkStatus();
410         return timeoutSeconds;
411     }
412
413     /**
414      * The queryTimeout limit is the number of seconds the driver will
415      * wait for a Statement to execute. If the limit is exceeded a
416      * SQLException is thrown.
417      *
418      * @param seconds the new query timeout limit in seconds; zero means unlimited
419      * @exception SQLException thrown on failure.
420      */

421     public final void setQueryTimeout(int seconds) throws SQLException JavaDoc {
422         checkStatus();
423         if (seconds < 0) {
424             throw newSQLException(SQLState.INVALID_QUERYTIMEOUT_VALUE,
425                                   new Integer JavaDoc(seconds));
426         }
427         timeoutSeconds = seconds;
428     }
429
430     /**
431      * Cancel can be used by one thread to cancel a statement that
432      * is being executed by another thread.
433      * @exception SQLException thrown on failure.
434      */

435     public void cancel() throws SQLException JavaDoc {
436         throw Util.notImplemented("cancel");
437     }
438
439     /**
440      * The first warning reported by calls on this Statement is
441      * returned. A Statment's execute methods clear its SQLWarning
442      * chain. Subsequent Statement warnings will be chained to this
443      * SQLWarning.
444      *
445      * <p>The warning chain is automatically cleared each time
446      * a statement is (re)executed.
447      *
448      * <P><B>Note:</B> If you are processing a ResultSet then any
449      * warnings associated with ResultSet reads will be chained on the
450      * ResultSet object.
451      *
452      * @return the first SQLWarning or null
453      * @exception SQLException thrown on failure.
454      */

455     public SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc {
456         checkStatus();
457         return warnings;
458     }
459
460     /**
461      * After this call getWarnings returns null until a new warning is
462      * reported for this Statement.
463      * @exception SQLException thrown on failure.
464      */

465     public void clearWarnings() throws SQLException JavaDoc {
466         checkStatus();
467         warnings = null;
468     }
469
470     /**
471      * setCursorName defines the SQL cursor name that will be used by
472      * subsequent Statement execute methods. This name can then be
473      * used in SQL positioned update/delete statements to identify the
474      * current row in the ResultSet generated by this statement. If
475      * the database doesn't support positioned update/delete, this
476      * method is a noop.
477      *
478      * <P><B>Note:</B> By definition, positioned update/delete
479      * execution must be done by a different Statement than the one
480      * which generated the ResultSet being used for positioning. Also,
481      * cursor names must be unique within a Connection.
482      *
483      * @param name the new cursor name.
484      */

485     public void setCursorName(String JavaDoc name) throws SQLException JavaDoc {
486         checkStatus();
487         cursorName = name;
488     }
489
490     //----------------------- Multiple Results --------------------------
491

492     /**
493      * Execute a SQL statement that may return multiple results.
494      * Under some (uncommon) situations a single SQL statement may return
495      * multiple result sets and/or update counts. Normally you can ignore
496      * this, unless you're executing a stored procedure that you know may
497      * return multiple results, or unless you're dynamically executing an
498      * unknown SQL string. The "execute", "getMoreResults", "getResultSet"
499      * and "getUpdateCount" methods let you navigate through multiple results.
500      *
501      * The "execute" method executes a SQL statement and indicates the
502      * form of the first result. You can then use getResultSet or
503      * getUpdateCount to retrieve the result, and getMoreResults to
504      * move to any subsequent result(s).
505      *
506      * @param sql any SQL statement
507      *
508      * @return true if the first result is a ResultSet; false if it is an integer
509      * @see #getResultSet
510      * @see #getUpdateCount
511      * @see #getMoreResults
512      * @exception SQLException thrown on failure
513      */

514     public boolean execute(String JavaDoc sql)
515         throws SQLException JavaDoc
516     {
517         return execute(sql, false, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
518     }
519     
520     /**
521      * Execute a SQL statement that may return multiple results.
522      * Under some (uncommon) situations a single SQL statement may return
523      * multiple result sets and/or update counts. Normally you can ignore
524      * this, unless you're executing a stored procedure that you know may
525      * return multiple results, or unless you're dynamically executing an
526      * unknown SQL string. The "execute", "getMoreResults", "getResultSet"
527      * and "getUpdateCount" methods let you navigate through multiple results.
528      *
529      * The "execute" method executes a SQL statement and indicates the
530      * form of the first result. You can then use getResultSet or
531      * getUpdateCount to retrieve the result, and getMoreResults to
532      * move to any subsequent result(s).
533      *
534      * @param sql any SQL statement
535      * @param executeQuery caller is executeQuery()
536      * @param executeUpdate caller is executeUpdate()
537      * @param autoGeneratedKeys
538      * @param columnIndexes
539      * @param columnNames
540      *
541      * @return true if the first result is a ResultSet; false if it is an integer
542      * @see #getResultSet
543      * @see #getUpdateCount
544      * @see #getMoreResults
545      * @exception SQLException thrown on failure
546      */

547     private boolean execute(String JavaDoc sql, boolean executeQuery, boolean executeUpdate,
548         int autoGeneratedKeys, int[] columnIndexes, String JavaDoc[] columnNames) throws SQLException JavaDoc
549     {
550       synchronized (getConnectionSynchronization()) {
551
552         checkExecStatus();
553         if (sql == null) {
554             throw newSQLException(SQLState.NULL_SQL_TEXT);
555         }
556         checkIfInMiddleOfBatch();
557         clearResultSets(); // release the last statement executed, if any.
558

559         setupContextStack(); // make sure there's context
560

561
562         // try to remember the SQL statement in case anybody asks for it
563
SQLText = sql;
564
565         try {
566             Activation activation;
567             try {
568                 PreparedStatement preparedStatement = lcc.prepareInternalStatement
569                     (lcc.getDefaultSchema(), sql, resultSetConcurrency==JDBC20Translation.CONCUR_READ_ONLY, false);
570                 activation =
571                     preparedStatement.getActivation(lcc, resultSetType == JDBC20Translation.TYPE_SCROLL_INSENSITIVE);
572                 checkRequiresCallableStatement(activation);
573              } catch (Throwable JavaDoc t) {
574                 throw handleException(t);
575              }
576
577
578             // this is for a Statement execution
579
activation.setSingleExecution();
580
581             //bug 4838 - save the auto-generated key information in activation. keeping this
582
//information in lcc will not work work it can be tampered by a nested trasaction
583
if (autoGeneratedKeys == JDBC30Translation.RETURN_GENERATED_KEYS)
584                 activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);
585             return executeStatement(activation, executeQuery, executeUpdate);
586         } finally {
587             restoreContextStack();
588         }
589       }
590     }
591
592     /**
593      * JDBC 3.0
594      *
595      * Executes the given SQL statement, which may return multiple
596      * results, and signals the driver that any auto-generated keys
597      * should be made available for retrieval. The driver will ignore
598      * this signal if the SQL statement is not an INSERT statement.
599      *
600      * @param sql any SQL statement
601      * @param autoGeneratedKeys - a constant indicating whether
602      * auto-generated keys should be made available for retrieval using
603      * the method getGeneratedKeys; one of the following constants:
604      * Statement.RETURN_GENERATED_KEYS or Statement.NO_GENERATED_KEYS
605      * @return rue if the first result is a ResultSet object; false if
606      * it is an update count or there are no results
607      * @exception SQLException if a database access error occurs
608      */

609     public boolean execute(String JavaDoc sql, int autoGeneratedKeys) throws SQLException JavaDoc
610     {
611         return execute(sql, false, false, autoGeneratedKeys, null, null);
612     }
613
614     /**
615      * JDBC 3.0
616      *
617      * Executes the given SQL statement, which may return multiple
618      * results, and signals the driver that the auto-generated keys
619      * indicated in the given array should be made available for retrieval.
620      * This array contains the indexes of the columns in the target table
621      * that contain the auto-generated keys that should be made available.
622      * The driver will ignore the array if the given SQL statement is not an
623      * INSERT statement.
624      *
625      * @param sql any SQL statement
626      * @param columnIndexes - an array of the indexes of the columns in the
627      * inserted row that should be made available for retrieval by a call to
628      * the method getGeneratedKeys
629      * @return rue if the first result is a ResultSet object; false if
630      * it is an update count or there are no results
631      * @exception SQLException if a database access error occurs
632      */

633     public boolean execute(String JavaDoc sql, int[] columnIndexes) throws SQLException JavaDoc
634     {
635         throw Util.notImplemented("execute(String, int[])");
636     }
637
638     /**
639      * JDBC 3.0
640      *
641      * Executes the given SQL statement, which may return multiple
642      * results, and signals the driver that the auto-generated keys
643      * indicated in the given array should be made available for retrieval.
644      * This array contains the names of the columns in the target table
645      * that contain the auto-generated keys that should be made available.
646      * The driver will ignore the array if the given SQL statement is not an
647      * INSERT statement.
648      *
649      * @param sql any SQL statement
650      * @param columnNames - an array of the names of the columns in the
651      * inserted row that should be made available for retrieval by a call to
652      * the method getGeneratedKeys
653      * @return rue if the first result is a ResultSet object; false if
654      * it is an update count or there are no results
655      * @exception SQLException if a database access error occurs
656      */

657     public boolean execute(String JavaDoc sql, String JavaDoc[] columnNames) throws SQLException JavaDoc
658     {
659         throw Util.notImplemented("execute(String, String[])");
660     }
661
662     /**
663      * getResultSet returns the current result as a ResultSet. It
664      * should only be called once per result.
665      *
666      * @return the current result as a ResultSet; null if the result
667      * is an update count or there are no more results or the statement
668      * was closed.
669      * @see #execute
670      */

671     public final java.sql.ResultSet JavaDoc getResultSet() throws SQLException JavaDoc {
672         checkStatus();
673
674         return results;
675     }
676
677     /**
678      * getUpdateCount returns the current result as an update count;
679      * if the result is a ResultSet or there are no more results -1
680      * is returned. It should only be called once per result.
681      *
682      * <P>The only way to tell for sure that the result is an update
683      * count is to first test to see if it is a ResultSet. If it is
684      * not a ResultSet it is either an update count or there are no
685      * more results.
686      *
687      * @return the current result as an update count; -1 if it is a
688      * ResultSet or there are no more results
689      * @see #execute
690      */

691     public final int getUpdateCount() throws SQLException JavaDoc {
692         checkStatus();
693         return updateCount;
694     }
695
696     /**
697      * getMoreResults moves to a Statement's next result. It returns true if
698      * this result is a ResultSet. getMoreResults also implicitly
699      * closes any current ResultSet obtained with getResultSet.
700      *
701      * There are no more results when (!getMoreResults() &&
702      * (getUpdateCount() == -1)
703      *
704      * @return true if the next result is a ResultSet; false if it is
705      * an update count or there are no more results
706      * @see #execute
707      * @exception SQLException thrown on failure.
708      */

709     public final boolean getMoreResults() throws SQLException JavaDoc {
710         return getMoreResults(JDBC30Translation.CLOSE_ALL_RESULTS);
711     }
712
713     /////////////////////////////////////////////////////////////////////////
714
//
715
// JDBC 2.0 methods that are implemented here because EmbedPreparedStatement
716
// and EmbedCallableStatement in Local20 need access to them, and those
717
// classes extend their peer classes in Local, instead of EmbedStatement
718
// in Local20
719
//
720
// We do the same of JDBC 3.0 methods.
721
/////////////////////////////////////////////////////////////////////////
722

723     /**
724      * JDBC 2.0
725      *
726      * Determine the result set type.
727      *
728      * @exception SQLException Feature not implemented for now.
729      */

730     public final int getResultSetType()
731         throws SQLException JavaDoc
732     {
733         checkStatus();
734         return resultSetType;
735     }
736
737
738     /**
739      * JDBC 2.0
740      *
741      * Give a hint as to the direction in which the rows in a result set
742      * will be processed. The hint applies only to result sets created
743      * using this Statement object. The default value is
744      * ResultSet.FETCH_FORWARD.
745      *
746      * @param direction the initial direction for processing rows
747      * @exception SQLException if a database-access error occurs or direction
748      * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
749      * ResultSet.FETCH_UNKNOWN
750      */

751     public void setFetchDirection(int direction) throws SQLException JavaDoc {
752         
753         checkStatus();
754                 /* fetch direction is meaningless to us. we just save
755                  * it off if it is valid and return the current value if asked.
756                  */

757                 if (direction == JDBC20Translation.FETCH_FORWARD ||
758                     direction == JDBC20Translation.FETCH_REVERSE ||
759                     direction == JDBC20Translation.FETCH_UNKNOWN )
760                 {
761                     fetchDirection = direction;
762                 }else
763                     throw newSQLException(SQLState.INVALID_FETCH_DIRECTION,
764                                    new Integer JavaDoc(direction));
765     }
766
767     /**
768      * JDBC 2.0
769      *
770      * Determine the fetch direction.
771      *
772      * @return the default fetch direction
773      * @exception SQLException if a database-access error occurs
774      */

775     public int getFetchDirection() throws SQLException JavaDoc {
776         checkStatus();
777         return fetchDirection;
778     }
779
780
781     /**
782      * JDBC 2.0
783      *
784      * Give the JDBC driver a hint as to the number of rows that should
785      * be fetched from the database when more rows are needed. The number
786      * of rows specified only affects result sets created using this
787      * statement. If the value specified is zero, then the hint is ignored.
788      * The default value is zero.
789      *
790      * @param rows the number of rows to fetch
791      * @exception SQLException if a database-access error occurs, or the
792      * condition 0 <= rows <= this.getMaxRows() is not satisfied.
793      */

794     public void setFetchSize(int rows) throws SQLException JavaDoc {
795         checkStatus();
796         if (rows < 0 || (this.getMaxRows() != 0 &&
797                              rows > this.getMaxRows()))
798         {
799             throw newSQLException(SQLState.INVALID_ST_FETCH_SIZE, new Integer JavaDoc(rows));
800         }else if ( rows > 0 ) // ignore the call if the value is zero
801
fetchSize = rows;
802     }
803   
804     /**
805      * JDBC 2.0
806      *
807      * Determine the default fetch size.
808      * @exception SQLException if a database-access error occurs
809      *
810      */

811     public int getFetchSize() throws SQLException JavaDoc {
812         checkStatus();
813         return fetchSize;
814     }
815
816     /**
817      * JDBC 2.0
818      *
819      * Determine the result set concurrency.
820      *
821      * @exception SQLException Feature not implemented for now.
822      */

823     public int getResultSetConcurrency() throws SQLException JavaDoc {
824         checkStatus();
825         return resultSetConcurrency;
826     }
827
828     /**
829      * JDBC 3.0
830      *
831      * Retrieves the result set holdability for ResultSet objects
832      * generated by this Statement object.
833      *
834      * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or
835      * ResultSet.CLOSE_CURSORS_AT_COMMIT
836      * @exception SQLException Feature not implemented for now.
837      */

838     public final int getResultSetHoldability() throws SQLException JavaDoc {
839         checkStatus();
840         return resultSetHoldability;
841     }
842
843     /**
844      * JDBC 2.0
845      *
846      * Adds a SQL command to the current batch of commmands for the statement.
847      * This method is optional.
848      *
849      * @param sql typically this is a static SQL INSERT or UPDATE statement
850      * @exception SQLException if a database-access error occurs, or the
851      * driver does not support batch statements
852      */

853     public void addBatch( String JavaDoc sql ) throws SQLException JavaDoc {
854         checkStatus();
855       synchronized (getConnectionSynchronization()) {
856           if (batchStatements == null)
857               batchStatements = new Vector JavaDoc();
858         batchStatements.addElement(sql);
859         }
860     }
861
862     /**
863      * JDBC 2.0
864      *
865      * Make the set of commands in the current batch empty.
866      * This method is optional.
867      *
868      * @exception SQLException if a database-access error occurs, or the
869      * driver does not support batch statements
870      */

871     public final void clearBatch() throws SQLException JavaDoc {
872         checkStatus();
873       synchronized (getConnectionSynchronization()) {
874         batchStatements = null;
875         }
876     }
877
878     /**
879      * JDBC 2.0
880      *
881      * Submit a batch of commands to the database for execution.
882      * This method is optional.
883      *
884      * Moving jdbc2.0 batch related code in this class because
885      * callableStatement in jdbc 20 needs this code too and it doesn't derive
886      * from prepared statement in jdbc 20 in our implementation.
887      * BatchUpdateException is the only new class from jdbc 20 which is being
888      * referenced here and in order to avoid any jdk11x problems, using
889      * reflection code to make an instance of that class.
890      *
891      * @return an array of update counts containing one element for each
892      * command in the batch. The array is ordered according
893      * to the order in which commands were inserted into the batch
894      * @exception SQLException if a database-access error occurs, or the
895      * driver does not support batch statements
896      */

897     public int[] executeBatch() throws SQLException JavaDoc {
898         checkExecStatus();
899         synchronized (getConnectionSynchronization())
900         {
901                         setupContextStack();
902             int i = 0;
903             // As per the jdbc 2.0 specs, close the statement object's current resultset
904
// if one is open.
905
// Are there results?
906
// outside of the lower try/finally since results will
907
// setup and restore themselves.
908
clearResultSets();
909
910             Vector JavaDoc stmts = batchStatements;
911             batchStatements = null;
912             int size;
913             if (stmts == null)
914                 size = 0;
915             else
916                 size = stmts.size();
917
918             int[] returnUpdateCountForBatch = new int[size];
919
920             SQLException JavaDoc sqle;
921             try {
922                 for (; i< size; i++)
923                 {
924                     if (executeBatchElement(stmts.elementAt(i)))
925                         throw newSQLException(SQLState.RESULTSET_RETURN_NOT_ALLOWED);
926                     returnUpdateCountForBatch[i] = getUpdateCount();
927                 }
928                 return returnUpdateCountForBatch;
929             }
930             catch (StandardException se) {
931
932                 sqle = handleException(se);
933             }
934             catch (SQLException JavaDoc sqle2)
935             {
936                 sqle = sqle2;
937             }
938             finally
939             {
940                 restoreContextStack();
941             }
942
943             int successfulUpdateCount[] = new int[i];
944             for (int j=0; j<i; j++)
945             {
946                 successfulUpdateCount[j] = returnUpdateCountForBatch[j];
947             }
948
949             SQLException JavaDoc batch =
950             new java.sql.BatchUpdateException JavaDoc(sqle.getMessage(), sqle.getSQLState(),
951                                     sqle.getErrorCode(), successfulUpdateCount);
952
953             batch.setNextException(sqle);
954             throw batch;
955       }
956     }
957
958     /**
959         Execute a single element of the batch. Overridden by EmbedPreparedStatement
960     */

961     boolean executeBatchElement(Object JavaDoc batchElement) throws SQLException JavaDoc, StandardException {
962         return execute((String JavaDoc)batchElement, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);
963     }
964
965     /**
966      * JDBC 2.0
967      *
968      * Return the Connection that produced the Statement.
969      *
970      * @exception SQLException Exception if it cannot find the connection
971      * associated to this statement.
972      */

973     public final java.sql.Connection JavaDoc getConnection() throws SQLException JavaDoc {
974         checkStatus();
975
976         java.sql.Connection JavaDoc appConn = getEmbedConnection().getApplicationConnection();
977         if ((appConn != applicationConnection) || (appConn == null)) {
978
979             throw Util.noCurrentConnection();
980         }
981         return appConn;
982     }
983
984     /**
985      * JDBC 3.0
986      *
987      * Moves to this Statement obect's next result, deals with any current ResultSet
988      * object(s) according to the instructions specified by the given flag, and
989      * returns true if the next result is a ResultSet object
990      *
991      * @param current - one of the following Statement constants indicating what
992      * should happen to current ResultSet objects obtained using the method
993      * getResultSetCLOSE_CURRENT_RESULT, KEEP_CURRENT_RESULT, or CLOSE_ALL_RESULTS
994      * @return true if the next result is a ResultSet; false if it is
995      * an update count or there are no more results
996      * @see #execute
997      * @exception SQLException thrown on failure.
998      */

999     public final boolean getMoreResults(int current) throws SQLException JavaDoc {
1000        checkExecStatus();
1001
1002        synchronized (getConnectionSynchronization()) {
1003            if (dynamicResults == null) {
1004                // we only have the one resultset, so this is
1005
// simply a close for us.
1006
clearResultSets();
1007                return false;
1008            }
1009
1010            int startingClose;
1011            switch (current) {
1012            default:
1013            case JDBC30Translation.CLOSE_ALL_RESULTS:
1014                startingClose = 0;
1015                break;
1016            case JDBC30Translation.CLOSE_CURRENT_RESULT:
1017                // just close the current result set.
1018
startingClose = currentDynamicResultSet;
1019                break;
1020            case JDBC30Translation.KEEP_CURRENT_RESULT:
1021                // make the close loop a no-op.
1022
startingClose = dynamicResults.length;
1023                break;
1024            }
1025
1026            // Close loop.
1027
SQLException JavaDoc se = null;
1028            for (int i = startingClose; i <= currentDynamicResultSet && i < dynamicResults.length; i++) {
1029                EmbedResultSet lrs = dynamicResults[i];
1030                if (lrs == null)
1031                    continue;
1032
1033
1034                try {
1035                    lrs.close();
1036                } catch (SQLException JavaDoc sqle) {
1037                    if (se == null)
1038                        se = sqle;
1039                    else
1040                        se.setNextException(sqle);
1041                } finally {
1042                    dynamicResults[i] = null;
1043                }
1044            }
1045
1046            if (se != null) {
1047                // leave positioned on the current result set (?)
1048
throw se;
1049            }
1050
1051            updateCount = -1;
1052
1053            while (++currentDynamicResultSet < dynamicResults.length) {
1054
1055                EmbedResultSet lrs = dynamicResults[currentDynamicResultSet];
1056                if (lrs != null) {
1057                    if (lrs.isClosed) {
1058                        dynamicResults[currentDynamicResultSet] = null;
1059                        continue;
1060                    }
1061
1062                    results = lrs;
1063
1064                    return true;
1065                }
1066            }
1067
1068            results = null;
1069            return false;
1070        }
1071    }
1072
1073    /**
1074     * JDBC 3.0
1075     *
1076     * Retrieves any auto-generated keys created as a result of executing this
1077     * Statement object. If this Statement is a non-insert statement,
1078     * a null ResultSet object is returned.
1079     *
1080     * @return a ResultSet object containing the auto-generated key(s) generated by
1081     * the execution of this Statement object
1082     * @exception SQLException if a database access error occurs
1083     */

1084    public final java.sql.ResultSet JavaDoc getGeneratedKeys() throws SQLException JavaDoc {
1085        checkStatus();
1086        if (autoGeneratedKeysResultSet == null)
1087            return null;
1088        else {
1089            execute("VALUES IDENTITY_VAL_LOCAL()", true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);
1090            return results;
1091        }
1092    }
1093
1094    /////////////////////////////////////////////////////////////////////////
1095
//
1096
// Implementation specific methods
1097
//
1098
/////////////////////////////////////////////////////////////////////////
1099

1100    /**
1101        Execute the current statement.
1102        @exception SQLException thrown on failure.
1103    */

1104    boolean executeStatement(Activation a,
1105                     boolean executeQuery, boolean executeUpdate)
1106                     throws SQLException JavaDoc {
1107
1108        // we don't differentiate the update from the resultset case.
1109
// so, there could be a result set.
1110

1111        // note: the statement interface will paste together
1112
// an activation and make sure the prepared statement
1113
// is still valid, so it is preferrable, for now,
1114
// to creating our own activation and stuffing it in
1115
// the prepared statement.
1116

1117        synchronized (getConnectionSynchronization()) {
1118                        setupContextStack(); // make sure there's context
1119
boolean retval;
1120
1121            pvs = a.getParameterValueSet();
1122
1123            try {
1124                // The following is from the javadoc for java.sql.Statement
1125
// Only one ResultSet per Statement can be open at any point in time.
1126
// Therefore, if the reading of one ResultSet is interleaved with the
1127
// reading of another, each must have been generated by different Statements.
1128
// All statement execute methods implicitly close a
1129
// statment's current ResultSet if an open one exists.
1130
if (results != null) {
1131                    results.close();
1132                    results = null;
1133                }
1134
1135                clearWarnings();
1136
1137                if (! forMetaData) {
1138                    commitIfNeeded(); // commit the last statement if needed
1139
needCommit();
1140                } else {
1141
1142
1143                    if (lcc.getActivationCount() > 1) {
1144                      // we do not want to commit here as there seems to be other
1145
// statements/resultSets currently opened for this connection.
1146
} else {
1147                        commitIfNeeded(); // we can legitimately commit
1148
needCommit();
1149                    }
1150                }
1151
1152                // if this was a prepared statement, this just
1153
// gets it for us, it won't recompile unless it is invalid.
1154
PreparedStatement ps = a.getPreparedStatement();
1155                ps.rePrepare(lcc);
1156                addWarning(ps.getCompileTimeWarnings());
1157
1158
1159                /*
1160                ** WARNING WARNING
1161                **
1162                ** Any state set in the activation before execution *must* be copied
1163                ** to the new activation in GenericActivationHolder.execute() when
1164                ** the statement has been recompiled. State such as
1165                ** singleExecution, cursorName, holdability, maxRows.
1166                */

1167
1168                if (cursorName != null)
1169                {
1170                    a.setCursorName(cursorName);
1171                }
1172                
1173                boolean executeHoldable = getExecuteHoldable();
1174 
1175                a.setResultSetHoldability(executeHoldable);
1176
1177                //reset the activation to clear warnings
1178
//and clear existing result sets in case this has been cached
1179
a.reset();
1180                a.setMaxRows(maxRows);
1181                long timeoutMillis = (long)timeoutSeconds * 1000L;
1182                ResultSet resultsToWrap = ps.execute(a,
1183                                                     false,
1184                                                     timeoutMillis);
1185                addWarning(a.getWarnings());
1186
1187
1188                if (resultsToWrap.returnsRows()) {
1189
1190                    // The statement returns rows, so calling it with
1191
// executeUpdate() is not allowed.
1192
if (executeUpdate) {
1193                        throw StandardException.newException(
1194                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
1195                    }
1196
1197                    EmbedResultSet lresults = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap, forMetaData, this, ps.isAtomic());
1198                    results = lresults;
1199
1200
1201                    // Set up the finalization of the ResultSet to
1202
// mark the activation as unused. It will be
1203
// closed sometime later by the connection
1204
// outside of finalization.
1205
if (a.isSingleExecution())
1206                        lresults.singleUseActivation = a;
1207
1208                    updateCount = -1;
1209                    retval = true;
1210                }
1211                else {
1212
1213                    // Only applipable for an insert statement, which does not return rows.
1214
//the auto-generated keys resultset will be null if used for non-insert statement
1215
if (a.getAutoGeneratedKeysResultsetMode() && (resultsToWrap.getAutoGeneratedKeysResultset() != null))
1216                    {
1217                        resultsToWrap.getAutoGeneratedKeysResultset().open();
1218                        autoGeneratedKeysResultSet = factory.newEmbedResultSet(getEmbedConnection(),
1219                            resultsToWrap.getAutoGeneratedKeysResultset(), false, this, ps.isAtomic());
1220                    }
1221
1222                    updateCount = resultsToWrap.modifiedRowCount();
1223
1224                    resultsToWrap.finish(); // Don't need the result set any more
1225
results = null; // note that we have none.
1226

1227                    int dynamicResultCount = 0;
1228                    if (a.getDynamicResults() != null) {
1229                        dynamicResultCount =
1230                            processDynamicResults(a.getDynamicResults(),
1231                                                  a.getMaxDynamicResults());
1232                    }
1233
1234                    // executeQuery() is not allowed if the statement
1235
// doesn't return exactly one ResultSet.
1236
if (executeQuery && dynamicResultCount != 1) {
1237                        throw StandardException.newException(
1238                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_QUERY);
1239                    }
1240
1241                    // executeUpdate() is not allowed if the statement
1242
// returns ResultSets.
1243
if (executeUpdate && dynamicResultCount > 0) {
1244                        throw StandardException.newException(
1245                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
1246                    }
1247                    
1248                    if (dynamicResultCount == 0) {
1249                        if (a.isSingleExecution()) {
1250                            a.close();
1251                        }
1252
1253                        if (!forMetaData)
1254                            commitIfNeeded();
1255                        else {
1256
1257                            if (lcc.getActivationCount() > 1) {
1258                              // we do not want to commit here as there seems to be other
1259
// statements/resultSets currently opened for this connection.
1260
} else {
1261                                commitIfNeeded(); // we can legitimately commit
1262
}
1263                        }
1264                    }
1265
1266                    retval = (dynamicResultCount > 0);
1267                }
1268            } catch (Throwable JavaDoc t) {
1269                if (a.isSingleExecution()) {
1270                    try { a.close(); } catch (Throwable JavaDoc tt) {;}
1271                }
1272                throw handleException(t);
1273            } finally {
1274                restoreContextStack();
1275            }
1276            return retval;
1277        }
1278    }
1279
1280    /**
1281     * Add a SQLWarning to this Statement object.
1282     * If the Statement already has a SQLWarning then it
1283     * is added to the end of the chain.
1284     *
1285     * @see #getWarnings()
1286     */

1287    final void addWarning(SQLWarning JavaDoc sw)
1288    {
1289        if (sw != null) {
1290            if (warnings == null)
1291                warnings = sw;
1292            else
1293                warnings.setNextException(sw);
1294        }
1295    }
1296
1297
1298    /* package */
1299    public String JavaDoc getSQLText()
1300    {
1301        // no need to synchronize - accessing a reference is atomic
1302
// synchronized (getConnectionSynchronization())
1303
return SQLText;
1304    }
1305
1306    public ParameterValueSet getParameterValueSet()
1307    {
1308        return pvs;
1309    }
1310
1311    /**
1312     * Throw an exception if this Statement has been closed explictly
1313     * or it has noticed it has been closed implicitly.
1314     * JDBC specifications require nearly all methods throw a SQLException
1315     * if the Statement has been closed, thus most methods call this
1316     * method or checkExecStatus first.
1317     *
1318     * @exception SQLException Thrown if the statement is marked as closed.
1319     *
1320     * @see #checkExecStatus()
1321     */

1322    final void checkStatus() throws SQLException JavaDoc {
1323        if (!active) {
1324            //
1325
// Check the status of the connection first
1326
//
1327
java.sql.Connection JavaDoc appConn = getEmbedConnection().getApplicationConnection();
1328            if (appConn == null || appConn.isClosed()) {
1329                throw Util.noCurrentConnection();
1330            }
1331
1332            throw newSQLException(SQLState.ALREADY_CLOSED, "Statement");
1333        }
1334    }
1335
1336    /**
1337        A heavier weight version of checkStatus() that ensures the application's Connection
1338        object is still open. This is to stop errors or unexpected behaviour when a [Prepared]Statement
1339        object is used after the application has been closed. In particular to ensure that
1340        a Statement obtained from a PooledConnection cannot be used after the application has closed
1341        its connection (as the underlying Connection is still active).
1342        To avoid this heavier weight check on every method of [Prepared]Statement it is only used
1343        on those methods that would end up using the database's connection to read or modify data.
1344        E.g. execute*(), but not setXXX, etc.
1345        <BR>
1346        If this Statement's Connection is closed an exception will
1347        be thrown and the active field will be set to false,
1348        completely marking the Statement as closed.
1349        <BR>
1350        If the Statement is not currently connected to an active
1351        transaction, i.e. a suspended global transaction, then
1352        this method will throw a SQLException but the Statement
1353        will remain open. The Statement is open but unable to
1354        process any new requests until its global transaction
1355        is resumed.
1356        <BR>
1357        Upon return from the method, with or without a SQLException
1358        the field active will correctly represent the open state of
1359        the Statement.
1360        
1361        @exception SQLException Thrown if the statement is marked as closed
1362        or the Statement's transaction is suspended.
1363        
1364        @see #checkStatus()
1365    */

1366    final void checkExecStatus() throws SQLException JavaDoc {
1367        // getConnection() checks if the Statement is closed
1368
if (!getConnection().isClosed())
1369            return;
1370        
1371        // Now this connection is closed for all
1372
// future use.
1373
active = false;
1374            
1375        throw Util.noCurrentConnection();
1376    }
1377
1378    /**
1379        Close and clear all result sets associated with this statement
1380        from the last execution.
1381    */

1382    void clearResultSets() throws SQLException JavaDoc {
1383
1384        SQLException JavaDoc sqle = null;
1385
1386        try {
1387            // Are there results?
1388
// outside of the lower try/finally since results will
1389
// setup and restore themselves.
1390
if (results != null) {
1391                results.close();
1392                results = null;
1393            }
1394        } catch (SQLException JavaDoc s1) {
1395            sqle = s1;
1396        }
1397
1398        try {
1399            if (autoGeneratedKeysResultSet != null) {
1400                autoGeneratedKeysResultSet.close();
1401                autoGeneratedKeysResultSet = null;
1402            }
1403        } catch (SQLException JavaDoc sauto) {
1404            if (sqle == null)
1405                sqle = sauto;
1406            else
1407                sqle.setNextException(sauto);
1408        }
1409
1410        // close all the dynamic result sets.
1411
if (dynamicResults != null) {
1412            for (int i = 0; i < dynamicResults.length; i++) {
1413                EmbedResultSet lrs = dynamicResults[i];
1414                if (lrs == null)
1415                    continue;
1416
1417                try {
1418                    lrs.close();
1419                } catch (SQLException JavaDoc sdynamic) {
1420                    if (sqle == null)
1421                        sqle = sdynamic;
1422                    else
1423                        sqle.setNextException(sdynamic);
1424                }
1425            }
1426            dynamicResults = null;
1427        }
1428
1429        /*
1430              We don't reset statement to null because PreparedStatement
1431              relies on it being there for subsequent (post-close) execution
1432              requests. There is no close method on database statement objects.
1433        */

1434
1435        updateCount = -1; // reset field
1436

1437        if (sqle != null)
1438            throw sqle;
1439     }
1440    
1441    /**
1442        Check to see if a statement requires to be executed via a callable statement.
1443    */

1444    void checkRequiresCallableStatement(Activation activation) throws SQLException JavaDoc {
1445
1446        ParameterValueSet pvs = activation.getParameterValueSet();
1447
1448        if (pvs == null)
1449            return;
1450
1451        if (pvs.checkNoDeclaredOutputParameters()) {
1452            try {
1453                activation.close();
1454            } catch (StandardException se) {
1455            }
1456            throw newSQLException(SQLState.REQUIRES_CALLABLE_STATEMENT, SQLText);
1457        }
1458    }
1459
1460    /**
1461        Transfer my batch of Statements to a newly created Statement.
1462    */

1463    public void transferBatch(EmbedStatement other) throws SQLException JavaDoc {
1464        
1465        synchronized (getConnectionSynchronization()) {
1466            other.batchStatements = batchStatements;
1467            batchStatements = null;
1468        }
1469    }
1470    
1471    /**
1472     * Set the application statement for this Statement.
1473    */

1474    public final void setApplicationStatement(EngineStatement s) {
1475        this.applicationStatement = s;
1476    }
1477
1478    private EmbedResultSet[] dynamicResults;
1479    private int currentDynamicResultSet;
1480
1481    /**
1482     * Go through a holder of dynamic result sets, remove those that
1483     * should not be returned, and sort the result sets according to
1484     * their creation.
1485     *
1486     * @param holder a holder of dynamic result sets
1487     * @param maxDynamicResultSets the maximum number of result sets
1488     * to be returned
1489     * @return the actual number of result sets
1490     * @exception SQLException if an error occurs
1491     */

1492    private int processDynamicResults(java.sql.ResultSet JavaDoc[][] holder,
1493                                      int maxDynamicResultSets)
1494        throws SQLException JavaDoc
1495    {
1496
1497        EmbedResultSet[] sorted = new EmbedResultSet[holder.length];
1498
1499        int actualCount = 0;
1500        for (int i = 0; i < holder.length; i++) {
1501
1502            java.sql.ResultSet JavaDoc[] param = holder[i];
1503
1504            if (param[0] == null)
1505                continue;
1506
1507            java.sql.ResultSet JavaDoc rs = param[0];
1508            param[0] = null;
1509
1510            // ignore non-cloudscape result sets or results sets from another connection
1511
if (!(rs instanceof EmbedResultSet))
1512                continue;
1513
1514            EmbedResultSet lrs = (EmbedResultSet) rs;
1515
1516            if (lrs.getEmbedConnection().rootConnection != getEmbedConnection().rootConnection)
1517                continue;
1518
1519            // ignore closed result sets.
1520
if (lrs.isClosed)
1521                continue;
1522
1523            lrs.setDynamicResultSet(this);
1524            sorted[actualCount++] = lrs;
1525        }
1526
1527        if (actualCount != 0) {
1528
1529            // results are defined to be ordered according to their creation
1530
if (actualCount != 1) {
1531                java.util.Arrays.sort(sorted, 0, actualCount);
1532            }
1533
1534            dynamicResults = sorted;
1535
1536            if (actualCount > maxDynamicResultSets) {
1537                addWarning(StandardException.newWarning(SQLState.LANG_TOO_MANY_DYNAMIC_RESULTS_RETURNED));
1538
1539                for (int i = maxDynamicResultSets; i < actualCount; i++) {
1540                    sorted[i].close();
1541                    sorted[i] = null;
1542                }
1543
1544                actualCount = maxDynamicResultSets;
1545            }
1546
1547
1548            updateCount = -1;
1549            results = sorted[0];
1550            currentDynamicResultSet = 0;
1551
1552            // 0100C is not returned for procedures written in Java, from the SQL2003 spec.
1553
// getWarnings(StandardException.newWarning(SQLState.LANG_DYNAMIC_RESULTS_RETURNED));
1554
}
1555
1556
1557        return actualCount;
1558    }
1559
1560    /**
1561        Callback on the statement when one of its result sets is closed.
1562        This allows the statement to control when it completes and hence
1563        when it commits in auto commit mode.
1564
1565        Must have connection synchronization and setupContextStack(), this
1566        is required for the call to commitIfNeeded().
1567    */

1568    void resultSetClosing(EmbedResultSet closingLRS) throws SQLException JavaDoc {
1569
1570        // If the Connection is not in auto commit then this statement completion
1571
// cannot cause a commit.
1572
if (!getEmbedConnection().autoCommit)
1573            return;
1574
1575        // If we have dynamic results, see if there is another result set open.
1576
// If so, then no commit. The last result set to close will close the statement.
1577
if (dynamicResults != null) {
1578            for (int i = 0; i < dynamicResults.length; i++) {
1579                EmbedResultSet lrs = dynamicResults[i];
1580                if (lrs == null)
1581                    continue;
1582                if (lrs.isClosed)
1583                    continue;
1584                if (lrs == closingLRS)
1585                    continue;
1586
1587                // at least one still open so no commit now.
1588
return;
1589            }
1590        }
1591
1592        // new Throwable("COMMIT ON " + SQLText).printStackTrace(System.out);
1593

1594        // beetle 5383. Force a commit in autocommit always. Before this
1595
// change if client in autocommit opened a result set, did a commit,
1596
// then next then close a commit would not be forced on the close.
1597
commitIfAutoCommit();
1598    }
1599    
1600    /**
1601     * Get the execute time holdability for the Statement.
1602     * When in a global transaction holdabilty defaults to false.
1603     * @throws SQLException Error from getResultSetHoldability.
1604     */

1605    private boolean getExecuteHoldable() throws SQLException JavaDoc
1606    {
1607        if (resultSetHoldability == JDBC30Translation.CLOSE_CURSORS_AT_COMMIT)
1608            return false;
1609        
1610        // Simple non-XA case
1611
if (applicationStatement == this)
1612            return true;
1613        
1614        return applicationStatement.getResultSetHoldability() ==
1615            JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
1616    }
1617
1618    /**
1619     * Returns the value of the EmbedStatement's poolable hint,
1620     * indicating whether pooling is requested.
1621     *
1622     * @return The value of the poolable hint.
1623     * @throws SQLException if the Statement has been closed.
1624     */

1625
1626    public boolean isPoolable() throws SQLException JavaDoc {
1627        // Assert the statement is still active (not closed)
1628
checkStatus();
1629
1630        return isPoolable;
1631    }
1632
1633    /**
1634     * Requests that an EmbedStatement be pooled or not.
1635     *
1636     * @param poolable requests that the EmbedStatement be pooled if true
1637     * and not be pooled if false.
1638     * @throws SQLException if the EmbedStatement has been closed.
1639     */

1640     
1641    public void setPoolable(boolean poolable) throws SQLException JavaDoc {
1642        // Assert the statement is still active (not closed)
1643
checkStatus();
1644
1645        isPoolable = poolable;
1646    }
1647}
1648
1649
Popular Tags