001: package com.quadcap.jdbc;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.IOException;
042:
043: import java.sql.SQLException;
044: import java.sql.SQLWarning;
045:
046: import antlr.RecognitionException;
047: import antlr.TokenStreamException;
048:
049: import com.quadcap.sql.Database;
050: import com.quadcap.sql.Session;
051: import com.quadcap.sql.SQLParser;
052: import com.quadcap.sql.Stmt;
053:
054: import com.quadcap.util.ConfigNumber;
055: import com.quadcap.util.Debug;
056: import com.quadcap.util.Util;
057:
058: /**
059: * This class implements the <code>java.sql.Statement</code> interface, which
060: * provides facilities for executing SQL statements on a database
061: * connection, as part of that connection's transaction.
062: *
063: * TODO: setMaxFieldSize
064: * TODO: setQueryTimeout
065: * TODO: JDBC3.0: return generated keys
066: *
067: * @author Stan Bailes
068: */
069: public class Statement implements java.sql.Statement {
070: /*{com.quadcap.qed.Trace-vars.xml-1054}
071: * <config-var>
072: * <config-name>qed.trace.Statement</config-name>
073: * <config-dflt>0</config-dflt>
074: * <config-desc>
075: * <pre>
076: * bit 0: statement lifecycle
077: * bit 1: statement execution
078: * bit 2: statement + result
079: * bit 4: params in prepared statements
080: * </pre>
081: * </config-desc>
082: * </config-var>
083: */
084: static final ConfigNumber trace = ConfigNumber.find(
085: "qed.trace.Statement", "0");
086:
087: Connection conn;
088: com.quadcap.sql.Connection qConn = null;
089: Session session = null;
090: ResultSet rs = null;
091: int updateCount = -1;
092: protected boolean escapeProcessing = true;
093: int maxRows = -1;
094:
095: /**
096: * Create a new statement
097: */
098: public Statement(Connection conn) throws SQLException, IOException {
099: this .conn = conn;
100: this .qConn = conn.getConnection();
101: this .session = qConn.createSession();
102: //#ifdef DEBUG
103: if (trace.bit(0)) {
104: Debug.println(toString() + " created");
105: }
106: //#endif
107: }
108:
109: /**
110: * Create a new Statement with the specified result set type and
111: * concurrency.
112: */
113: public Statement(Connection conn, int resultSetType,
114: int resultSetConcurrency) throws SQLException, IOException {
115: this (conn);
116: this .resultSetType = resultSetType;
117: this .resultSetConcurrency = resultSetConcurrency;
118: }
119:
120: /**
121: * My short life is ended
122: */
123: public void finalize() throws Throwable {
124: try {
125: close();
126: } catch (Throwable t) {
127: }
128: super .finalize();
129: }
130:
131: /**
132: * This QED release doesn't support batch statement execution.
133: *
134: * @exception SQLException "not implemented"
135: */
136: public void addBatch(String sql) throws SQLException {
137: throw new SQLException("not implemented", "0A000");
138: }
139:
140: /**
141: * QED does not support the <code>cancel()</code> feature.
142: */
143: public void cancel() throws SQLException {
144: }
145:
146: /**
147: * This QED release doesn't support batch statement execution.
148: *
149: * @exception SQLException "not implemented"
150: */
151: public void clearBatch() throws SQLException {
152: throw new SQLException("not implemented", "0A000");
153: }
154:
155: /**
156: * Clear any warnings associated with this <code>Statement</code>
157: * object. Since this QED release doesn't generate
158: * <code>SQLWarning</code>s, this function does nothing.
159: */
160: public void clearWarnings() {
161: }
162:
163: /**
164: * Close this statement object and free up any resources held by it.
165: */
166: public void close() {
167: //#ifdef DEBUG
168: if (trace.bit(0)) {
169: Debug.println(toString() + ".close()");
170: }
171: //#endif
172: if (session != null) {
173: try {
174: session.close();
175: } catch (SQLException e) {
176: } catch (IOException e) {
177: } finally {
178: session = null;
179: qConn = null;
180: }
181: }
182: }
183:
184: //#ifdef DEBUG
185: public String toString() {
186: return "Statement[" + session == null ? "" : session.toString()
187: + "]";
188: }
189:
190: //#endif
191:
192: /**
193: * Execute the specified SQL statement, returning <code>true</code>
194: * if the statement generates a <code>ResultSet</code> object.
195: *
196: * @param sql an SQL statement
197: * @return true if execution of the statement results in the creation
198: * of a <code>ResultSet</code>
199: * @see #getResultSet()
200: * @exception SQLException may be thrown
201: */
202: public boolean execute(String sql) throws SQLException {
203: //#ifdef DEBUG
204: if (trace.bit(1)) {
205: Debug.println(toString() + ".execute(" + sql + ")");
206: }
207: //#endif
208: if (this .qConn == null || this .qConn.isClosed()) {
209: throw new SQLException("Connection closed");
210: }
211:
212: if (this .rs != null) {
213: this .rs.close();
214: this .rs = null;
215: }
216: this .updateCount = -1;
217:
218: session.makeTransaction();
219: SQLParser p = new SQLParser(session, sql, escapeProcessing);
220: String auth = qConn.getAuth();
221: //#ifdef DEBUG
222: String res = "";
223: //#endif
224: try {
225: try {
226: Stmt s = p.statement();
227: if (s == null) {
228: throw new SQLException("Parse error", "42000");
229: }
230: session.doStatement(s);
231: this .rs = (ResultSet) session.getResultSet(this );
232: if (rs != null) {
233: //#ifdef DEBUG
234: res = "true";
235: //#endif
236: return true;
237: } else {
238: this .updateCount = session.getUpdateCount();
239: //#ifdef DEBUG
240: res = String.valueOf(updateCount);
241: //#endif
242: return false;
243: }
244: } catch (IOException e) {
245: //#ifdef DEBUG
246: res = e.toString();
247: //#endif
248: Debug.print(e);
249: session.endStatement(true);
250: throw new SQLException(e.toString(), "Q0012");
251: } catch (RecognitionException e) {
252: //#ifdef DEBUG
253: Debug.print(e);
254: Debug.println("SQL: " + sql);
255: res = e.toString();
256: //#endif
257: session.endStatement(true);
258: SQLException se = new SQLException("Statment: " + sql);
259: SQLException s2 = new SQLException(e.toString(),
260: "42000");
261: s2.setNextException(se);
262: throw s2;
263: } catch (TokenStreamException e) {
264: //#ifdef DEBUG
265: res = e.toString();
266: //#endif
267: session.endStatement(true);
268: SQLException se = new SQLException("Statment: " + sql);
269: SQLException s2 = new SQLException(e.toString(),
270: "42000");
271: s2.setNextException(se);
272: throw s2;
273: } catch (SQLException e) {
274: //#ifdef DEBUG
275: res = e.toString();
276: //#endif
277: session.endStatement(true);
278: throw e;
279: } catch (Throwable e) {
280: //#ifdef DEBUG
281: res = e.toString();
282: Debug.println("Throwable: " + e);
283: Debug.print(e);
284: //#endif
285: session.endStatement(true);
286: throw new SQLException(e.toString(), "Q0013");
287: }
288: } catch (IOException e) {
289: Debug.print(e);
290: throw new SQLException(e.toString(), "Q0014");
291: } finally {
292: // XXX restore auth in case of createSchema
293: // This is a hack. 'create schema' will temporarily set the
294: // 'auth' to the schema name, and this is the first place where
295: // we get a chance to restore the correct auth.
296: //
297: // This is made worse by the fact that names are resolved during
298: // the parse phase, and could be made better if antlr parser
299: // rules allowed you to specify a 'finally' handler.
300:
301: // Also 'create schema' where the schema name is a parameter is
302: // going to fail badly.
303: session.getConnection().setAuth(auth, null);
304: //#ifdef DEBUG
305: if (trace.bit(2)) {
306: Debug
307: .println("Statement.execute(" + sql + ") = "
308: + res);
309: }
310: //#endif
311: }
312: }
313:
314: /**
315: * This QED release doesn't support batch statement execution.
316: *
317: * @exception SQLException "not implemented"
318: */
319: public int[] executeBatch() throws SQLException {
320: throw new SQLException("not implemented", "0A000");
321: }
322:
323: /**
324: * Execute the specified SQL query statement, returning the
325: * <code>ResultSet</code> object containing the results of the
326: * query.
327: *
328: * @param sql an SQL query statement
329: * @return a <code>ResultSet</code> object containing the results of
330: * the query
331: * @exception SQLException may be thrown
332: */
333: public java.sql.ResultSet executeQuery(String sql)
334: throws SQLException {
335: if (execute(sql)) {
336: return this .rs;
337: } else {
338: return null;
339: }
340: }
341:
342: /**
343: * Execute the specified SQL update statement, returning the update
344: * count, meaning the number of rows updated or inserted by this
345: * statement.
346: *
347: * @param sql an SQL update statement
348: * @return the update count
349: * @exception SQLException may be thrown
350: */
351: public int executeUpdate(String sql) throws SQLException {
352: if (!execute(sql)) {
353: return this .updateCount;
354: } else {
355: return 0;
356: }
357: }
358:
359: /**
360: * Return the <code>Connection</code> object used to create this
361: * <code>Statement</code> object.
362: *
363: * @return this statement's connection.
364: */
365: public java.sql.Connection getConnection() {
366: return conn;
367: }
368:
369: /**
370: * In QED, the fetch size is always 1.
371: *
372: * @return one
373: */
374: public int getFetchSize() {
375: return 1;
376: }
377:
378: /**
379: * QED imposes no maximum field size.
380: *
381: * @return zero, meaning unlimited
382: */
383: public int getMaxFieldSize() {
384: return 0;
385: }
386:
387: /**
388: * QED imposes no limit on the number of rows in a <code>ResultSet</code>.
389: *
390: * @return zero, meaning unlimited
391: */
392: public int getMaxRows() {
393: return 0;
394: }
395:
396: /**
397: * QED only returns one <code>ResultSet</code> per statement, so
398: * this function always returns <code>false</code> (after closing
399: * the current <code>ResultSet</code> object for this
400: * <code>Statement</code>.
401: *
402: * @return false
403: * @exception SQLException may be thrown
404: */
405: public boolean getMoreResults() throws SQLException {
406: if (rs != null)
407: rs.close();
408: this .updateCount = -1;
409: return false;
410: }
411:
412: /**
413: * QED doesn't support query timeouts, so this method always returns
414: * zero.
415: *
416: * @return zero, meaning unlimited
417: */
418: public int getQueryTimeout() {
419: return 0;
420: }
421:
422: /**
423: * Return the <code>ResultSet</code> generated by the last call to
424: * <code>execute()</code>, unless that <code>ResultSet</code> has
425: * been closed, or if there was no <code>ResultSet</code> generated
426: * by the last call to <code>execute()</code>, in which case, return
427: * <code>null</code>.
428: *
429: * @return the current <code>ResultSet</code>
430: *
431: */
432: public java.sql.ResultSet getResultSet() {
433: return rs;
434: }
435:
436: /**
437: * Return the update count for the last statement executed. If no
438: * records were updated, inserted, or deleted, return -1.
439: *
440: * @return the update count for the last <code>execute()</code>
441: * operation
442: */
443: public int getUpdateCount() {
444: return updateCount;
445: }
446:
447: /**
448: * Since this QED release doesn't generate
449: * <code>SQLWarning</code>s, this function always returns null.
450: *
451: * @return null
452: */
453: public SQLWarning getWarnings() {
454: return null;
455: }
456:
457: /**
458: * This QED release doesn't support SQL named cursors
459: *
460: * @exception SQLException "not implemented"
461: */
462: public void setCursorName(String name) throws SQLException {
463: throw new SQLException("not implemented", "0A000");
464: }
465:
466: /**
467: * Enable or disable JDBC escape processing mode.
468: *
469: * @boolean enable <code>true</code> is the driver should perform
470: * JDBC escape processing on statement execution.
471: */
472: public void setEscapeProcessing(boolean enable) {
473: escapeProcessing = enable;
474: }
475:
476: /**
477: * Set the default fetch direction for <code>ResultSet</code> objects
478: * generated by this <code>Statement</code> object.
479: */
480: public void setFetchDirection(int dir) throws SQLException {
481: }
482:
483: /**
484: * QED, being an embedded driver, fetches rows only when they are
485: * needed, with no performance penalty. Thus, the fetch size is
486: * always <code>one</code>, and this function has no effect.
487: */
488: public void setFetchSize(int x) throws SQLException {
489: }
490:
491: /**
492: * Not implemented in this release of QED
493: *
494: * @exception SQLException "not implemented"
495: */
496: public void setMaxFieldSize(int x) throws SQLException {
497: throw new SQLException("not implemented", "0A000");
498: }
499:
500: /**
501: * Set the maximum number of rows that will be returned by this
502: * ResultSet
503: */
504: public void setMaxRows(int x) throws SQLException {
505: maxRows = x;
506: }
507:
508: /**
509: * Not implemented in this release of QED
510: *
511: * @exception SQLException "not implemented"
512: */
513: public void setQueryTimeout(int x) throws SQLException {
514: throw new SQLException("not implemented", "0A000");
515: }
516:
517: int resultSetType = ResultSet.TYPE_SCROLL_INSENSITIVE;
518: int resultSetConcurrency = ResultSet.CONCUR_UPDATABLE;
519:
520: /**
521: * Return the default result set concurrency for <code>ResultSet</code>
522: * objects generated by this <code>Statement</code> object.
523: *
524: * @return the default result set concurrency
525: */
526: public int getResultSetConcurrency() {
527: return resultSetConcurrency;
528: }
529:
530: /**
531: * Return the default result set type for <code>ResultSet</code>
532: * objects generated by this <code>Statement</code> object.
533: *
534: * @return the default result set type
535: */
536: public int getResultSetType() {
537: return resultSetType;
538: }
539:
540: /**
541: * This release of QED only supports the fetch direction:
542: * <code>ResultSet.FETCH_FORWARD</code>
543: *
544: * @return <code>ResultSet.FETCH_FORWARD</code>
545: */
546: public int getFetchDirection() {
547: return ResultSet.FETCH_FORWARD;
548: }
549:
550: // JDBC 3.0 -------------------------------------------------------
551: //#ifdef JDK14
552: /**
553: * Moves to this <code>Statement</code> object's next result, deals with
554: * any current <code>ResultSet</code> object(s) according to the
555: * instructions specified by the given flag, and returns
556: * <code>true</code> if the next result is a <code>ResultSet</code> object.
557: *
558: * <P>There are no more results when the following is true:
559: * <PRE>
560: * <code>(!getMoreResults() && (getUpdateCount() == -1)</code>
561: * </PRE>
562: *
563: * @param current one of the following <code>Statement</code>
564: * constants indicating what should happen to current
565: * <code>ResultSet</code> objects obtained using the method
566: * <code>getResultSet</code:
567: * <code>CLOSE_CURRENT_RESULT</code>,
568: * <code>KEEP_CURRENT_RESULT</code>, or
569: * <code>CLOSE_ALL_RESULTS</code>
570: * @return <code>true</code> if the next result is a <code>ResultSet</code>
571: * object; <code>false</code> if it is an update count or there are no
572: * more results
573: * @exception SQLException if a database access error occurs
574: * @since 1.4
575: * @see #execute
576: */
577: public boolean getMoreResults(int current) throws SQLException {
578: if (current == KEEP_CURRENT_RESULT) {
579: throw new SQLException(
580: "JDBC 3.0 feature KEEP_CURRENT_RESULT "
581: + "not implemented");
582: }
583: return getMoreResults();
584: }
585:
586: /**
587: * Retrieves any auto-generated keys created as a result of executing this
588: * <code>Statement</code> object. If this <code>Statement</code> object
589: * did not generate any keys, an empty <code>ResultSet</code>
590: * object is returned.
591: *
592: * @return a <code>ResultSet</code> object containing the auto-generated
593: * key(s) generated by the execution of this
594: * <code>Statement</code> object
595: * @exception SQLException if a database access error occurs
596: * @since 1.4
597: */
598: public java.sql.ResultSet getGeneratedKeys() throws SQLException {
599: throw new SQLException("JDBC3.0 feature not implemented");
600: }
601:
602: /**
603: * Executes the given SQL statement and signals the driver with the
604: * given flag about whether the
605: * auto-generated keys produced by this <code>Statement</code> object
606: * should be made available for retrieval.
607: *
608: * @param sql must be an SQL <code>INSERT</code>, <code>UPDATE</code> or
609: * <code>DELETE</code> statement or an SQL statement that
610: * returns nothing
611: * @param autoGeneratedKeys a flag indicating whether auto-generated keys
612: * should be made available for retrieval;
613: * one of the following constants:
614: * <code>Statement.RETURN_GENERATED_KEYS</code>
615: * <code>Statement.NO_GENERATED_KEYS</code>
616: * @return either the row count for <code>INSERT</code>,
617: * <code>UPDATE</code>
618: * or <code>DELETE</code> statements, or <code>0</code> for SQL
619: * statements that return nothing
620: * @exception SQLException if a database access error occurs, the given
621: * SQL statement returns a <code>ResultSet</code> object, or
622: * the given constant is not one of those allowed
623: * @since 1.4
624: */
625: public int executeUpdate(String sql, int autoGeneratedKeys)
626: throws SQLException {
627: if (autoGeneratedKeys == RETURN_GENERATED_KEYS) {
628: throw new SQLException("JDBC3.0 feature not implemented");
629: }
630: return executeUpdate(sql);
631: }
632:
633: /**
634: * Executes the given SQL statement and signals the driver that the
635: * auto-generated keys indicated in the given array should be made
636: * available for retrieval. The driver will ignore the array if the
637: * SQL statement is not an <code>INSERT</code> statement.
638: *
639: * @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
640: * <code>DELETE</code> statement or an SQL statement that returns
641: * nothing, such as an SQL DDL statement
642: * @param columnIndexes an array of column indexes indicating the columns
643: * that should be returned from the inserted row
644: * @return either the row count for <code>INSERT</code>,
645: * <code>UPDATE</code>,
646: * or <code>DELETE</code> statements, or 0 for SQL statements
647: * that return nothing
648: * @exception SQLException if a database access error occurs or the SQL
649: * statement returns a <code>ResultSet</code> object
650: * @since 1.4
651: */
652: public int executeUpdate(String sql, int columnIndexes[])
653: throws SQLException {
654: return executeUpdate(sql);
655: }
656:
657: /**
658: * Executes the given SQL statement and signals the driver that the
659: * auto-generated keys indicated in the given array should be made available
660: * for retrieval. The driver will ignore the array if the SQL statement
661: * is not an <code>INSERT</code> statement.
662: *
663: * @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
664: * <code>DELETE</code> statement or an SQL statement that returns nothing
665: * @param columnNames an array of the names of the columns that should be
666: * returned from the inserted row
667: * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>,
668: * or <code>DELETE</code> statements, or 0 for SQL statements
669: * that return nothing
670: * @exception SQLException if a database access error occurs
671: *
672: * @since 1.4
673: */
674: public int executeUpdate(String sql, String columnNames[])
675: throws SQLException {
676: return executeUpdate(sql);
677: }
678:
679: /**
680: * Executes the given SQL statement, which may return multiple results,
681: * and signals the driver that any
682: * auto-generated keys should be made available
683: * for retrieval. The driver will ignore this signal if the SQL statement
684: * is not an <code>INSERT</code> statement.
685: * <P>
686: * In some (uncommon) situations, a single SQL statement may return
687: * multiple result sets and/or update counts. Normally you can ignore
688: * this unless you are (1) executing a stored procedure that you know may
689: * return multiple results or (2) you are dynamically executing an
690: * unknown SQL string.
691: * <P>
692: * The <code>execute</code> method executes an SQL statement and indicates the
693: * form of the first result. You must then use the methods
694: * <code>getResultSet</code> or <code>getUpdateCount</code>
695: * to retrieve the result, and <code>getMoreResults</code> to
696: * move to any subsequent result(s).
697: *
698: * @param sql any SQL statement
699: * @param autoGeneratedKeys a constant indicating whether auto-generated
700: * keys should be made available for retrieval using the method
701: * <code>getGeneratedKeys</code>; one of the following constants:
702: * <code>Statement.RETURN_GENERATED_KEYS</code> or
703: * <code>Statement.NO_GENERATED_KEYS</code>
704: * @return <code>true</code> if the first result is a <code>ResultSet</code>
705: * object; <code>false</code> if it is an update count or there are
706: * no results
707: * @exception SQLException if a database access error occurs
708: * @see #getResultSet
709: * @see #getUpdateCount
710: * @see #getMoreResults
711: * @see #getGeneratedKeys
712: *
713: * @since 1.4
714: */
715: public boolean execute(String sql, int autoGeneratedKeys)
716: throws SQLException {
717: return execute(sql);
718: }
719:
720: /**
721: * Executes the given SQL statement, which may return multiple results,
722: * and signals the driver that the
723: * auto-generated keys indicated in the given array should be made available
724: * for retrieval. This array contains the indexes of the columns in the
725: * target table that contain the auto-generated keys that should be made
726: * available. The driver will ignore the array if the given SQL statement
727: * is not an <code>INSERT</code> statement.
728: * <P>
729: * Under some (uncommon) situations, a single SQL statement may return
730: * multiple result sets and/or update counts. Normally you can ignore
731: * this unless you are (1) executing a stored procedure that you know may
732: * return multiple results or (2) you are dynamically executing an
733: * unknown SQL string.
734: * <P>
735: * The <code>execute</code> method executes an SQL statement and indicates the
736: * form of the first result. You must then use the methods
737: * <code>getResultSet</code> or <code>getUpdateCount</code>
738: * to retrieve the result, and <code>getMoreResults</code> to
739: * move to any subsequent result(s).
740: *
741: * @param sql any SQL statement
742: * @param columnIndexes an array of the indexes of the columns in the
743: * inserted row that should be made available for retrieval by a
744: * call to the method <code>getGeneratedKeys</code>
745: * @return <code>true</code> if the first result is a <code>ResultSet</code>
746: * object; <code>false</code> if it is an update count or there
747: * are no results
748: * @exception SQLException if a database access error occurs
749: * @see #getResultSet
750: * @see #getUpdateCount
751: * @see #getMoreResults
752: *
753: * @since 1.4
754: */
755: public boolean execute(String sql, int columnIndexes[])
756: throws SQLException {
757: return execute(sql);
758: }
759:
760: /**
761: * Executes the given SQL statement, which may return multiple results,
762: * and signals the driver that the
763: * auto-generated keys indicated in the given array should be made available
764: * for retrieval. This array contains the names of the columns in the
765: * target table that contain the auto-generated keys that should be made
766: * available. The driver will ignore the array if the given SQL statement
767: * is not an <code>INSERT</code> statement.
768: * <P>
769: * In some (uncommon) situations, a single SQL statement may return
770: * multiple result sets and/or update counts. Normally you can ignore
771: * this unless you are (1) executing a stored procedure that you know may
772: * return multiple results or (2) you are dynamically executing an
773: * unknown SQL string.
774: * <P>
775: * The <code>execute</code> method executes an SQL statement and indicates the
776: * form of the first result. You must then use the methods
777: * <code>getResultSet</code> or <code>getUpdateCount</code>
778: * to retrieve the result, and <code>getMoreResults</code> to
779: * move to any subsequent result(s).
780: *
781: * @param sql any SQL statement
782: * @param columnNames an array of the names of the columns in the inserted
783: * row that should be made available for retrieval by a call to the
784: * method <code>getGeneratedKeys</code>
785: * @return <code>true</code> if the next result is a <code>ResultSet</code>
786: * object; <code>false</code> if it is an update count or there
787: * are no more results
788: * @exception SQLException if a database access error occurs
789: * @see #getResultSet
790: * @see #getUpdateCount
791: * @see #getMoreResults
792: * @see #getGeneratedKeys
793: *
794: * @since 1.4
795: */
796: public boolean execute(String sql, String columnNames[])
797: throws SQLException {
798: return execute(sql);
799: }
800:
801: /**
802: * Retrieves the result set holdability for <code>ResultSet</code> objects
803: * generated by this <code>Statement</code> object.
804: *
805: * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
806: * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
807: * @exception SQLException if a database access error occurs
808: *
809: * @since 1.4
810: */
811: public int getResultSetHoldability() throws SQLException {
812: return ResultSet.CLOSE_CURSORS_AT_COMMIT;
813: }
814: //#endif
815:
816: }
|