OSDN Git Service

changed to allow multiple SQL statements in executeUpdate(sql)
authorleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Tue, 18 Aug 2009 02:52:02 +0000 (02:52 +0000)
committerleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Tue, 18 Aug 2009 02:52:02 +0000 (02:52 +0000)
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
src/main/java/org/sqlite/NativeDB.c
src/main/java/org/sqlite/NativeDB.java
src/main/java/org/sqlite/NestedDB.java
src/main/java/org/sqlite/Stmt.java
src/main/resources/native/Windows/x86/sqlitejdbc.dll
src/test/java/org/sqlite/StatementTest.java

index d8667d7..acec1ce 100644 (file)
@@ -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);
         }
index fa8af0e..5955d20 100644 (file)
@@ -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)));
index 59afb60..8224534 100644 (file)
@@ -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);
index 07fdab3..91fb316 100644 (file)
@@ -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);
index 9b9b660..6e3b122 100644 (file)
  */
 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;
+    }
 }
index a23f9bd..64ef3e1 100644 (file)
Binary files a/src/main/resources/native/Windows/x86/sqlitejdbc.dll and b/src/main/resources/native/Windows/x86/sqlitejdbc.dll differ
index 61cdff6..5a47752 100644 (file)
@@ -1,58 +1,82 @@
 package org.sqlite;
 
-import java.sql.*;
-import org.junit.*;
 import static org.junit.Assert.*;
 
