EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [JdbcStatement.java]

nameclass, %method, %block, %line, %
JdbcStatement.java100% (1/1)95%  (53/56)83%  (1076/1293)79%  (283.9/360)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcStatement100% (1/1)95%  (53/56)83%  (1076/1293)79%  (283.9/360)
closeOnCompletion (): void 0%   (0/1)0%   (0/1)0%   (0/1)
isCloseOnCompletion (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getMoreResults (int): boolean 100% (1/1)58%  (15/26)60%  (6/10)
setMaxRows (int): void 100% (1/1)60%  (15/25)67%  (6/9)
clearWarnings (): void 100% (1/1)62%  (8/13)67%  (4/6)
getFetchDirection (): int 100% (1/1)62%  (8/13)60%  (3/5)
getMaxFieldSize (): int 100% (1/1)62%  (8/13)60%  (3/5)
getResultSetHoldability (): int 100% (1/1)62%  (8/13)60%  (3/5)
getWarnings (): SQLWarning 100% (1/1)62%  (8/13)60%  (3/5)
closeOldResultSet (): void 100% (1/1)62%  (20/32)79%  (6.4/8)
setFetchSize (int): void 100% (1/1)63%  (24/38)71%  (7.8/11)
getFetchSize (): int 100% (1/1)64%  (9/14)60%  (3/5)
getMaxRows (): int 100% (1/1)64%  (9/14)60%  (3/5)
getResultSetConcurrency (): int 100% (1/1)64%  (9/14)60%  (3/5)
getResultSetType (): int 100% (1/1)64%  (9/14)60%  (3/5)
getUpdateCount (): int 100% (1/1)64%  (9/14)60%  (3/5)
setCursorName (String): void 100% (1/1)64%  (9/14)67%  (4/6)
checkClosed (boolean): boolean 100% (1/1)67%  (20/30)67%  (6/9)
getMoreResults (): boolean 100% (1/1)67%  (10/15)67%  (4/6)
getQueryTimeout (): int 100% (1/1)67%  (10/15)60%  (3/5)
isClosed (): boolean 100% (1/1)67%  (10/15)50%  (2/4)
setFetchDirection (int): void 100% (1/1)67%  (10/15)67%  (4/6)
setMaxFieldSize (int): void 100% (1/1)67%  (10/15)67%  (4/6)
close (): void 100% (1/1)68%  (21/31)74%  (7.4/10)
clearBatch (): void 100% (1/1)69%  (11/16)71%  (5/7)
getResultSet (): ResultSet 100% (1/1)71%  (20/28)67%  (6/9)
getGeneratedKeys (): ResultSet 100% (1/1)81%  (21/26)71%  (5/7)
cancel (): void 100% (1/1)82%  (27/33)95%  (11.4/12)
setEscapeProcessing (boolean): void 100% (1/1)82%  (23/28)75%  (6/8)
execute (String, int): boolean 100% (1/1)83%  (24/29)60%  (3/5)
executeUpdate (String, int): int 100% (1/1)83%  (24/29)60%  (3/5)
addBatch (String): void 100% (1/1)83%  (25/30)80%  (8/10)
execute (String, String []): boolean 100% (1/1)83%  (25/30)60%  (3/5)
execute (String, int []): boolean 100% (1/1)83%  (25/30)60%  (3/5)
executeUpdate (String, String []): int 100% (1/1)83%  (25/30)60%  (3/5)
executeUpdate (String, int []): int 100% (1/1)83%  (25/30)60%  (3/5)
JdbcStatement (JdbcConnection, int, int, int, boolean): void 100% (1/1)100% (32/32)100% (10/10)
afterWriting (): void 100% (1/1)100% (7/7)100% (3/3)
checkClosed (): boolean 100% (1/1)100% (4/4)100% (1/1)
checkClosedForWrite (): boolean 100% (1/1)100% (4/4)100% (1/1)
execute (String): boolean 100% (1/1)100% (13/13)100% (4/4)
executeBatch (): int [] 100% (1/1)100% (91/91)100% (27/27)
executeInternal (String): boolean 100% (1/1)100% (107/107)100% (22/22)
executeQuery (String): ResultSet 100% (1/1)100% (111/111)100% (20/20)
executeUpdate (String): int 100% (1/1)100% (13/13)100% (4/4)
executeUpdateInternal (String): int 100% (1/1)100% (61/61)100% (13/13)
getConnection (): Connection 100% (1/1)100% (6/6)100% (2/2)
getLastExecutedCommandType (): int 100% (1/1)100% (3/3)100% (1/1)
isPoolable (): boolean 100% (1/1)100% (5/5)100% (2/2)
isWrapperFor (Class): boolean 100% (1/1)100% (11/11)100% (1/1)
setExecutingStatement (CommandInterface): void 100% (1/1)100% (19/19)100% (6/6)
setPoolable (boolean): void 100% (1/1)100% (16/16)100% (3/3)
setQueryTimeout (int): void 100% (1/1)100% (26/26)100% (9/9)
unwrap (Class): Object 100% (1/1)100% (10/10)100% (3/3)
wasCancelled (): boolean 100% (1/1)100% (3/3)100% (1/1)

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

[all classes][org.h2.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov