2 * Copyright (c) 2007 David Crawshaw <david@zentus.com>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 import java.sql.BatchUpdateException;
19 import java.sql.Connection;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.sql.SQLWarning;
23 import java.sql.Statement;
25 class Stmt extends Unused implements Statement, Codes
35 Object[] batch = null;
36 boolean resultsWaiting = false;
45 protected final void checkOpen() throws SQLException
48 throw new SQLException("statement is not executing");
51 boolean isOpen() throws SQLException
53 return (pointer != 0);
56 /** Calls sqlite3_step() and sets up results. Expects a clean stmt. */
57 protected boolean exec() throws SQLException
60 throw new SQLException("SQLiteJDBC internal error: sql==null");
62 throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec.");
67 rc = db.execute(this, null);
74 return db.column_count(pointer) != 0;
77 // PUBLIC INTERFACE /////////////////////////////////////////////
79 public void close() throws SQLException
86 int resp = db.finalize(this);
87 if (resp != SQLITE_OK && resp != SQLITE_MISUSE)
91 protected void finalize() throws SQLException
96 public boolean execute(String sql) throws SQLException
104 public ResultSet executeQuery(String sql) throws SQLException
112 throw new SQLException("query does not return ResultSet");
114 return getResultSet();
117 public int executeUpdate(String sql) throws SQLException
125 //changes = db.executeUpdate(this, null);
127 int statusCode = db._exec(sql);
128 if (statusCode != SQLITE_OK)
129 throw DB.newSQLException(statusCode, "");
131 changes = db.changes();
140 public ResultSet getResultSet() throws SQLException
144 throw new SQLException("ResultSet already requested");
145 if (db.column_count(pointer) == 0)
146 throw new SQLException("no ResultSet available");
147 if (rs.colsMeta == null)
148 rs.colsMeta = db.column_names(pointer);
149 rs.cols = rs.colsMeta;
151 rs.open = resultsWaiting;
152 resultsWaiting = false;
157 * This function has a complex behaviour best understood by carefully
158 * reading the JavaDoc for getMoreResults() and considering the test
159 * StatementTest.execute().
161 public int getUpdateCount() throws SQLException
163 if (pointer != 0 && !rs.isOpen() && !resultsWaiting && db.column_count(pointer) == 0)
168 public void addBatch(String sql) throws SQLException
171 if (batch == null || batchPos + 1 >= batch.length)
173 Object[] nb = new Object[Math.max(10, batchPos * 2)];
175 System.arraycopy(batch, 0, nb, 0, batch.length);
178 batch[batchPos++] = sql;
181 public void clearBatch() throws SQLException
185 for (int i = 0; i < batch.length; i++)
189 public int[] executeBatch() throws SQLException
193 if (batch == null || batchPos == 0)
196 int[] changes = new int[batchPos];
202 for (int i = 0; i < changes.length; i++)
206 this.sql = (String) batch[i];
208 changes[i] = db.executeUpdate(this, null);
210 catch (SQLException e)
212 throw new BatchUpdateException("batch entry " + i + ": " + e.getMessage(), changes);
229 public void setCursorName(String name)
232 public SQLWarning getWarnings() throws SQLException
237 public void clearWarnings() throws SQLException
240 public Connection getConnection() throws SQLException
245 public void cancel() throws SQLException
251 public int getQueryTimeout() throws SQLException
253 return conn.getTimeout();
256 public void setQueryTimeout(int seconds) throws SQLException
259 throw new SQLException("query timeout must be >= 0");
260 conn.setTimeout(1000 * seconds);
264 public int getMaxRows() throws SQLException
270 public void setMaxRows(int max) throws SQLException
274 throw new SQLException("max row count must be >= 0");
278 public int getMaxFieldSize() throws SQLException
283 public void setMaxFieldSize(int max) throws SQLException
286 throw new SQLException("max field size " + max + " cannot be negative");
289 public int getFetchSize() throws SQLException
291 return rs.getFetchSize();
294 public void setFetchSize(int r) throws SQLException
299 public int getFetchDirection() throws SQLException
301 return rs.getFetchDirection();
304 public void setFetchDirection(int d) throws SQLException
306 rs.setFetchDirection(d);
310 * As SQLite's last_insert_rowid() function is DB-specific not statement
311 * specific, this function introduces a race condition if the same
312 * connection is used by two threads and both insert.
314 public ResultSet getGeneratedKeys() throws SQLException
316 return ((MetaData) conn.getMetaData()).getGeneratedKeys();
319 /** SQLite does not support multiple results from execute(). */
320 public boolean getMoreResults() throws SQLException
322 return getMoreResults(0);
325 public boolean getMoreResults(int c) throws SQLException
328 close(); // as we never have another result, clean up pointer
332 public int getResultSetConcurrency() throws SQLException
334 return ResultSet.CONCUR_READ_ONLY;
337 public int getResultSetHoldability() throws SQLException
339 return ResultSet.CLOSE_CURSORS_AT_COMMIT;
342 public int getResultSetType() throws SQLException
344 return ResultSet.TYPE_FORWARD_ONLY;