File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\jdbc\JdbcStatement.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.jdbc;
8
9 import java.sql.Connection;
10 import java.sql.ResultSet;
11 import java.sql.SQLException;
12 import java.sql.SQLWarning;
13 import java.sql.Statement;
14 import java.util.ArrayList;
15 import org.h2.command.CommandInterface;
16 import org.h2.constant.ErrorCode;
17 import org.h2.constant.SysProperties;
18 import org.h2.engine.SessionInterface;
19 import org.h2.message.DbException;
20 import org.h2.message.TraceObject;
21 import org.h2.result.ResultInterface;
22 import org.h2.util.New;
23
24 /**
25 * Represents a statement.
26 */
27 public class JdbcStatement extends TraceObject implements Statement {
28
29 protected JdbcConnection conn;
30 protected SessionInterface session;
31 protected JdbcResultSet resultSet;
32 protected int maxRows;
33 protected int fetchSize = SysProperties.SERVER_RESULT_SET_FETCH_SIZE;
34 protected int updateCount;
35 protected final int resultSetType;
36 protected final int resultSetConcurrency;
37 protected final boolean closedByResultSet;
38 private CommandInterface executingCommand;
39 private int lastExecutedCommandType;
40 private ArrayList<String> batchCommands;
41 private boolean escapeProcessing = true;
42
43 JdbcStatement(JdbcConnection conn, int id, int resultSetType, int resultSetConcurrency, boolean closeWithResultSet) {
44 this.conn = conn;
45 this.session = conn.getSession();
46 setTrace(session.getTrace(), TraceObject.STATEMENT, id);
47 this.resultSetType = resultSetType;
48 this.resultSetConcurrency = resultSetConcurrency;
49 this.closedByResultSet = closeWithResultSet;
50 }
51
52 /**
53 * Executes a query (select statement) and returns the result set.
54 * If another result set exists for this statement, this will be closed
55 * (even if this statement fails).
56 *
57 * @param sql the SQL statement to execute
58 * @return the result set
59 */
60 public ResultSet executeQuery(String sql) throws SQLException {
61 try {
62 int id = getNextId(TraceObject.RESULT_SET);
63 if (isDebugEnabled()) {
64 debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id, "executeQuery(" + quote(sql) + ")");
65 }
66 synchronized (session) {
67 checkClosed();
68 closeOldResultSet();
69 sql = JdbcConnection.translateSQL(sql, escapeProcessing);
70 CommandInterface command = conn.prepareCommand(sql, fetchSize);
71 ResultInterface result;
72 boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
73 boolean updatable = resultSetConcurrency == ResultSet.CONCUR_UPDATABLE;
74 setExecutingStatement(command);
75 try {
76 result = command.executeQuery(maxRows, scrollable);
77 } finally {
78 setExecutingStatement(null);
79 }
80 command.close();
81 resultSet = new JdbcResultSet(conn, this, result, id, closedByResultSet, scrollable, updatable);
82 }
83 return resultSet;
84 } catch (Exception e) {
85 throw logAndConvert(e);
86 }
87 }
88
89 /**
90 * Executes a statement (insert, update, delete, create, drop)
91 * and returns the update count.
92 * If another result set exists for this statement, this will be closed
93 * (even if this statement fails).
94 *
95 * If auto commit is on, this statement will be committed.
96 * If the statement is a DDL statement (create, drop, alter) and does not
97 * throw an exception, the current transaction (if any) is committed after
98 * executing the statement.
99 *
100 * @param sql the SQL statement
101 * @return the update count (number of row affected by an insert,
102 * update or delete, or 0 if no rows or the statement was a
103 * create, drop, commit or rollback)
104 * @throws SQLException if a database error occurred or a
105 * select statement was executed
106 */
107 public int executeUpdate(String sql) throws SQLException {
108 try {
109 debugCodeCall("executeUpdate", sql);
110 return executeUpdateInternal(sql);
111 } catch (Exception e) {
112 throw logAndConvert(e);
113 }
114 }
115
116 private int executeUpdateInternal(String sql) throws SQLException {
117 checkClosedForWrite();
118 try {
119 closeOldResultSet();
120 sql = JdbcConnection.translateSQL(sql, escapeProcessing);
121 CommandInterface command = conn.prepareCommand(sql, fetchSize);
122 synchronized (session) {
123 setExecutingStatement(command);
124 try {
125 updateCount = command.executeUpdate();
126 } finally {
127 setExecutingStatement(null);
128 }
129 }
130 command.close();
131 return updateCount;
132 } finally {
133 afterWriting();
134 }
135 }
136
137 /**
138 * Executes an arbitrary statement. If another result set exists for this
139 * statement, this will be closed (even if this statement fails).
140 *
141 * If the statement is a create or drop and does not throw an exception, the
142 * current transaction (if any) is committed after executing the statement.
143 * If auto commit is on, and the statement is not a select, this statement
144 * will be committed.
145 *
146 * @param sql the SQL statement to execute
147 * @return true if a result set is available, false if not
148 */
149 public boolean execute(String sql) throws SQLException {
150 try {
151 debugCodeCall("execute", sql);
152 return executeInternal(sql);
153 } catch (Exception e) {
154 throw logAndConvert(e);
155 }
156 }
157
158 private boolean executeInternal(String sql) throws SQLException {
159 int id = getNextId(TraceObject.RESULT_SET);
160 checkClosedForWrite();
161 try {
162 closeOldResultSet();
163 sql = JdbcConnection.translateSQL(sql, escapeProcessing);
164 CommandInterface command = conn.prepareCommand(sql, fetchSize);
165 boolean returnsResultSet;
166 synchronized (session) {
167 setExecutingStatement(command);
168 try {
169 if (command.isQuery()) {
170 returnsResultSet = true;
171 boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
172 boolean updatable = resultSetConcurrency == ResultSet.CONCUR_UPDATABLE;
173 ResultInterface result = command.executeQuery(maxRows, scrollable);
174 resultSet = new JdbcResultSet(conn, this, result, id, closedByResultSet, scrollable, updatable);
175 } else {
176 returnsResultSet = false;
177 updateCount = command.executeUpdate();
178 }
179 } finally {
180 setExecutingStatement(null);
181 }
182 }
183 command.close();
184 return returnsResultSet;
185 } finally {
186 afterWriting();
187 }
188 }
189
190 /**
191 * Returns the last result set produces by this statement.
192 *
193 * @return the result set
194 */
195 public ResultSet getResultSet() throws SQLException {
196 try {
197 checkClosed();
198 if (resultSet != null) {
199 int id = resultSet.getTraceId();
200 debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id, "getResultSet()");
201 } else {
202 debugCodeCall("getResultSet");
203 }
204 return resultSet;
205 } catch (Exception e) {
206 throw logAndConvert(e);
207 }
208 }
209
210 /**
211 * Returns the last update count of this statement.
212 *
213 * @return the update count (number of row affected by an insert,
214 * update or delete, or 0 if no rows or the statement was a
215 * create, drop, commit or rollback; -1 if the statement was a select).
216 * @throws SQLException if this object is closed or invalid
217 */
218 public int getUpdateCount() throws SQLException {
219 try {
220 debugCodeCall("getUpdateCount");
221 checkClosed();
222 return updateCount;
223 } catch (Exception e) {
224 throw logAndConvert(e);
225 }
226 }
227
228 /**
229 * Closes this statement.
230 * All result sets that where created by this statement
231 * become invalid after calling this method.
232 */
233 public void close() throws SQLException {
234 try {
235 debugCodeCall("close");
236 synchronized (session) {
237 closeOldResultSet();
238 if (conn != null) {
239 conn = null;
240 }
241 }
242 } catch (Exception e) {
243 throw logAndConvert(e);
244 }
245 }
246
247 /**
248 * Returns the connection that created this object.
249 *
250 * @return the connection
251 */
252 public Connection getConnection() {
253 debugCodeCall("getConnection");
254 return conn;
255 }
256
257 /**
258 * Gets the first warning reported by calls on this object.
259 * This driver does not support warnings, and will always return null.
260 *
261 * @return null
262 */
263 public SQLWarning getWarnings() throws SQLException {
264 try {
265 debugCodeCall("getWarnings");
266 checkClosed();
267 return null;
268 } catch (Exception e) {
269 throw logAndConvert(e);
270 }
271 }
272
273 /**
274 * Clears all warnings. As this driver does not support warnings,
275 * this call is ignored.
276 */
277 public void clearWarnings() throws SQLException {
278 try {
279 debugCodeCall("clearWarnings");
280 checkClosed();
281 } catch (Exception e) {
282 throw logAndConvert(e);
283 }
284 }
285
286 /**
287 * Sets the name of the cursor. This call is ignored.
288 *
289 * @param name ignored
290 * @throws SQLException if this object is closed
291 */
292 public void setCursorName(String name) throws SQLException {
293 try {
294 debugCodeCall("setCursorName", name);
295 checkClosed();
296 } catch (Exception e) {
297 throw logAndConvert(e);
298 }
299 }
300
301 /**
302 * Sets the fetch direction.
303 * This call is ignored by this driver.
304 *
305 * @param direction ignored
306 * @throws SQLException if this object is closed
307 */
308 public void setFetchDirection(int direction) throws SQLException {
309 try {
310 debugCodeCall("setFetchDirection", direction);
311 checkClosed();
312 } catch (Exception e) {
313 throw logAndConvert(e);
314 }
315 }
316
317 /**
318 * Gets the fetch direction.
319 *
320 * @return FETCH_FORWARD
321 * @throws SQLException if this object is closed
322 */
323 public int getFetchDirection() throws SQLException {
324 try {
325 debugCodeCall("getFetchDirection");
326 checkClosed();
327 return ResultSet.FETCH_FORWARD;
328 } catch (Exception e) {
329 throw logAndConvert(e);
330 }
331 }
332
333 /**
334 * Gets the maximum number of rows for a ResultSet.
335 *
336 * @return the number of rows where 0 means no limit
337 * @throws SQLException if this object is closed
338 */
339 public int getMaxRows() throws SQLException {
340 try {
341 debugCodeCall("getMaxRows");
342 checkClosed();
343 return maxRows;
344 } catch (Exception e) {
345 throw logAndConvert(e);
346 }
347 }
348
349 /**
350 * Gets the maximum number of rows for a ResultSet.
351 *
352 * @param maxRows the number of rows where 0 means no limit
353 * @throws SQLException if this object is closed
354 */
355 public void setMaxRows(int maxRows) throws SQLException {
356 try {
357 debugCodeCall("setMaxRows", maxRows);
358 checkClosed();
359 if (maxRows < 0) {
360 throw DbException.getInvalidValueException("maxRows", maxRows);
361 }
362 this.maxRows = maxRows;
363 } catch (Exception e) {
364 throw logAndConvert(e);
365 }
366 }
367
368 /**
369 * Sets the number of rows suggested to read in one step.
370 * This value cannot be higher than the maximum rows (setMaxRows)
371 * set by the statement or prepared statement, otherwise an exception
372 * is throws. Setting the value to 0 will set the default value.
373 * The default value can be changed using the system property
374 * h2.serverResultSetFetchSize.
375 *
376 * @param rows the number of rows
377 * @throws SQLException if this object is closed
378 */
379 public void setFetchSize(int rows) throws SQLException {
380 try {
381 debugCodeCall("setFetchSize", rows);
382 checkClosed();
383 if (rows < 0 || (rows > 0 && maxRows > 0 && rows > maxRows)) {
384 throw DbException.getInvalidValueException("rows", rows);
385 }
386 if (rows == 0) {
387 rows = SysProperties.SERVER_RESULT_SET_FETCH_SIZE;
388 }
389 fetchSize = rows;
390 } catch (Exception e) {
391 throw logAndConvert(e);
392 }
393 }
394
395 /**
396 * Gets the number of rows suggested to read in one step.
397 *
398 * @return the current fetch size
399 * @throws SQLException if this object is closed
400 */
401 public int getFetchSize() throws SQLException {
402 try {
403 debugCodeCall("getFetchSize");
404 checkClosed();
405 return fetchSize;
406 } catch (Exception e) {
407 throw logAndConvert(e);
408 }
409 }
410
411 /**
412 * Gets the result set concurrency created by this object.
413 *
414 * @return the concurrency
415 */
416 public int getResultSetConcurrency() throws SQLException {
417 try {
418 debugCodeCall("getResultSetConcurrency");
419 checkClosed();
420 return resultSetConcurrency;
421 } catch (Exception e) {
422 throw logAndConvert(e);
423 }
424 }
425
426 /**
427 * Gets the result set type.
428 *
429 * @return the type
430 * @throws SQLException if this object is closed
431 */
432 public int getResultSetType() throws SQLException {
433 try {
434 debugCodeCall("getResultSetType");
435 checkClosed();
436 return resultSetType;
437 } catch (Exception e) {
438 throw logAndConvert(e);
439 }
440 }
441
442 /**
443 * Gets the maximum number of bytes for a result set column.
444 *
445 * @return always 0 for no limit
446 * @throws SQLException if this object is closed
447 */
448 public int getMaxFieldSize() throws SQLException {
449 try {
450 debugCodeCall("getMaxFieldSize");
451 checkClosed();
452 return 0;
453 } catch (Exception e) {
454 throw logAndConvert(e);
455 }
456 }
457
458 /**
459 * Sets the maximum number of bytes for a result set column.
460 * This method does currently do nothing for this driver.
461 *
462 * @param max the maximum size - ignored
463 * @throws SQLException if this object is closed
464 */
465 public void setMaxFieldSize(int max) throws SQLException {
466 try {
467 debugCodeCall("setMaxFieldSize", max);
468 checkClosed();
469 } catch (Exception e) {
470 throw logAndConvert(e);
471 }
472 }
473
474 /**
475 * Enables or disables processing or JDBC escape syntax.
476 * See also Connection.nativeSQL.
477 *
478 * @param enable - true (default) or false (no conversion is attempted)
479 * @throws SQLException if this object is closed
480 */
481 public void setEscapeProcessing(boolean enable) throws SQLException {
482 try {
483 if (isDebugEnabled()) {
484 debugCode("setEscapeProcessing("+enable+");");
485 }
486 checkClosed();
487 escapeProcessing = enable;
488 } catch (Exception e) {
489 throw logAndConvert(e);
490 }
491 }
492
493 /**
494 * Cancels a currently running statement.
495 * This method must be called from within another
496 * thread than the execute method.
497 * Operations on large objects are not interrupted,
498 * only operations that process many rows.
499 *
500 * @throws SQLException if this object is closed
501 */
502 public void cancel() throws SQLException {
503 try {
504 debugCodeCall("cancel");
505 checkClosed();
506 // executingCommand can be reset by another thread
507 CommandInterface c = executingCommand;
508 try {
509 if (c != null) {
510 c.cancel();
511 }
512 } finally {
513 setExecutingStatement(null);
514 }
515 } catch (Exception e) {
516 throw logAndConvert(e);
517 }
518 }
519
520 /**
521 * Gets the current query timeout in seconds.
522 * This method will return 0 if no query timeout is set.
523 * The result is rounded to the next second.
524 * For performance reasons, only the first call to this method
525 * will query the database. If the query timeout was changed in another
526 * way than calling setQueryTimeout, this method will always return
527 * the last value.
528 *
529 * @return the timeout in seconds
530 * @throws SQLException if this object is closed
531 */
532 public int getQueryTimeout() throws SQLException {
533 try {
534 debugCodeCall("getQueryTimeout");
535 checkClosed();
536 return conn.getQueryTimeout();
537 } catch (Exception e) {
538 throw logAndConvert(e);
539 }
540 }
541
542 /**
543 * Sets the current query timeout in seconds.
544 * Changing the value will affect all statements of this connection.
545 * This method does not commit a transaction,
546 * and rolling back a transaction does not affect this setting.
547 *
548 * @param seconds the timeout in seconds - 0 means no timeout, values
549 * smaller 0 will throw an exception
550 * @throws SQLException if this object is closed
551 */
552 public void setQueryTimeout(int seconds) throws SQLException {
553 try {
554 debugCodeCall("setQueryTimeout", seconds);
555 checkClosed();
556 if (seconds < 0) {
557 throw DbException.getInvalidValueException("seconds", seconds);
558 }
559 conn.setQueryTimeout(seconds);
560 } catch (Exception e) {
561 throw logAndConvert(e);
562 }
563 }
564
565 /**
566 * Adds a statement to the batch.
567 *
568 * @param sql the SQL statement
569 */
570 public void addBatch(String sql) throws SQLException {
571 try {
572 debugCodeCall("addBatch", sql);
573 checkClosed();
574 sql = JdbcConnection.translateSQL(sql, escapeProcessing);
575 if (batchCommands == null) {
576 batchCommands = New.arrayList();
577 }
578 batchCommands.add(sql);
579 } catch (Exception e) {
580 throw logAndConvert(e);
581 }
582 }
583
584 /**
585 * Clears the batch.
586 */
587 public void clearBatch() throws SQLException {
588 try {
589 debugCodeCall("clearBatch");
590 checkClosed();
591 batchCommands = null;
592 } catch (Exception e) {
593 throw logAndConvert(e);
594 }
595 }
596
597 /**
598 * Executes the batch.
599 * If one of the batched statements fails, this database will continue.
600 *
601 * @return the array of update counts
602 */
603 public int[] executeBatch() throws SQLException {
604 try {
605 debugCodeCall("executeBatch");
606 checkClosedForWrite();
607 try {
608 if (batchCommands == null) {
609 // TODO batch: check what other database do if no commands are set
610 batchCommands = New.arrayList();
611 }
612 int size = batchCommands.size();
613 int[] result = new int[size];
614 boolean error = false;
615 SQLException next = null;
616 for (int i = 0; i < size; i++) {
617 String sql = batchCommands.get(i);
618 try {
619 result[i] = executeUpdateInternal(sql);
620 } catch (Exception re) {
621 SQLException e = logAndConvert(re);
622 if (next == null) {
623 next = e;
624 } else {
625 e.setNextException(next);
626 next = e;
627 }
628 result[i] = Statement.EXECUTE_FAILED;
629 error = true;
630 }
631 }
632 batchCommands = null;
633 if (error) {
634 throw new JdbcBatchUpdateException(next, result);
635 }
636 return result;
637 } finally {
638 afterWriting();
639 }
640 } catch (Exception e) {
641 throw logAndConvert(e);
642 }
643 }
644
645 /**
646 * Return a result set that contains the last generated auto-increment key
647 * for this connection, if there was one. If no key was generated by the
648 * last modification statement, then an empty result set is returned.
649 * The returned result set only contains the data for the very last row.
650 *
651 * @return the result set with one row and one column containing the key
652 * @throws SQLException if this object is closed
653 */
654 public ResultSet getGeneratedKeys() throws SQLException {
655 try {
656 int id = getNextId(TraceObject.RESULT_SET);
657 if (isDebugEnabled()) {
658 debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id, "getGeneratedKeys()");
659 }
660 checkClosed();
661 return conn.getGeneratedKeys(this, id);
662 } catch (Exception e) {
663 throw logAndConvert(e);
664 }
665 }
666
667 /**
668 * Moves to the next result set - however there is always only one result
669 * set. This call also closes the current result set (if there is one).
670 * Returns true if there is a next result set (that means - it always
671 * returns false).
672 *
673 * @return false
674 * @throws SQLException if this object is closed.
675 */
676 public boolean getMoreResults() throws SQLException {
677 try {
678 debugCodeCall("getMoreResults");
679 checkClosed();
680 closeOldResultSet();
681 return false;
682 } catch (Exception e) {
683 throw logAndConvert(e);
684 }
685 }
686
687 /**
688 * Move to the next result set.
689 * This method always returns false.
690 *
691 * @param current Statement.CLOSE_CURRENT_RESULT,
692 * Statement.KEEP_CURRENT_RESULT,
693 * or Statement.CLOSE_ALL_RESULTS
694 * @return false
695 */
696 public boolean getMoreResults(int current) throws SQLException {
697 try {
698 debugCodeCall("getMoreResults", current);
699 switch (current) {
700 case Statement.CLOSE_CURRENT_RESULT:
701 case Statement.CLOSE_ALL_RESULTS:
702 checkClosed();
703 closeOldResultSet();
704 break;
705 case Statement.KEEP_CURRENT_RESULT:
706 // nothing to do
707 break;
708 default:
709 throw DbException.getInvalidValueException("current", current);
710 }
711 return false;
712 } catch (Exception e) {
713 throw logAndConvert(e);
714 }
715 }
716
717 /**
718 * Executes a statement and returns the update count.
719 * This method just calls executeUpdate(String sql) internally.
720 * The method getGeneratedKeys supports at most one columns and row.
721 *
722 * @param sql the SQL statement
723 * @param autoGeneratedKeys ignored
724 * @return the update count (number of row affected by an insert,
725 * update or delete, or 0 if no rows or the statement was a
726 * create, drop, commit or rollback)
727 * @throws SQLException if a database error occurred or a
728 * select statement was executed
729 */
730 public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
731 try {
732 if (isDebugEnabled()) {
733 debugCode("executeUpdate("+quote(sql)+", "+autoGeneratedKeys+");");
734 }
735 return executeUpdateInternal(sql);
736 } catch (Exception e) {
737 throw logAndConvert(e);
738 }
739 }
740
741 /**
742 * Executes a statement and returns the update count.
743 * This method just calls executeUpdate(String sql) internally.
744 * The method getGeneratedKeys supports at most one columns and row.
745 *
746 * @param sql the SQL statement
747 * @param columnIndexes ignored
748 * @return the update count (number of row affected by an insert,
749 * update or delete, or 0 if no rows or the statement was a
750 * create, drop, commit or rollback)
751 * @throws SQLException if a database error occurred or a
752 * select statement was executed
753 */
754 public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
755 try {
756 if (isDebugEnabled()) {
757 debugCode("executeUpdate("+quote(sql)+", "+quoteIntArray(columnIndexes)+");");
758 }
759 return executeUpdateInternal(sql);
760 } catch (Exception e) {
761 throw logAndConvert(e);
762 }
763 }
764
765 /**
766 * Executes a statement and returns the update count.
767 * This method just calls executeUpdate(String sql) internally.
768 * The method getGeneratedKeys supports at most one columns and row.
769 *
770 * @param sql the SQL statement
771 * @param columnNames ignored
772 * @return the update count (number of row affected by an insert,
773 * update or delete, or 0 if no rows or the statement was a
774 * create, drop, commit or rollback)
775 * @throws SQLException if a database error occurred or a
776 * select statement was executed
777 */
778 public int executeUpdate(String sql, String[] columnNames) throws SQLException {
779 try {
780 if (isDebugEnabled()) {
781 debugCode("executeUpdate("+quote(sql)+", "+quoteArray(columnNames)+");");
782 }
783 return executeUpdateInternal(sql);
784 } catch (Exception e) {
785 throw logAndConvert(e);
786 }
787 }
788
789 /**
790 * Executes a statement and returns the update count.
791 * This method just calls execute(String sql) internally.
792 * The method getGeneratedKeys supports at most one columns and row.
793 *
794 * @param sql the SQL statement
795 * @param autoGeneratedKeys ignored
796 * @return the update count (number of row affected by an insert,
797 * update or delete, or 0 if no rows or the statement was a
798 * create, drop, commit or rollback)
799 * @throws SQLException if a database error occurred or a
800 * select statement was executed
801 */
802 public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
803 try {
804 if (isDebugEnabled()) {
805 debugCode("execute("+quote(sql)+", "+autoGeneratedKeys+");");
806 }
807 return executeInternal(sql);
808 } catch (Exception e) {
809 throw logAndConvert(e);
810 }
811 }
812
813 /**
814 * Executes a statement and returns the update count.
815 * This method just calls execute(String sql) internally.
816 * The method getGeneratedKeys supports at most one columns and row.
817 *
818 * @param sql the SQL statement
819 * @param columnIndexes ignored
820 * @return the update count (number of row affected by an insert,
821 * update or delete, or 0 if no rows or the statement was a
822 * create, drop, commit or rollback)
823 * @throws SQLException if a database error occurred or a
824 * select statement was executed
825 */
826 public boolean execute(String sql, int[] columnIndexes) throws SQLException {
827 try {
828 if (isDebugEnabled()) {
829 debugCode("execute("+quote(sql)+", "+quoteIntArray(columnIndexes)+");");
830 }
831 return executeInternal(sql);
832 } catch (Exception e) {
833 throw logAndConvert(e);
834 }
835 }
836
837 /**
838 * Executes a statement and returns the update count.
839 * This method just calls execute(String sql) internally.
840 * The method getGeneratedKeys supports at most one columns and row.
841 *
842 * @param sql the SQL statement
843 * @param columnNames ignored
844 * @return the update count (number of row affected by an insert,
845 * update or delete, or 0 if no rows or the statement was a
846 * create, drop, commit or rollback)
847 * @throws SQLException if a database error occurred or a
848 * select statement was executed
849 */
850 public boolean execute(String sql, String[] columnNames) throws SQLException {
851 try {
852 if (isDebugEnabled()) {
853 debugCode("execute("+quote(sql)+", "+quoteArray(columnNames)+");");
854 }
855 return executeInternal(sql);
856 } catch (Exception e) {
857 throw logAndConvert(e);
858 }
859 }
860
861 /**
862 * Gets the result set holdability.
863 *
864 * @return the holdability
865 */
866 public int getResultSetHoldability() throws SQLException {
867 try {
868 debugCodeCall("getResultSetHoldability");
869 checkClosed();
870 return ResultSet.HOLD_CURSORS_OVER_COMMIT;
871 } catch (Exception e) {
872 throw logAndConvert(e);
873 }
874 }
875
876 /**
877 * [Not supported]
878 */
879 /*## Java 1.7 ##
880 public void closeOnCompletion() {
881 // not supported
882 }
883 //*/
884
885 /**
886 * [Not supported]
887 */
888 /*## Java 1.7 ##
889 public boolean isCloseOnCompletion() {
890 return true;
891 }
892 //*/
893
894 // =============================================================
895
896 /**
897 * Check if this connection is closed.
898 * The next operation is a read request.
899 *
900 * @return true if the session was re-connected
901 * @throws DbException if the connection or session is closed
902 */
903 boolean checkClosed() {
904 return checkClosed(false);
905 }
906
907 /**
908 * Check if this connection is closed.
909 * The next operation may be a write request.
910 *
911 * @return true if the session was re-connected
912 * @throws DbException if the connection or session is closed
913 */
914 boolean checkClosedForWrite() {
915 return checkClosed(true);
916 }
917
918 /**
919 * INTERNAL.
920 * Check if the statement is closed.
921 *
922 * @param write if the next operation is possibly writing
923 * @return true if a reconnect was required
924 * @throws DbException if it is closed
925 */
926 protected boolean checkClosed(boolean write) {
927 if (conn == null) {
928 throw DbException.get(ErrorCode.OBJECT_CLOSED);
929 }
930 conn.checkClosed(write);
931 SessionInterface s = conn.getSession();
932 if (s != session) {
933 session = s;
934 trace = session.getTrace();
935 return true;
936 }
937 return false;
938 }
939
940 /**
941 * Called after each write operation.
942 */
943 void afterWriting() {
944 if (conn != null) {
945 conn.afterWriting();
946 }
947 }
948
949 /**
950 * INTERNAL.
951 * Close and old result set if there is still one open.
952 */
953 protected void closeOldResultSet() throws SQLException {
954 try {
955 if (!closedByResultSet) {
956 if (resultSet != null) {
957 resultSet.closeInternal();
958 }
959 }
960 } finally {
961 resultSet = null;
962 updateCount = -1;
963 }
964 }
965
966 /**
967 * INTERNAL.
968 * Set the statement that is currently running.
969 *
970 * @param c the command
971 */
972 protected void setExecutingStatement(CommandInterface c) {
973 if (c == null) {
974 conn.setExecutingStatement(null);
975 } else {
976 conn.setExecutingStatement(this);
977 lastExecutedCommandType = c.getCommandType();
978 }
979 executingCommand = c;
980 }
981
982 /**
983 * INTERNAL.
984 * Get the command type of the last executed command.
985 */
986 public int getLastExecutedCommandType() {
987 return lastExecutedCommandType;
988 }
989
990 /**
991 * Returns whether this statement is closed.
992 *
993 * @return true if the statement is closed
994 */
995 public boolean isClosed() throws SQLException {
996 try {
997 debugCodeCall("isClosed");
998 return conn == null;
999 } catch (Exception e) {
1000 throw logAndConvert(e);
1001 }
1002 }
1003
1004 /**
1005 * [Not supported] Return an object of this class if possible.
1006 */
1007 //## Java 1.6 ##
1008 public <T> T unwrap(Class<T> iface) throws SQLException {
1009 throw unsupported("unwrap");
1010 }
1011 //*/
1012
1013 /**
1014 * [Not supported] Checks if unwrap can return an object of this class.
1015 */
1016 //## Java 1.6 ##
1017 public boolean isWrapperFor(Class<?> iface) throws SQLException {
1018 throw unsupported("isWrapperFor");
1019 }
1020 //*/
1021
1022 /**
1023 * Returns whether this object is poolable.
1024 * @return false
1025 */
1026 public boolean isPoolable() {
1027 debugCodeCall("isPoolable");
1028 return false;
1029 }
1030
1031 /**
1032 * Requests that this object should be pooled or not.
1033 * This call is ignored.
1034 *
1035 * @param poolable the requested value
1036 */
1037 public void setPoolable(boolean poolable) {
1038 if (isDebugEnabled()) {
1039 debugCode("setPoolable("+poolable+");");
1040 }
1041 }
1042
1043 /**
1044 * INTERNAL
1045 */
1046 public String toString() {
1047 return getTraceObjectName();
1048 }
1049
1050 }
1051
1052