summaryrefslogtreecommitdiffstats
path: root/sqlite-jdbc/src/main/java/SQLite
diff options
context:
space:
mode:
Diffstat (limited to 'sqlite-jdbc/src/main/java/SQLite')
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Authorizer.java25
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Blob.java323
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/BusyHandler.java20
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Callback.java68
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Constants.java157
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Database.java615
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Exception.java18
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Function.java59
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/FunctionContext.java82
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java452
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java1578
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java752
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java932
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java212
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java287
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java37
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java109
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/ProgressHandler.java17
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Shell.java669
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Stmt.java288
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/StringEncoder.java201
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/TableResult.java133
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Trace.java17
-rw-r--r--sqlite-jdbc/src/main/java/SQLite/Vm.java78
24 files changed, 7129 insertions, 0 deletions
diff --git a/sqlite-jdbc/src/main/java/SQLite/Authorizer.java b/sqlite-jdbc/src/main/java/SQLite/Authorizer.java
new file mode 100644
index 0000000..cdc321d
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Authorizer.java
@@ -0,0 +1,25 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's authorizer function.
+ */
+
+public interface Authorizer {
+
+ /**
+ * Callback to authorize access.
+ *
+ * @param what integer indicating type of access
+ * @param arg1 first argument (table, view, index, or trigger name)
+ * @param arg2 second argument (file, table, or column name)
+ * @param arg3 third argument (database name)
+ * @param arg4 third argument (trigger name)
+ * @return Constants.SQLITE_OK for success, Constants.SQLITE_IGNORE
+ * for don't allow access but don't raise an error, Constants.SQLITE_DENY
+ * for abort SQL statement with error.
+ */
+
+ public int authorize(int what, String arg1, String arg2, String arg3,
+ String arg4);
+}
+
diff --git a/sqlite-jdbc/src/main/java/SQLite/Blob.java b/sqlite-jdbc/src/main/java/SQLite/Blob.java
new file mode 100644
index 0000000..3de9f8a
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Blob.java
@@ -0,0 +1,323 @@
+package SQLite;
+
+import java.io.*;
+
+/**
+ * Internal class implementing java.io.InputStream on
+ * SQLite 3.4.0 incremental blob I/O interface.
+ */
+
+class BlobR extends InputStream {
+
+ /**
+ * Blob instance
+ */
+
+ private Blob blob;
+
+ /**
+ * Read position, file pointer.
+ */
+
+ private int pos;
+
+ /**
+ * Contruct InputStream from blob instance.
+ */
+
+ BlobR(Blob blob) {
+ this.blob = blob;
+ this.pos = 0;
+ }
+
+ /**
+ * Return number of available bytes for reading.
+ * @return available input bytes
+ */
+
+ public int available() throws IOException {
+ int ret = blob.size - pos;
+ return (ret < 0) ? 0 : ret;
+ }
+
+ /**
+ * Mark method; dummy to satisfy InputStream class.
+ */
+
+ public void mark(int limit) {
+ }
+
+ /**
+ * Reset method; dummy to satisfy InputStream class.
+ */
+
+ public void reset() throws IOException {
+ }
+
+ /**
+ * Mark support; not for this class.
+ * @return always false
+ */
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Close this blob InputStream.
+ */
+
+ public void close() throws IOException {
+ blob.close();
+ blob = null;
+ pos = 0;
+ }
+
+ /**
+ * Skip over blob data.
+ */
+
+ public long skip(long n) throws IOException {
+ long ret = pos + n;
+ if (ret < 0) {
+ ret = 0;
+ pos = 0;
+ } else if (ret > blob.size) {
+ ret = blob.size;
+ pos = blob.size;
+ } else {
+ pos = (int) ret;
+ }
+ return ret;
+ }
+
+ /**
+ * Read single byte from blob.
+ * @return byte read
+ */
+
+ public int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = blob.read(b, 0, pos, b.length);
+ if (n > 0) {
+ pos += n;
+ return b[0];
+ }
+ return -1;
+ }
+
+ /**
+ * Read byte array from blob.
+ * @param b byte array to be filled
+ * @return number of bytes read
+ */
+
+ public int read(byte b[]) throws IOException {
+ int n = blob.read(b, 0, pos, b.length);
+ if (n > 0) {
+ pos += n;
+ return n;
+ }
+ return -1;
+ }
+
+ /**
+ * Read slice of byte array from blob.
+ * @param b byte array to be filled
+ * @param off offset into byte array
+ * @param len length to be read
+ * @return number of bytes read
+ */
+
+ public int read(byte b[], int off, int len) throws IOException {
+ if (off + len > b.length) {
+ len = b.length - off;
+ }
+ if (len < 0) {
+ return -1;
+ }
+ if (len == 0) {
+ return 0;
+ }
+ int n = blob.read(b, off, pos, len);
+ if (n > 0) {
+ pos += n;
+ return n;
+ }
+ return -1;
+ }
+}
+
+/**
+ * Internal class implementing java.io.OutputStream on
+ * SQLite 3.4.0 incremental blob I/O interface.
+ */
+
+class BlobW extends OutputStream {
+
+ /**
+ * Blob instance
+ */
+
+ private Blob blob;
+
+ /**
+ * Read position, file pointer.
+ */
+
+ private int pos;
+
+ /**
+ * Contruct OutputStream from blob instance.
+ */
+
+ BlobW(Blob blob) {
+ this.blob = blob;
+ this.pos = 0;
+ }
+
+ /**
+ * Flush blob; dummy to satisfy OutputStream class.
+ */
+
+ public void flush() throws IOException {
+ }
+
+ /**
+ * Close this blob OutputStream.
+ */
+
+ public void close() throws IOException {
+ blob.close();
+ blob = null;
+ pos = 0;
+ }
+
+ /**
+ * Write blob data.
+ * @param v byte to be written at current position.
+ */
+
+ public void write(int v) throws IOException {
+ byte b[] = new byte[1];
+ b[0] = (byte) v;
+ pos += blob.write(b, 0, pos, 1);
+ }
+
+ /**
+ * Write blob data.
+ * @param b byte array to be written at current position.
+ */
+
+ public void write(byte[] b) throws IOException {
+ if (b != null && b.length > 0) {
+ pos += blob.write(b, 0, pos, b.length);
+ }
+ }
+
+ /**
+ * Write blob data.
+ * @param b byte array to be written.
+ * @param off offset within byte array
+ * @param len length of data to be written
+ */
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (b != null) {
+ if (off + len > b.length) {
+ len = b.length - off;
+ }
+ if (len <= 0) {
+ return;
+ }
+ pos += blob.write(b, off, pos, len);
+ }
+ }
+}
+
+/**
+ * Class to represent SQLite3 3.4.0 incremental blob I/O interface.
+ *
+ * Note, that all native methods of this class are
+ * not synchronized, i.e. it is up to the caller
+ * to ensure that only one thread is in these
+ * methods at any one time.
+ */
+
+public class Blob {
+
+ /**
+ * Internal handle for the SQLite3 blob.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Cached size of blob, setup right after blob
+ * has been opened.
+ */
+
+ protected int size = 0;
+
+ /**
+ * Return InputStream for this blob
+ * @return InputStream
+ */
+
+ public InputStream getInputStream() {
+ return (InputStream) new BlobR(this);
+ }
+
+ /**
+ * Return OutputStream for this blob
+ * @return OutputStream
+ */
+
+ public OutputStream getOutputStream() {
+ return (OutputStream) new BlobW(this);
+ }
+
+ /**
+ * Close blob.
+ */
+
+ public native void close();
+
+ /**
+ * Internal blob write method.
+ * @param b byte array to be written
+ * @param off offset into byte array
+ * @param pos offset into blob
+ * @param len length to be written
+ * @return number of bytes written to blob
+ */
+
+ native int write(byte[] b, int off, int pos, int len) throws IOException;
+
+ /**
+ * Internal blob read method.
+ * @param b byte array to be written
+ * @param off offset into byte array
+ * @param pos offset into blob
+ * @param len length to be written
+ * @return number of bytes written to blob
+ */
+
+ native int read(byte[] b, int off, int pos, int len) throws IOException;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected native void finalize();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/BusyHandler.java b/sqlite-jdbc/src/main/java/SQLite/BusyHandler.java
new file mode 100644
index 0000000..c39b39d
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/BusyHandler.java
@@ -0,0 +1,20 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined busy handler.
+ */
+
+public interface BusyHandler {
+
+ /**
+ * Invoked when a table is locked by another process
+ * or thread. The method should return true for waiting
+ * until the table becomes unlocked, or false in order
+ * to abandon the action.<BR><BR>
+ *
+ * @param table the name of the locked table
+ * @param count number of times the table was locked
+ */
+
+ public boolean busy(String table, int count);
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Callback.java b/sqlite-jdbc/src/main/java/SQLite/Callback.java
new file mode 100644
index 0000000..3eeb605
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Callback.java
@@ -0,0 +1,68 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's query results.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * class TableFmt implements SQLite.Callback {
+ * public void columns(String cols[]) {
+ * System.out.println("&lt;TH&gt;&lt;TR&gt;");
+ * for (int i = 0; i &lt; cols.length; i++) {
+ * System.out.println("&lt;TD&gt;" + cols[i] + "&lt;/TD&gt;");
+ * }
+ * System.out.println("&lt;/TR&gt;&lt;/TH&gt;");
+ * }
+ * public boolean newrow(String cols[]) {
+ * System.out.println("&lt;TR&gt;");
+ * for (int i = 0; i &lt; cols.length; i++) {
+ * System.out.println("&lt;TD&gt;" + cols[i] + "&lt;/TD&gt;");
+ * }
+ * System.out.println("&lt;/TR&gt;");
+ * return false;
+ * }
+ * }
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.println("&lt;TABLE&gt;");
+ * db.exec("select * from TEST", new TableFmt());
+ * System.out.println("&lt;/TABLE&gt;");
+ * ...
+ * </PRE>
+ */
+
+public interface Callback {
+
+ /**
+ * Reports column names of the query result.
+ * This method is invoked first (and once) when
+ * the SQLite engine returns the result set.<BR><BR>
+ *
+ * @param coldata string array holding the column names
+ */
+
+ public void columns(String coldata[]);
+
+ /**
+ * Reports type names of the columns of the query result.
+ * This is available from SQLite 2.6.0 on and needs
+ * the PRAGMA show_datatypes to be turned on.<BR><BR>
+ *
+ * @param types string array holding column types
+ */
+
+ public void types(String types[]);
+
+ /**
+ * Reports row data of the query result.
+ * This method is invoked for each row of the
+ * result set. If true is returned the running
+ * SQLite query is aborted.<BR><BR>
+ *
+ * @param rowdata string array holding the column values of the row
+ */
+
+ public boolean newrow(String rowdata[]);
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Constants.java b/sqlite-jdbc/src/main/java/SQLite/Constants.java
new file mode 100644
index 0000000..4e636b9
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Constants.java
@@ -0,0 +1,157 @@
+/* DO NOT EDIT */
+
+package SQLite;
+
+/**
+ * Container for SQLite constants.
+ */
+
+public final class Constants {
+ /*
+ * Error code: 0
+ */
+ public static final int SQLITE_OK = 0;
+ /*
+ * Error code: 1
+ */
+ public static final int SQLITE_ERROR = 1;
+ /*
+ * Error code: 2
+ */
+ public static final int SQLITE_INTERNAL = 2;
+ /*
+ * Error code: 3
+ */
+ public static final int SQLITE_PERM = 3;
+ /*
+ * Error code: 4
+ */
+ public static final int SQLITE_ABORT = 4;
+ /*
+ * Error code: 5
+ */
+ public static final int SQLITE_BUSY = 5;
+ /*
+ * Error code: 6
+ */
+ public static final int SQLITE_LOCKED = 6;
+ /*
+ * Error code: 7
+ */
+ public static final int SQLITE_NOMEM = 7;
+ /*
+ * Error code: 8
+ */
+ public static final int SQLITE_READONLY = 8;
+ /*
+ * Error code: 9
+ */
+ public static final int SQLITE_INTERRUPT = 9;
+ /*
+ * Error code: 10
+ */
+ public static final int SQLITE_IOERR = 10;
+ /*
+ * Error code: 11
+ */
+ public static final int SQLITE_CORRUPT = 11;
+ /*
+ * Error code: 12
+ */
+ public static final int SQLITE_NOTFOUND = 12;
+ /*
+ * Error code: 13
+ */
+ public static final int SQLITE_FULL = 13;
+ /*
+ * Error code: 14
+ */
+ public static final int SQLITE_CANTOPEN = 14;
+ /*
+ * Error code: 15
+ */
+ public static final int SQLITE_PROTOCOL = 15;
+ /*
+ * Error code: 16
+ */
+ public static final int SQLITE_EMPTY = 16;
+ /*
+ * Error code: 17
+ */
+ public static final int SQLITE_SCHEMA = 17;
+ /*
+ * Error code: 18
+ */
+ public static final int SQLITE_TOOBIG = 18;
+ /*
+ * Error code: 19
+ */
+ public static final int SQLITE_CONSTRAINT = 19;
+ /*
+ * Error code: 20
+ */
+ public static final int SQLITE_MISMATCH = 20;
+ /*
+ * Error code: 21
+ */
+ public static final int SQLITE_MISUSE = 21;
+ /*
+ * Error code: 22
+ */
+ public static final int SQLITE_NOLFS = 22;
+ /*
+ * Error code: 23
+ */
+ public static final int SQLITE_AUTH = 23;
+ /*
+ * Error code: 24
+ */
+ public static final int SQLITE_FORMAT = 24;
+ /*
+ * Error code: 25
+ */
+ public static final int SQLITE_RANGE = 25;
+ /*
+ * Error code: 26
+ */
+ public static final int SQLITE_NOTADB = 26;
+ public static final int SQLITE_ROW = 100;
+ public static final int SQLITE_DONE = 101;
+ public static final int SQLITE_INTEGER = 1;
+ public static final int SQLITE_FLOAT = 2;
+ public static final int SQLITE_BLOB = 4;
+ public static final int SQLITE_NULL = 5;
+ public static final int SQLITE3_TEXT = 3;
+ public static final int SQLITE_NUMERIC = -1;
+ public static final int SQLITE_TEXT = 3;
+ public static final int SQLITE2_TEXT = -2;
+ public static final int SQLITE_ARGS = -3;
+ public static final int SQLITE_COPY = 0;
+ public static final int SQLITE_CREATE_INDEX = 1;
+ public static final int SQLITE_CREATE_TABLE = 2;
+ public static final int SQLITE_CREATE_TEMP_INDEX = 3;
+ public static final int SQLITE_CREATE_TEMP_TABLE = 4;
+ public static final int SQLITE_CREATE_TEMP_TRIGGER = 5;
+ public static final int SQLITE_CREATE_TEMP_VIEW = 6;
+ public static final int SQLITE_CREATE_TRIGGER = 7;
+ public static final int SQLITE_CREATE_VIEW = 8;
+ public static final int SQLITE_DELETE = 9;
+ public static final int SQLITE_DROP_INDEX = 10;
+ public static final int SQLITE_DROP_TABLE = 11;
+ public static final int SQLITE_DROP_TEMP_INDEX = 12;
+ public static final int SQLITE_DROP_TEMP_TABLE = 13;
+ public static final int SQLITE_DROP_TEMP_TRIGGER = 14;
+ public static final int SQLITE_DROP_TEMP_VIEW = 15;
+ public static final int SQLITE_DROP_TRIGGER = 16;
+ public static final int SQLITE_DROP_VIEW = 17;
+ public static final int SQLITE_INSERT = 18;
+ public static final int SQLITE_PRAGMA = 19;
+ public static final int SQLITE_READ = 20;
+ public static final int SQLITE_SELECT = 21;
+ public static final int SQLITE_TRANSACTION = 22;
+ public static final int SQLITE_UPDATE = 23;
+ public static final int SQLITE_ATTACH = 24;
+ public static final int SQLITE_DETACH = 25;
+ public static final int SQLITE_DENY = 1;
+ public static final int SQLITE_IGNORE = 2;
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Database.java b/sqlite-jdbc/src/main/java/SQLite/Database.java
new file mode 100644
index 0000000..fbb5d29
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Database.java
@@ -0,0 +1,615 @@
+package SQLite;
+
+/**
+ * Main class wrapping an SQLite database.
+ */
+
+public class Database {
+
+ /**
+ * Internal handle for the native SQLite API.
+ */
+
+ protected long handle = 0;
+
+ /**
+ * Internal last error code for exec() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Open an SQLite database file.
+ *
+ * @param filename the name of the database file
+ * @param mode open mode, currently ignored
+ */
+
+ public void open(String filename, int mode) throws SQLite.Exception {
+ synchronized(this) {
+ _open(filename, mode);
+ }
+ }
+
+ private native void _open(String filename, int mode)
+ throws SQLite.Exception;
+
+ /**
+ * Open SQLite auxiliary database file for temporary
+ * tables.
+ *
+ * @param filename the name of the auxiliary file or null
+ */
+
+ public void open_aux_file(String filename) throws SQLite.Exception {
+ synchronized(this) {
+ _open_aux_file(filename);
+ }
+ }
+
+ private native void _open_aux_file(String filename)
+ throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected void finalize() {
+ synchronized(this) {
+ _finalize();
+ }
+ }
+
+ private native void _finalize();
+
+ /**
+ * Close the underlying SQLite database file.
+ */
+
+ public void close() throws SQLite.Exception {
+ synchronized(this) {
+ _close();
+ }
+ }
+
+ private native void _close()
+ throws SQLite.Exception;
+
+ /**
+ * Execute an SQL statement and invoke callback methods
+ * for each row of the result set.<P>
+ *
+ * It the method fails, an SQLite.Exception is thrown and
+ * an error code is set, which later can be retrieved by
+ * the last_error() method.
+ *
+ * @param sql the SQL statement to be executed
+ * @param cb the object implementing the callback methods
+ */
+
+ public void exec(String sql, SQLite.Callback cb) throws SQLite.Exception {
+ synchronized(this) {
+ _exec(sql, cb);
+ }
+ }
+
+ private native void _exec(String sql, SQLite.Callback cb)
+ throws SQLite.Exception;
+
+ /**
+ * Execute an SQL statement and invoke callback methods
+ * for each row of the result set. Each '%q' or %Q in the
+ * statement string is substituted by its corresponding
+ * element in the argument vector.
+ * <BR><BR>
+ * Example:<BR>
+ * <PRE>
+ * String args[] = new String[1];
+ * args[0] = "tab%";
+ * db.exec("select * from sqlite_master where type like '%q'",
+ * null, args);
+ * </PRE>
+ *
+ * It the method fails, an SQLite.Exception is thrown and
+ * an error code is set, which later can be retrieved by
+ * the last_error() method.
+ *
+ * @param sql the SQL statement to be executed
+ * @param cb the object implementing the callback methods
+ * @param args arguments for the SQL statement, '%q' substitution
+ */
+
+ public void exec(String sql, SQLite.Callback cb,
+ String args[]) throws SQLite.Exception {
+ synchronized(this) {
+ _exec(sql, cb, args);
+ }
+ }
+
+ private native void _exec(String sql, SQLite.Callback cb, String args[])
+ throws SQLite.Exception;
+
+ /**
+ * Return the row identifier of the last inserted
+ * row.
+ */
+
+ public long last_insert_rowid() {
+ synchronized(this) {
+ return _last_insert_rowid();
+ }
+ }
+
+ private native long _last_insert_rowid();
+
+ /**
+ * Abort the current SQLite operation.
+ */
+
+ public void interrupt() {
+ synchronized(this) {
+ _interrupt();
+ }
+ }
+
+ private native void _interrupt();
+
+ /**
+ * Return the number of changed rows for the last statement.
+ */
+
+ public long changes() {
+ synchronized(this) {
+ return _changes();
+ }
+ }
+
+ private native long _changes();
+
+ /**
+ * Establish a busy callback method which gets called when
+ * an SQLite table is locked.
+ *
+ * @param bh the object implementing the busy callback method
+ */
+
+ public void busy_handler(SQLite.BusyHandler bh) {
+ synchronized(this) {
+ _busy_handler(bh);
+ }
+ }
+
+ private native void _busy_handler(SQLite.BusyHandler bh);
+
+ /**
+ * Set the timeout for waiting for an SQLite table to become
+ * unlocked.
+ *
+ * @param ms number of millisecond to wait
+ */
+
+ public void busy_timeout(int ms) {
+ synchronized(this) {
+ _busy_timeout(ms);
+ }
+ }
+
+ private native void _busy_timeout(int ms);
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @return result set
+ */
+
+ public TableResult get_table(String sql) throws SQLite.Exception {
+ TableResult ret = new TableResult();
+ if (!is3()) {
+ exec(sql, ret);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql);
+ set_last_error(vm.error_code);
+ while (vm.step(ret)) {
+ set_last_error(vm.error_code);
+ }
+ vm.finalize();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @return result set
+ */
+
+ public TableResult get_table(String sql, String args[])
+ throws SQLite.Exception {
+ TableResult ret = new TableResult();
+ if (!is3()) {
+ exec(sql, ret, args);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql, args);
+ set_last_error(vm.error_code);
+ while (vm.step(ret)) {
+ set_last_error(vm.error_code);
+ }
+ vm.finalize();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @param tbl TableResult to receive result set
+ * @return result set
+ */
+
+ public void get_table(String sql, String args[], TableResult tbl)
+ throws SQLite.Exception {
+ tbl.clear();
+ if (!is3()) {
+ exec(sql, tbl, args);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql, args);
+ while (vm.step(tbl)) {
+ }
+ vm.finalize();
+ }
+ }
+ }
+
+ /**
+ * See if an SQL statement is complete.
+ * Returns true if the input string comprises
+ * one or more complete SQL statements.
+ *
+ * @param sql the SQL statement to be checked
+ */
+
+ public synchronized static boolean complete(String sql) {
+ return _complete(sql);
+ }
+
+ private native static boolean _complete(String sql);
+
+ /**
+ * Return SQLite version number as string.
+ * Don't rely on this when both SQLite 2 and 3 are compiled
+ * into the native part. Use the class method in this case.
+ */
+
+ public native static String version();
+
+ /**
+ * Return SQLite version number as string.
+ * If the database is not open, <tt>unknown</tt> is returned.
+ */
+
+ public native String dbversion();
+
+ /**
+ * Create regular function.
+ *
+ * @param name the name of the new function
+ * @param nargs number of arguments to function
+ * @param f interface of function
+ */
+
+ public void create_function(String name, int nargs, Function f) {
+ synchronized(this) {
+ _create_function(name, nargs, f);
+ }
+ }
+
+ private native void _create_function(String name, int nargs, Function f);
+
+ /**
+ * Create aggregate function.
+ *
+ * @param name the name of the new function
+ * @param nargs number of arguments to function
+ * @param f interface of function
+ */
+
+ public void create_aggregate(String name, int nargs, Function f) {
+ synchronized(this) {
+ _create_aggregate(name, nargs, f);
+ }
+ }
+
+ private native void _create_aggregate(String name, int nargs, Function f);
+
+ /**
+ * Set function return type. Only available in SQLite 2.6.0 and
+ * above, otherwise a no-op.
+ *
+ * @param name the name of the function whose return type is to be set
+ * @param type return type code, e.g. SQLite.Constants.SQLITE_NUMERIC
+ */
+
+ public void function_type(String name, int type) {
+ synchronized(this) {
+ _function_type(name, type);
+ }
+ }
+
+ private native void _function_type(String name, int type);
+
+ /**
+ * Return the code of the last error occured in
+ * any of the exec() methods. The value is valid
+ * after an Exception has been reported by one of
+ * these methods. See the <A HREF="Constants.html">Constants</A>
+ * class for possible values.
+ *
+ * @return SQLite error code
+ */
+
+ public int last_error() {
+ return error_code;
+ }
+
+ /**
+ * Internal: set error code.
+ * @param error_code new error code
+ */
+
+ protected void set_last_error(int error_code) {
+ this.error_code = error_code;
+ }
+
+ /**
+ * Return last error message of SQLite3 engine.
+ *
+ * @return error string or null
+ */
+
+ public String error_message() {
+ synchronized(this) {
+ return _errmsg();
+ }
+ }
+
+ private native String _errmsg();
+
+ /**
+ * Return error string given SQLite error code (SQLite2).
+ *
+ * @param error_code the error code
+ * @return error string
+ */
+
+ public static native String error_string(int error_code);
+
+ /**
+ * Set character encoding.
+ * @param enc name of encoding
+ */
+
+ public void set_encoding(String enc) throws SQLite.Exception {
+ synchronized(this) {
+ _set_encoding(enc);
+ }
+ }
+
+ private native void _set_encoding(String enc)
+ throws SQLite.Exception;
+
+ /**
+ * Set authorizer function. Only available in SQLite 2.7.6 and
+ * above, otherwise a no-op.
+ *
+ * @param auth the authorizer function
+ */
+
+ public void set_authorizer(Authorizer auth) {
+ synchronized(this) {
+ _set_authorizer(auth);
+ }
+ }
+
+ private native void _set_authorizer(Authorizer auth);
+
+ /**
+ * Set trace function. Only available in SQLite 2.7.6 and above,
+ * otherwise a no-op.
+ *
+ * @param tr the trace function
+ */
+
+ public void trace(Trace tr) {
+ synchronized(this) {
+ _trace(tr);
+ }
+ }
+
+ private native void _trace(Trace tr);
+
+ /**
+ * Compile and return SQLite VM for SQL statement. Only available
+ * in SQLite 2.8.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be compiled
+ * @return a Vm object
+ */
+
+ public Vm compile(String sql) throws SQLite.Exception {
+ synchronized(this) {
+ Vm vm = new Vm();
+ vm_compile(sql, vm);
+ return vm;
+ }
+ }
+
+ /**
+ * Compile and return SQLite VM for SQL statement. Only available
+ * in SQLite 3.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be compiled
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @return a Vm object
+ */
+
+ public Vm compile(String sql, String args[]) throws SQLite.Exception {
+ synchronized(this) {
+ Vm vm = new Vm();
+ vm_compile_args(sql, vm, args);
+ return vm;
+ }
+ }
+
+ /**
+ * Prepare and return SQLite3 statement for SQL. Only available
+ * in SQLite 3.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be prepared
+ * @return a Stmt object
+ */
+
+ public Stmt prepare(String sql) throws SQLite.Exception {
+ synchronized(this) {
+ Stmt stmt = new Stmt();
+ stmt_prepare(sql, stmt);
+ return stmt;
+ }
+ }
+
+ /**
+ * Open an SQLite3 blob. Only available in SQLite 3.4.0 and above.
+ * @param db database name
+ * @param table table name
+ * @param column column name
+ * @param row row identifier
+ * @param rw if true, open for read-write, else read-only
+ * @return a Blob object
+ */
+
+ public Blob open_blob(String db, String table, String column,
+ long row, boolean rw) throws SQLite.Exception {
+ synchronized(this) {
+ Blob blob = new Blob();
+ _open_blob(db, table, column, row, rw, blob);
+ return blob;
+ }
+ }
+
+ /**
+ * Check type of open database.
+ * @return true if SQLite3 database
+ */
+
+ public native boolean is3();
+
+ /**
+ * Internal compile method.
+ * @param sql SQL statement
+ * @param vm Vm object
+ */
+
+ private native void vm_compile(String sql, Vm vm)
+ throws SQLite.Exception;
+
+ /**
+ * Internal compile method, SQLite 3.0 only.
+ * @param sql SQL statement
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @param vm Vm object
+ */
+
+ private native void vm_compile_args(String sql, Vm vm, String args[])
+ throws SQLite.Exception;
+
+ /**
+ * Internal SQLite3 prepare method.
+ * @param sql SQL statement
+ * @param stmt Stmt object
+ */
+
+ private native void stmt_prepare(String sql, Stmt stmt)
+ throws SQLite.Exception;
+
+ /**
+ * Internal SQLite open blob method.
+ * @param db database name
+ * @param table table name
+ * @param column column name
+ * @param row row identifier
+ * @param rw if true, open for read-write, else read-only
+ * @param blob Blob object
+ */
+
+ private native void _open_blob(String db, String table, String column,
+ long row, boolean rw, Blob blob)
+ throws SQLite.Exception;
+
+ /**
+ * Establish a progress callback method which gets called after
+ * N SQLite VM opcodes.
+ *
+ * @param n number of SQLite VM opcodes until callback is invoked
+ * @param p the object implementing the progress callback method
+ */
+
+ public void progress_handler(int n, SQLite.ProgressHandler p) {
+ synchronized(this) {
+ _progress_handler(n, p);
+ }
+ }
+
+ private native void _progress_handler(int n, SQLite.ProgressHandler p);
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ /**
+ * Static initializer to load the native part.
+ */
+
+ static {
+ try {
+ String path = System.getProperty("SQLite.library.path");
+ if (path == null || path.length() == 0){
+ System.loadLibrary("sqlite_jni");
+ } else {
+ try {
+ java.lang.reflect.Method mapLibraryName;
+ Class param[] = new Class[1];
+ param[0] = String.class;
+ mapLibraryName = System.class.getMethod("mapLibraryName",
+ param);
+ Object args[] = new Object[1];
+ args[0] = "sqlite_jni";
+ String mapped = (String) mapLibraryName.invoke(null, args);
+ System.load(path + java.io.File.separator + mapped);
+ } catch (Throwable t) {
+ System.loadLibrary("sqlite_jni");
+ }
+ }
+ internal_init();
+ } catch (Throwable t) {
+ System.err.println("Unable to load sqlite: " + t);
+ }
+ }
+}
+
diff --git a/sqlite-jdbc/src/main/java/SQLite/Exception.java b/sqlite-jdbc/src/main/java/SQLite/Exception.java
new file mode 100644
index 0000000..cc26b99
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Exception.java
@@ -0,0 +1,18 @@
+package SQLite;
+
+/**
+ * Class for SQLite related exceptions.
+ */
+
+public class Exception extends java.lang.Exception {
+
+ /**
+ * Construct a new SQLite exception.
+ *
+ * @param string error message
+ */
+
+ public Exception(String string) {
+ super(string);
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Function.java b/sqlite-jdbc/src/main/java/SQLite/Function.java
new file mode 100644
index 0000000..5aa5e33
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Function.java
@@ -0,0 +1,59 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined functions.
+ * Each callback method receives a
+ * <A HREF="FunctionContext.html">FunctionContext</A> object
+ * which is used to set the function result or error code.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * class SinFunc implements SQLite.Function {
+ * public void function(SQLite.FunctionContext fc, String args[]) {
+ * try {
+ * Double d = new Double(args[0]);
+ * fc.set_result(Math.sin(d.doubleValue()));
+ * } catch (Exception e) {
+ * fc.set_error("sin(" + args[0] + "):" + e);
+ * }
+ * }
+ * ...
+ * }
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * db.create_function("sin", 1, SinFunc);
+ * ...
+ * db.exec("select sin(1.0) from test", null);
+ * </PRE>
+ */
+
+public interface Function {
+
+ /**
+ * Callback for regular function.
+ *
+ * @param fc function's context for reporting result
+ * @param args String array of arguments
+ */
+
+ public void function(FunctionContext fc, String args[]);
+
+ /**
+ * Callback for one step in aggregate function.
+ *
+ * @param fc function's context for reporting result
+ * @param args String array of arguments
+ */
+
+ public void step(FunctionContext fc, String args[]);
+
+ /**
+ * Callback for final step in aggregate function.
+ *
+ * @param fc function's context for reporting result
+ */
+
+ public void last_step(FunctionContext fc);
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java b/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java
new file mode 100644
index 0000000..d0b5182
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java
@@ -0,0 +1,82 @@
+package SQLite;
+
+/**
+ * Context for execution of SQLite's user defined functions.
+ * A reference to an instance of this class is passed to
+ * user defined functions.
+ */
+
+public class FunctionContext {
+
+ /**
+ * Internal handle for the native SQLite API.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Set function result from string.
+ *
+ * @param r result string
+ */
+
+ public native void set_result(String r);
+
+ /**
+ * Set function result from integer.
+ *
+ * @param r result integer
+ */
+
+ public native void set_result(int r);
+
+ /**
+ * Set function result from double.
+ *
+ * @param r result double
+ */
+
+ public native void set_result(double r);
+
+ /**
+ * Set function result from error message.
+ *
+ * @param r result string (error message)
+ */
+
+ public native void set_error(String r);
+
+ /**
+ * Set function result from byte array.
+ * Only provided by SQLite3 databases.
+ *
+ * @param r result byte array
+ */
+
+ public native void set_result(byte[] r);
+
+ /**
+ * Set function result as empty blob given size.
+ * Only provided by SQLite3 databases.
+ *
+ * @param n size for empty blob
+ */
+
+ public native void set_result_zeroblob(int n);
+
+ /**
+ * Retrieve number of rows for aggregate function.
+ */
+
+ public native int count();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java
new file mode 100644
index 0000000..20c98e3
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java
@@ -0,0 +1,452 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCConnection
+ implements java.sql.Connection, SQLite.BusyHandler {
+
+ /**
+ * Open database.
+ */
+ protected DatabaseX db;
+
+ /**
+ * Database URL.
+ */
+ protected String url;
+
+ /**
+ * Character encoding.
+ */
+ protected String enc;
+
+ /**
+ * Autocommit flag, true means autocommit.
+ */
+ protected boolean autocommit = true;
+
+ /**
+ * In-transaction flag.
+ * Can be true only when autocommit false.
+ */
+ protected boolean intrans = false;
+
+ /**
+ * Timeout for Database.exec()
+ */
+ protected int timeout = 1000000;
+
+ /**
+ * File name of database.
+ */
+ private String dbfile = null;
+
+ /**
+ * Reference to meta data or null.
+ */
+ private JDBCDatabaseMetaData meta = null;
+
+ /**
+ * Base time value for timeout handling.
+ */
+ private long t0;
+
+ /**
+ * Database in readonly mode.
+ */
+ private boolean readonly = false;
+
+
+ private boolean busy0(DatabaseX db, int count) {
+ if (count <= 1) {
+ t0 = System.currentTimeMillis();
+ }
+ if (db != null) {
+ long t1 = System.currentTimeMillis();
+ if (t1 - t0 > timeout) {
+ return false;
+ }
+ db.wait(100);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean busy(String table, int count) {
+ return busy0(db, count);
+ }
+
+ protected boolean busy3(DatabaseX db, int count) {
+ if (count <= 1) {
+ t0 = System.currentTimeMillis();
+ }
+ if (db != null) {
+ long t1 = System.currentTimeMillis();
+ if (t1 - t0 > timeout) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private DatabaseX open(boolean readonly) throws SQLException {
+ DatabaseX db = null;
+ try {
+ db = new DatabaseX();
+ db.open(dbfile, readonly ? 0444 : 0644);
+ db.set_encoding(enc);
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ int loop = 0;
+ while (true) {
+ try {
+ db.exec("PRAGMA short_column_names = off;", null);
+ db.exec("PRAGMA full_column_names = on;", null);
+ db.exec("PRAGMA empty_result_callbacks = on;", null);
+ if (SQLite.Database.version().compareTo("2.6.0") >= 0) {
+ db.exec("PRAGMA show_datatypes = on;", null);
+ }
+ } catch (SQLite.Exception e) {
+ if (db.last_error() != SQLite.Constants.SQLITE_BUSY ||
+ !busy0(db, ++loop)) {
+ try {
+ db.close();
+ } catch (SQLite.Exception ee) {
+ }
+ throw new SQLException(e.toString());
+ }
+ continue;
+ }
+ break;
+ }
+ return db;
+ }
+
+ public JDBCConnection(String url, String enc) throws SQLException {
+ if (url.startsWith("sqlite:/")) {
+ dbfile = url.substring(8);
+ } else if (url.startsWith("jdbc:sqlite:/")) {
+ dbfile = url.substring(13);
+ } else {
+ throw new SQLException("unsupported url");
+ }
+ this.url = url;
+ this.enc = enc;
+ try {
+ db = open(readonly);
+ db.busy_handler(this);
+ } catch (SQLException e) {
+ if (db != null) {
+ try {
+ db.close();
+ } catch (SQLite.Exception ee) {
+ }
+ }
+ throw e;
+ }
+ }
+
+ /* non-standard */
+ public SQLite.Database getSQLiteDatabase() {
+ return (SQLite.Database) db;
+ }
+
+ public Statement createStatement() {
+ JDBCStatement s = new JDBCStatement(this);
+ return s;
+ }
+
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency)
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(this);
+ return s;
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ if (meta == null) {
+ meta = new JDBCDatabaseMetaData(this);
+ }
+ return meta;
+ }
+
+ public void close() throws SQLException {
+ try {
+ rollback();
+ } catch (SQLException e) {
+ /* ignored */
+ }
+ intrans = false;
+ if (db != null) {
+ try {
+ db.close();
+ db = null;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+ }
+
+ public boolean isClosed() throws SQLException {
+ return db == null;
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return readonly;
+ }
+
+ public void clearWarnings() throws SQLException {
+ }
+
+ public void commit() throws SQLException {
+ if (db == null) {
+ throw new SQLException("stale connection");
+ }
+ if (!intrans) {
+ return;
+ }
+ try {
+ db.exec("COMMIT", null);
+ intrans = false;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return autocommit;
+ }
+
+ public String getCatalog() throws SQLException {
+ return null;
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return TRANSACTION_SERIALIZABLE;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public CallableStatement prepareCall(String sql, int x, int y)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
+ return s;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency)
+ throws SQLException {
+ JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
+ return s;
+ }
+
+ public void rollback() throws SQLException {
+ if (db == null) {
+ throw new SQLException("stale connection");
+ }
+ if (!intrans) {
+ return;
+ }
+ try {
+ db.exec("ROLLBACK", null);
+ intrans = false;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+
+ public void setAutoCommit(boolean ac) throws SQLException {
+ if (ac && intrans && db != null) {
+ try {
+ db.exec("ROLLBACK", null);
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+ intrans = false;
+ autocommit = ac;
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ }
+
+ public void setReadOnly(boolean ro) throws SQLException {
+ if (intrans) {
+ throw new SQLException("incomplete transaction");
+ }
+ if (ro != readonly) {
+ DatabaseX db = null;
+ try {
+ db = open(ro);
+ this.db.close();
+ this.db = db;
+ db = null;
+ readonly = ro;
+ } catch (SQLException e) {
+ throw e;
+ } catch (SQLite.Exception ee) {
+ if (db != null) {
+ try {
+ db.close();
+ } catch (SQLite.Exception eee) {
+ }
+ }
+ throw new SQLException(ee.toString());
+ }
+ }
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ if (level != TRANSACTION_SERIALIZABLE) {
+ throw new SQLException("not supported");
+ }
+ }
+
+ public java.util.Map<String, Class<?>> getTypeMap() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTypeMap(java.util.Map map) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+ public void setHoldability(int holdability) throws SQLException {
+ if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ return;
+ }
+ throw new SQLException("not supported");
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void rollback(Savepoint x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void releaseSavepoint(Savepoint x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability)
+ throws SQLException {
+ if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ throw new SQLException("not supported");
+ }
+ return createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability)
+ throws SQLException {
+ if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ throw new SQLException("not supported");
+ }
+ return prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public CallableStatement prepareCall(String sql, int x, int y, int z)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return prepareStatement(sql);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql, String columns[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
+
+class DatabaseX extends SQLite.Database {
+
+ static Object lock = new Object();
+
+ public DatabaseX() {
+ super();
+ }
+
+ void wait(int ms) {
+ try {
+ synchronized (lock) {
+ lock.wait(ms);
+ }
+ } catch (java.lang.Exception e) {
+ }
+ }
+
+ public void exec(String sql, SQLite.Callback cb)
+ throws SQLite.Exception {
+ super.exec(sql, cb);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+ public void exec(String sql, SQLite.Callback cb, String args[])
+ throws SQLite.Exception {
+ super.exec(sql, cb, args);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+ public SQLite.TableResult get_table(String sql, String args[])
+ throws SQLite.Exception {
+ SQLite.TableResult ret = super.get_table(sql, args);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ return ret;
+ }
+
+ public void get_table(String sql, String args[], SQLite.TableResult tbl)
+ throws SQLite.Exception {
+ super.get_table(sql, args, tbl);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
new file mode 100644
index 0000000..8c14d1d
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
@@ -0,0 +1,1578 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.Hashtable;
+
+public class JDBCDatabaseMetaData implements DatabaseMetaData {
+
+ private JDBCConnection conn;
+
+ public JDBCDatabaseMetaData(JDBCConnection conn) {
+ this.conn = conn;
+ }
+
+ public boolean allProceduresAreCallable() throws SQLException {
+ return false;
+ }
+
+ public boolean allTablesAreSelectable() throws SQLException {
+ return true;
+ }
+
+ public String getURL() throws SQLException {
+ return conn.url;
+ }
+
+ public String getUserName() throws SQLException {
+ return "";
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedHigh() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedLow() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedAtStart() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedAtEnd() throws SQLException {
+ return false;
+ }
+
+ public String getDatabaseProductName() throws SQLException {
+ return "SQLite";
+ }
+
+ public String getDatabaseProductVersion() throws SQLException {
+ return SQLite.Database.version();
+ }
+
+ public String getDriverName() throws SQLException {
+ return "SQLite/JDBC";
+ }
+
+ public String getDriverVersion() throws SQLException {
+ return "" + SQLite.JDBCDriver.MAJORVERSION + "." +
+ SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public int getDriverMajorVersion() {
+ return SQLite.JDBCDriver.MAJORVERSION;
+ }
+
+ public int getDriverMinorVersion() {
+ return SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public boolean usesLocalFiles() throws SQLException {
+ return true;
+ }
+
+ public boolean usesLocalFilePerTable() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMixedCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesUpperCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesLowerCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesMixedCaseIdentifiers() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
+ return true;
+ }
+
+ public String getIdentifierQuoteString() throws SQLException {
+ return "\"";
+ }
+
+ public String getSQLKeywords() throws SQLException {
+ return "SELECT,UPDATE,CREATE,TABLE,VIEW,DELETE,FROM,WHERE" +
+ ",COMMIT,ROLLBACK,TRIGGER";
+ }
+
+ public String getNumericFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getStringFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getSystemFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getTimeDateFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getSearchStringEscape() throws SQLException {
+ return "\\";
+ }
+
+ public String getExtraNameCharacters() throws SQLException {
+ return "";
+ }
+
+ public boolean supportsAlterTableWithAddColumn() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsAlterTableWithDropColumn() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsColumnAliasing() throws SQLException {
+ return true;
+ }
+
+ public boolean nullPlusNonNullIsNull() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsConvert() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsConvert(int fromType, int toType)
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsTableCorrelationNames() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsDifferentTableCorrelationNames()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsExpressionsInOrderBy() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsOrderByUnrelated() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupBy() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupByUnrelated() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupByBeyondSelect() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsLikeEscapeClause() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMultipleResultSets() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMultipleTransactions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsNonNullableColumns() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsMinimumSQLGrammar() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsCoreSQLGrammar() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsExtendedSQLGrammar() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsANSI92IntermediateSQL() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsANSI92FullSQL() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsIntegrityEnhancementFacility()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsFullOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsLimitedOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public String getSchemaTerm() throws SQLException {
+ return "";
+ }
+
+ public String getProcedureTerm() throws SQLException {
+ return "";
+ }
+
+ public String getCatalogTerm() throws SQLException {
+ return "";
+ }
+
+ public boolean isCatalogAtStart() throws SQLException {
+ return false;
+ }
+
+ public String getCatalogSeparator() throws SQLException {
+ return "";
+ }
+
+ public boolean supportsSchemasInDataManipulation() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInProcedureCalls() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInTableDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInPrivilegeDefinitions()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInDataManipulation() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInPrivilegeDefinitions()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsPositionedDelete() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsPositionedUpdate() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSelectForUpdate() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsStoredProcedures() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSubqueriesInComparisons() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInExists() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInIns() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCorrelatedSubqueries() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsUnion() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsUnionAll() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
+ return false;
+ }
+
+ public int getMaxBinaryLiteralLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCharLiteralLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInGroupBy() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInIndex() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInOrderBy() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInSelect() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInTable() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxConnections() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCursorNameLength() throws SQLException {
+ return 8;
+ }
+
+ public int getMaxIndexLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxSchemaNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxProcedureNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCatalogNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxRowSize() throws SQLException {
+ return 0;
+ }
+
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
+ return true;
+ }
+
+ public int getMaxStatementLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxStatements() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxTableNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxTablesInSelect() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxUserNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getDefaultTransactionIsolation() throws SQLException {
+ return Connection.TRANSACTION_SERIALIZABLE;
+ }
+
+ public boolean supportsTransactions() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsTransactionIsolationLevel(int level)
+ throws SQLException {
+ return level == Connection.TRANSACTION_SERIALIZABLE;
+ }
+
+ public boolean supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException {
+ return true;
+ }
+
+ public boolean supportsDataManipulationTransactionsOnly()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean dataDefinitionCausesTransactionCommit()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
+ return false;
+ }
+
+ public ResultSet getProcedures(String catalog, String schemaPattern,
+ String procedureNamePattern)
+ throws SQLException {
+ return null;
+ }
+
+ public ResultSet getProcedureColumns(String catalog,
+ String schemaPattern,
+ String procedureNamePattern,
+ String columnNamePattern)
+ throws SQLException {
+ return null;
+ }
+
+ public ResultSet getTables(String catalog, String schemaPattern,
+ String tableNamePattern, String types[])
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(conn);
+ StringBuffer sb = new StringBuffer();
+ sb.append("SELECT '' AS 'TABLE_CAT', " +
+ "'' AS 'TABLE_SCHEM', " +
+ "tbl_name AS 'TABLE_NAME', " +
+ "upper(type) AS 'TABLE_TYPE', " +
+ "'' AS REMARKS FROM sqlite_master " +
+ "WHERE tbl_name like ");
+ if (tableNamePattern != null) {
+ sb.append(SQLite.Shell.sql_quote(tableNamePattern));
+ } else {
+ sb.append("'%'");
+ }
+ sb.append(" AND ");
+ if (types == null || types.length == 0) {
+ sb.append("(type = 'table' or type = 'view')");
+ } else {
+ sb.append("(");
+ String sep = "";
+ for (int i = 0; i < types.length; i++) {
+ sb.append(sep);
+ sb.append("type = ");
+ sb.append(SQLite.Shell.sql_quote(types[i].toLowerCase()));
+ sep = " or ";
+ }
+ sb.append(")");
+ }
+ ResultSet rs = null;
+ try {
+ rs = s.executeQuery(sb.toString());
+ s.close();
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s.close();
+ }
+ return rs;
+ }
+
+ public ResultSet getSchemas() throws SQLException {
+ String cols[] = { "TABLE_SCHEM" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = { "" };
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getCatalogs() throws SQLException {
+ String cols[] = { "TABLE_CAT" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = { "" };
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getTableTypes() throws SQLException {
+ String cols[] = { "TABLE_TYPE" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = new String[1];
+ row[0] = "TABLE";
+ tr.newrow(row);
+ row = new String[1];
+ row[0] = "VIEW";
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getColumns(String catalog, String schemaPattern,
+ String tableNamePattern,
+ String columnNamePattern)
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(tableNamePattern) +
+ ")"));
+ s.close();
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME",
+ "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_POINTS",
+ "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
+ "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
+ "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT, Types.VARCHAR,
+ Types.INTEGER, Types.INTEGER, Types.INTEGER,
+ Types.INTEGER, Types.INTEGER, Types.VARCHAR,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.INTEGER, Types.INTEGER, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h.put(rs0.tr.column[i], new Integer(i));
+ }
+ if (columnNamePattern != null &&
+ columnNamePattern.charAt(0) == '%') {
+ columnNamePattern = null;
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h.get("name")).intValue();
+ if (columnNamePattern != null) {
+ if (r0[col].compareTo(columnNamePattern) != 0) {
+ continue;
+ }
+ }
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = tableNamePattern;
+ row[3] = r0[col];
+ col = ((Integer) h.get("type")).intValue();
+ String typeStr = r0[col];
+ int type = mapSqlType(typeStr);
+ row[4] = "" + type;
+ row[5] = mapTypeName(type);
+ row[6] = "" + getD(typeStr, type);
+ row[7] = "" + getM(typeStr, type);
+ row[8] = "10";
+ row[9] = "0";
+ row[11] = null;
+ col = ((Integer) h.get("dflt_value")).intValue();
+ row[12] = r0[col];
+ row[13] = "0";
+ row[14] = "0";
+ row[15] = "65536";
+ col = ((Integer) h.get("cid")).intValue();
+ Integer cid = new Integer(r0[col]);
+ row[16] = "" + (cid.intValue() + 1);
+ col = ((Integer) h.get("notnull")).intValue();
+ row[17] = (r0[col].charAt(0) == '0') ? "YES" : "NO";
+ row[10] = (r0[col].charAt(0) == '0') ? "" + columnNullable :
+ "" + columnNoNulls;
+ tr.newrow(row);
+ }
+ }
+ return rs;
+ }
+
+ public ResultSet getColumnPrivileges(String catalog, String schema,
+ String table,
+ String columnNamePattern)
+ throws SQLException {
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "GRANTOR", "GRANTEE",
+ "PRIVILEGE", "IS_GRANTABLE"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern,
+ String tableNamePattern)
+ throws SQLException {
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "GRANTOR", "GRANTEE",
+ "PRIVILEGE", "IS_GRANTABLE"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getBestRowIdentifier(String catalog, String schema,
+ String table, int scope,
+ boolean nullable)
+ throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ s1.close();
+ }
+ String cols[] = {
+ "SCOPE", "COLUMN_NAME", "DATA_TYPE",
+ "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "PSEUDO_COLUMN"
+ };
+ int types[] = {
+ Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.SMALLINT, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0 &&
+ rs1 != null && rs1.tr != null && rs1.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ Hashtable<String, Integer> h1 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs1.tr.ncolumns; i++) {
+ h1.put(rs1.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s2 = new JDBCStatement(conn);
+ JDBCResultSet rs2 = null;
+ try {
+ rs2 = (JDBCResultSet)
+ (s2.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s2.close();
+ }
+ if (rs2 == null || rs2.tr == null || rs2.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h2 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs2.tr.ncolumns; k++) {
+ h2.put(rs2.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs2.tr.nrows; k++) {
+ String r2[] = (String [])(rs2.tr.rows.elementAt(k));
+ col = ((Integer) h2.get("name")).intValue();
+ String cname = r2[col];
+ for (int m = 0; m < rs1.tr.nrows; m++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(m));
+ col = ((Integer) h1.get("name")).intValue();
+ if (cname.compareTo(r1[col]) == 0) {
+ String row[] = new String[cols.length];
+ row[0] = "" + scope;
+ row[1] = cname;
+ row[2] = "" + Types.VARCHAR;
+ row[3] = "VARCHAR";
+ row[4] = "65536";
+ row[5] = "0";
+ row[6] = "0";
+ row[7] = "" + bestRowNotPseudo;
+ tr.newrow(row);
+ }
+ }
+ }
+ }
+ }
+ if (tr.nrows <= 0) {
+ String row[] = new String[cols.length];
+ row[0] = "" + scope;
+ row[1] = "_ROWID_";
+ row[2] = "" + Types.INTEGER;
+ row[3] = "INTEGER";
+ row[4] = "10";
+ row[5] = "0";
+ row[6] = "0";
+ row[7] = "" + bestRowPseudo;
+ tr.newrow(row);
+ }
+ return rs;
+ }
+
+ public ResultSet getVersionColumns(String catalog, String schema,
+ String table) throws SQLException {
+ String cols[] = {
+ "SCOPE", "COLUMN_NAME", "DATA_TYPE",
+ "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "PSEUDO_COLUMN"
+ };
+ int types[] = {
+ Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.SMALLINT, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getPrimaryKeys(String catalog, String schema,
+ String table) throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "KEY_SEQ", "PK_NAME"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s1.close();
+ }
+ if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h1 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs1.tr.ncolumns; k++) {
+ h1.put(rs1.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs1.tr.nrows; k++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(k));
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ col = ((Integer) h1.get("name")).intValue();
+ row[3] = r1[col];
+ col = ((Integer) h1.get("seqno")).intValue();
+// BEGIN android-changed
+ row[4] = "" + (Integer.parseInt(r1[col]) + 1);
+// END android-changed
+ row[5] = iname;
+ tr.newrow(row);
+ }
+ }
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ try {
+ rs0 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s1.close();
+ }
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("type")).intValue();
+ String type = r0[col];
+ if (!type.equalsIgnoreCase("integer")) {
+ continue;
+ }
+ col = ((Integer) h0.get("pk")).intValue();
+ String pk = r0[col];
+ if (pk.charAt(0) == '0') {
+ continue;
+ }
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ col = ((Integer) h0.get("name")).intValue();
+ row[3] = r0[col];
+ col = ((Integer) h0.get("cid")).intValue();
+// BEGIN android-changed
+ row[4] = "" + (Integer.parseInt(r0[col]) + 1);
+// END android-changed
+ row[5] = "";
+ tr.newrow(row);
+ }
+ }
+ return rs;
+ }
+
+ private void internalImportedKeys(String table, String pktable,
+ JDBCResultSet in, TableResultX out) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < in.tr.ncolumns; i++) {
+ h0.put(in.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < in.tr.nrows; i++) {
+ String r0[] = (String [])(in.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("table")).intValue();
+ String pktab = r0[col];
+ if (pktable != null && !pktable.equalsIgnoreCase(pktab)) {
+ continue;
+ }
+ col = ((Integer) h0.get("from")).intValue();
+ String pkcol = r0[col];
+ col = ((Integer) h0.get("to")).intValue();
+ String fkcol = r0[col];
+ col = ((Integer) h0.get("seq")).intValue();
+ String seq = r0[col];
+ String row[] = new String[out.ncolumns];
+ row[0] = "";
+ row[1] = "";
+ row[2] = pktab;
+ row[3] = pkcol;
+ row[4] = "";
+ row[5] = "";
+ row[6] = table;
+ row[7] = fkcol == null ? pkcol : fkcol;
+// BEGIN android-changed
+ row[8] = "" + ((Integer.parseInt(seq)) + 1);
+// END android-changed
+ row[9] =
+ "" + java.sql.DatabaseMetaData.importedKeyNoAction;
+ row[10] =
+ "" + java.sql.DatabaseMetaData.importedKeyNoAction;
+ row[11] = null;
+ row[12] = null;
+ row[13] =
+ "" + java.sql.DatabaseMetaData.importedKeyNotDeferrable;
+ out.newrow(row);
+ }
+ }
+
+ public ResultSet getImportedKeys(String catalog, String schema,
+ String table) throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA foreign_key_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
+ "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
+ "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
+ "PK_NAME", "DEFERRABILITY"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ internalImportedKeys(table, null, rs0, tr);
+ }
+ return rs;
+ }
+
+ public ResultSet getExportedKeys(String catalog, String schema,
+ String table) throws SQLException {
+ String cols[] = {
+ "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
+ "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
+ "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
+ "PK_NAME", "DEFERRABILITY"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return rs;
+ }
+
+ public ResultSet getCrossReference(String primaryCatalog,
+ String primarySchema,
+ String primaryTable,
+ String foreignCatalog,
+ String foreignSchema,
+ String foreignTable)
+ throws SQLException {
+ JDBCResultSet rs0 = null;
+ if (foreignTable != null && foreignTable.charAt(0) != '%') {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA foreign_key_list(" +
+ SQLite.Shell.sql_quote(foreignTable) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ }
+ String cols[] = {
+ "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
+ "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
+ "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
+ "PK_NAME", "DEFERRABILITY"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ String pktable = null;
+ if (primaryTable != null && primaryTable.charAt(0) != '%') {
+ pktable = primaryTable;
+ }
+ internalImportedKeys(foreignTable, pktable, rs0, tr);
+ }
+ return rs;
+ }
+
+ public ResultSet getTypeInfo() throws SQLException {
+ String cols[] = {
+ "TYPE_NAME", "DATA_TYPE", "PRECISION",
+ "LITERAL_PREFIX", "LITERAL_SUFFIX", "CREATE_PARAMS",
+ "NULLABLE", "CASE_SENSITIVE", "SEARCHABLE",
+ "UNSIGNED_ATTRIBUTE", "FIXED_PREC_SCALE", "AUTO_INCREMENT",
+ "LOCAL_TYPE_NAME", "MINIMUM_SCALE", "MAXIMUM_SCALE",
+ "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "NUM_PREC_RADIX"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.SMALLINT, Types.INTEGER,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.SMALLINT, Types.BIT, Types.SMALLINT,
+ Types.BIT, Types.BIT, Types.BIT,
+ Types.VARCHAR, Types.SMALLINT, Types.SMALLINT,
+ Types.INTEGER, Types.INTEGER, Types.INTEGER
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ String row1[] = {
+ "VARCHAR", "" + Types.VARCHAR, "65536",
+ "'", "'", null,
+ "" + typeNullable, "1", "" + typeSearchable,
+ "0", "0", "0",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row1);
+ String row2[] = {
+ "INTEGER", "" + Types.INTEGER, "32",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row2);
+ String row3[] = {
+ "DOUBLE", "" + Types.DOUBLE, "16",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "10"
+ };
+ tr.newrow(row3);
+ String row4[] = {
+ "FLOAT", "" + Types.FLOAT, "7",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "10"
+ };
+ tr.newrow(row4);
+ String row5[] = {
+ "SMALLINT", "" + Types.SMALLINT, "16",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row5);
+ String row6[] = {
+ "BIT", "" + Types.BIT, "1",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row6);
+ String row7[] = {
+ "TIMESTAMP", "" + Types.TIMESTAMP, "30",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row7);
+ String row8[] = {
+ "DATE", "" + Types.DATE, "10",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row8);
+ String row9[] = {
+ "TIME", "" + Types.TIME, "8",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row9);
+ String row10[] = {
+ "BINARY", "" + Types.BINARY, "65536",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row10);
+ String row11[] = {
+ "VARBINARY", "" + Types.VARBINARY, "65536",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row11);
+ return rs;
+ }
+
+ public ResultSet getIndexInfo(String catalog, String schema, String table,
+ boolean unique, boolean approximate)
+ throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME",
+ "TYPE", "ORDINAL_POSITION", "COLUMN_NAME",
+ "ASC_OR_DESC", "CARDINALITY", "PAGES",
+ "FILTER_CONDITION"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.BIT, Types.VARCHAR, Types.VARCHAR,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (unique && uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s1.close();
+ }
+ if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h1 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs1.tr.ncolumns; k++) {
+ h1.put(rs1.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs1.tr.nrows; k++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(k));
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ row[3] = (uniq.charAt(0) != '0' ||
+ (iname.charAt(0) == '(' &&
+ iname.indexOf(" autoindex ") > 0)) ? "0" : "1";
+ row[4] = "";
+ row[5] = iname;
+ row[6] = "" + tableIndexOther;
+ col = ((Integer) h1.get("seqno")).intValue();
+// BEGIN android-changed
+ row[7] = "" + (Integer.parseInt(r1[col]) + 1);
+// END android-changed
+ col = ((Integer) h1.get("name")).intValue();
+ row[8] = r1[col];
+ row[9] = "A";
+ row[10] = "0";
+ row[11] = "0";
+ row[12] = null;
+ tr.newrow(row);
+ }
+ }
+ }
+ return rs;
+ }
+
+ public boolean supportsResultSetType(int type) throws SQLException {
+ return type == ResultSet.CONCUR_READ_ONLY;
+ }
+
+ public boolean supportsResultSetConcurrency(int type, int concurrency)
+ throws SQLException {
+ return false;
+ }
+
+ public boolean ownUpdatesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean ownDeletesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean ownInsertsAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersUpdatesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersDeletesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersInsertsAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean updatesAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean deletesAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean insertsAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean supportsBatchUpdates() throws SQLException {
+ return false;
+ }
+
+ public ResultSet getUDTs(String catalog, String schemaPattern,
+ String typeNamePattern, int[] types)
+ throws SQLException {
+ return null;
+ }
+
+ public Connection getConnection() throws SQLException {
+ return conn;
+ }
+
+ static String mapTypeName(int type) {
+ switch (type) {
+ case Types.INTEGER: return "integer";
+ case Types.SMALLINT: return "smallint";
+ case Types.FLOAT: return "float";
+ case Types.DOUBLE: return "double";
+ case Types.TIMESTAMP: return "timestamp";
+ case Types.DATE: return "date";
+ case Types.TIME: return "time";
+ case Types.BINARY: return "binary";
+ case Types.VARBINARY: return "varbinary";
+ }
+ return "varchar";
+ }
+
+ static int mapSqlType(String type) {
+ if (type == null) {
+ return Types.VARCHAR;
+ }
+ type = type.toLowerCase();
+ if (type.startsWith("inter")) {
+ return Types.VARCHAR;
+ }
+ if (type.startsWith("numeric") ||
+ type.startsWith("int")) {
+ return Types.INTEGER;
+ }
+ if (type.startsWith("tinyint") ||
+ type.startsWith("smallint")) {
+ return Types.SMALLINT;
+ }
+ if (type.startsWith("float")) {
+ return Types.FLOAT;
+ }
+ if (type.startsWith("double")) {
+ return Types.DOUBLE;
+ }
+ if (type.startsWith("datetime") ||
+ type.startsWith("timestamp")) {
+ return Types.TIMESTAMP;
+ }
+ if (type.startsWith("date")) {
+ return Types.DATE;
+ }
+ if (type.startsWith("time")) {
+ return Types.TIME;
+ }
+ if (type.startsWith("blob")) {
+ return Types.BINARY;
+ }
+ if (type.startsWith("binary")) {
+ return Types.BINARY;
+ }
+ if (type.startsWith("varbinary")) {
+ return Types.VARBINARY;
+ }
+ return Types.VARCHAR;
+ }
+
+ static int getM(String typeStr, int type) {
+ int m = 65536;
+ switch (type) {
+ case Types.INTEGER: m = 11; break;
+ case Types.SMALLINT: m = 6; break;
+ case Types.FLOAT: m = 25; break;
+ case Types.DOUBLE: m = 54; break;
+ case Types.TIMESTAMP: return 30;
+ case Types.DATE: return 10;
+ case Types.TIME: return 8;
+ }
+ typeStr = typeStr.toLowerCase();
+ int i1 = typeStr.indexOf('(');
+ if (i1 > 0) {
+ ++i1;
+ int i2 = typeStr.indexOf(',', i1);
+ if (i2 < 0) {
+ i2 = typeStr.indexOf(')', i1);
+ }
+ if (i2 - i1 > 0) {
+ String num = typeStr.substring(i1, i2);
+ try {
+ m = java.lang.Integer.parseInt(num, 10);
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ return m;
+ }
+
+ static int getD(String typeStr, int type) {
+ int d = 0;
+ switch (type) {
+ case Types.INTEGER: d = 10; break;
+ case Types.SMALLINT: d = 5; break;
+ case Types.FLOAT: d = 24; break;
+ case Types.DOUBLE: d = 53; break;
+ default: return getM(typeStr, type);
+ }
+ typeStr = typeStr.toLowerCase();
+ int i1 = typeStr.indexOf('(');
+ if (i1 > 0) {
+ ++i1;
+ int i2 = typeStr.indexOf(',', i1);
+ if (i2 < 0) {
+ return getM(typeStr, type);
+ }
+ i1 = i2;
+ i2 = typeStr.indexOf(')', i1);
+ if (i2 - i1 > 0) {
+ String num = typeStr.substring(i1, i2);
+ try {
+ d = java.lang.Integer.parseInt(num, 10);
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ return d;
+ }
+
+ public boolean supportsSavepoints() {
+ return false;
+ }
+
+ public boolean supportsNamedParameters() {
+ return false;
+ }
+
+ public boolean supportsMultipleOpenResults() {
+ return false;
+ }
+
+ public boolean supportsGetGeneratedKeys() {
+ return false;
+ }
+
+ public boolean supportsResultSetHoldability(int x) {
+ return false;
+ }
+
+ public boolean supportsStatementPooling() {
+ return false;
+ }
+
+ public boolean locatorsUpdateCopy() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getSuperTypes(String catalog, String schemaPattern,
+ String typeNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getSuperTables(String catalog, String schemaPattern,
+ String tableNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getAttributes(String catalog, String schemaPattern,
+ String typeNamePattern,
+ String attributeNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getResultSetHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+ public int getDatabaseMajorVersion() {
+ return SQLite.JDBCDriver.MAJORVERSION;
+ }
+
+ public int getDatabaseMinorVersion() {
+ return SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public int getJDBCMajorVersion() {
+ return 1;
+ }
+
+ public int getJDBCMinorVersion() {
+ return 0;
+ }
+
+ public int getSQLStateType() throws SQLException {
+ return sqlStateXOpen;
+ }
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
new file mode 100644
index 0000000..ab81867
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
@@ -0,0 +1,752 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.math.BigDecimal;
+import java.util.*;
+
+class BatchArg {
+ String arg;
+ boolean blob;
+
+ BatchArg(String arg, boolean blob) {
+ if (arg == null) {
+ this.arg = null;
+ } else {
+ this.arg = new String(arg);
+ }
+ this.blob = blob;
+ }
+}
+
+public class JDBCPreparedStatement extends JDBCStatement
+ implements java.sql.PreparedStatement {
+
+ private String sql;
+ private String args[];
+ private boolean blobs[];
+ private ArrayList<BatchArg> batch;
+ private static final boolean nullrepl =
+ SQLite.Database.version().compareTo("2.5.0") < 0;
+
+ public JDBCPreparedStatement(JDBCConnection conn, String sql) {
+ super(conn);
+ this.args = null;
+ this.blobs = null;
+ this.batch = null;
+ this.sql = fixup(sql);
+ }
+
+ private String fixup(String sql) {
+ StringBuffer sb = new StringBuffer();
+ boolean inq = false;
+ int nparm = 0;
+ for (int i = 0; i < sql.length(); i++) {
+ char c = sql.charAt(i);
+ if (c == '\'') {
+ if (inq) {
+ char nextChar = 0;
+ if(i + 1 < sql.length()) {
+ nextChar = sql.charAt(i + 1);
+ }
+ if (nextChar == '\'') {
+ sb.append(c);
+ sb.append(nextChar);
+ i++;
+ } else {
+ inq = false;
+ sb.append(c);
+ }
+ } else {
+ inq = true;
+ sb.append(c);
+ }
+ } else if (c == '?') {
+ if (inq) {
+ sb.append(c);
+ } else {
+ ++nparm;
+ sb.append(nullrepl ? "'%q'" : "%Q");
+ }
+ } else if (c == ';') {
+ if (!inq) {
+ break;
+ }
+ sb.append(c);
+ } else if (c == '%') {
+ sb.append("%%");
+ } else {
+ sb.append(c);
+ }
+ }
+ args = new String[nparm];
+ blobs = new boolean[nparm];
+ try {
+ clearParameters();
+ } catch (SQLException e) {
+ }
+ return sb.toString();
+ }
+
+ private String fixup2(String sql) {
+ if (!conn.db.is3()) {
+ return sql;
+ }
+ StringBuffer sb = new StringBuffer();
+ int parm = -1;
+ for (int i = 0; i < sql.length(); i++) {
+ char c = sql.charAt(i);
+ if (c == '%') {
+ sb.append(c);
+ ++i;
+ c = sql.charAt(i);
+ if (c == 'Q') {
+ parm++;
+ if (blobs[parm]) {
+ c = 's';
+ }
+ }
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ public ResultSet executeQuery() throws SQLException {
+ return executeQuery(fixup2(sql), args, false);
+ }
+
+ public int executeUpdate() throws SQLException {
+ executeQuery(fixup2(sql), args, true);
+ return updcnt;
+ }
+
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBoolean(int parameterIndex, boolean x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = x ? "1" : "0";
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setByte(int parameterIndex, byte x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setShort(int parameterIndex, short x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setInt(int parameterIndex, int x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setLong(int parameterIndex, long x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setFloat(int parameterIndex, float x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setDouble(int parameterIndex, double x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBigDecimal(int parameterIndex, BigDecimal x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = "" + x;
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setString(int parameterIndex, String x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x;
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ blobs[parameterIndex - 1] = false;
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] = SQLite.StringEncoder.encodeX(x);
+ blobs[parameterIndex - 1] = true;
+ } else {
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(x);
+ }
+ }
+ }
+
+ public void setDate(int parameterIndex, java.sql.Date x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setTime(int parameterIndex, java.sql.Time x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setAsciiStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public void setUnicodeStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBinaryStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void clearParameters() throws SQLException {
+ for (int i = 0; i < args.length; i++) {
+ args[i] = nullrepl ? "" : null;
+ blobs[i] = false;
+ }
+ }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType,
+ int scale) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setObject(int parameterIndex, Object x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public boolean execute() throws SQLException {
+ return executeQuery(fixup2(sql), args, false) != null;
+ }
+
+ public void addBatch() throws SQLException {
+ if (batch == null) {
+ batch = new ArrayList<BatchArg>(args.length);
+ }
+ for (int i = 0; i < args.length; i++) {
+ batch.add(new BatchArg(args[i], blobs[i]));
+ }
+ }
+
+ public int[] executeBatch() throws SQLException {
+ if (batch == null) {
+ return new int[0];
+ }
+ int[] ret = new int[batch.size() / args.length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = EXECUTE_FAILED;
+ }
+ int errs = 0;
+ int index = 0;
+ for (int i = 0; i < ret.length; i++) {
+ for (int k = 0; k < args.length; k++) {
+ BatchArg b = (BatchArg) batch.get(index++);
+
+ args[i] = b.arg;
+ blobs[i] = b.blob;
+ }
+ try {
+ ret[i] = executeUpdate();
+ } catch (SQLException e) {
+ ++errs;
+ }
+ }
+ if (errs > 0) {
+ throw new BatchUpdateException("batch failed", ret);
+ }
+ return ret;
+ }
+
+ public void clearBatch() throws SQLException {
+ if (batch != null) {
+ batch.clear();
+ batch = null;
+ }
+ }
+
+ public void setCharacterStream(int parameterIndex,
+ java.io.Reader reader,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setRef(int i, Ref x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBlob(int i, Blob x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setClob(int i, Clob x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setArray(int i, Array x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return rs.getMetaData();
+ }
+
+ public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
+ throws SQLException {
+ setDate(parameterIndex, x);
+ }
+
+ public void setTime(int parameterIndex, java.sql.Time x, Calendar cal)
+ throws SQLException {
+ setTime(parameterIndex, x);
+ }
+
+ public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
+ Calendar cal) throws SQLException {
+ setTimestamp(parameterIndex, x);
+ }
+
+ public void setNull(int parameterIndex, int sqlType, String typeName)
+ throws SQLException {
+ setNull(parameterIndex, sqlType);
+ }
+
+ public ParameterMetaData getParameterMetaData() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType,
+ int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType,
+ String typeName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.net.URL getURL(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setURL(int parameterIndex, java.net.URL url)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setNull(String parameterName, int sqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBoolean(String parameterName, boolean val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setByte(String parameterName, byte val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setShort(String parameterName, short val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setInt(String parameterName, int val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setLong(String parameterName, long val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFloat(String parameterName, float val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDouble(String parameterName, double val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBigDecimal(String parameterName, BigDecimal val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setString(String parameterName, String val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBytes(String parameterName, byte val[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDate(String parameterName, java.sql.Date val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTime(String parameterName, java.sql.Time val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTimestamp(String parameterName, java.sql.Timestamp val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setAsciiStream(String parameterName,
+ java.io.InputStream s, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBinaryStream(String parameterName,
+ java.io.InputStream s, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val, int targetSqlType,
+ int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val, int targetSqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setCharacterStream(String parameterName,
+ java.io.Reader r, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDate(String parameterName, java.sql.Date val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTime(String parameterName, java.sql.Time val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTimestamp(String parameterName, java.sql.Timestamp val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setNull(String parameterName, int sqlType, String typeName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public String getString(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getBoolean(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public short getShort(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getInt(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public long getLong(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public float getFloat(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public double getDouble(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte[] getBytes(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(String parameterName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String parameterName, Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(int parameterIndex, Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Ref getRef(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Ref getRef(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Blob getBlob(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Blob getBlob(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Clob getClob(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Clob getClob(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Array getArray(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Array getArray(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.net.URL getURL(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
new file mode 100644
index 0000000..06384eb
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
@@ -0,0 +1,932 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.math.BigDecimal;
+
+public class JDBCResultSet implements java.sql.ResultSet {
+
+ /**
+ * Current row to be retrieved.
+ */
+ private int row;
+
+ /**
+ * Table returned by Database.get_table()
+ */
+ protected SQLite.TableResult tr;
+
+ /**
+ * Statement from which result set was produced.
+ */
+ private JDBCStatement s;
+
+ /**
+ * Meta data for result set or null.
+ */
+ private JDBCResultSetMetaData m;
+
+ /**
+ * Last result cell retrieved or null.
+ */
+ private String lastg;
+
+
+ public JDBCResultSet(SQLite.TableResult tr, JDBCStatement s) {
+ this.tr = tr;
+ this.s = s;
+ this.m = null;
+ this.lastg = null;
+ this.row = -1;
+ }
+
+ public boolean next() throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ row++;
+ return row < tr.nrows;
+ }
+
+ public int findColumn(String columnName) throws SQLException {
+ JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+ return m.findColByName(columnName);
+ }
+
+ public int getRow() throws SQLException {
+ if (tr == null) {
+ throw new SQLException("no rows");
+ }
+ return row + 1;
+ }
+
+ public boolean previous() throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (row >= 0) {
+ row--;
+ }
+ return row >= 0;
+ }
+
+ public boolean absolute(int row) throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (row < 0) {
+ row = tr.nrows + 1 + row;
+ }
+ row--;
+ if (row < 0 || row > tr.nrows) {
+ return false;
+ }
+ this.row = row;
+ return true;
+ }
+
+ public boolean relative(int row) throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (this.row + row < 0 || this.row + row >= tr.nrows) {
+ return false;
+ }
+ this.row += row;
+ return true;
+ }
+
+ public void setFetchDirection(int dir) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchDirection() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFetchSize(int fsize) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchSize() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public String getString(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ return lastg;
+ }
+
+ public String getString(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getString(col);
+ }
+
+ public int getInt(int columnIndex) throws SQLException {
+ Integer i = internalGetInt(columnIndex);
+ if (i != null) {
+ return i.intValue();
+ }
+ return 0;
+ }
+
+ private Integer internalGetInt(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Integer.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public int getInt(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getInt(col);
+ }
+
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getBoolean(String columnName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ if (m == null) {
+ m = new JDBCResultSetMetaData(this);
+ }
+ return m;
+ }
+
+ public short getShort(int columnIndex) throws SQLException {
+ Short s = internalGetShort(columnIndex);
+ if (s != null) {
+ return s.shortValue();
+ }
+ return 0;
+ }
+
+ private Short internalGetShort(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Short.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public short getShort(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getShort(col);
+ }
+
+ public java.sql.Time getTime(int columnIndex) throws SQLException {
+ return internalGetTime(columnIndex, null);
+ }
+
+ private java.sql.Time internalGetTime(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Time.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Time getTime(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getTime(col);
+ }
+
+ public java.sql.Time getTime(int columnIndex, java.util.Calendar cal)
+ throws SQLException {
+ return internalGetTime(columnIndex, cal);
+ }
+
+ public java.sql.Time getTime(String columnName, java.util.Calendar cal)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getTime(col, cal);
+ }
+
+ public java.sql.Timestamp getTimestamp(int columnIndex)
+ throws SQLException{
+ return internalGetTimestamp(columnIndex, null);
+ }
+
+ private java.sql.Timestamp internalGetTimestamp(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Timestamp.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Timestamp getTimestamp(String columnName)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getTimestamp(col);
+ }
+
+ public java.sql.Timestamp getTimestamp(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ return internalGetTimestamp(columnIndex, cal);
+ }
+
+ public java.sql.Timestamp getTimestamp(String columnName,
+ java.util.Calendar cal)
+ throws SQLException {
+ int col = findColumn(columnName);
+ return getTimestamp(col, cal);
+ }
+
+ public java.sql.Date getDate(int columnIndex) throws SQLException {
+ return internalGetDate(columnIndex, null);
+ }
+
+ private java.sql.Date internalGetDate(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Date.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Date getDate(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getDate(col);
+ }
+
+ public java.sql.Date getDate(int columnIndex, java.util.Calendar cal)
+ throws SQLException{
+ return internalGetDate(columnIndex, cal);
+ }
+
+ public java.sql.Date getDate(String columnName, java.util.Calendar cal)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getDate(col, cal);
+ }
+
+ public double getDouble(int columnIndex) throws SQLException {
+ Double d = internalGetDouble(columnIndex);
+ if (d != null) {
+ return d.doubleValue();
+ }
+ return 0;
+ }
+
+ private Double internalGetDouble(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Double.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public double getDouble(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getDouble(col);
+ }
+
+ public float getFloat(int columnIndex) throws SQLException {
+ Float f = internalGetFloat(columnIndex);
+ if (f != null) {
+ return f.floatValue();
+ }
+ return 0;
+ }
+
+ private Float internalGetFloat(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Float.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public float getFloat(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getFloat(col);
+ }
+
+ public long getLong(int columnIndex) throws SQLException {
+ Long l = internalGetLong(columnIndex);
+ if (l != null) {
+ return l.longValue();
+ }
+ return 0;
+ }
+
+ private Long internalGetLong(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Long.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public long getLong(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getLong(col);
+ }
+
+ @Deprecated
+ public java.io.InputStream getUnicodeStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public java.io.InputStream getUnicodeStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getAsciiStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getAsciiStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getBinaryStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getBinaryStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(String columnName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ byte ret[] = null;
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ if (lastg != null) {
+ ret = SQLite.StringEncoder.decode(lastg);
+ }
+ return ret;
+ }
+
+ public byte[] getBytes(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getBytes(col);
+ }
+
+ public String getCursorName() throws SQLException {
+ return null;
+ }
+
+ public Object getObject(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ Object ret = lastg;
+ if (tr instanceof TableResultX) {
+ switch (((TableResultX) tr).sql_type[columnIndex - 1]) {
+ case Types.SMALLINT:
+ ret = internalGetShort(columnIndex);
+ break;
+ case Types.INTEGER:
+ ret = internalGetInt(columnIndex);
+ break;
+ case Types.DOUBLE:
+ ret = internalGetDouble(columnIndex);
+ break;
+ case Types.FLOAT:
+ ret = internalGetFloat(columnIndex);
+ break;
+ case Types.BIGINT:
+ ret = internalGetLong(columnIndex);
+ break;
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY:
+ ret = getBytes(columnIndex);
+ break;
+ case Types.NULL:
+ ret = null;
+ break;
+ /* defaults to String below */
+ }
+ }
+ return ret;
+ }
+
+ public Object getObject(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getObject(col);
+ }
+
+ public Object getObject(int columnIndex, java.util.Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String columnIndex, java.util.Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Ref getRef(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Ref getRef(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Blob getBlob(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Blob getBlob(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Clob getClob(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Clob getClob(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Array getArray(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Array getArray(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.Reader getCharacterStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.Reader getCharacterStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean wasNull() throws SQLException {
+ return lastg == null;
+ }
+
+ public void clearWarnings() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean isFirst() throws SQLException {
+ if (tr == null) {
+ return true;
+ }
+ return row == 0;
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ return row < 0;
+ }
+
+ public void beforeFirst() throws SQLException {
+ if (tr == null) {
+ return;
+ }
+ row = -1;
+ }
+
+ public boolean first() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ row = 0;
+ return true;
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ return row >= tr.nrows;
+ }
+
+ public void afterLast() throws SQLException {
+ if (tr == null) {
+ return;
+ }
+ row = tr.nrows;
+ }
+
+ public boolean isLast() throws SQLException {
+ if (tr == null) {
+ return true;
+ }
+ return row == tr.nrows - 1;
+ }
+
+ public boolean last() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ row = tr.nrows -1;
+ return true;
+ }
+
+ public int getType() throws SQLException {
+ return TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public int getConcurrency() throws SQLException {
+ return CONCUR_READ_ONLY;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean rowInserted() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void insertRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void deleteRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void refreshRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateNull(int colIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBoolean(int colIndex, boolean b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateByte(int colIndex, byte b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateShort(int colIndex, short b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateInt(int colIndex, int b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateLong(int colIndex, long b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateFloat(int colIndex, float f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDouble(int colIndex, double f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBigDecimal(int colIndex, BigDecimal f)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateString(int colIndex, String s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBytes(int colIndex, byte[] s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDate(int colIndex, java.sql.Date d) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTime(int colIndex, java.sql.Time t) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTimestamp(int colIndex, java.sql.Timestamp t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateAsciiStream(int colIndex, java.io.InputStream in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBinaryStream(int colIndex, java.io.InputStream in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateCharacterStream(int colIndex, java.io.Reader in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(int colIndex, Object obj) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(int colIndex, Object obj, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateNull(String colIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBoolean(String colIndex, boolean b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateByte(String colIndex, byte b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateShort(String colIndex, short b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateInt(String colIndex, int b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateLong(String colIndex, long b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateFloat(String colIndex, float f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDouble(String colIndex, double f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBigDecimal(String colIndex, BigDecimal f)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateString(String colIndex, String s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBytes(String colIndex, byte[] s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDate(String colIndex, java.sql.Date d)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTime(String colIndex, java.sql.Time t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTimestamp(String colIndex, java.sql.Timestamp t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateAsciiStream(String colIndex, java.io.InputStream in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBinaryStream(String colIndex, java.io.InputStream in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateCharacterStream(String colIndex, java.io.Reader in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(String colIndex, Object obj)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(String colIndex, Object obj, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Statement getStatement() throws SQLException {
+ if (s == null) {
+ throw new SQLException("stale result set");
+ }
+ return s;
+ }
+
+ public void close() throws SQLException {
+ s = null;
+ tr = null;
+ lastg = null;
+ row = -1;
+ }
+
+ public java.net.URL getURL(int colIndex) throws SQLException {
+ if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+ throw new SQLException("column " + colIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[colIndex - 1];
+ java.net.URL url = null;
+ if (lastg == null) {
+ return url;
+ }
+ try {
+ url = new java.net.URL(lastg);
+ } catch (java.lang.Exception e) {
+ url = null;
+ }
+ return url;
+ }
+
+ public java.net.URL getURL(String colIndex) throws SQLException {
+ int col = findColumn(colIndex);
+ return getURL(col);
+ }
+
+ public void updateRef(int colIndex, java.sql.Ref x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateRef(String colIndex, java.sql.Ref x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBlob(int colIndex, java.sql.Blob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBlob(String colIndex, java.sql.Blob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateClob(int colIndex, java.sql.Clob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateClob(String colIndex, java.sql.Clob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateArray(int colIndex, java.sql.Array x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateArray(String colIndex, java.sql.Array x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
new file mode 100644
index 0000000..934ca78
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
@@ -0,0 +1,212 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+
+public class JDBCResultSetMetaData implements java.sql.ResultSetMetaData {
+
+ private JDBCResultSet r;
+
+ public JDBCResultSetMetaData(JDBCResultSet r) {
+ this.r = r;
+ }
+
+ public String getCatalogName(int column) throws java.sql.SQLException {
+ return null;
+ }
+
+ public String getColumnClassName(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return null;
+ }
+ if (r.tr instanceof TableResultX) {
+ switch (((TableResultX) r.tr).sql_type[column]) {
+ case Types.SMALLINT: return "java.lang.Short";
+ case Types.INTEGER: return "java.lang.Integer";
+ case Types.DOUBLE: return "java.lang.Double";
+ case Types.FLOAT: return "java.lang.Float";
+ case Types.BIGINT: return "java.lang.Long";
+ case Types.DATE: return "java.sql.Date";
+ case Types.TIME: return "java.sql.Time";
+ case Types.TIMESTAMP: return "java.sql.Timestamp";
+ case Types.BINARY:
+ case Types.VARBINARY: return "[B";
+ /* defaults to varchar below */
+ }
+ }
+ return "java.lang.String";
+ }
+ return null;
+ }
+
+ public int getColumnCount() throws java.sql.SQLException {
+ if (r != null && r.tr != null) {
+ return r.tr.ncolumns;
+ }
+ return 0;
+ }
+
+ public int getColumnDisplaySize(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public String getColumnLabel(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ }
+ return c;
+ }
+
+ public String getColumnName(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ if (c != null) {
+ int i = c.indexOf('.');
+ if (i > 0) {
+ return c.substring(i + 1);
+ }
+ }
+ }
+ return c;
+ }
+
+ public int getColumnType(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column >= 0 && column < r.tr.ncolumns) {
+ if (r.tr instanceof TableResultX) {
+ return ((TableResultX) r.tr).sql_type[column];
+ }
+ return Types.VARCHAR;
+ }
+ }
+ throw new SQLException("bad column index");
+ }
+
+ public String getColumnTypeName(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column >= 0 && column < r.tr.ncolumns) {
+ if (r.tr instanceof TableResultX) {
+ switch (((TableResultX) r.tr).sql_type[column]) {
+ case Types.SMALLINT: return "smallint";
+ case Types.INTEGER: return "integer";
+ case Types.DOUBLE: return "double";
+ case Types.FLOAT: return "float";
+ case Types.BIGINT: return "bigint";
+ case Types.DATE: return "date";
+ case Types.TIME: return "time";
+ case Types.TIMESTAMP: return "timestamp";
+ case Types.BINARY: return "binary";
+ case Types.VARBINARY: return "varbinary";
+ /* defaults to varchar below */
+ }
+ }
+ return "varchar";
+ }
+ }
+ throw new SQLException("bad column index");
+ }
+
+ public int getPrecision(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public int getScale(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public String getSchemaName(int column) throws java.sql.SQLException {
+ return null;
+ }
+
+ public String getTableName(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ if (c != null) {
+ int i = c.indexOf('.');
+ if (i > 0) {
+ return c.substring(0, i);
+ }
+ c = null;
+ }
+ }
+ return c;
+ }
+
+ public boolean isAutoIncrement(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isCaseSensitive(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isCurrency(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isDefinitelyWritable(int column)
+ throws java.sql.SQLException {
+ return true;
+ }
+
+ public int isNullable(int column) throws java.sql.SQLException {
+ return columnNullableUnknown;
+ }
+
+ public boolean isReadOnly(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isSearchable(int column) throws java.sql.SQLException {
+ return true;
+ }
+
+ public boolean isSigned(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isWritable(int column) throws java.sql.SQLException {
+ return true;
+ }
+
+ int findColByName(String columnName) throws java.sql.SQLException {
+ String c = null;
+ if (r != null && r.tr != null) {
+ for (int i = 0; i < r.tr.ncolumns; i++) {
+ c = r.tr.column[i];
+ if (c != null) {
+ if (c.compareToIgnoreCase(columnName) == 0) {
+ return i + 1;
+ }
+ int k = c.indexOf('.');
+ if (k > 0) {
+ c = c.substring(k + 1);
+ if (c.compareToIgnoreCase(columnName) == 0) {
+ return i + 1;
+ }
+ }
+ }
+ c = null;
+ }
+ }
+ throw new SQLException("column " + columnName + " not found");
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java
new file mode 100644
index 0000000..99d12d3
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java
@@ -0,0 +1,287 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCStatement implements java.sql.Statement {
+
+ protected JDBCConnection conn;
+ protected JDBCResultSet rs;
+ protected int updcnt;
+ private ArrayList<String> batch;
+
+ public JDBCStatement(JDBCConnection conn) {
+ this.conn = conn;
+ this.updcnt = 0;
+ this.rs = null;
+ this.batch = null;
+ }
+
+ public void setFetchSize(int fetchSize) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchSize() throws SQLException {
+ return 1;
+ }
+
+ public int getMaxRows() throws SQLException {
+ return 0;
+ }
+
+ public void setMaxRows(int max) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFetchDirection(int fetchDirection) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchDirection() throws SQLException {
+ return ResultSet.FETCH_UNKNOWN;
+ }
+
+ public int getResultSetConcurrency() throws SQLException {
+ return ResultSet.CONCUR_READ_ONLY;
+ }
+
+ public int getResultSetType() throws SQLException {
+ return ResultSet.TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public void setQueryTimeout(int seconds) throws SQLException {
+ conn.timeout = seconds * 1000;
+ if (conn.timeout < 0) {
+ conn.timeout = 120000;
+ } else if (conn.timeout < 1000) {
+ conn.timeout = 5000;
+ }
+ }
+
+ public int getQueryTimeout() throws SQLException {
+ return conn.timeout;
+ }
+
+ public ResultSet getResultSet() throws SQLException {
+ return rs;
+ }
+
+ ResultSet executeQuery(String sql, String args[], boolean updonly)
+ throws SQLException {
+ SQLite.TableResult tr = null;
+ if (rs != null) {
+ rs.close();
+ rs = null;
+ }
+ updcnt = -1;
+ if (conn == null || conn.db == null) {
+ throw new SQLException("stale connection");
+ }
+ int busy = 0;
+ boolean starttrans = !conn.autocommit && !conn.intrans;
+ while (true) {
+ try {
+ if (starttrans) {
+ conn.db.exec("BEGIN TRANSACTION", null);
+ conn.intrans = true;
+ }
+ if (args == null) {
+ if (updonly) {
+ conn.db.exec(sql, null);
+ } else {
+ tr = conn.db.get_table(sql);
+ }
+ } else {
+ if (updonly) {
+ conn.db.exec(sql, null, args);
+ } else {
+ tr = conn.db.get_table(sql, args);
+ }
+ }
+ updcnt = (int) conn.db.changes();
+ } catch (SQLite.Exception e) {
+ if (conn.db.is3() &&
+ conn.db.last_error() == SQLite.Constants.SQLITE_BUSY &&
+ conn.busy3(conn.db, ++busy)) {
+ try {
+ if (starttrans && conn.intrans) {
+ conn.db.exec("ROLLBACK", null);
+ conn.intrans = false;
+ }
+ } catch (SQLite.Exception ee) {
+ }
+ try {
+ int ms = 20 + busy * 10;
+ if (ms > 1000) {
+ ms = 1000;
+ }
+ synchronized (this) {
+ this.wait(ms);
+ }
+ } catch (java.lang.Exception eee) {
+ }
+ continue;
+ }
+ throw new SQLException(e.toString());
+ }
+ break;
+ }
+ if (!updonly && tr == null) {
+ throw new SQLException("no result set produced");
+ }
+ if (!updonly && tr != null) {
+ rs = new JDBCResultSet(new TableResultX(tr), this);
+ }
+ return rs;
+ }
+
+ public ResultSet executeQuery(String sql) throws SQLException {
+ return executeQuery(sql, null, false);
+ }
+
+ public boolean execute(String sql) throws SQLException {
+ return executeQuery(sql) != null;
+ }
+
+ public void cancel() throws SQLException {
+ if (conn == null || conn.db == null) {
+ throw new SQLException("stale connection");
+ }
+ conn.db.interrupt();
+ }
+
+ public void clearWarnings() throws SQLException {
+ }
+
+ public Connection getConnection() throws SQLException {
+ return conn;
+ }
+
+ public void addBatch(String sql) throws SQLException {
+ if (batch == null) {
+ batch = new ArrayList<String>(1);
+ }
+ batch.add(sql);
+ }
+
+ public int[] executeBatch() throws SQLException {
+ if (batch == null) {
+ return new int[0];
+ }
+ int[] ret = new int[batch.size()];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = EXECUTE_FAILED;
+ }
+ int errs = 0;
+ for (int i = 0; i < ret.length; i++) {
+ try {
+ execute((String) batch.get(i));
+ ret[i] = updcnt;
+ } catch (SQLException e) {
+ ++errs;
+ }
+ }
+ if (errs > 0) {
+ throw new BatchUpdateException("batch failed", ret);
+ }
+ return ret;
+ }
+
+ public void clearBatch() throws SQLException {
+ if (batch != null) {
+ batch.clear();
+ batch = null;
+ }
+ }
+
+ public void close() throws SQLException {
+ clearBatch();
+ conn = null;
+ }
+
+ public int executeUpdate(String sql) throws SQLException {
+ executeQuery(sql, null, true);
+ return updcnt;
+ }
+
+ public int getMaxFieldSize() throws SQLException {
+ return 0;
+ }
+
+ public boolean getMoreResults() throws SQLException {
+ if (rs != null) {
+ rs.close();
+ rs = null;
+ }
+ return false;
+ }
+
+ public int getUpdateCount() throws SQLException {
+ return updcnt;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public void setCursorName(String name) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setMaxFieldSize(int max) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getMoreResults(int x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getGeneratedKeys() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int executeUpdate(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return executeUpdate(sql);
+ }
+
+ public int executeUpdate(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int executeUpdate(String sql, String colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean execute(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return execute(sql);
+ }
+
+ public boolean execute(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean execute(String sql, String colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getResultSetHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java
new file mode 100644
index 0000000..205372f
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java
@@ -0,0 +1,37 @@
+package SQLite.JDBC2y;
+
+import java.sql.Types;
+import java.util.Vector;
+
+public class TableResultX extends SQLite.TableResult {
+ public int sql_type[];
+
+ public TableResultX() {
+ super();
+ sql_type = new int[this.ncolumns];
+ for (int i = 0; i < this.ncolumns; i++) {
+ sql_type[i] = Types.VARCHAR;
+ }
+ }
+
+ public TableResultX(SQLite.TableResult tr) {
+ this.column = tr.column;
+ this.rows = tr.rows;
+ this.ncolumns = tr.ncolumns;
+ this.nrows = tr.nrows;
+ this.types = tr.types;
+ sql_type = new int[tr.ncolumns];
+ for (int i = 0; i < this.ncolumns; i++) {
+ sql_type[i] = Types.VARCHAR;
+ }
+ if (tr.types != null) {
+ for (int i = 0; i < tr.types.length; i++) {
+ sql_type[i] = JDBCDatabaseMetaData.mapSqlType(tr.types[i]);
+ }
+ }
+ }
+
+ void sql_types(int types[]) {
+ sql_type = types;
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java b/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java
new file mode 100644
index 0000000..63b95ee
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java
@@ -0,0 +1,109 @@
+package SQLite;
+
+import java.sql.*;
+import java.util.Properties;
+
+public class JDBCDriver implements java.sql.Driver {
+
+ public static final int MAJORVERSION = 1;
+ public static final int MINORVERSION = 2;
+
+ private static java.lang.reflect.Constructor makeConn = null;
+
+ protected Connection conn;
+
+ static {
+ try {
+ Class connClass = null;
+ Class args[] = new Class[2];
+ args[0] = Class.forName("java.lang.String");
+ args[1] = args[0];
+ String jvers = java.lang.System.getProperty("java.version");
+ String cvers;
+ if (jvers == null || jvers.startsWith("1.0")) {
+ throw new java.lang.Exception("unsupported java version");
+ } else if (jvers.startsWith("1.1")) {
+ cvers = "SQLite.JDBC1.JDBCConnection";
+ } else if (jvers.startsWith("1.2") || jvers.startsWith("1.3")) {
+ cvers = "SQLite.JDBC2.JDBCConnection";
+ } else if (jvers.startsWith("1.4")) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ } else if (jvers.startsWith("1.5")) {
+ cvers = "SQLite.JDBC2y.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception e) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ }
+ } else {
+ cvers = "SQLite.JDBC2z.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception e) {
+ cvers = "SQLite.JDBC2y.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception ee) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ }
+ }
+ }
+ connClass = Class.forName(cvers);
+ makeConn = connClass.getConstructor(args);
+ java.sql.DriverManager.registerDriver(new JDBCDriver());
+ } catch (java.lang.Exception e) {
+ System.err.println(e);
+ }
+ }
+
+ public JDBCDriver() {
+ }
+
+ public boolean acceptsURL(String url) throws SQLException {
+ return url.startsWith("sqlite:/") ||
+ url.startsWith("jdbc:sqlite:/");
+ }
+
+ public Connection connect(String url, Properties info)
+ throws SQLException {
+ if (!acceptsURL(url)) {
+ return null;
+ }
+ Object args[] = new Object[2];
+ args[0] = url;
+ if (info != null) {
+ args[1] = info.getProperty("encoding");
+ }
+ if (args[1] == null) {
+ args[1] = java.lang.System.getProperty("SQLite.encoding");
+ }
+ try {
+ conn = (Connection) makeConn.newInstance(args);
+ } catch (java.lang.reflect.InvocationTargetException ie) {
+ throw new SQLException(ie.getTargetException().toString());
+ } catch (java.lang.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ return conn;
+ }
+
+ public int getMajorVersion() {
+ return MAJORVERSION;
+ }
+
+ public int getMinorVersion() {
+ return MINORVERSION;
+ }
+
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException {
+ DriverPropertyInfo p[] = new DriverPropertyInfo[1];
+ DriverPropertyInfo pp = new DriverPropertyInfo("encoding", "");
+ p[0] = pp;
+ return p;
+ }
+
+ public boolean jdbcCompliant() {
+ return false;
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/ProgressHandler.java b/sqlite-jdbc/src/main/java/SQLite/ProgressHandler.java
new file mode 100644
index 0000000..b2ec7c0
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/ProgressHandler.java
@@ -0,0 +1,17 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined progress handler.
+ */
+
+public interface ProgressHandler {
+
+ /**
+ * Invoked for N SQLite VM opcodes.
+ * The method should return true to continue the
+ * current query, or false in order
+ * to abandon the action.<BR><BR>
+ */
+
+ public boolean progress();
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Shell.java b/sqlite-jdbc/src/main/java/SQLite/Shell.java
new file mode 100644
index 0000000..78d37a1
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Shell.java
@@ -0,0 +1,669 @@
+package SQLite;
+
+import SQLite.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * SQLite command line shell. This is a partial reimplementaion
+ * of sqlite/src/shell.c and can be invoked by:<P>
+ *
+ * <verb>
+ * java SQLite.Shell [OPTIONS] database [SHELLCMD]
+ * or
+ * java -jar sqlite.jar [OPTIONS] database [SHELLCMD]
+ * </verb>
+ */
+
+public class Shell implements Callback {
+ Database db;
+ boolean echo;
+ int count;
+ int mode;
+ boolean showHeader;
+ String tableName;
+ String sep;
+ String cols[];
+ int colwidth[];
+ String destTable;
+ PrintWriter pw;
+ PrintWriter err;
+
+ static final int MODE_Line = 0;
+ static final int MODE_Column = 1;
+ static final int MODE_List = 2;
+ static final int MODE_Semi = 3;
+ static final int MODE_Html = 4;
+ static final int MODE_Insert = 5;
+ static final int MODE_Insert2 = 6;
+
+ public Shell(PrintWriter pw, PrintWriter err) {
+ this.pw = pw;
+ this.err = err;
+ }
+
+ public Shell(PrintStream ps, PrintStream errs) {
+ pw = new PrintWriter(ps);
+ err = new PrintWriter(errs);
+ }
+
+ protected Object clone() {
+ Shell s = new Shell(this.pw, this.err);
+ s.db = db;
+ s.echo = echo;
+ s.mode = mode;
+ s.count = 0;
+ s.showHeader = showHeader;
+ s.tableName = tableName;
+ s.sep = sep;
+ s.colwidth = colwidth;
+ return s;
+ }
+
+ static public String sql_quote_dbl(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ int i, single = 0, dbl = 0;
+ for (i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == '\'') {
+ single++;
+ } else if (str.charAt(i) == '"') {
+ dbl++;
+ }
+ }
+ if (dbl == 0) {
+ return "\"" + str + "\"";
+ }
+ StringBuffer sb = new StringBuffer("\"");
+ for (i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '"') {
+ sb.append("\"\"");
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static public String sql_quote(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ int i, single = 0, dbl = 0;
+ for (i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == '\'') {
+ single++;
+ } else if (str.charAt(i) == '"') {
+ dbl++;
+ }
+ }
+ if (single == 0) {
+ return "'" + str + "'";
+ }
+ if (dbl == 0) {
+ return "\"" + str + "\"";
+ }
+ StringBuffer sb = new StringBuffer("'");
+ for (i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '\'') {
+ sb.append("''");
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static String html_quote(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '<') {
+ sb.append("&lt;");
+ } else if (c == '>') {
+ sb.append("&gt;");
+ } else if (c == '&') {
+ sb.append("&amp;");
+ } else {
+ int x = c;
+ if (x < 32 || x > 127) {
+ sb.append("&#" + x + ";");
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ static boolean is_numeric(String str) {
+ try {
+ Double d = Double.valueOf(str);
+ } catch (java.lang.Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ void set_table_name(String str) {
+ if (str == null) {
+ tableName = "";
+ return;
+ }
+ tableName = Shell.sql_quote(str);
+ }
+
+ public void columns(String args[]) {
+ cols = args;
+ }
+
+ public void types(String args[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public boolean newrow(String args[]) {
+ int i;
+ String tname;
+ switch (mode) {
+ case Shell.MODE_Line:
+ if (args.length == 0) {
+ break;
+ }
+ if (count++ > 0) {
+ pw.println("");
+ }
+ for (i = 0; i < args.length; i++) {
+ pw.println(cols[i] + " = " +
+ args[i] == null ? "NULL" : args[i]);
+ }
+ break;
+ case Shell.MODE_Column:
+ String csep = "";
+ if (count++ == 0) {
+ colwidth = new int[args.length];
+ for (i = 0; i < args.length; i++) {
+ int w, n;
+ w = cols[i].length();
+ if (w < 10) {
+ w = 10;
+ }
+ colwidth[i] = w;
+ if (showHeader) {
+ pw.print(csep + cols[i]);
+ csep = " ";
+ }
+ }
+ if (showHeader) {
+ pw.println("");
+ }
+ }
+ if (args.length == 0) {
+ break;
+ }
+ csep = "";
+ for (i = 0; i < args.length; i++) {
+ pw.print(csep + (args[i] == null ? "NULL" : args[i]));
+ csep = " ";
+ }
+ pw.println("");
+ break;
+ case Shell.MODE_Semi:
+ case Shell.MODE_List:
+ if (count++ == 0 && showHeader) {
+ for (i = 0; i < args.length; i++) {
+ pw.print(cols[i] +
+ (i == args.length - 1 ? "\n" : sep));
+ }
+ }
+ if (args.length == 0) {
+ break;
+ }
+ for (i = 0; i < args.length; i++) {
+ pw.print(args[i] == null ? "NULL" : args[i]);
+ if (mode == Shell.MODE_Semi) {
+ pw.print(";");
+ } else if (i < args.length - 1) {
+ pw.print(sep);
+ }
+ }
+ pw.println("");
+ break;
+ case MODE_Html:
+ if (count++ == 0 && showHeader) {
+ pw.print("<TR>");
+ for (i = 0; i < args.length; i++) {
+ pw.print("<TH>" + html_quote(cols[i]) + "</TH>");
+ }
+ pw.println("</TR>");
+ }
+ if (args.length == 0) {
+ break;
+ }
+ pw.print("<TR>");
+ for (i = 0; i < args.length; i++) {
+ pw.print("<TD>" + html_quote(args[i]) + "</TD>");
+ }
+ pw.println("</TR>");
+ break;
+ case MODE_Insert:
+ if (args.length == 0) {
+ break;
+ }
+ tname = tableName;
+ if (destTable != null) {
+ tname = destTable;
+ }
+ pw.print("INSERT INTO " + tname + " VALUES(");
+ for (i = 0; i < args.length; i++) {
+ String tsep = i > 0 ? "," : "";
+ if (args[i] == null) {
+ pw.print(tsep + "NULL");
+ } else if (is_numeric(args[i])) {
+ pw.print(tsep + args[i]);
+ } else {
+ pw.print(tsep + sql_quote(args[i]));
+ }
+ }
+ pw.println(");");
+ break;
+ case MODE_Insert2:
+ if (args.length == 0) {
+ break;
+ }
+ tname = tableName;
+ if (destTable != null) {
+ tname = destTable;
+ }
+ pw.print("INSERT INTO " + tname + " VALUES(");
+ for (i = 0; i < args.length; i++) {
+ String tsep = i > 0 ? "," : "";
+ pw.print(tsep + args[i]);
+ }
+ pw.println(");");
+ break;
+ }
+ return false;
+ }
+
+ void do_meta(String line) {
+ StringTokenizer st = new StringTokenizer(line.toLowerCase());
+ int n = st.countTokens();
+ if (n <= 0) {
+ return;
+ }
+ String cmd = st.nextToken();
+ String args[] = new String[n - 1];
+ int i = 0;
+ while (st.hasMoreTokens()) {
+ args[i] = st.nextToken();
+ ++i;
+ }
+ if (cmd.compareTo(".dump") == 0) {
+ new DBDump(this, args);
+ return;
+ }
+ if (cmd.compareTo(".echo") == 0) {
+ if (args.length > 0 &&
+ (args[0].startsWith("y") || args[0].startsWith("on"))) {
+ echo = true;
+ }
+ return;
+ }
+ if (cmd.compareTo(".exit") == 0) {
+ try {
+ db.close();
+ } catch (Exception e) {
+ }
+ System.exit(0);
+ }
+ if (cmd.compareTo(".header") == 0) {
+ if (args.length > 0 &&
+ (args[0].startsWith("y") || args[0].startsWith("on"))) {
+ showHeader = true;
+ }
+ return;
+ }
+ if (cmd.compareTo(".help") == 0) {
+ pw.println(".dump ?TABLE? ... Dump database in text fmt");
+ pw.println(".echo ON|OFF Command echo on or off");
+ pw.println(".enc ?NAME? Change encoding");
+ pw.println(".exit Exit program");
+ pw.println(".header ON|OFF Display headers on or off");
+ pw.println(".help This message");
+ pw.println(".mode MODE Set output mode to\n" +
+ " line, column, insert\n" +
+ " list, or html");
+ pw.println(".mode insert TABLE Generate SQL insert stmts");
+ pw.println(".schema ?PATTERN? List table schema");
+ pw.println(".separator STRING Set separator string");
+ pw.println(".tables ?PATTERN? List table names");
+ return;
+ }
+ if (cmd.compareTo(".mode") == 0) {
+ if (args.length > 0) {
+ if (args[0].compareTo("line") == 0) {
+ mode = Shell.MODE_Line;
+ } else if (args[0].compareTo("column") == 0) {
+ mode = Shell.MODE_Column;
+ } else if (args[0].compareTo("list") == 0) {
+ mode = Shell.MODE_List;
+ } else if (args[0].compareTo("html") == 0) {
+ mode = Shell.MODE_Html;
+ } else if (args[0].compareTo("insert") == 0) {
+ mode = Shell.MODE_Insert;
+ if (args.length > 1) {
+ destTable = args[1];
+ }
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".separator") == 0) {
+ if (args.length > 0) {
+ sep = args[0];
+ }
+ return;
+ }
+ if (cmd.compareTo(".tables") == 0) {
+ TableResult t = null;
+ if (args.length > 0) {
+ try {
+ String qarg[] = new String[1];
+ qarg[0] = args[0];
+ t = db.get_table("SELECT name FROM sqlite_master " +
+ "WHERE type='table' AND " +
+ "name LIKE '%%%q%%' " +
+ "ORDER BY name", qarg);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ } else {
+ try {
+ t = db.get_table("SELECT name FROM sqlite_master " +
+ "WHERE type='table' ORDER BY name");
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ if (t != null) {
+ for (i = 0; i < t.nrows; i++) {
+ String tab = ((String[]) t.rows.elementAt(i))[0];
+ if (tab != null) {
+ pw.println(tab);
+ }
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".schema") == 0) {
+ if (args.length > 0) {
+ try {
+ String qarg[] = new String[1];
+ qarg[0] = args[0];
+ db.exec("SELECT sql FROM sqlite_master " +
+ "WHERE type!='meta' AND " +
+ "name LIKE '%%%q%%' AND " +
+ "sql NOTNULL " +
+ "ORDER BY type DESC, name",
+ this, qarg);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ } else {
+ try {
+ db.exec("SELECT sql FROM sqlite_master " +
+ "WHERE type!='meta' AND " +
+ "sql NOTNULL " +
+ "ORDER BY tbl_name, type DESC, name",
+ this);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".enc") == 0) {
+ try {
+ db.set_encoding(args.length > 0 ? args[0] : null);
+ } catch (Exception e) {
+ err.println("" + e);
+ err.flush();
+ }
+ return;
+ }
+ err.println("Unknown command '" + cmd + "'");
+ err.flush();
+ }
+
+ String read_line(BufferedReader is, String prompt) {
+ try {
+ if (prompt != null) {
+ pw.print(prompt);
+ pw.flush();
+ }
+ String line = is.readLine();
+ return line;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ void do_input(BufferedReader is) {
+ String line, sql = null;
+ String prompt = "SQLITE> ";
+ while ((line = read_line(is, prompt)) != null) {
+ if (echo) {
+ pw.println(line);
+ }
+ if (line.length() > 0 && line.charAt(0) == '.') {
+ do_meta(line);
+ } else {
+ if (sql == null) {
+ sql = line;
+ } else {
+ sql = sql + " " + line;
+ }
+ if (Database.complete(sql)) {
+ try {
+ db.exec(sql, this);
+ } catch (Exception e) {
+ if (!echo) {
+ err.println(sql);
+ }
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ sql = null;
+ prompt = "SQLITE> ";
+ } else {
+ prompt = "SQLITE? ";
+ }
+ }
+ pw.flush();
+ }
+ if (sql != null) {
+ err.println("Incomplete SQL: " + sql);
+ err.flush();
+ }
+ }
+
+ void do_cmd(String sql) {
+ if (db == null) {
+ return;
+ }
+ if (sql.length() > 0 && sql.charAt(0) == '.') {
+ do_meta(sql);
+ } else {
+ try {
+ db.exec(sql, this);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ Shell s = new Shell(System.out, System.err);
+ s.mode = Shell.MODE_List;
+ s.sep = "|";
+ s.showHeader = false;
+ s.db = new Database();
+ String dbname = null, sql = null;
+ for (int i = 0; i < args.length; i++) {
+ if(args[i].compareTo("-html") ==0) {
+ s.mode = Shell.MODE_Html;
+ } else if (args[i].compareTo("-list") == 0) {
+ s.mode = Shell.MODE_List;
+ } else if (args[i].compareTo("-line") == 0) {
+ s.mode = Shell.MODE_Line;
+ } else if (i < args.length - 1 &&
+ args[i].compareTo("-separator") == 0) {
+ ++i;
+ s.sep = args[i];
+ } else if (args[i].compareTo("-header") == 0) {
+ s.showHeader = true;
+ } else if (args[i].compareTo("-noheader") == 0) {
+ s.showHeader = false;
+ } else if (args[i].compareTo("-echo") == 0) {
+ s.echo = true;
+ } else if (dbname == null) {
+ dbname = args[i];
+ } else if (sql == null) {
+ sql = args[i];
+ } else {
+ System.err.println("Arguments: ?OPTIONS? FILENAME ?SQL?");
+ System.exit(1);
+ }
+ }
+ if (dbname == null) {
+ System.err.println("No database file given");
+ System.exit(1);
+ }
+ try {
+ s.db.open(dbname, 0);
+ } catch (Exception e) {
+ System.err.println("Unable to open database: " + e);
+ System.exit(1);
+ }
+ if (sql != null) {
+ s.do_cmd(sql);
+ } else {
+ // BEGIN android-modified
+ BufferedReader is =
+ new BufferedReader(new InputStreamReader(System.in), 8192);
+ // END android-modified
+ s.do_input(is);
+ }
+ try {
+ s.db.close();
+ } catch (Exception ee) {
+ }
+ }
+}
+
+/**
+ * Internal class for dumping an entire database.
+ * It contains a special callback interface to traverse the
+ * tables of the current database and output create SQL statements
+ * and for the data insert SQL statements.
+ */
+
+class DBDump implements Callback {
+ Shell s;
+
+ DBDump(Shell s, String tables[]) {
+ this.s = s;
+ s.pw.println("BEGIN TRANSACTION;");
+ if (tables == null || tables.length == 0) {
+ try {
+ s.db.exec("SELECT name, type, sql FROM sqlite_master " +
+ "WHERE type!='meta' AND sql NOT NULL " +
+ "ORDER BY substr(type,2,1), name", this);
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ }
+ } else {
+ String arg[] = new String[1];
+ for (int i = 0; i < tables.length; i++) {
+ arg[0] = tables[i];
+ try {
+ s.db.exec("SELECT name, type, sql FROM sqlite_master " +
+ "WHERE tbl_name LIKE '%q' AND type!='meta' " +
+ " AND sql NOT NULL " +
+ " ORDER BY substr(type,2,1), name",
+ this, arg);
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ }
+ }
+ }
+ s.pw.println("COMMIT;");
+ }
+
+ public void columns(String col[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public void types(String args[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public boolean newrow(String args[]) {
+ if (args.length != 3) {
+ return true;
+ }
+ s.pw.println(args[2] + ";");
+ if (args[1].compareTo("table") == 0) {
+ Shell s2 = (Shell) s.clone();
+ s2.mode = Shell.MODE_Insert;
+ s2.set_table_name(args[0]);
+ String qargs[] = new String[1];
+ qargs[0] = args[0];
+ try {
+ if (s2.db.is3()) {
+ TableResult t = null;
+ t = s2.db.get_table("PRAGMA table_info('%q')", qargs);
+ String query;
+ if (t != null) {
+ StringBuffer sb = new StringBuffer();
+ String sep = "";
+
+ sb.append("SELECT ");
+ for (int i = 0; i < t.nrows; i++) {
+ String col = ((String[]) t.rows.elementAt(i))[1];
+ sb.append(sep + "quote(" +
+ Shell.sql_quote_dbl(col) + ")");
+ sep = ",";
+ }
+ sb.append(" from '%q'");
+ query = sb.toString();
+ s2.mode = Shell.MODE_Insert2;
+ } else {
+ query = "SELECT * from '%q'";
+ }
+ s2.db.exec(query, s2, qargs);
+ } else {
+ s2.db.exec("SELECT * from '%q'", s2, qargs);
+ }
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Stmt.java b/sqlite-jdbc/src/main/java/SQLite/Stmt.java
new file mode 100644
index 0000000..c4f72ed
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Stmt.java
@@ -0,0 +1,288 @@
+package SQLite;
+
+/**
+ * Class to represent compiled SQLite3 statement.
+ *
+ * Note, that all native methods of this class are
+ * not synchronized, i.e. it is up to the caller
+ * to ensure that only one thread is in these
+ * methods at any one time.
+ */
+
+public class Stmt {
+
+ /**
+ * Internal handle for the SQLite3 statement.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Internal last error code for prepare()/step() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Prepare the next SQL statement for the Stmt instance.
+ * @return true when the next piece of the SQL statement sequence
+ * has been prepared, false on end of statement sequence.
+ */
+
+ public native boolean prepare() throws SQLite.Exception;
+
+ /**
+ * Perform one step of compiled SQLite3 statement.
+ *
+ * Example:<BR>
+ * <PRE>
+ * ...
+ * try {
+ * Stmt s = db.prepare("select * from x; select * from y;");
+ * s.bind(...);
+ * ...
+ * s.bind(...);
+ * while (s.step(cb)) {
+ * Object o = s.value(...);
+ * ...
+ * }
+ * // s.reset() for re-execution or
+ * // s.prepare() for the next piece of SQL
+ * while (s.prepare()) {
+ * s.bind(...);
+ * ...
+ * s.bind(...);
+ * while (s.step(cb)) {
+ * Object o = s.value(...);
+ * ...
+ * }
+ * }
+ * } catch (SQLite.Exception e) {
+ * s.close();
+ * }
+ * </PRE>
+ *
+ * @return true when row data is available, false on end
+ * of result set.
+ */
+
+ public native boolean step() throws SQLite.Exception;
+
+ /**
+ * Close the compiled SQLite3 statement.
+ */
+
+ public native void close() throws SQLite.Exception;
+
+ /**
+ * Reset the compiled SQLite3 statement without
+ * clearing parameter bindings.
+ */
+
+ public native void reset() throws SQLite.Exception;
+
+ /**
+ * Clear all bound parameters of the compiled SQLite3 statement.
+ */
+
+ public native void clear_bindings() throws SQLite.Exception;
+
+ /**
+ * Bind positional integer value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, int value) throws SQLite.Exception;
+
+ /**
+ * Bind positional long value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, long value) throws SQLite.Exception;
+
+ /**
+ * Bind positional double value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, double value) throws SQLite.Exception;
+
+ /**
+ * Bind positional byte array to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter, may be null
+ */
+
+ public native void bind(int pos, byte[] value) throws SQLite.Exception;
+
+ /**
+ * Bind positional String to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter, may be null
+ */
+
+ public native void bind(int pos, String value) throws SQLite.Exception;
+
+ /**
+ * Bind positional SQL null to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ */
+
+ public native void bind(int pos) throws SQLite.Exception;
+
+ /**
+ * Bind positional zero'ed blob to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param length byte size of zero blob
+ */
+
+ public native void bind_zeroblob(int pos, int length)
+ throws SQLite.Exception;
+
+ /**
+ * Return number of parameters in compiled SQLite3 statement.
+ * @return int number of parameters
+ */
+
+ public native int bind_parameter_count() throws SQLite.Exception;
+
+ /**
+ * Return name of parameter in compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @return String parameter name
+ */
+
+ public native String bind_parameter_name(int pos) throws SQLite.Exception;
+
+ /**
+ * Return index of named parameter in compiled SQLite3 statement.
+ * @param name of parameter
+ * @return int index of parameter, 1-based
+ */
+
+ public native int bind_parameter_index(String name)
+ throws SQLite.Exception;
+
+
+ /**
+ * Retrieve integer column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return int column value
+ */
+
+ public native int column_int(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve long column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return long column value
+ */
+ public native long column_long(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve double column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return double column value
+ */
+ public native double column_double(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve blob column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return byte[] column value
+ */
+ public native byte[] column_bytes(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve string column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String column value
+ */
+ public native String column_string(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve column type from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return column type code, e.g. SQLite.Constants.SQLITE_INTEGER
+ */
+ public native int column_type(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve number of columns of exec'ed SQLite3 statement.
+ * @return int number of columns
+ */
+
+ public native int column_count() throws SQLite.Exception;
+
+ /**
+ * Retrieve column data as object from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return Object or null
+ */
+
+ public Object column(int col) throws SQLite.Exception {
+ switch (column_type(col)) {
+ case Constants.SQLITE_INTEGER:
+ return new Long(column_long(col));
+ case Constants.SQLITE_FLOAT:
+ return new Double(column_double(col));
+ case Constants.SQLITE_BLOB:
+ return column_bytes(col);
+ case Constants.SQLITE3_TEXT:
+ return column_string(col);
+ }
+ return null;
+ }
+
+ /**
+ * Return table name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_table_name(int col) throws SQLite.Exception;
+
+ /**
+ * Return database name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_database_name(int col) throws SQLite.Exception;
+
+ /**
+ * Return declared column type of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_decltype(int col) throws SQLite.Exception;
+
+ /**
+ * Return origin column name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_origin_name(int col) throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected native void finalize();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java b/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java
new file mode 100644
index 0000000..c2f20ad
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java
@@ -0,0 +1,201 @@
+package SQLite;
+
+/**
+ * String encoder/decoder for SQLite.
+ *
+ * This module was kindly donated by Eric van der Maarel of Nedap N.V.
+ *
+ * This encoder was implemented based on an original idea from an anonymous
+ * author in the source code of the SQLite distribution.
+ * I feel obliged to provide a quote from the original C-source code:
+ *
+ * "The author disclaims copyright to this source code. In place of
+ * a legal notice, here is a blessing:
+ *
+ * May you do good and not evil.
+ * May you find forgiveness for yourself and forgive others.
+ * May you share freely, never taking more than you give."
+ *
+ */
+
+public class StringEncoder {
+
+ /**
+ * Encodes the given byte array into a string that can be used by
+ * the SQLite database. The database cannot handle null (0x00) and
+ * the character '\'' (0x27). The encoding consists of escaping
+ * these characters with a reserved character (0x01). The escaping
+ * is applied after determining and applying a shift that minimizes
+ * the number of escapes required.
+ * With this encoding the data of original size n is increased to a
+ * maximum of 1+(n*257)/254.
+ * For sufficiently large n the overhead is thus less than 1.2%.
+ * @param a the byte array to be encoded. A null reference is handled as
+ * an empty array.
+ * @return the encoded bytes as a string. When an empty array is
+ * provided a string of length 1 is returned, the value of
+ * which is bogus.
+ * When decoded with this class' <code>decode</code> method
+ * a string of size 1 will return an empty byte array.
+ */
+
+ public static String encode(byte[] a) {
+ // check input
+ if (a == null || a.length == 0) {
+ // bogus shift, no data
+ return "x";
+ }
+ // determine count
+ int[] cnt = new int[256];
+ for (int i = 0 ; i < a.length; i++) {
+ cnt[a[i] & 0xff]++;
+ }
+ // determine shift for minimum number of escapes
+ int shift = 1;
+ int nEscapes = a.length;
+ for (int i = 1; i < 256; i++) {
+ if (i == '\'') {
+ continue;
+ }
+ int sum = cnt[i] + cnt[(i + 1) & 0xff] + cnt[(i + '\'') & 0xff];
+ if (sum < nEscapes) {
+ nEscapes = sum;
+ shift = i;
+ if (nEscapes == 0) {
+ // cannot become smaller
+ break;
+ }
+ }
+ }
+ // construct encoded output
+ int outLen = a.length + nEscapes + 1;
+ StringBuffer out = new StringBuffer(outLen);
+ out.append((char)shift);
+ for (int i = 0; i < a.length; i++) {
+ // apply shift
+ char c = (char)((a[i] - shift)&0xff);
+ // insert escapes
+ if (c == 0) { // forbidden
+ out.append((char)1);
+ out.append((char)1);
+ } else if (c == 1) { // escape character
+ out.append((char)1);
+ out.append((char)2);
+ } else if (c == '\'') { // forbidden
+ out.append((char)1);
+ out.append((char)3);
+ } else {
+ out.append(c);
+ }
+ }
+ return out.toString();
+ }
+
+ /**
+ * Decodes the given string that is assumed to be a valid encoding
+ * of a byte array. Typically the given string is generated by
+ * this class' <code>encode</code> method.
+ * @param s the given string encoding.
+ * @return the byte array obtained from the decoding.
+ * @throws IllegalArgumentException when the string given is not
+ * a valid encoded string for this encoder.
+ */
+
+ public static byte[] decode(String s) {
+ char[] a = s.toCharArray();
+ if (a.length > 2 && a[0] == 'X' &&
+ a[1] == '\'' && a[a.length-1] == '\'') {
+ // SQLite3 BLOB syntax
+ byte[] result = new byte[(a.length-3)/2];
+ for (int i = 2, k = 0; i < a.length - 1; i += 2, k++) {
+ byte tmp = (byte) (a[i] - '0');
+ if (tmp > 15) {
+ tmp -= 0x20;
+ }
+ result[k] = (byte) (tmp << 4);
+ tmp = (byte) (a[i+1] - '0');
+ if (tmp > 15) {
+ tmp -= 0x20;
+ }
+ result[k] |= tmp;
+ }
+ return result;
+ }
+ // first element is the shift
+ byte[] result = new byte[a.length-1];
+ int i = 0;
+ int shift = s.charAt(i++);
+ int j = 0;
+ while (i < s.length()) {
+ int c;
+ if ((c = s.charAt(i++)) == 1) { // escape character found
+ if ((c = s.charAt(i++)) == 1) {
+ c = 0;
+ } else if (c == 2) {
+ c = 1;
+ } else if (c == 3) {
+ c = '\'';
+ } else {
+ throw new IllegalArgumentException(
+ "invalid string passed to decoder: " + j);
+ }
+ }
+ // do shift
+ result[j++] = (byte)((c + shift) & 0xff);
+ }
+ int outLen = j;
+ // provide array of correct length
+ if (result.length != outLen) {
+ result = byteCopy(result, 0, outLen, new byte[outLen]);
+ }
+ return result;
+ }
+
+ /**
+ * Copies count elements from source, starting at element with
+ * index offset, to the given target.
+ * @param source the source.
+ * @param offset the offset.
+ * @param count the number of elements to be copied.
+ * @param target the target to be returned.
+ * @return the target being copied to.
+ */
+
+ private static byte[] byteCopy(byte[] source, int offset,
+ int count, byte[] target) {
+ for (int i = offset, j = 0; i < offset + count; i++, j++) {
+ target[j] = source[i];
+ }
+ return target;
+ }
+
+
+ static final char[] xdigits = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /**
+ * Encodes the given byte array into SQLite3 blob notation, ie X'..'
+ * @param a the byte array to be encoded. A null reference is handled as
+ * an empty array.
+ * @return the encoded bytes as a string.
+ */
+
+ public static String encodeX(byte[] a) {
+ // check input
+ if (a == null || a.length == 0) {
+ return "X''";
+ }
+ int outLen = a.length + 3;
+ StringBuffer out = new StringBuffer(outLen);
+ out.append('X');
+ out.append('\'');
+ for (int i = 0; i < a.length; i++) {
+ out.append(xdigits[a[i] >> 4]);
+ out.append(xdigits[a[i] & 0x0F]);
+ }
+ out.append('\'');
+ return out.toString();
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/TableResult.java b/sqlite-jdbc/src/main/java/SQLite/TableResult.java
new file mode 100644
index 0000000..1a7fb57
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/TableResult.java
@@ -0,0 +1,133 @@
+package SQLite;
+
+import java.util.Vector;
+
+/**
+ * Class representing an SQLite result set as
+ * returned by the
+ * <A HREF="Database.html#get_table(java.lang.String)">Database.get_table</A>
+ * convenience method.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.print(db.get_table("select * from TEST"));
+ * ...
+ * </PRE>
+ * Example output:<BR>
+ *
+ * <PRE>
+ * id|firstname|lastname|
+ * 0|John|Doe|
+ * 1|Speedy|Gonzales|
+ * ...
+ * </PRE>
+ */
+
+public class TableResult implements Callback {
+
+ /**
+ * Number of columns in the result set.
+ */
+
+ public int ncolumns;
+
+ /**
+ * Number of rows in the result set.
+ */
+
+ public int nrows;
+
+ /**
+ * Column names of the result set.
+ */
+
+ public String column[];
+
+ /**
+ * Types of columns of the result set or null.
+ */
+
+ public String types[];
+
+ /**
+ * Rows of the result set. Each row is stored as a String array.
+ */
+
+ public Vector rows;
+
+ /**
+ * Create an empty result set.
+ */
+
+ public TableResult() {
+ clear();
+ }
+
+ /**
+ * Clear result set.
+ */
+
+ public void clear() {
+ column = new String[0];
+ types = null;
+ rows = new Vector();
+ ncolumns = nrows = 0;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public void columns(String coldata[]) {
+ column = coldata;
+ ncolumns = column.length;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public void types(String types[]) {
+ this.types = types;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public boolean newrow(String rowdata[]) {
+ if (rowdata != null) {
+ rows.addElement(rowdata);
+ nrows++;
+ }
+ return false;
+ }
+
+ /**
+ * Make String representation of result set.
+ */
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ int i;
+ for (i = 0; i < ncolumns; i++) {
+ sb.append(column[i] == null ? "NULL" : column[i]);
+ sb.append('|');
+ }
+ sb.append('\n');
+ for (i = 0; i < nrows; i++) {
+ int k;
+ String row[] = (String[]) rows.elementAt(i);
+ for (k = 0; k < ncolumns; k++) {
+ sb.append(row[k] == null ? "NULL" : row[k]);
+ sb.append('|');
+ }
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+}
diff --git a/sqlite-jdbc/src/main/java/SQLite/Trace.java b/sqlite-jdbc/src/main/java/SQLite/Trace.java
new file mode 100644
index 0000000..19ed2a1
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Trace.java
@@ -0,0 +1,17 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's trace function.
+ */
+
+public interface Trace {
+
+ /**
+ * Callback to trace (ie log) one SQL statement.
+ *
+ * @param stmt SQL statement string
+ */
+
+ public void trace(String stmt);
+}
+
diff --git a/sqlite-jdbc/src/main/java/SQLite/Vm.java b/sqlite-jdbc/src/main/java/SQLite/Vm.java
new file mode 100644
index 0000000..9856ed0
--- /dev/null
+++ b/sqlite-jdbc/src/main/java/SQLite/Vm.java
@@ -0,0 +1,78 @@
+package SQLite;
+
+/**
+ * Class to represent compiled SQLite VM.
+ */
+
+public class Vm {
+
+ /**
+ * Internal handle for the compiled SQLite VM.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Internal last error code for compile()/step() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Perform one step on compiled SQLite VM.
+ * The result row is passed to the given callback interface.<BR><BR>
+ *
+ * Example:<BR>
+ * <PRE>
+ * ...
+ * try {
+ * Vm vm = db.compile("select * from x; select * from y;");
+ * while (vm.step(cb)) {
+ * ...
+ * }
+ * while (vm.compile()) {
+ * while (vm.step(cb)) {
+ * ...
+ * }
+ * }
+ * } catch (SQLite.Exception e) {
+ * }
+ * </PRE>
+ *
+ * @param cb the object implementing the callback methods.
+ * @return true as long as more row data can be retrieved,
+ * false, otherwise.
+ */
+
+ public native boolean step(Callback cb) throws SQLite.Exception;
+
+ /**
+ * Compile the next SQL statement for the SQLite VM instance.
+ * @return true when SQL statement has been compiled, false
+ * on end of statement sequence.
+ */
+
+ public native boolean compile() throws SQLite.Exception;
+
+ /**
+ * Abort the compiled SQLite VM.
+ */
+
+ public native void stop() throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected native void finalize();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}