OSDN Git Service

added enable_load_extension feature
authorleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Wed, 8 Apr 2009 10:12:24 +0000 (10:12 +0000)
committerleo <leo@ae02f08e-27ec-0310-ae8c-8ba02fe2eafd>
Wed, 8 Apr 2009 10:12:24 +0000 (10:12 +0000)
git-svn-id: http://www.xerial.org/svn/project/XerialJ/trunk/sqlite-jdbc@3181 ae02f08e-27ec-0310-ae8c-8ba02fe2eafd

Makefile
sqlitejdbc/Makefile
sqlitejdbc/Makefile.nested
src/main/java/org/sqlite/Conn.java
src/main/java/org/sqlite/DB.java
src/main/java/org/sqlite/JDBC.java
src/main/java/org/sqlite/NativeDB.c
src/main/java/org/sqlite/NativeDB.java
src/main/java/org/sqlite/NestedDB.java
src/main/resources/native/Windows/x86/sqlitejdbc.dll
src/test/java/org/sqlite/JDBCTest.java [new file with mode: 0644]

index 21c23c9..34ffd01 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ OSINFO_PROG=target/sqlitejdbc/$(OSInfoClass).class
 SQLITE_DLL=sqlitejdbc/build/$(target)/$(LIBNAME)\r
 SQLITE_BUILD_DIR=sqlitejdbc/build/$(sqlite)-$(target)\r
 \r
-LIB_FOLDER = $(shell java -cp target/sqlitejdbc org.xerial.db.sql.sqlite.OSInfo)\r
+LIB_FOLDER = $(shell java -cp target/sqlitejdbc $(OSInfoClass))\r
 WORK_DIR=target/dll/$(sqlite)/native\r
 UPDATE_FLAG=target/dll/$(sqlite)/UPDATE\r
 \r
index 920a9a1..e414e1e 100644 (file)
@@ -51,7 +51,7 @@ build/$(sqlite)-%/sqlite3.o: dl/$(sqlite)-amal.zip
            -DSQLITE_CORE \
            -DSQLITE_ENABLE_FTS3 \
                -DSQLITE_ENABLE_RTREE \
-           -DSQLITE_OMIT_LOAD_EXTENSION sqlite3.c)
+           sqlite3.c)
 
 build/org/sqlite/%.class: ../src/main/java/org/sqlite/%.java
        @mkdir -p build
index e7e2244..624c389 100644 (file)
@@ -63,7 +63,6 @@ build/SQLite.mips: $(nestedvm)/Makefile $(nestedvm)/env.sh dl/$(sqlite)-amal.zip
            -DSQLITE_CORE \
            -DSQLITE_ENABLE_FTS3 \
                -DSQLITE_ENABLE_RTREE \
-           -DSQLITE_OMIT_LOAD_EXTENSION \
                sqlite3.c; \
        $$CC -c $$CFLAGS -o NestedDB.o Nested*.c)
 
index 6da13a6..f0b6685 100644 (file)
@@ -27,6 +27,7 @@ import java.sql.Savepoint;
 import java.sql.Statement;
 import java.sql.Struct;
 import java.util.Map;
