From eb956897a193a19c2468658e6fa790d6c981644b Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 18 Aug 2009 02:52:02 +0000 Subject: [PATCH] changed to allow multiple SQL statements in executeUpdate(sql) git-svn-id: http://www.xerial.org/svn/project/XerialJ/trunk/sqlite-jdbc@3531 ae02f08e-27ec-0310-ae8c-8ba02fe2eafd --- src/main/java/org/sqlite/DB.java | 151 +++++++---- src/main/java/org/sqlite/NativeDB.c | 21 ++ src/main/java/org/sqlite/NativeDB.java | 2 + src/main/java/org/sqlite/NestedDB.java | 19 +- src/main/java/org/sqlite/Stmt.java | 278 ++++++++++++++------- .../resources/native/Windows/x86/sqlitejdbc.dll | Bin 461312 -> 461312 bytes src/test/java/org/sqlite/StatementTest.java | 186 +++++++++----- 7 files changed, 457 insertions(+), 200 deletions(-) diff --git a/src/main/java/org/sqlite/DB.java b/src/main/java/org/sqlite/DB.java index d8667d7..acec1ce 100644 --- a/src/main/java/org/sqlite/DB.java +++ b/src/main/java/org/sqlite/DB.java @@ -34,7 +34,8 @@ import java.util.Map; * The two subclasses, NativeDB and NestedDB, provide the actual access to * SQLite functions. */ -abstract class DB implements Codes { +abstract class DB implements Codes +{ /** The JDBC Connection that 'owns' this database instance. */ Conn conn = null; @@ -61,11 +62,14 @@ abstract class DB implements Codes { abstract int enable_load_extension(boolean enable) throws SQLException; - final synchronized void exec(String sql) throws SQLException { + final synchronized void exec(String sql) throws SQLException + { long pointer = 0; - try { + try + { pointer = prepare(sql); - switch (step(pointer)) { + switch (step(pointer)) + { case SQLITE_DONE: ensureAutoCommit(); return; @@ -75,25 +79,31 @@ abstract class DB implements Codes { throwex(); } } - finally { + finally + { finalize(pointer); } } - final synchronized void open(Conn conn, String file) throws SQLException { + final synchronized void open(Conn conn, String file) throws SQLException + { this.conn = conn; _open(file); } - final synchronized void close() throws SQLException { + final synchronized void close() throws SQLException + { // finalize any remaining statements before closing db - synchronized (stmts) { + synchronized (stmts) + { Iterator i = stmts.entrySet().iterator(); - while (i.hasNext()) { + while (i.hasNext()) + { Map.Entry entry = (Map.Entry) i.next(); Stmt stmt = (Stmt) entry.getValue(); finalize(((Long) entry.getKey()).longValue()); - if (stmt != null) { + if (stmt != null) + { stmt.pointer = 0; } i.remove(); @@ -104,11 +114,13 @@ abstract class DB implements Codes { free_functions(); // clean up commit object - if (begin != 0) { + if (begin != 0) + { finalize(begin); begin = 0; } - if (commit != 0) { + if (commit != 0) + { finalize(commit); commit = 0; } @@ -116,21 +128,25 @@ abstract class DB implements Codes { _close(); } - final synchronized void prepare(Stmt stmt) throws SQLException { + final synchronized void prepare(Stmt stmt) throws SQLException + { if (stmt.pointer != 0) finalize(stmt); stmt.pointer = prepare(stmt.sql); stmts.put(new Long(stmt.pointer), stmt); } - final synchronized int finalize(Stmt stmt) throws SQLException { + final synchronized int finalize(Stmt stmt) throws SQLException + { if (stmt.pointer == 0) return 0; int rc = SQLITE_ERROR; - try { + try + { rc = finalize(stmt.pointer); } - finally { + finally + { stmts.remove(new Long(stmt.pointer)); stmt.pointer = 0; } @@ -141,6 +157,8 @@ abstract class DB implements Codes { protected abstract void _close() throws SQLException; + protected abstract int _exec(String sql) throws SQLException; + protected abstract long prepare(String sql) throws SQLException; protected abstract int finalize(long stmt) throws SQLException; @@ -228,45 +246,57 @@ abstract class DB implements Codes { // COMPOUND FUNCTIONS //////////////////////////////////////////// - final synchronized String[] column_names(long stmt) throws SQLException { + final synchronized String[] column_names(long stmt) throws SQLException + { String[] names = new String[column_count(stmt)]; for (int i = 0; i < names.length; i++) names[i] = column_name(stmt, i); return names; } - final synchronized int sqlbind(long stmt, int pos, Object v) throws SQLException { + final synchronized int sqlbind(long stmt, int pos, Object v) throws SQLException + { pos++; - if (v == null) { + if (v == null) + { return bind_null(stmt, pos); } - else if (v instanceof Integer) { + else if (v instanceof Integer) + { return bind_int(stmt, pos, ((Integer) v).intValue()); } - else if (v instanceof Short) { + else if (v instanceof Short) + { return bind_int(stmt, pos, ((Short) v).intValue()); } - else if (v instanceof Long) { + else if (v instanceof Long) + { return bind_long(stmt, pos, ((Long) v).longValue()); } - else if (v instanceof Float) { + else if (v instanceof Float) + { return bind_double(stmt, pos, ((Float) v).doubleValue()); } - else if (v instanceof Double) { + else if (v instanceof Double) + { return bind_double(stmt, pos, ((Double) v).doubleValue()); } - else if (v instanceof String) { + else if (v instanceof String) + { return bind_text(stmt, pos, (String) v); } - else if (v instanceof byte[]) { + else if (v instanceof byte[]) + { return bind_blob(stmt, pos, (byte[]) v); } - else { + else + { throw new SQLException("unexpected param type: " + v.getClass()); } } - final synchronized int[] executeBatch(long stmt, int count, Object[] vals) throws SQLException { + final synchronized int[] executeBatch(long stmt, int count, Object[] vals) throws SQLException + { if (count < 1) throw new SQLException("count (" + count + ") < 1"); @@ -275,26 +305,29 @@ abstract class DB implements Codes { int rc; int[] changes = new int[count]; - try { - for (int i = 0; i < count; i++) { + try + { + for (int i = 0; i < count; i++) + { reset(stmt); for (int j = 0; j < params; j++) if (sqlbind(stmt, j, vals[(i * params) + j]) != SQLITE_OK) throwex(); rc = step(stmt); - if (rc != SQLITE_DONE) { + if (rc != SQLITE_DONE) + { reset(stmt); if (rc == SQLITE_ROW) - throw new BatchUpdateException("batch entry " + i - + ": query returns results", changes); + throw new BatchUpdateException("batch entry " + i + ": query returns results", changes); throwex(); } changes[i] = changes(); } } - finally { + finally + { ensureAutoCommit(); } @@ -302,12 +335,14 @@ abstract class DB implements Codes { return changes; } - final synchronized boolean execute(Stmt stmt, Object[] vals) throws SQLException { - if (vals != null) { + final synchronized boolean execute(Stmt stmt, Object[] vals) throws SQLException + { + if (vals != null) + { final int params = bind_parameter_count(stmt.pointer); if (params != vals.length) - throw new SQLException("assertion failure: param count (" + params - + ") != value count (" + vals.length + ")"); + throw new SQLException("assertion failure: param count (" + params + ") != value count (" + vals.length + + ")"); for (int i = 0; i < params; i++) if (sqlbind(stmt.pointer, i, vals[i]) != SQLITE_OK) @@ -315,7 +350,8 @@ abstract class DB implements Codes { } int statusCode = step(stmt.pointer); - switch (statusCode) { + switch (statusCode) + { case SQLITE_DONE: reset(stmt.pointer); ensureAutoCommit(); @@ -330,26 +366,41 @@ abstract class DB implements Codes { finalize(stmt); throw newSQLException(statusCode); } + } - final synchronized int executeUpdate(Stmt stmt, Object[] vals) throws SQLException { + final synchronized int executeUpdate(Stmt stmt, Object[] vals) throws SQLException + { if (execute(stmt, vals)) throw new SQLException("query returns results"); reset(stmt.pointer); return changes(); } - final void throwex() throws SQLException { + final void throwex() throws SQLException + { throw new SQLException(errmsg()); } - final void throwex(int errorCode) throws SQLException { + final void throwex(int errorCode) throws SQLException + { throw newSQLException(errorCode); } - private SQLException newSQLException(int errorCode) throws SQLException { + final void throwex(int errorCode, String errorMessage) throws SQLException + { + throw newSQLException(errorCode, errorMessage); + } + + static SQLException newSQLException(int errorCode, String errorMessage) throws SQLException + { SQLiteErrorCode code = SQLiteErrorCode.getErrorCode(errorCode); - return new SQLException(String.format("%s (%s)", code, errmsg())); + return new SQLException(String.format("%s (%s)", code, errorMessage)); + } + + private SQLException newSQLException(int errorCode) throws SQLException + { + return newSQLException(errorCode, errmsg()); } /* @@ -383,7 +434,8 @@ abstract class DB implements Codes { * As a solution, we call "commit" after every statement in auto-commit * mode. */ - final void ensureAutoCommit() throws SQLException { + final void ensureAutoCommit() throws SQLException + { if (!conn.getAutoCommit()) return; @@ -392,16 +444,19 @@ abstract class DB implements Codes { if (commit == 0) commit = prepare("commit;"); - try { + try + { if (step(begin) != SQLITE_DONE) return; // assume we are in a transaction - if (step(commit) != SQLITE_DONE) { + if (step(commit) != SQLITE_DONE) + { reset(commit); throwex(); } //throw new SQLException("unable to auto-commit"); } - finally { + finally + { reset(begin); reset(commit); } diff --git a/src/main/java/org/sqlite/NativeDB.c b/src/main/java/org/sqlite/NativeDB.c index fa8af0e..5955d20 100644 --- a/src/main/java/org/sqlite/NativeDB.c +++ b/src/main/java/org/sqlite/NativeDB.c @@ -367,6 +367,27 @@ JNIEXPORT jlong JNICALL Java_org_sqlite_NativeDB_prepare( return fromref(stmt); } +JNIEXPORT jint JNICALL Java_org_sqlite_NativeDB__1exec( + JNIEnv *env, jobject this, jstring sql) +{ + sqlite3* db = gethandle(env, this); + sqlite3_stmt* stmt; + + const char *strsql = (*env)->GetStringUTFChars(env, sql, 0); + char* errorMsg; + int status = sqlite3_exec(db, strsql, 0, 0, &errorMsg); + + (*env)->ReleaseStringUTFChars(env, sql, strsql); + + if (status != SQLITE_OK) { + throwexmsg(env, errorMsg); + sqlite3_free(&errorMsg); + } + return status; +} + + + JNIEXPORT jstring JNICALL Java_org_sqlite_NativeDB_errmsg(JNIEnv *env, jobject this) { return (*env)->NewStringUTF(env, sqlite3_errmsg(gethandle(env, this))); diff --git a/src/main/java/org/sqlite/NativeDB.java b/src/main/java/org/sqlite/NativeDB.java index 59afb60..8224534 100644 --- a/src/main/java/org/sqlite/NativeDB.java +++ b/src/main/java/org/sqlite/NativeDB.java @@ -46,6 +46,8 @@ final class NativeDB extends DB protected native synchronized void _close() throws SQLException; + protected native synchronized int _exec(String sql) throws SQLException; + native synchronized int shared_cache(boolean enable); native synchronized int enable_load_extension(boolean enable); diff --git a/src/main/java/org/sqlite/NestedDB.java b/src/main/java/org/sqlite/NestedDB.java index 07fdab3..91fb316 100644 --- a/src/main/java/org/sqlite/NestedDB.java +++ b/src/main/java/org/sqlite/NestedDB.java @@ -137,7 +137,7 @@ final class NestedDB extends DB implements Runtime.CallJavaCB if (ret != SQLITE_OK) { rt.free(passback); - throwex(); + throwex(ret); } int pointer = deref(passback); rt.free(passback); @@ -159,6 +159,23 @@ final class NestedDB extends DB implements Runtime.CallJavaCB return call("sqlite3_changes", handle); } + @Override + protected int _exec(String sql) throws SQLException + { + int passback = rt.malloc(4); + int str = rt.strdup(sql); + int status = call("sqlite3_exec", handle, str, 0, 0, passback); + if (status != SQLITE_OK) + { + String errorMessage = cstring(passback); + call("sqlite3_free", passback); + rt.free(passback); + throwex(status, errorMessage); + } + rt.free(passback); + return status; + } + protected synchronized int finalize(long stmt) throws SQLException { return call("sqlite3_finalize", (int) stmt); diff --git a/src/main/java/org/sqlite/Stmt.java b/src/main/java/org/sqlite/Stmt.java index 9b9b660..6e3b122 100644 --- a/src/main/java/org/sqlite/Stmt.java +++ b/src/main/java/org/sqlite/Stmt.java @@ -15,8 +15,12 @@ */ package org.sqlite; -import java.sql.*; -import java.util.ArrayList; +import java.sql.BatchUpdateException; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; class Stmt extends Unused implements Statement, Codes { @@ -31,41 +35,51 @@ class Stmt extends Unused implements Statement, Codes Object[] batch = null; boolean resultsWaiting = false; - Stmt(Conn c) { + Stmt(Conn c) + { conn = c; db = conn.db(); rs = new RS(this); } - protected final void checkOpen() throws SQLException { - if (pointer == 0) throw new SQLException("statement is not executing"); + protected final void checkOpen() throws SQLException + { + if (pointer == 0) + throw new SQLException("statement is not executing"); } - boolean isOpen() throws SQLException { + + boolean isOpen() throws SQLException + { return (pointer != 0); } /** Calls sqlite3_step() and sets up results. Expects a clean stmt. */ - protected boolean exec() throws SQLException { - if (sql == null) throw new SQLException( - "SQLiteJDBC internal error: sql==null"); - if (rs.isOpen()) throw new SQLException( - "SQLite JDBC internal error: rs.isOpen() on exec."); + protected boolean exec() throws SQLException + { + if (sql == null) + throw new SQLException("SQLiteJDBC internal error: sql==null"); + if (rs.isOpen()) + throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec."); boolean rc = false; - try { + try + { rc = db.execute(this, null); - } finally { + } + finally + { resultsWaiting = rc; } return db.column_count(pointer) != 0; } - // PUBLIC INTERFACE ///////////////////////////////////////////// - public void close() throws SQLException { - if (pointer == 0) return; + public void close() throws SQLException + { + if (pointer == 0) + return; rs.close(); batch = null; batchPos = 0; @@ -74,42 +88,62 @@ class Stmt extends Unused implements Statement, Codes db.throwex(); } - protected void finalize() throws SQLException { close(); } + protected void finalize() throws SQLException + { + close(); + } - public boolean execute(String sql) throws SQLException { + public boolean execute(String sql) throws SQLException + { close(); this.sql = sql; db.prepare(this); return exec(); } - public ResultSet executeQuery(String sql) throws SQLException { + public ResultSet executeQuery(String sql) throws SQLException + { close(); this.sql = sql; db.prepare(this); - if (!exec()) { + if (!exec()) + { close(); throw new SQLException("query does not return ResultSet"); } return getResultSet(); } - public int executeUpdate(String sql) throws SQLException { + public int executeUpdate(String sql) throws SQLException + { close(); this.sql = sql; int changes = 0; - try { - db.prepare(this); - changes = db.executeUpdate(this, null); - } finally { close(); } + try + { + //db.prepare(this); + //changes = db.executeUpdate(this, null); + + int statusCode = db._exec(sql); + if (statusCode != SQLITE_OK) + throw DB.newSQLException(statusCode, ""); + + changes = db.changes(); + } + finally + { + close(); + } return changes; } - public ResultSet getResultSet() throws SQLException { + public ResultSet getResultSet() throws SQLException + { checkOpen(); - if (rs.isOpen()) throw new SQLException("ResultSet already requested"); - if (db.column_count(pointer) == 0) throw new SQLException( - "no ResultSet available"); + if (rs.isOpen()) + throw new SQLException("ResultSet already requested"); + if (db.column_count(pointer) == 0) + throw new SQLException("no ResultSet available"); if (rs.colsMeta == null) rs.colsMeta = db.column_names(pointer); rs.cols = rs.colsMeta; @@ -124,18 +158,18 @@ class Stmt extends Unused implements Statement, Codes * reading the JavaDoc for getMoreResults() and considering the test * StatementTest.execute(). */ - public int getUpdateCount() throws SQLException { - if (pointer != 0 - && !rs.isOpen() - && !resultsWaiting - && db.column_count(pointer) == 0) + public int getUpdateCount() throws SQLException + { + if (pointer != 0 && !rs.isOpen() && !resultsWaiting && db.column_count(pointer) == 0) return db.changes(); return -1; } - public void addBatch(String sql) throws SQLException { + public void addBatch(String sql) throws SQLException + { close(); - if (batch == null || batchPos + 1 >= batch.length) { + if (batch == null || batchPos + 1 >= batch.length) + { Object[] nb = new Object[Math.max(10, batchPos * 2)]; if (batch != null) System.arraycopy(batch, 0, nb, 0, batch.length); @@ -144,103 +178,169 @@ class Stmt extends Unused implements Statement, Codes batch[batchPos++] = sql; } - public void clearBatch() throws SQLException { + public void clearBatch() throws SQLException + { batchPos = 0; if (batch != null) - for (int i=0; i < batch.length; i++) + for (int i = 0; i < batch.length; i++) batch[i] = null; } - public int[] executeBatch() throws SQLException { - // TODO: optimise + public int[] executeBatch() throws SQLException + { + // TODO: optimize close(); - if (batch == null || batchPos == 0) return new int[] {}; + if (batch == null || batchPos == 0) + return new int[] {}; int[] changes = new int[batchPos]; - synchronized (db) { try { - for (int i=0; i < changes.length; i++) { - try { - this.sql = (String)batch[i]; - db.prepare(this); - changes[i] = db.executeUpdate(this, null); - } catch (SQLException e) { - throw new BatchUpdateException( - "batch entry " + i + ": " + e.getMessage(), changes); - } finally { - db.finalize(this); + synchronized (db) + { + try + { + for (int i = 0; i < changes.length; i++) + { + try + { + this.sql = (String) batch[i]; + db.prepare(this); + changes[i] = db.executeUpdate(this, null); + } + catch (SQLException e) + { + throw new BatchUpdateException("batch entry " + i + ": " + e.getMessage(), changes); + } + finally + { + db.finalize(this); + } } } - } finally { - clearBatch(); - } } + finally + { + clearBatch(); + } + } return changes; } - public void setCursorName(String name) {} + public void setCursorName(String name) + {} + + public SQLWarning getWarnings() throws SQLException + { + return null; + } + + public void clearWarnings() throws SQLException + {} + + public Connection getConnection() throws SQLException + { + return conn; + } - public SQLWarning getWarnings() throws SQLException { return null; } - public void clearWarnings() throws SQLException {} + public void cancel() throws SQLException + { + rs.checkOpen(); + db.interrupt(); + } - public Connection getConnection() throws SQLException { - return conn; } + public int getQueryTimeout() throws SQLException + { + return conn.getTimeout(); + } - public void cancel() throws SQLException { rs.checkOpen(); db.interrupt(); } - public int getQueryTimeout() throws SQLException { - return conn.getTimeout(); } - public void setQueryTimeout(int seconds) throws SQLException { - if (seconds < 0) throw new SQLException("query timeout must be >= 0"); + public void setQueryTimeout(int seconds) throws SQLException + { + if (seconds < 0) + throw new SQLException("query timeout must be >= 0"); conn.setTimeout(1000 * seconds); } // TODO: write test - public int getMaxRows() throws SQLException { + public int getMaxRows() throws SQLException + { checkOpen(); return rs.maxRows; } - public void setMaxRows(int max) throws SQLException { + + public void setMaxRows(int max) throws SQLException + { checkOpen(); - if (max < 0) throw new SQLException("max row count must be >= 0"); + if (max < 0) + throw new SQLException("max row count must be >= 0"); rs.maxRows = max; } - public int getMaxFieldSize() throws SQLException { return 0; } - public void setMaxFieldSize(int max) throws SQLException { - if (max < 0) throw new SQLException( - "max field size "+max+" cannot be negative"); + public int getMaxFieldSize() throws SQLException + { + return 0; + } + + public void setMaxFieldSize(int max) throws SQLException + { + if (max < 0) + throw new SQLException("max field size " + max + " cannot be negative"); + } + + public int getFetchSize() throws SQLException + { + return rs.getFetchSize(); + } + + public void setFetchSize(int r) throws SQLException + { + rs.setFetchSize(r); } - public int getFetchSize() throws SQLException { return rs.getFetchSize(); } - public void setFetchSize(int r) throws SQLException { rs.setFetchSize(r); } - public int getFetchDirection() throws SQLException { + public int getFetchDirection() throws SQLException + { return rs.getFetchDirection(); } - public void setFetchDirection(int d) throws SQLException { + + public void setFetchDirection(int d) throws SQLException + { rs.setFetchDirection(d); } - /** As SQLite's last_insert_rowid() function is DB-specific not - * statement specific, this function introduces a race condition - * if the same connection is used by two threads and both insert. */ - public ResultSet getGeneratedKeys() throws SQLException { - return ((MetaData)conn.getMetaData()).getGeneratedKeys(); + /** + * As SQLite's last_insert_rowid() function is DB-specific not statement + * specific, this function introduces a race condition if the same + * connection is used by two threads and both insert. + */ + public ResultSet getGeneratedKeys() throws SQLException + { + return ((MetaData) conn.getMetaData()).getGeneratedKeys(); } /** SQLite does not support multiple results from execute(). */ - public boolean getMoreResults() throws SQLException { + public boolean getMoreResults() throws SQLException + { return getMoreResults(0); } - public boolean getMoreResults(int c) throws SQLException { + + public boolean getMoreResults(int c) throws SQLException + { checkOpen(); close(); // as we never have another result, clean up pointer return false; } - public int getResultSetConcurrency() throws SQLException { - return ResultSet.CONCUR_READ_ONLY; } - public int getResultSetHoldability() throws SQLException { - return ResultSet.CLOSE_CURSORS_AT_COMMIT; } - public int getResultSetType() throws SQLException { - return ResultSet.TYPE_FORWARD_ONLY; } + public int getResultSetConcurrency() throws SQLException + { + return ResultSet.CONCUR_READ_ONLY; + } + + public int getResultSetHoldability() throws SQLException + { + return ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + public int getResultSetType() throws SQLException + { + return ResultSet.TYPE_FORWARD_ONLY; + } } diff --git a/src/main/resources/native/Windows/x86/sqlitejdbc.dll b/src/main/resources/native/Windows/x86/sqlitejdbc.dll index a23f9bdef7db46b693a9951bb0709dd993ce1b1f..64ef3e17da95a29f412750daa9ad5da25b30dc92 100644 GIT binary patch delta 16500 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