+import java.sql.BatchUpdateException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
 /** These tests are designed to stress Statements on memory databases. */
 public class StatementTest
 {
     private Connection conn;
     private Statement stat;
 
-    @BeforeClass public static void forName() throws Exception {
+    @BeforeClass
+    public static void forName() throws Exception
+    {
         Class.forName("org.sqlite.JDBC");
     }
 
-    @Before public void connect() throws Exception {
+    @Before
+    public void connect() throws Exception
+    {
         conn = DriverManager.getConnection("jdbc:sqlite:");
         stat = conn.createStatement();
     }
 
-    @After public void close() throws SQLException {
+    @After
+    public void close() throws SQLException
+    {
         stat.close();
         conn.close();
     }
 
-    @Test public void stmtUpdate() throws SQLException {
+    @Test
+    public void stmtUpdate() throws SQLException
+    {
         assertEquals(stat.executeUpdate("create table s1 (c1);"), 0);
         assertEquals(stat.executeUpdate("insert into s1 values (0);"), 1);
         assertEquals(stat.executeUpdate("insert into s1 values (1);"), 1);
         assertEquals(stat.executeUpdate("insert into s1 values (2);"), 1);
         assertEquals(stat.executeUpdate("update s1 set c1 = 5;"), 3);
-               // count_changes_pgrama. truncate_optimization
-        assertEquals(stat.executeUpdate("delete from s1;"), 3); 
+        // count_changes_pgrama. truncate_optimization
+        assertEquals(stat.executeUpdate("delete from s1;"), 3);
         assertEquals(stat.executeUpdate("drop table s1;"), 3);
     }
 
-    @Test public void emptyRS() throws SQLException {
+    @Test
+    public void emptyRS() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select null limit 0;");
         assertFalse(rs.next());
         rs.close();
     }
 
-    @Test public void singleRowRS() throws SQLException {
+    @Test
+    public void singleRowRS() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select " + Integer.MAX_VALUE + ";");
         assertTrue(rs.next());
         assertEquals(rs.getInt(1), Integer.MAX_VALUE);
         assertEquals(rs.getString(1), Integer.toString(Integer.MAX_VALUE));
-        assertEquals(rs.getDouble(1),
-                new Integer(Integer.MAX_VALUE).doubleValue());
+        assertEquals(rs.getDouble(1), new Integer(Integer.MAX_VALUE).doubleValue());
         assertFalse(rs.next());
         rs.close();
     }
 
-    @Test public void twoRowRS() throws SQLException {
+    @Test
+    public void twoRowRS() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select 9 union all select 7;");
         assertTrue(rs.next());
         assertEquals(rs.getInt(1), 9);
@@ -62,11 +86,15 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void autoClose() throws SQLException {
+    @Test
+    public void autoClose() throws SQLException
+    {
         conn.createStatement().executeQuery("select 1;");
     }
 
-    @Test public void stringRS() throws SQLException {
+    @Test
+    public void stringRS() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select \"Russell\";");
         assertTrue(rs.next());
         assertEquals(rs.getString(1), "Russell");
@@ -74,7 +102,9 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void execute() throws SQLException {
+    @Test
+    public void execute() throws SQLException
+    {
         assertTrue(stat.execute("select null;"));
         ResultSet rs = stat.getResultSet();
         assertNotNull(rs);
@@ -94,15 +124,13 @@ public class StatementTest
         assertEquals(stat.getUpdateCount(), -1);
     }
 
-    @Test public void colNameAccess() throws SQLException {
-        assertEquals(stat.executeUpdate(
-                    "create table tab (id, firstname, surname);"), 0);
-        assertEquals(stat.executeUpdate(
-                    "insert into tab values (0, 'Bob', 'Builder');"), 1);
-        assertEquals(stat.executeUpdate(
-                    "insert into tab values (1, 'Fred', 'Blogs');"), 1);
-        assertEquals(stat.executeUpdate(
-                    "insert into tab values (2, 'John', 'Smith');"), 1);
+    @Test
+    public void colNameAccess() throws SQLException
+    {
+        assertEquals(stat.executeUpdate("create table tab (id, firstname, surname);"), 0);
+        assertEquals(stat.executeUpdate("insert into tab values (0, 'Bob', 'Builder');"), 1);
+        assertEquals(stat.executeUpdate("insert into tab values (1, 'Fred', 'Blogs');"), 1);
+        assertEquals(stat.executeUpdate("insert into tab values (2, 'John', 'Smith');"), 1);
         ResultSet rs = stat.executeQuery("select * from tab;");
         assertTrue(rs.next());
         assertEquals(rs.getInt("id"), 0);
@@ -114,7 +142,7 @@ public class StatementTest
         assertEquals(rs.getString("surname"), "Blogs");
         assertTrue(rs.next());
         assertEquals(rs.getInt("id"), 2);
-        assertEquals( rs.getString("id"), "2");
+        assertEquals(rs.getString("id"), "2");
         assertEquals(rs.getString("firstname"), "John");
         assertEquals(rs.getString("surname"), "Smith");
         assertFalse(rs.next());
@@ -122,7 +150,9 @@ public class StatementTest
         assertEquals(stat.executeUpdate("drop table tab;"), 1);
     }
 
-    @Test public void nulls() throws SQLException {
+    @Test
+    public void nulls() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select null union all select null;");
         assertTrue(rs.next());
         assertNull(rs.getString(1));
@@ -134,17 +164,20 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void tempTable() throws SQLException {
+    @Test
+    public void tempTable() throws SQLException
+    {
         assertEquals(stat.executeUpdate("create temp table myTemp (a);"), 0);
         assertEquals(stat.executeUpdate("insert into myTemp values (2);"), 1);
     }
 
-    @Test public void insert1000() throws SQLException {
+    @Test
+    public void insert1000() throws SQLException
+    {
         assertEquals(stat.executeUpdate("create table in1000 (a);"), 0);
         conn.setAutoCommit(false);
-        for (int i=0; i < 1000; i++)
-            assertEquals(stat.executeUpdate(
-                "insert into in1000 values ("+i+");"), 1);
+        for (int i = 0; i < 1000; i++)
+            assertEquals(stat.executeUpdate("insert into in1000 values (" + i + ");"), 1);
         conn.commit();
 
         ResultSet rs = stat.executeQuery("select count(a) from in1000;");
@@ -155,15 +188,18 @@ public class StatementTest
         assertEquals(stat.executeUpdate("drop table in1000;"), 1);
     }
 
-    private void assertArrayEq(int[] a, int[] b) {
+    private void assertArrayEq(int[] a, int[] b)
+    {
         assertNotNull(a);
         assertNotNull(b);
         assertEquals(a.length, b.length);
-        for (int i=0; i < a.length; i++)
+        for (int i = 0; i < a.length; i++)
             assertEquals(a[i], b[i]);
     }
 
-    @Test public void batch() throws SQLException {
+    @Test
+    public void batch() throws SQLException
+    {
         stat.addBatch("create table batch (c1);");
         stat.addBatch("insert into batch values (1);");
         stat.addBatch("insert into batch values (1);");
@@ -171,7 +207,7 @@ public class StatementTest
         stat.addBatch("insert into batch values (3);");
         stat.addBatch("insert into batch values (4);");
         assertArrayEq(new int[] { 0, 1, 1, 1, 1, 1 }, stat.executeBatch());
-        assertArrayEq(new int[] { }, stat.executeBatch());
+        assertArrayEq(new int[] {}, stat.executeBatch());
         stat.clearBatch();
         stat.addBatch("insert into batch values (9);");
         assertArrayEq(new int[] { 1 }, stat.executeBatch());
@@ -188,13 +224,17 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void closeOnFalseNext() throws SQLException {
+    @Test
+    public void closeOnFalseNext() throws SQLException
+    {
         stat.executeUpdate("create table t1 (c1);");
         conn.createStatement().executeQuery("select * from t1;").next();
         stat.executeUpdate("drop table t1;");
     }
 
-    @Test public void getGeneratedKeys() throws SQLException {
+    @Test
+    public void getGeneratedKeys() throws SQLException
+    {
         ResultSet rs;
         stat.executeUpdate("create table t1 (c1 integer primary key, v);");
         stat.executeUpdate("insert into t1 (v) values ('red');");
@@ -209,7 +249,9 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void isBeforeFirst() throws SQLException {
+    @Test
+    public void isBeforeFirst() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select 1 union all select 2;");
         assertTrue(rs.isBeforeFirst());
         assertTrue(rs.next());
@@ -224,19 +266,22 @@ public class StatementTest
         rs.close();
     }
 
-    @Test public void columnNaming() throws SQLException {
+    @Test
+    public void columnNaming() throws SQLException
+    {
         stat.executeUpdate("create table t1 (c1 integer);");
         stat.executeUpdate("create table t2 (c1 integer);");
         stat.executeUpdate("insert into t1 values (1);");
         stat.executeUpdate("insert into t2 values (1);");
-        ResultSet rs = stat.executeQuery(
-            "select a.c1 AS c1 from t1 a, t2 where a.c1=t2.c1;");
+        ResultSet rs = stat.executeQuery("select a.c1 AS c1 from t1 a, t2 where a.c1=t2.c1;");
         assertTrue(rs.next());
         assertEquals(rs.getInt("c1"), 1);
         rs.close();
     }
 
-    @Test public void nullDate() throws SQLException {
+    @Test
+    public void nullDate() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select null;");
         assertTrue(rs.next());
         assertEquals(rs.getDate(1), null);
@@ -245,21 +290,22 @@ public class StatementTest
     }
 
     @Ignore
-    @Test(expected= SQLException.class)
-    public void ambiguousColumnNaming() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void ambiguousColumnNaming() throws SQLException
+    {
         stat.executeUpdate("create table t1 (c1 int);");
         stat.executeUpdate("create table t2 (c1 int, c2 int);");
         stat.executeUpdate("insert into t1 values (1);");
         stat.executeUpdate("insert into t2 values (2, 1);");
-        ResultSet rs = stat.executeQuery(
-            "select a.c1, b.c1 from t1 a, t2 b where a.c1=b.c2;");
+        ResultSet rs = stat.executeQuery("select a.c1, b.c1 from t1 a, t2 b where a.c1=b.c2;");
         assertTrue(rs.next());
         assertEquals(rs.getInt("c1"), 1);
         rs.close();
     }
 
-    @Test(expected= SQLException.class)
-    public void failToDropWhenRSOpen() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void failToDropWhenRSOpen() throws SQLException
+    {
         stat.executeUpdate("create table t1 (c1);");
         stat.executeUpdate("insert into t1 values (4);");
         stat.executeUpdate("insert into t1 values (4);");
@@ -267,40 +313,56 @@ public class StatementTest
         stat.executeUpdate("drop table t1;");
     }
 
-    @Test(expected= SQLException.class)
-    public void executeNoRS() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void executeNoRS() throws SQLException
+    {
         assertFalse(stat.execute("insert into test values (8);"));
         stat.getResultSet();
     }
 
-    @Test(expected= SQLException.class)
-    public void executeClearRS() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void executeClearRS() throws SQLException
+    {
         assertTrue(stat.execute("select null;"));
         assertNotNull(stat.getResultSet());
         assertFalse(stat.getMoreResults());
         stat.getResultSet();
     }
 
-    @Test(expected= BatchUpdateException.class)
-    public void batchReturnsResults() throws SQLException {
+    @Test(expected = BatchUpdateException.class)
+    public void batchReturnsResults() throws SQLException
+    {
         stat.addBatch("select null;");
         stat.executeBatch();
     }
 
-    @Test(expected= SQLException.class)
-    public void noSuchTable() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void noSuchTable() throws SQLException
+    {
         stat.executeQuery("select * from doesnotexist;");
     }
-    
-    @Test(expected= SQLException.class)
-    public void noSuchCol() throws SQLException {
+
+    @Test(expected = SQLException.class)
+    public void noSuchCol() throws SQLException
+    {
         stat.executeQuery("select notacol from (select 1);");
     }
 
-    @Test(expected= SQLException.class)
-    public void noSuchColName() throws SQLException {
+    @Test(expected = SQLException.class)
+    public void noSuchColName() throws SQLException
+    {
         ResultSet rs = stat.executeQuery("select 1;");
         assertTrue(rs.next());
         rs.getInt("noSuchColName");
     }
+
+    @Test
+    public void multipleStatements() throws SQLException
+    {
+        // ; insert into person values(1,'leo')
+        int count = stat
+                .executeUpdate("create table person (id integer, name string); insert into person values(1, 'leo'); insert into person values(2, 'yui');");
+        ResultSet rs = stat.executeQuery("select * from person");
+        assertTrue(rs.next());
+    }
 }