+import java.util.Properties;
 
 class Conn implements Connection
 {
@@ -37,10 +38,15 @@ class Conn implements Connection
     private int transactionIsolation = TRANSACTION_SERIALIZABLE;
     private int timeout = 0;
 
-    public Conn(String url, String filename, boolean sharedCache) throws SQLException
+    public Conn(String url, String filename, Properties prop) throws SQLException
     {
         this(url, filename);
-        db.shared_cache(sharedCache);
+
+        boolean enableSharedCache = Boolean.parseBoolean(prop.getProperty("shared_cache", "false"));
+        boolean enableLoadExtension = Boolean.parseBoolean(prop.getProperty("enable_load_extension", "false"));
+
+        db.shared_cache(enableSharedCache);
+        db.enable_load_extension(enableLoadExtension);
     }
 
     public Conn(String url, String filename) throws SQLException
index 8cc51ee..54da776 100644 (file)
@@ -60,6 +60,8 @@ abstract class DB implements Codes
 
     abstract int shared_cache(boolean enable) throws SQLException;
 
+    abstract int enable_load_extension(boolean enable) throws SQLException;
+
     final synchronized void exec(String sql) throws SQLException
     {
         long pointer = 0;
index 5db5362..afc248b 100644 (file)
 
 package org.sqlite;
 
-import java.sql.*;
-import java.util.*;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
 
 public class JDBC implements Driver
 {
     private static final String PREFIX = "jdbc:sqlite:";
 
-    static {
-        try {
+    static
+    {
+        try
+        {
             DriverManager.registerDriver(new JDBC());
-        } catch (SQLException e) {
+        }
+        catch (SQLException e)
+        {
             e.printStackTrace();
         }
     }
 
-    public int getMajorVersion() { return 1; }
-    public int getMinorVersion() { return 1; }
+    public int getMajorVersion()
+    {
+        return 1;
+    }
 
-    public boolean jdbcCompliant() { return false; }
+    public int getMinorVersion()
+    {
+        return 1;
+    }
+
+    public boolean jdbcCompliant()
+    {
+        return false;
+    }
 
-    public boolean acceptsURL(String url) {
+    public boolean acceptsURL(String url)
+    {
         return url != null && url.toLowerCase().startsWith(PREFIX);
     }
 
-    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
-            throws SQLException {
-        DriverPropertyInfo sharedCache = new DriverPropertyInfo(
-            "shared_cache", "false");
+    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
+    {
+        DriverPropertyInfo sharedCache = new DriverPropertyInfo("shared_cache", "false");
         sharedCache.choices = new String[] { "true", "false" };
-        sharedCache.description =
-            "Enable SQLite Shared-Cache mode, native driver only.";
+        sharedCache.description = "Enable SQLite Shared-Cache mode, native driver only.";
         sharedCache.required = false;
 
         return new DriverPropertyInfo[] { sharedCache };
     }
 
-    public Connection connect(String url, Properties info) throws SQLException {
-        if (!acceptsURL(url)) return null;
+    public Connection connect(String url, Properties info) throws SQLException
+    {
+        if (!acceptsURL(url))
+            return null;
         url = url.trim();
 
         // if no file name is given use a memory database
-        String file = PREFIX.equalsIgnoreCase(url) ?
-            ":memory:" : url.substring(PREFIX.length());
+        String file = PREFIX.equalsIgnoreCase(url) ? ":memory:" : url.substring(PREFIX.length());
 
-        if (info.getProperty("shared_cache") == null)
-            return new Conn(url, file);
-        else
-            return new Conn(url, file,
-                Boolean.parseBoolean(info.getProperty("shared_cache")));
+        return new Conn(url, file, info);
     }
 }
index 4edc2aa..fd16081 100644 (file)
@@ -288,6 +288,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_NativeDB_shared_1cache(
     return sqlite3_enable_shared_cache(enable ? 1 : 0);
 }
 
+
+JNIEXPORT jint JNICALL Java_org_sqlite_NativeDB_enable_1load_1extension(
+        JNIEnv *env, jobject this, jboolean enable)
+{
+       return sqlite3_enable_load_extension(gethandle(env, this), enable ? 1 : 0);
+}
+
+
 JNIEXPORT void JNICALL Java_org_sqlite_NativeDB__1open(
         JNIEnv *env, jobject this, jstring file)
 {
index 1301d8f..59afb60 100644 (file)
@@ -35,58 +35,6 @@ final class NativeDB extends DB
         loadSucceeded = SQLiteJDBCLoader.initialize();
         isLoaded = true;
         return loadSucceeded;
-
-        //        String libpath = System.getProperty("org.sqlite.lib.path");
-        //        String libname = System.getProperty("org.sqlite.lib.name");
-        //        if (libname == null) libname = System.mapLibraryName("sqlitejdbc");
-        //
-        //        // look for a pre-installed library
-        //        try {
-        //            if (libpath == null) System.loadLibrary("sqlitejdbc");
-        //            else System.load(new File(libpath, libname).getAbsolutePath());
-        //
-        //            loaded = Boolean.TRUE;
-        //            return true;
-        //        } catch (UnsatisfiedLinkError e) { } // fall through
-        //
-        //        // guess what a bundled library would be called
-        //        String osname = System.getProperty("os.name").toLowerCase();
-        //        String osarch = System.getProperty("os.arch");
-        //        if (osname.startsWith("mac os")) {
-        //            osname = "mac";
-        //            osarch = "universal";
-        //        }
-        //        if (osname.startsWith("windows"))
-        //            osname = "win";
-        //        if (osname.startsWith("sunos"))
-        //            osname = "solaris";
-        //        if (osarch.startsWith("i") && osarch.endsWith("86"))
-        //            osarch = "x86";
-        //        libname = osname + '-' + osarch + ".lib";
-        //
-        //        // try a bundled library
-        //        try {
-        //            ClassLoader cl = NativeDB.class.getClassLoader();
-        //            InputStream in = cl.getResourceAsStream(libname);
-        //            if (in == null)
-        //                throw new Exception("libname: "+libname+" not found");
-        //            File tmplib = File.createTempFile("libsqlitejdbc-", ".lib");
-        //            tmplib.deleteOnExit();
-        //            OutputStream out = new FileOutputStream(tmplib);
-        //            byte[] buf = new byte[1024];
-        //            for (int len; (len = in.read(buf)) != -1;)
-        //                out.write(buf, 0, len);
-        //            in.close();
-        //            out.close();
-        //
-        //            System.load(tmplib.getAbsolutePath());
-        //
-        //            loaded = Boolean.TRUE;
-        //            return true;
-        //        } catch (Exception e) { }
-        //
-        //        loaded = Boolean.FALSE;
-        //        return false;
     }
 
     /** linked list of all instanced UDFDatas */
@@ -100,6 +48,8 @@ final class NativeDB extends DB
 
     native synchronized int shared_cache(boolean enable);
 
+    native synchronized int enable_load_extension(boolean enable);
+
     native synchronized void interrupt();
 
     native synchronized void busy_timeout(int ms);
index 52116b2..84eac64 100644 (file)
  */
 package org.sqlite;
 
-import org.ibex.nestedvm.Runtime;
-
-import java.io.File;
 import java.io.PrintWriter;
-import java.sql.*;
+import java.sql.SQLException;
+
+import org.ibex.nestedvm.Runtime;
 
 // FEATURE: strdup is wasteful, SQLite interface will take unterminated char*
 
@@ -34,18 +33,21 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
 
     /** user defined functions referenced by position (stored in used data) */
     private Function[] functions = null;
-    private String[]   funcNames = null;
-
+    private String[] funcNames = null;
 
     // WRAPPER FUNCTIONS ////////////////////////////////////////////
 
-    protected synchronized void _open(String filename) throws SQLException {
-        if (handle != 0) throw new SQLException("DB already open");
+    protected synchronized void _open(String filename) throws SQLException
+    {
+        if (handle != 0)
+            throw new SQLException("DB already open");
 
         // handle silly windows drive letter mapping
-        if (filename.length() > 2) {
+        if (filename.length() > 2)
+        {
             char drive = Character.toLowerCase(filename.charAt(0));
-            if (filename.charAt(1) == ':' && drive >= 'a' && drive <= 'z') {
+            if (filename.charAt(1) == ':' && drive >= 'a' && drive <= 'z')
+            {
 
                 // convert to nestedvm's "/c:/file" format
                 filename = filename.substring(2);
@@ -55,11 +57,13 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
         }
 
         // start the nestedvm runtime
-        try {
-            rt = (Runtime)Class.forName("org.sqlite.SQLite")
-                .newInstance();
+        try
+        {
+            rt = (Runtime) Class.forName("org.sqlite.SQLite").newInstance();
             rt.start();
-        } catch (Exception e) {
+        }
+        catch (Exception e)
+        {
             throw new CausedSQLException(e);
         }
 
@@ -77,40 +81,59 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
     }
 
     /* callback for Runtime.CallJavaCB above */
-    public int call(int xType, int context, int args, int value) {
+    public int call(int xType, int context, int args, int value)
+    {
         xUDF(xType, context, args, value);
         return 0;
     }
 
-    protected synchronized void _close() throws SQLException {
-        if (handle == 0) return;
-        try {
+    protected synchronized void _close() throws SQLException
+    {
+        if (handle == 0)
+            return;
+        try
+        {
             if (call("sqlite3_close", handle) != SQLITE_OK)
                 throwex();
-        } finally {
+        }
+        finally
+        {
             handle = 0;
             rt.stop();
             rt = null;
         }
     }
 
-    int shared_cache(boolean enable) throws SQLException {
+    int shared_cache(boolean enable) throws SQLException
+    {
         // The shared cache is per-process, so it is useless as
         // each nested connection is its own process.
         return -1;
     }
-    synchronized void interrupt() throws SQLException {
+
+    int enable_load_extension(boolean enable) throws SQLException
+    {
+        return call("sqlite3_enable_load_extension", handle, enable ? 1 : 0);
+    }
+
+    synchronized void interrupt() throws SQLException
+    {
         call("sqlite3_interrupt", handle);
     }
-    synchronized void busy_timeout(int ms) throws SQLException {
+
+    synchronized void busy_timeout(int ms) throws SQLException
+    {
         call("sqlite3_busy_timeout", handle, ms);
     }
-    protected synchronized long prepare(String sql) throws SQLException {
+
+    protected synchronized long prepare(String sql) throws SQLException
+    {
         int passback = rt.xmalloc(4);
         int str = rt.strdup(sql);
         int ret = call("sqlite3_prepare_v2", handle, str, -1, passback, 0);
         rt.free(str);
-        if (ret != SQLITE_OK) {
+        if (ret != SQLITE_OK)
+        {
             rt.free(passback);
             throwex();
         }
@@ -118,161 +141,258 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
         rt.free(passback);
         return pointer;
     }
-    synchronized String errmsg() throws SQLException {
+
+    synchronized String errmsg() throws SQLException
+    {
         return cstring(call("sqlite3_errmsg", handle));
     }
-    synchronized String libversion() throws SQLException {
+
+    synchronized String libversion() throws SQLException
+    {
         return cstring(call("sqlite3_libversion", handle));
     }
-    synchronized int changes() throws SQLException {
-        return call("sqlite3_changes", handle); }
-
-    protected synchronized int finalize(long stmt) throws SQLException {
-        return call("sqlite3_finalize", (int)stmt); }
-    protected synchronized int step(long stmt) throws SQLException {
-        return call("sqlite3_step", (int)stmt); }
-    protected synchronized int reset(long stmt) throws SQLException {
-        return call("sqlite3_reset", (int)stmt); }
-    synchronized int clear_bindings(long stmt) throws SQLException {
-        return call("sqlite3_clear_bindings", (int)stmt); }
-
-    synchronized int bind_parameter_count(long stmt) throws SQLException {
-        return call("sqlite3_bind_parameter_count", (int)stmt); }
-
-    synchronized int column_count(long stmt) throws SQLException {
-        return call("sqlite3_column_count", (int)stmt); }
-    synchronized int column_type(long stmt, int col) throws SQLException {
-        return call("sqlite3_column_type", (int)stmt, col); }
-    synchronized String column_name(long stmt, int col) throws SQLException {
-        return utfstring(call("sqlite3_column_name", (int)stmt, col));
-    }
-    synchronized String column_text(long stmt, int col) throws SQLException {
-        return utfstring(call("sqlite3_column_text", (int)stmt, col));
-    }
-    synchronized byte[] column_blob(long stmt, int col) throws SQLException {
-        int addr = call("sqlite3_column_blob", (int)stmt, col);
-        if (addr == 0) return null;
-        byte[] blob = new byte[call("sqlite3_column_bytes", (int)stmt, col)];
+
+    synchronized int changes() throws SQLException
+    {
+        return call("sqlite3_changes", handle);
+    }
+
+    protected synchronized int finalize(long stmt) throws SQLException
+    {
+        return call("sqlite3_finalize", (int) stmt);
+    }
+
+    protected synchronized int step(long stmt) throws SQLException
+    {
+        return call("sqlite3_step", (int) stmt);
+    }
+
+    protected synchronized int reset(long stmt) throws SQLException
+    {
+        return call("sqlite3_reset", (int) stmt);
+    }
+
+    synchronized int clear_bindings(long stmt) throws SQLException
+    {
+        return call("sqlite3_clear_bindings", (int) stmt);
+    }
+
+    synchronized int bind_parameter_count(long stmt) throws SQLException
+    {
+        return call("sqlite3_bind_parameter_count", (int) stmt);
+    }
+
+    synchronized int column_count(long stmt) throws SQLException
+    {
+        return call("sqlite3_column_count", (int) stmt);
+    }
+
+    synchronized int column_type(long stmt, int col) throws SQLException
+    {
+        return call("sqlite3_column_type", (int) stmt, col);
+    }
+
+    synchronized String column_name(long stmt, int col) throws SQLException
+    {
+        return utfstring(call("sqlite3_column_name", (int) stmt, col));
+    }
+
+    synchronized String column_text(long stmt, int col) throws SQLException
+    {
+        return utfstring(call("sqlite3_column_text", (int) stmt, col));
+    }
+
+    synchronized byte[] column_blob(long stmt, int col) throws SQLException
+    {
+        int addr = call("sqlite3_column_blob", (int) stmt, col);
+        if (addr == 0)
+            return null;
+        byte[] blob = new byte[call("sqlite3_column_bytes", (int) stmt, col)];
         copyin(addr, blob, blob.length);
         return blob;
     }
-    synchronized double column_double(long stmt, int col) throws SQLException {
-        try { return Double.parseDouble(column_text(stmt, col)); }
-        catch (NumberFormatException e) { return Double.NaN; } // TODO
+
+    synchronized double column_double(long stmt, int col) throws SQLException
+    {
+        try
+        {
+            return Double.parseDouble(column_text(stmt, col));
+        }
+        catch (NumberFormatException e)
+        {
+            return Double.NaN;
+        } // TODO
     }
-    synchronized long column_long(long stmt, int col) throws SQLException {
-        try { return Long.parseLong(column_text(stmt, col)); }
-        catch (NumberFormatException e) { return 0; } // TODO
+
+    synchronized long column_long(long stmt, int col) throws SQLException
+    {
+        try
+        {
+            return Long.parseLong(column_text(stmt, col));
+        }
+        catch (NumberFormatException e)
+        {
+            return 0;
+        } // TODO
     }
-    synchronized int column_int(long stmt, int col) throws SQLException {
-        return call("sqlite3_column_int", (int)stmt, col); }
-    synchronized String column_decltype(long stmt, int col)
-            throws SQLException {
-        return utfstring(call("sqlite3_column_decltype", (int)stmt, col));
+
+    synchronized int column_int(long stmt, int col) throws SQLException
+    {
+        return call("sqlite3_column_int", (int) stmt, col);
     }
-    synchronized String column_table_name(long stmt, int col)
-            throws SQLException {
-        return utfstring(call("sqlite3_column_table_name", (int)stmt, col));
+
+    synchronized String column_decltype(long stmt, int col) throws SQLException
+    {
+        return utfstring(call("sqlite3_column_decltype", (int) stmt, col));
     }
 
-    synchronized int bind_null(long stmt, int pos) throws SQLException {
-        return call("sqlite3_bind_null", (int)stmt, pos);
+    synchronized String column_table_name(long stmt, int col) throws SQLException
+    {
+        return utfstring(call("sqlite3_column_table_name", (int) stmt, col));
     }
-    synchronized int bind_int(long stmt, int pos, int v) throws SQLException {
-        return call("sqlite3_bind_int", (int)stmt, pos, v);
+
+    synchronized int bind_null(long stmt, int pos) throws SQLException
+    {
+        return call("sqlite3_bind_null", (int) stmt, pos);
     }
-    synchronized int bind_long(long stmt, int pos, long v) throws SQLException {
-            return bind_text(stmt, pos, Long.toString(v)); // TODO
+
+    synchronized int bind_int(long stmt, int pos, int v) throws SQLException
+    {
+        return call("sqlite3_bind_int", (int) stmt, pos, v);
     }
-    synchronized int bind_double(long stmt, int pos, double v)
-            throws SQLException {
-            return bind_text(stmt, pos, Double.toString(v)); // TODO
+
+    synchronized int bind_long(long stmt, int pos, long v) throws SQLException
+    {
+        return bind_text(stmt, pos, Long.toString(v)); // TODO
     }
-    synchronized int bind_text(long stmt, int pos, String v)
-            throws SQLException {
-        if (v == null) return bind_null(stmt, pos);
-        return call("sqlite3_bind_text", (int)stmt, pos, rt.strdup(v),
-                    -1, rt.lookupSymbol("free"));
+
+    synchronized int bind_double(long stmt, int pos, double v) throws SQLException
+    {
+        return bind_text(stmt, pos, Double.toString(v)); // TODO
+    }
+
+    synchronized int bind_text(long stmt, int pos, String v) throws SQLException
+    {
+        if (v == null)
+            return bind_null(stmt, pos);
+        return call("sqlite3_bind_text", (int) stmt, pos, rt.strdup(v), -1, rt.lookupSymbol("free"));
     }
-    synchronized int bind_blob(long stmt, int pos, byte[] buf)
-            throws SQLException {
-        if (buf == null || buf.length < 1) return bind_null(stmt, pos);
+
+    synchronized int bind_blob(long stmt, int pos, byte[] buf) throws SQLException
+    {
+        if (buf == null || buf.length < 1)
+            return bind_null(stmt, pos);
         int len = buf.length;
         int blob = rt.xmalloc(len); // free()ed by sqlite3_bind_blob
         copyout(buf, blob, len);
-        return call("sqlite3_bind_blob", (int)stmt, pos, blob, len,
-                    rt.lookupSymbol("free"));
+        return call("sqlite3_bind_blob", (int) stmt, pos, blob, len, rt.lookupSymbol("free"));
     }
 
-    synchronized void result_null(long cxt) throws SQLException {
-        call("sqlite3_result_null", (int)cxt); }
-    synchronized void result_text(long cxt, String val) throws SQLException {
-        call("sqlite3_result_text", (int)cxt, rt.strdup(val), -1,
-             rt.lookupSymbol("free"));
+    synchronized void result_null(long cxt) throws SQLException
+    {
+        call("sqlite3_result_null", (int) cxt);
     }
-    synchronized void result_blob(long cxt, byte[] val) throws SQLException {
-        if (val == null || val.length == 0) { result_null(cxt); return; }
+
+    synchronized void result_text(long cxt, String val) throws SQLException
+    {
+        call("sqlite3_result_text", (int) cxt, rt.strdup(val), -1, rt.lookupSymbol("free"));
+    }
+
+    synchronized void result_blob(long cxt, byte[] val) throws SQLException
+    {
+        if (val == null || val.length == 0)
+        {
+            result_null(cxt);
+            return;
+        }
         int blob = rt.xmalloc(val.length);
         copyout(val, blob, val.length);
-        call("sqlite3_result_blob", (int)cxt, blob,
-             val.length, rt.lookupSymbol("free"));
-    }
-    synchronized void result_double(long cxt, double val) throws SQLException {
-        result_text(cxt, Double.toString(val)); } // TODO
-    synchronized void result_long(long cxt, long val) throws SQLException {
-        result_text(cxt, Long.toString(val)); } // TODO
-    synchronized void result_int(long cxt, int val) throws SQLException {
-        call("sqlite3_result_int", (int)cxt, val); }
-    synchronized void result_error(long cxt, String err) throws SQLException {
+        call("sqlite3_result_blob", (int) cxt, blob, val.length, rt.lookupSymbol("free"));
+    }
+
+    synchronized void result_double(long cxt, double val) throws SQLException
+    {
+        result_text(cxt, Double.toString(val));
+    } // TODO
+
+    synchronized void result_long(long cxt, long val) throws SQLException
+    {
+        result_text(cxt, Long.toString(val));
+    } // TODO
+
+    synchronized void result_int(long cxt, int val) throws SQLException
+    {
+        call("sqlite3_result_int", (int) cxt, val);
+    }
+
+    synchronized void result_error(long cxt, String err) throws SQLException
+    {
         int str = rt.strdup(err);
-        call("sqlite3_result_error", (int)cxt, str, -1);
+        call("sqlite3_result_error", (int) cxt, str, -1);
         rt.free(str);
     }
 
-    synchronized int value_bytes(Function f, int arg) throws SQLException {
+    synchronized int value_bytes(Function f, int arg) throws SQLException
+    {
         return call("sqlite3_value_bytes", value(f, arg));
     }
-    synchronized String value_text(Function f, int arg) throws SQLException {
+
+    synchronized String value_text(Function f, int arg) throws SQLException
+    {
         return utfstring(call("sqlite3_value_text", value(f, arg)));
     }
-    synchronized byte[] value_blob(Function f, int arg) throws SQLException {
+
+    synchronized byte[] value_blob(Function f, int arg) throws SQLException
+    {
         int addr = call("sqlite3_value_blob", value(f, arg));
-        if (addr == 0) return null;
+        if (addr == 0)
+            return null;
         byte[] blob = new byte[value_bytes(f, arg)];
         copyin(addr, blob, blob.length);
         return blob;
     }
-    synchronized double value_double(Function f, int arg) throws SQLException {
+
+    synchronized double value_double(Function f, int arg) throws SQLException
+    {
         return Double.parseDouble(value_text(f, arg)); // TODO
     }
-    synchronized long value_long(Function f, int arg) throws SQLException {
+
+    synchronized long value_long(Function f, int arg) throws SQLException
+    {
         return Long.parseLong(value_text(f, arg)); // TODO
     }
-    synchronized int value_int(Function f, int arg) throws SQLException {
+
+    synchronized int value_int(Function f, int arg) throws SQLException
+    {
         return call("sqlite3_value_int", value(f, arg));
     }
-    synchronized int value_type(Function f, int arg) throws SQLException {
+
+    synchronized int value_type(Function f, int arg) throws SQLException
+    {
         return call("sqlite3_value_type", value(f, arg));
     }
 
-    private int value(Function f, int arg) throws SQLException {
-        return deref((int)f.value + (arg*4));
+    private int value(Function f, int arg) throws SQLException
+    {
+        return deref((int) f.value + (arg * 4));
     }
 
-
-    synchronized int create_function(String name, Function func)
-            throws SQLException {
-        if (functions == null) {
+    synchronized int create_function(String name, Function func) throws SQLException
+    {
+        if (functions == null)
+        {
             functions = new Function[10];
             funcNames = new String[10];
         }
 
         // find a position
         int pos;
-        for (pos=0; pos < functions.length; pos++)
-            if (functions[pos] == null) break;
+        for (pos = 0; pos < functions.length; pos++)
+            if (functions[pos] == null)
+                break;
 
-        if (pos == functions.length) { // expand function arrays
+        if (pos == functions.length)
+        { // expand function arrays
             Function[] fnew = new Function[functions.length * 2];
             String[] nnew = new String[funcNames.length * 2];
             System.arraycopy(functions, 0, fnew, 0, functions.length);
@@ -286,20 +406,23 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
         funcNames[pos] = name;
         int rc;
         int str = rt.strdup(name);
-        rc = call("create_function_helper", handle, str, pos,
-                      func instanceof Function.Aggregate ? 1 : 0);
+        rc = call("create_function_helper", handle, str, pos, func instanceof Function.Aggregate ? 1 : 0);
         rt.free(str);
         return rc;
     }
 
-    synchronized int destroy_function(String name) throws SQLException {
-        if (name == null) return 0;
+    synchronized int destroy_function(String name) throws SQLException
+    {
+        if (name == null)
+            return 0;
 
         // find function position number
         int pos;
         for (pos = 0; pos < funcNames.length; pos++)
-            if (name.equals(funcNames[pos])) break;
-        if (pos == funcNames.length) return 0;
+            if (name.equals(funcNames[pos]))
+                break;
+        if (pos == funcNames.length)
+            return 0;
 
         functions[pos] = null;
         funcNames[pos] = null;
@@ -313,13 +436,16 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
     }
 
     /* unused as we use the user_data pointer to store a single word */
-    synchronized void free_functions() {}
+    synchronized void free_functions()
+    {}
 
     /** Callback used by xFunc (1), xStep (2) and xFinal (3). */
-    synchronized void xUDF(int xType, int context, int args, int value) {
+    synchronized void xUDF(int xType, int context, int args, int value)
+    {
         Function func = null;
 
-        try {
+        try
+        {
             int pos = call("sqlite3_user_data", context);
             func = functions[pos];
             if (func == null)
@@ -329,23 +455,39 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
             func.value = value;
             func.args = args;
 
-            switch (xType) {
-                case 1: func.xFunc(); break;
-                case 2: ((Function.Aggregate)func).xStep(); break;
-                case 3: ((Function.Aggregate)func).xFinal(); break;
+            switch (xType)
+            {
+            case 1:
+                func.xFunc();
+                break;
+            case 2:
+                ((Function.Aggregate) func).xStep();
+                break;
+            case 3:
+                ((Function.Aggregate) func).xFinal();
+                break;
             }
-        } catch (SQLException e) {
-            try {
+        }
+        catch (SQLException e)
+        {
+            try
+            {
                 String err = e.toString();
-                if (err == null) err = "unknown error";
+                if (err == null)
+                    err = "unknown error";
                 int str = rt.strdup(err);
                 call("sqlite3_result_error", context, str, -1);
                 rt.free(str);
-            } catch (SQLException exp) {
+            }
+            catch (SQLException exp)
+            {
                 exp.printStackTrace();//TODO
             }
-        } finally {
-            if (func != null) {
+        }
+        finally
+        {
+            if (func != null)
+            {
                 func.context = 0;
                 func.value = 0;
                 func.args = 0;
@@ -353,17 +495,18 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
         }
     }
 
-
     /** Calls support function found in upstream/sqlite-metadata.patch */
-    synchronized boolean[][] column_metadata(long stmt) throws SQLException {
-        int colCount = call("sqlite3_column_count", (int)stmt);
+    synchronized boolean[][] column_metadata(long stmt) throws SQLException
+    {
+        int colCount = call("sqlite3_column_count", (int) stmt);
         boolean[][] meta = new boolean[colCount][3];
         int pass;
-        
+
         pass = rt.xmalloc(12); // struct metadata
 
-        for (int i=0; i < colCount; i++) {
-            call("column_metadata_helper", handle, (int)stmt, i, pass);
+        for (int i = 0; i < colCount; i++)
+        {
+            call("column_metadata_helper", handle, (int) stmt, i, pass);
             meta[i][0] = deref(pass) == 1;
             meta[i][1] = deref(pass + 4) == 1;
             meta[i][2] = deref(pass + 8) == 1;
@@ -373,75 +516,165 @@ final class NestedDB extends DB implements Runtime.CallJavaCB
         return meta;
     }
 
-
     // HELPER FUNCTIONS /////////////////////////////////////////////
 
     /** safe to reuse parameter arrays as all functions are syncrhonized */
-    private final int[]
-        p0 = new int[] {},
-        p1 = new int[] { 0 },
-        p2 = new int[] { 0, 0 },
-        p3 = new int[] { 0, 0, 0 },
-        p4 = new int[] { 0, 0, 0, 0 },
-        p5 = new int[] { 0, 0, 0, 0, 0 };
-
-    private int call(String addr, int a0) throws SQLException {
-        p1[0] = a0; return call(addr, p1); }
-    private int call(String addr, int a0, int a1) throws SQLException {
-        p2[0] = a0; p2[1] = a1; return call(addr, p2); }
-    private int call(String addr, int a0, int a1, int a2) throws SQLException {
-        p3[0] = a0; p3[1] = a1; p3[2] = a2; return call(addr, p3); }
-    private int call(String addr, int a0, int a1, int a2, int a3)
-            throws SQLException {
-        p4[0] = a0; p4[1] = a1; p4[2] = a2; p4[3] = a3;
+    private final int[] p0 = new int[] {}, p1 = new int[] { 0 }, p2 = new int[] { 0, 0 }, p3 = new int[] { 0, 0, 0 },
+            p4 = new int[] { 0, 0, 0, 0 }, p5 = new int[] { 0, 0, 0, 0, 0 };
+
+    private int call(String addr, int a0) throws SQLException
+    {
+        p1[0] = a0;
+        return call(addr, p1);
+    }
+
+    private int call(String addr, int a0, int a1) throws SQLException
+    {
+        p2[0] = a0;
+        p2[1] = a1;
+        return call(addr, p2);
+    }
+
+    private int call(String addr, int a0, int a1, int a2) throws SQLException
+    {
+        p3[0] = a0;
+        p3[1] = a1;
+        p3[2] = a2;
+        return call(addr, p3);
+    }
+
+    private int call(String addr, int a0, int a1, int a2, int a3) throws SQLException
+    {
+        p4[0] = a0;
+        p4[1] = a1;
+        p4[2] = a2;
+        p4[3] = a3;
         return call(addr, p4);
     }
-    private int call(String addr, int a0, int a1, int a2, int a3, int a4)
-            throws SQLException {
-        p5[0] = a0; p5[1] = a1; p5[2] = a2; p5[3] = a3; p5[4] = a4;
+
+    private int call(String addr, int a0, int a1, int a2, int a3, int a4) throws SQLException
+    {
+        p5[0] = a0;
+        p5[1] = a1;
+        p5[2] = a2;
+        p5[3] = a3;
+        p5[4] = a4;
         return call(addr, p5);
     }
-    private int call(String func, int[] args) throws SQLException {
-        try {
+
+    private int call(String func, int[] args) throws SQLException
+    {
+        try
+        {
             return rt.call(func, args);
-        } catch (Runtime.CallException e) { throw new CausedSQLException(e); }
+        }
+        catch (Runtime.CallException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
 
     /** Dereferences a pointer, returning the word it points to. */
-    private int deref(int pointer) throws SQLException {
-        try { return rt.memRead(pointer); }
-        catch (Runtime.ReadFaultException e) { throw new CausedSQLException(e);}
+    private int deref(int pointer) throws SQLException
+    {
+        try
+        {
+            return rt.memRead(pointer);
+        }
+        catch (Runtime.ReadFaultException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
-    private String utfstring(int str) throws SQLException {
-        try { return rt.utfstring(str); }
-        catch (Runtime.ReadFaultException e) { throw new CausedSQLException(e);}
+
+    private String utfstring(int str) throws SQLException
+    {
+        try
+        {
+            return rt.utfstring(str);
+        }
+        catch (Runtime.ReadFaultException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
-    private String cstring(int str) throws SQLException {
-        try { return rt.cstring(str); }
-        catch (Runtime.ReadFaultException e) { throw new CausedSQLException(e);}
+
+    private String cstring(int str) throws SQLException
+    {
+        try
+        {
+            return rt.cstring(str);
+        }
+        catch (Runtime.ReadFaultException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
-    private void copyin(int addr, byte[] buf, int count) throws SQLException {
-        try { rt.copyin(addr, buf, count); }
-        catch (Runtime.ReadFaultException e) { throw new CausedSQLException(e);}
+
+    private void copyin(int addr, byte[] buf, int count) throws SQLException
+    {
+        try
+        {
+            rt.copyin(addr, buf, count);
+        }
+        catch (Runtime.ReadFaultException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
-    private void copyout(byte[] buf, int addr, int count) throws SQLException {
-        try { rt.copyout(buf, addr, count); }
-        catch (Runtime.FaultException e) { throw new CausedSQLException(e);}
+
+    private void copyout(byte[] buf, int addr, int count) throws SQLException
+    {
+        try
+        {
+            rt.copyout(buf, addr, count);
+        }
+        catch (Runtime.FaultException e)
+        {
+            throw new CausedSQLException(e);
+        }
     }
 
     /** Maps any exception onto an SQLException. */
-    private static final class CausedSQLException extends SQLException {
+    private static final class CausedSQLException extends SQLException
+    {
         private final Exception cause;
-        CausedSQLException(Exception e) {
-            if (e == null) throw new RuntimeException("null exception cause");
+
+        CausedSQLException(Exception e)
+        {
+            if (e == null)
+                throw new RuntimeException("null exception cause");
             cause = e;
         }
-        public Throwable getCause() { return cause; }
-        public void printStackTrace() { cause.printStackTrace(); }
-        public void printStackTrace(PrintWriter s) { cause.printStackTrace(s); }
-        public Throwable fillInStackTrace() { return cause.fillInStackTrace(); }
-        public StackTraceElement[] getStackTrace() {
-            return cause.getStackTrace(); }
-        public String getMessage() { return cause.getMessage(); }
+
+        public Throwable getCause()
+        {
+            return cause;
+        }
+
+        public void printStackTrace()
+        {
+            cause.printStackTrace();
+        }
+
+        public void printStackTrace(PrintWriter s)
+        {
+            cause.printStackTrace(s);
+        }
+
+        public Throwable fillInStackTrace()
+        {
+            return cause.fillInStackTrace();
+        }
+
+        public StackTraceElement[] getStackTrace()
+        {
+            return cause.getStackTrace();
+        }
+
+        public String getMessage()
+        {
+            return cause.getMessage();
+        }
     }
 }
index 2a4b60a..e820469 100644 (file)
Binary files a/src/main/resources/native/Windows/x86/sqlitejdbc.dll and b/src/main/resources/native/Windows/x86/sqlitejdbc.dll differ
diff --git a/src/test/java/org/sqlite/JDBCTest.java b/src/test/java/org/sqlite/JDBCTest.java
new file mode 100644 (file)
index 0000000..f0e0232
--- /dev/null
@@ -0,0 +1,49 @@
+//--------------------------------------
+// sqlite-jdbc Project
+//
+// JDBCTest.java
+// Since: Apr 8, 2009
+//
+// $URL$ 
+// $Author$
+//--------------------------------------
+package org.sqlite;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class JDBCTest
+{
+    @BeforeClass
+    public static void forName() throws Exception
+    {
+        Class.forName("org.sqlite.JDBC");
+    }
+
+    @Test
+    public void enableLoadExtensionTest() throws Exception
+    {
+        Properties prop = new Properties();
+        prop.setProperty("enable_load_extension", "true");
+
+        Connection conn = null;
+        try
+        {
+            conn = DriverManager.getConnection("jdbc:sqlite:", prop);
+            Statement stat = conn.createStatement();
+            stat.executeUpdate("create table test (id integer primary key, fn, sn);");
+            stat.executeUpdate("create view testView as select * from test;");
+        }
+        finally
+        {
+            if (conn != null)
+                conn.close();
+        }
+    }
+
+}