Upgrade our sqlite JDBC driver to version 20100131.

This fixes a bunch of KnownFailures, and adds a bunch of new features. I've
updated the tests correspondingly (though doubtless we could add a lot more
tests now, if we wanted to).

I regenerated Constants.java manually, and explained how in its javadoc.

I've added the upstream VERSION file so it's easier to see what upstream
version we're at. (Constants now contains the version number too, but that's
less obvious.)

All our changes now have android-changed markers. I'll see about getting them
pushed upstream next week.

(This change best reviewed with "ignore whitespace". It looks like we made a
bunch of whitespace "corrections" when we imported this source, which just
makes it harder to stay in sync. I've taken the upstream copies of files that
only had whitespace differences.)
diff --git a/libcore/sql/src/test/java/tests/SQLite/AllTests.java b/libcore/sql/src/test/java/tests/SQLite/AllTests.java
index e2aa55c..ea8b841 100644
--- a/libcore/sql/src/test/java/tests/SQLite/AllTests.java
+++ b/libcore/sql/src/test/java/tests/SQLite/AllTests.java
@@ -28,7 +28,6 @@
         suite.addTestSuite(DatabaseTest.class);
         suite.addTestSuite(JDBCDriverFunctionalTest.class);
         suite.addTestSuite(JDBCDriverTest.class);
-        suite.addTestSuite(ConstantsTest.class);
         suite.addTestSuite(BlobTest.class);
         suite.addTestSuite(StmtTest.class);
         suite.addTestSuite(ExceptionTest.class);
diff --git a/libcore/sql/src/test/java/tests/SQLite/ConstantsTest.java b/libcore/sql/src/test/java/tests/SQLite/ConstantsTest.java
deleted file mode 100644
index 2a4961f..0000000
--- a/libcore/sql/src/test/java/tests/SQLite/ConstantsTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package tests.SQLite;
-
-import SQLite.Constants;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargetClass;
-
-import junit.framework.TestCase;
-
-@TestTargetClass(Constants.class)
-public class ConstantsTest extends TestCase {
-
-    /**
-     * @tests Constants#Constants()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "constructor test",
-        method = "Constants",
-        args = {}
-    )
-    public void testConstants() {
-        Constants c = new Constants();
-            
-        assertNotNull(c);
-        assertEquals(c.SQLITE_OK, 0);
-        assertEquals(c.SQLITE_ERROR, 1);
-        assertEquals(c.SQLITE_INTERNAL, 2);
-        assertEquals(c.SQLITE_PERM, 3);
-        assertEquals(c.SQLITE_ABORT, 4);
-        assertEquals(c.SQLITE_BUSY, 5);
-        assertEquals(c.SQLITE_LOCKED, 6);
-        assertEquals(c.SQLITE_NOMEM, 7);
-        assertEquals(c.SQLITE_READONLY, 8);
-        assertEquals(c.SQLITE_INTERRUPT, 9);
-        assertEquals(c.SQLITE_IOERR, 10);
-        assertEquals(c.SQLITE_CORRUPT, 11);
-        assertEquals(c.SQLITE_NOTFOUND, 12);
-        assertEquals(c.SQLITE_FULL, 13);
-        assertEquals(c.SQLITE_CANTOPEN, 14);
-        assertEquals(c.SQLITE_PROTOCOL, 15);
-        assertEquals(c.SQLITE_EMPTY, 16);
-        assertEquals(c.SQLITE_SCHEMA, 17);
-        assertEquals(c.SQLITE_TOOBIG, 18);
-        assertEquals(c.SQLITE_CONSTRAINT, 19);
-        assertEquals(c.SQLITE_MISMATCH, 20);
-        assertEquals(c.SQLITE_MISUSE, 21);
-        assertEquals(c.SQLITE_NOLFS, 22);
-        assertEquals(c.SQLITE_AUTH, 23);
-        assertEquals(c.SQLITE_FORMAT, 24);
-        assertEquals(c.SQLITE_RANGE, 25);
-        assertEquals(c.SQLITE_NOTADB, 26);
-        assertEquals(c.SQLITE_ROW, 100);
-        assertEquals(c.SQLITE_DONE, 101);
-        assertEquals(c.SQLITE_INTEGER, 1);
-        assertEquals(c.SQLITE_FLOAT, 2);
-        assertEquals(c.SQLITE_BLOB, 4);
-        assertEquals(c.SQLITE_NULL, 5);
-        assertEquals(c.SQLITE3_TEXT, 3);
-        assertEquals(c.SQLITE_NUMERIC, -1);
-        assertEquals(c.SQLITE_TEXT, 3);
-        assertEquals(c.SQLITE2_TEXT, -2);
-        assertEquals(c.SQLITE_ARGS, -3);
-        assertEquals(c.SQLITE_COPY, 0);
-        assertEquals(c.SQLITE_CREATE_INDEX, 1);
-        assertEquals(c.SQLITE_CREATE_TABLE, 2);
-        assertEquals(c.SQLITE_CREATE_TEMP_INDEX, 3);
-        assertEquals(c.SQLITE_CREATE_TEMP_TABLE, 4);
-        assertEquals(c.SQLITE_CREATE_TEMP_TRIGGER, 5);
-        assertEquals(c.SQLITE_CREATE_TEMP_VIEW, 6);
-        assertEquals(c.SQLITE_CREATE_TRIGGER, 7);
-        assertEquals(c.SQLITE_CREATE_VIEW, 8);
-        assertEquals(c.SQLITE_DELETE, 9);
-        assertEquals(c.SQLITE_DROP_INDEX, 10);
-        assertEquals(c.SQLITE_DROP_TABLE, 11);
-        assertEquals(c.SQLITE_DROP_TEMP_INDEX, 12);
-        assertEquals(c.SQLITE_DROP_TEMP_TABLE, 13);
-        assertEquals(c.SQLITE_DROP_TEMP_TRIGGER, 14);
-        assertEquals(c.SQLITE_DROP_TEMP_VIEW, 15);
-        assertEquals(c.SQLITE_DROP_TRIGGER, 16);
-        assertEquals(c.SQLITE_DROP_VIEW, 17);
-        assertEquals(c.SQLITE_INSERT, 18);
-        assertEquals(c.SQLITE_PRAGMA, 19);
-        assertEquals(c.SQLITE_READ, 20);
-        assertEquals(c.SQLITE_SELECT, 21);
-        assertEquals(c.SQLITE_TRANSACTION, 22);
-        assertEquals(c.SQLITE_UPDATE, 23);
-        assertEquals(c.SQLITE_ATTACH, 24);
-        assertEquals(c.SQLITE_DETACH, 25);
-        assertEquals(c.SQLITE_DENY, 1);
-        assertEquals(c.SQLITE_IGNORE, 2);
-    }
-}
diff --git a/libcore/sql/src/test/java/tests/SQLite/DatabaseTest.java b/libcore/sql/src/test/java/tests/SQLite/DatabaseTest.java
index 95ce7c8..12a556d 100644
--- a/libcore/sql/src/test/java/tests/SQLite/DatabaseTest.java
+++ b/libcore/sql/src/test/java/tests/SQLite/DatabaseTest.java
@@ -1069,7 +1069,7 @@
             db.exec("insert into TEST values(4, 'Fiona', 'Apple'); ", null);
             db.trace((Trace) t);
             db.create_aggregate("myaggfunc", 1, aggFunction);
-            db.function_type("myaggfunc", Constants.SQLITE_TEXT);
+            db.function_type("myaggfunc", Constants.SQLITE3_TEXT);
             db.exec("PRAGMA show_datatypes = on", null);
             
             assertFalse(aggFunction.functionCalled);
@@ -1125,7 +1125,7 @@
                 null);
         
         db.create_function("sin", 1, sinFunc);
-        db.function_type("sin", Constants.SQLITE_NUMERIC);
+        db.function_type("sin", Constants.SQLITE_FLOAT);
         res = db.get_table("select sin(res) from TEST WHERE res = "
                 + Double.toString(input));
          
@@ -2036,4 +2036,3 @@
     }
    
 }
-
diff --git a/libcore/sql/src/test/java/tests/SQLite/StmtTest.java b/libcore/sql/src/test/java/tests/SQLite/StmtTest.java
index cb71243..7a37154 100644
--- a/libcore/sql/src/test/java/tests/SQLite/StmtTest.java
+++ b/libcore/sql/src/test/java/tests/SQLite/StmtTest.java
@@ -982,17 +982,6 @@
         }
     }
     
-    /**
-     * @throws Exception 
-     * @tests {@link Stmt#column_type(int)}
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "method test",
-        method = "column_type",
-        args = {int.class}
-    )
-    @KnownFailure("For numeric, float and blob wrong type is returned")
     public void testColumn_type() throws Exception {
         db.exec(createAllTypes, null);
         db.exec(insertAllTypes, null);
@@ -1033,10 +1022,8 @@
         assertEquals(Constants.SQLITE_NULL, st.column_type(29));
 
         // Failing tests
-        assertTrue("NUMERIC".equalsIgnoreCase(st.column_decltype(12)));
-        assertEquals(Constants.SQLITE_NUMERIC, st.column_type(12)); // NUMERIC
-                                                                    // -> got
-                                                                    // INTEGER
+        assertTrue("INTEGER".equalsIgnoreCase(st.column_decltype(12)));
+        assertEquals(Constants.SQLITE_INTEGER, st.column_type(12));
         
         assertTrue("FLOAT".equalsIgnoreCase(st.column_decltype(11)));
         assertEquals(Constants.SQLITE_FLOAT, st.column_type(11)); // FLOAT ->
diff --git a/libcore/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java b/libcore/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java
index b09b779..c03bd6f 100644
--- a/libcore/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java
+++ b/libcore/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java
@@ -941,23 +941,14 @@
                 meta.ownInsertsAreVisible(100));
     }
 
-    /**
-     * @tests {@link java.sql.DatabaseMetaData#ownUpdatesAreVisible(int)}
-     */
-    @TestTargetNew(
-        level = TestLevel.NOT_FEASIBLE,
-        notes = "not supported. Verification with invalid parameters missed.",
-        method = "ownUpdatesAreVisible",
-        args = {int.class}
-    )
     public void test_ownUpdatesAreVisibleI() throws SQLException {
-        assertFalse(
+        assertTrue(
                 "result set's own updates are visible for TYPE_FORWARD_ONLY type",
                 meta.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
-        assertFalse(
+        assertTrue(
                 "result set's own updates are visible for TYPE_SCROLL_INSENSITIVE type",
                 meta.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
-        assertFalse(
+        assertTrue(
                 "result set's own updates are visible for TYPE_SCROLL_SENSITIVE type",
                 meta.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
         assertFalse("result set's own updates are visible for unknown type",
@@ -1090,18 +1081,8 @@
 
     }
 
-    /**
-     * @tests java.sql.DatabaseMetaData#supportsBatchUpdates()
-     */
-    @TestTargetNew(
-        level = TestLevel.NOT_FEASIBLE,
-        notes = "not supported",
-        method = "supportsBatchUpdates",
-        args = {}
-    )
     public void test_supportsBatchUpdates() throws SQLException {
-        // NOT_FEASIBLE: SQLITE does not implement this functionality
-        assertFalse(meta.supportsBatchUpdates());
+        assertTrue(meta.supportsBatchUpdates());
     }
 
     /**
@@ -1792,32 +1773,12 @@
         assertFalse(meta.supportsTransactions());
     }
 
-    /**
-     * @tests java.sql.DatabaseMetaData#supportsUnion()
-     */
-    @TestTargetNew(
-        level = TestLevel.NOT_FEASIBLE,
-        notes = "not supported",
-        method = "supportsUnion",
-        args = {}
-    )
     public void test_supportsUnion() throws SQLException {
-        // NOT_FEASIBLE: SQLITE does not implement this functionality
-        assertFalse(meta.supportsUnion());
+        assertTrue(meta.supportsUnion());
     }
 
-    /**
-     * @tests java.sql.DatabaseMetaData#supportsUnionAll()
-     */
-    @TestTargetNew(
-        level = TestLevel.NOT_FEASIBLE,
-        notes = "not supported",
-        method = "supportsUnionAll",
-        args = {}
-    )
     public void test_supportsUnionAll() throws SQLException {
-        // NOT_FEASIBLE: SQLITE does not implement this functionality
-        assertFalse(meta.supportsUnionAll());
+        assertTrue(meta.supportsUnionAll());
     }
     
     /**
diff --git a/libcore/sql/src/test/java/tests/sql/PreparedStatementTest.java b/libcore/sql/src/test/java/tests/sql/PreparedStatementTest.java
index 26147ed..1546d38 100755
--- a/libcore/sql/src/test/java/tests/sql/PreparedStatementTest.java
+++ b/libcore/sql/src/test/java/tests/sql/PreparedStatementTest.java
@@ -2981,16 +2981,6 @@
         }
     }
     
-    /**
-     * @test {@link java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int)}
-     * 
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "not supported",
-        method = "setCharacterStream",
-        args = {int.class, java.io.Reader.class, int.class}
-    )
     public void testSetCharacterSteam() {
         ResultSet res = null;
         PreparedStatement ps = null;
@@ -3002,9 +2992,6 @@
             assertNotNull("Error in test setup: file not found",file);
             Reader reader = new InputStreamReader(file);
             ps.setCharacterStream(1, reader, 100);
-            fail("Exception expected not supported"); 
-        } catch (SQLException e) {
-            // ok     
         } catch (Exception e) {
             fail("Error in test setup "+e.getMessage());
             e.printStackTrace();
diff --git a/libcore/sql/src/test/java/tests/sql/ResultSetGetterTests.java b/libcore/sql/src/test/java/tests/sql/ResultSetGetterTests.java
index 9b12fc1..fccfd94 100644
--- a/libcore/sql/src/test/java/tests/sql/ResultSetGetterTests.java
+++ b/libcore/sql/src/test/java/tests/sql/ResultSetGetterTests.java
@@ -299,7 +299,6 @@
         method = "getBytes",
         args = {int.class}
     )
-    @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
     public void testGetBytesIntVarbinary() throws SQLException {
 
         Statement st = null;
@@ -347,7 +346,6 @@
         method = "getBytes",
         args = {int.class}
     )
-     @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
     public void testGetBytesIntBinary() throws SQLException {
 
         Statement st = null;
@@ -511,18 +509,9 @@
         }
     }
 
-    /**
-     * Test method for {@link java.sql.ResultSet#getConcurrency()}.
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "Not fully supported: CONCUR_UPDATABLE not supported",
-        method = "getConcurrency",
-        args = {}
-    )
     public void testGetConcurrency() {
         try {
-            assertEquals(ResultSet.CONCUR_READ_ONLY, res.getConcurrency());
+            assertEquals(ResultSet.CONCUR_UPDATABLE, res.getConcurrency());
         } catch (SQLException e) {
             fail("Unexpected exception: " + e.getMessage());
         }
diff --git a/libcore/sql/src/test/java/tests/sql/ResultSetTest.java b/libcore/sql/src/test/java/tests/sql/ResultSetTest.java
index 796c6a4..5b6d74a 100644
--- a/libcore/sql/src/test/java/tests/sql/ResultSetTest.java
+++ b/libcore/sql/src/test/java/tests/sql/ResultSetTest.java
@@ -107,19 +107,6 @@
         } catch (SQLException e) {
             fail("Unexpected exception: " + e.getMessage());
         }
-        
-        try {
-//          Go back in position with forward only cursor
-            assertEquals(ResultSet.TYPE_FORWARD_ONLY, target.getFetchDirection());
-            target.absolute(2);
-            target.absolute(1);
-            fail("Should get SQLException");
-        } catch (SQLException e) {
-            // ok
-        }
-        
-        
-        
     }
 
     /**
@@ -598,42 +585,8 @@
         
     }
 
-    /**
-     * Test method for {@link java.sql.ResultSet#previous()}.
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "tests SQLException",
-        method = "previous",
-        args = {}
-    )
-    public void testPrevious() {
-        
+    public void testPrevious() throws SQLException {
         try {
-            assertEquals(ResultSet.FETCH_FORWARD, target.getFetchDirection());
-            target.last();
-            target.previous();
-            fail("Should get SQLException");
-        } catch (SQLException e) {
-            // ok
-        }
-    }
-    
-    /**
-     * Test method for {@link java.sql.ResultSet#previous()}.
-     * @throws SQLException 
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "not supported",
-        method = "previous",
-        args = {}
-    )
-    @KnownFailure("not supported")
-    public void testPrevious2() throws SQLException {
-        try {
-            assertSame(ResultSet.TYPE_SCROLL_INSENSITIVE, scrollableTarget.getFetchDirection());
-            
             target.first();
             target.previous();
             assertTrue(target.isBeforeFirst());
diff --git a/libcore/sql/src/test/java/tests/sql/StatementTest.java b/libcore/sql/src/test/java/tests/sql/StatementTest.java
index f884782..55bd7ab 100755
--- a/libcore/sql/src/test/java/tests/sql/StatementTest.java
+++ b/libcore/sql/src/test/java/tests/sql/StatementTest.java
@@ -692,29 +692,28 @@
         }
     }
 
-    /**
-     * @test java.sql.Statement#setMaxRows(int max)
-     * TODO not supported
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "not supported",
-        method = "setMaxRows",
-        args = {int.class}
-    )
-    public void testSetMaxRows() {
+    public void testMaxRows() {
         Statement st = null;
         try {
             st = conn.createStatement();
-            st.execute("select * from zoo;");
-            for (int i = 0; i < 300; i += 50) {
+            for (int i = 0; i < 300; i += 50) { 
                 try {
                     st.setMaxRows(i);
                     assertEquals(i, st.getMaxRows());
-                    fail("Revise test implemenation for feature impl. has changed");
+                    ResultSet r = st.executeQuery("select * from zoo;");
+                    int rowCount = 0;
+                    while (r.next()) {
+                        ++rowCount;
+                    }
+                    if (i == 0) {
+                        // 0 means unlimited.
+                        assertTrue("rowCount=" + rowCount + " i=" + i, rowCount > i);
+                    } else {
+                        assertTrue("rowCount=" + rowCount + " i=" + i, rowCount <= i);
+                    }
+                    r.close();
                 } catch (SQLException sqle) {
-                    assertEquals("not supported", sqle.getMessage());
-//                   fail("SQLException is thrown: " + sqle.getMessage());
+                    fail("SQLException is thrown: " + sqle.getMessage());
                 }
             }
             try {
@@ -735,41 +734,6 @@
     }
 
     /**
-     * @test java.sql.Statement#getMaxRows()
-     * TODO not supported
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "not supported",
-        method = "getMaxRows",
-        args = {}
-    )
-    public void testGetMaxRows() {
-        Statement st = null;
-        try {
-            st = conn.createStatement();
-            for (int i = 200; i < 500; i += 50) {
-                try {
-                    st.setMaxRows(i);
-                    assertEquals(i, st.getMaxRows());
-                    fail("Revise test implemenation for feature impl. has changed");
-                } catch (SQLException sqle) {
-                    assertEquals("not supported", sqle.getMessage());
-//                    fail("SQLException is thrown: " + sqle.getMessage());
-                }
-            }
-        } catch (SQLException e) {
-            fail("Can't create statement, SQLException is thrown: "
-                    + e.getMessage());
-        } finally {
-            try {
-                st.close();
-            } catch (SQLException ee) {
-            }
-        }
-    }
-
-    /**
      * @test java.sql.Statement#close()
      * not passed according to Java Docs: should release all resources 
      * IMMEDIATELY
diff --git a/libcore/sqlite-jdbc/VERSION b/libcore/sqlite-jdbc/VERSION
new file mode 100644
index 0000000..23bd019
--- /dev/null
+++ b/libcore/sqlite-jdbc/VERSION
@@ -0,0 +1 @@
+20100131
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Authorizer.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Authorizer.java
index cdc321d..24fc459 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Authorizer.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Authorizer.java
@@ -20,6 +20,6 @@
      */
 
     public int authorize(int what, String arg1, String arg2, String arg3,
-             String arg4);
+			 String arg4);
 }
 
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Blob.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Blob.java
index 3de9f8a..3e28225 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Blob.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Blob.java
@@ -26,8 +26,8 @@
      */
 
     BlobR(Blob blob) {
-    this.blob = blob;
-    this.pos = 0;
+	this.blob = blob;
+	this.pos = 0;
     }
 
     /**
@@ -36,8 +36,8 @@
      */
 
     public int available() throws IOException {
-    int ret = blob.size - pos;
-    return (ret < 0) ? 0 : ret;
+	int ret = blob.size - pos;
+	return (ret < 0) ? 0 : ret;
     }
 
     /**
@@ -60,7 +60,7 @@
      */
 
     public boolean markSupported() {
-    return false;
+	return false;
     }
 
     /**
@@ -69,8 +69,8 @@
 
     public void close() throws IOException {
         blob.close();
-    blob = null;
-    pos = 0;
+	blob = null;
+	pos = 0;
     }
 
     /**
@@ -78,17 +78,17 @@
      */
 
     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;
+	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;
     }
 
     /**
@@ -97,13 +97,13 @@
      */
 
     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;
+	byte b[] = new byte[1];
+	int n = blob.read(b, 0, pos, b.length);
+	if (n > 0) {
+	    pos += n;
+	    return b[0];
+	}
+	return -1;
     }
 
     /**
@@ -113,12 +113,12 @@
      */
 
     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;
+	int n = blob.read(b, 0, pos, b.length);
+	if (n > 0) {
+	    pos += n;
+	    return n;
+	}
+	return -1;
     }
 
     /**
@@ -130,21 +130,21 @@
      */
 
     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;
+	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;
     }
 }
 
@@ -172,8 +172,8 @@
      */
 
     BlobW(Blob blob) {
-    this.blob = blob;
-    this.pos = 0;
+	this.blob = blob;
+	this.pos = 0;
     }
 
     /**
@@ -189,8 +189,8 @@
 
     public void close() throws IOException {
         blob.close();
-    blob = null;
-    pos = 0;
+	blob = null;
+	pos = 0;
     }
 
     /**
@@ -199,9 +199,9 @@
      */
 
     public void write(int v) throws IOException {
-    byte b[] = new byte[1];
-    b[0] = (byte) v;
-    pos += blob.write(b, 0, pos, 1);
+	byte b[] = new byte[1];
+	b[0] = (byte) v;
+	pos += blob.write(b, 0, pos, 1);
     }
 
     /**
@@ -210,9 +210,9 @@
      */
 
     public void write(byte[] b) throws IOException {
-    if (b != null && b.length > 0) {
-        pos += blob.write(b, 0, pos, b.length);
-    }
+	if (b != null && b.length > 0) {
+	    pos += blob.write(b, 0, pos, b.length);
+	}
     }
 
     /**
@@ -223,15 +223,15 @@
      */
 
     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);
-    }
+	if (b != null) {
+	    if (off + len > b.length) {
+		len = b.length - off;
+	    }
+	    if (len <= 0) {
+		return;
+	    }
+	    pos += blob.write(b, off, pos, len);
+	}
     }
 }
 
@@ -265,7 +265,7 @@
      */
 
     public InputStream getInputStream() {
-    return (InputStream) new BlobR(this);
+	return (InputStream) new BlobR(this);
     }
 
     /**
@@ -274,7 +274,7 @@
      */
 
     public OutputStream getOutputStream() {
-    return (OutputStream) new BlobW(this);
+	return (OutputStream) new BlobW(this);
     }
 
     /**
@@ -318,6 +318,6 @@
     private static native void internal_init();
 
     static {
-    internal_init();
+	internal_init();
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Constants.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Constants.java
index 4e636b9..017c49c 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Constants.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Constants.java
@@ -4,154 +4,198 @@
 
 /**
  * Container for SQLite constants.
+ * 
+ * Usually generated by "native/mkconst.c". For Android, I pasted in the output of this one-liner:
+ * 
+ * perl -ne '$_ =~ s/#define\s+(SQLITE\S+)\s+([0-9x]+)/    public static final int $1 = $2;/ && print $_;' external/sqlite/dist/sqlite3.h
  */
-
 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;
+    // Copied from VERSION.
+    public static final int drv_minor = 20100131;
+    // Generated by the one-liner above.
+    public static final int SQLITE_VERSION_NUMBER = 3006022;
+    public static final int SQLITE_OK = 0;   /* Successful result */
+    public static final int SQLITE_ERROR = 1;   /* SQL error or missing database */
+    public static final int SQLITE_INTERNAL = 2;   /* Internal logic error in SQLite */
+    public static final int SQLITE_PERM = 3;   /* Access permission denied */
+    public static final int SQLITE_ABORT = 4;   /* Callback routine requested an abort */
+    public static final int SQLITE_BUSY = 5;   /* The database file is locked */
+    public static final int SQLITE_LOCKED = 6;   /* A table in the database is locked */
+    public static final int SQLITE_NOMEM = 7;   /* A malloc() failed */
+    public static final int SQLITE_READONLY = 8;   /* Attempt to write a readonly database */
+    public static final int SQLITE_INTERRUPT = 9;   /* Operation terminated by sqlite3_interrupt()*/
+    public static final int SQLITE_IOERR = 10;   /* Some kind of disk I/O error occurred */
+    public static final int SQLITE_CORRUPT = 11;   /* The database disk image is malformed */
+    public static final int SQLITE_NOTFOUND = 12;   /* NOT USED. Table or record not found */
+    public static final int SQLITE_FULL = 13;   /* Insertion failed because database is full */
+    public static final int SQLITE_CANTOPEN = 14;   /* Unable to open the database file */
+    public static final int SQLITE_PROTOCOL = 15;   /* NOT USED. Database lock protocol error */
+    public static final int SQLITE_EMPTY = 16;   /* Database is empty */
+    public static final int SQLITE_SCHEMA = 17;   /* The database schema changed */
+    public static final int SQLITE_TOOBIG = 18;   /* String or BLOB exceeds size limit */
+    public static final int SQLITE_CONSTRAINT = 19;   /* Abort due to constraint violation */
+    public static final int SQLITE_MISMATCH = 20;   /* Data type mismatch */
+    public static final int SQLITE_MISUSE = 21;   /* Library used incorrectly */
+    public static final int SQLITE_NOLFS = 22;   /* Uses OS features not supported on host */
+    public static final int SQLITE_AUTH = 23;   /* Authorization denied */
+    public static final int SQLITE_FORMAT = 24;   /* Auxiliary database format error */
+    public static final int SQLITE_RANGE = 25;   /* 2nd parameter to sqlite3_bind out of range */
+    public static final int SQLITE_NOTADB = 26;   /* File opened that is not a database file */
+    public static final int SQLITE_ROW = 100;  /* sqlite3_step() has another row ready */
+    public static final int SQLITE_DONE = 101;  /* sqlite3_step() has finished executing */
+    public static final int SQLITE_OPEN_READONLY = 0x00000001;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_READWRITE = 0x00000002;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_CREATE = 0x00000004;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_DELETEONCLOSE = 0x00000008;  /* VFS only */
+    public static final int SQLITE_OPEN_EXCLUSIVE = 0x00000010;  /* VFS only */
+    public static final int SQLITE_OPEN_MAIN_DB = 0x00000100;  /* VFS only */
+    public static final int SQLITE_OPEN_TEMP_DB = 0x00000200;  /* VFS only */
+    public static final int SQLITE_OPEN_TRANSIENT_DB = 0x00000400;  /* VFS only */
+    public static final int SQLITE_OPEN_MAIN_JOURNAL = 0x00000800;  /* VFS only */
+    public static final int SQLITE_OPEN_TEMP_JOURNAL = 0x00001000;  /* VFS only */
+    public static final int SQLITE_OPEN_SUBJOURNAL = 0x00002000;  /* VFS only */
+    public static final int SQLITE_OPEN_MASTER_JOURNAL = 0x00004000;  /* VFS only */
+    public static final int SQLITE_OPEN_NOMUTEX = 0x00008000;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_FULLMUTEX = 0x00010000;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_SHAREDCACHE = 0x00020000;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_OPEN_PRIVATECACHE = 0x00040000;  /* Ok for sqlite3_open_v2() */
+    public static final int SQLITE_IOCAP_ATOMIC = 0x00000001;
+    public static final int SQLITE_IOCAP_ATOMIC512 = 0x00000002;
+    public static final int SQLITE_IOCAP_ATOMIC1K = 0x00000004;
+    public static final int SQLITE_IOCAP_ATOMIC2K = 0x00000008;
+    public static final int SQLITE_IOCAP_ATOMIC4K = 0x00000010;
+    public static final int SQLITE_IOCAP_ATOMIC8K = 0x00000020;
+    public static final int SQLITE_IOCAP_ATOMIC16K = 0x00000040;
+    public static final int SQLITE_IOCAP_ATOMIC32K = 0x00000080;
+    public static final int SQLITE_IOCAP_ATOMIC64K = 0x00000100;
+    public static final int SQLITE_IOCAP_SAFE_APPEND = 0x00000200;
+    public static final int SQLITE_IOCAP_SEQUENTIAL = 0x00000400;
+    public static final int SQLITE_LOCK_NONE = 0;
+    public static final int SQLITE_LOCK_SHARED = 1;
+    public static final int SQLITE_LOCK_RESERVED = 2;
+    public static final int SQLITE_LOCK_PENDING = 3;
+    public static final int SQLITE_LOCK_EXCLUSIVE = 4;
+    public static final int SQLITE_SYNC_NORMAL = 0x00002;
+    public static final int SQLITE_SYNC_FULL = 0x00003;
+    public static final int SQLITE_SYNC_DATAONLY = 0x00010;
+    public static final int SQLITE_FCNTL_LOCKSTATE = 1;
+    public static final int SQLITE_GET_LOCKPROXYFILE = 2;
+    public static final int SQLITE_SET_LOCKPROXYFILE = 3;
+    public static final int SQLITE_LAST_ERRNO = 4;
+    public static final int SQLITE_ACCESS_EXISTS = 0;
+    public static final int SQLITE_ACCESS_READWRITE = 1;
+    public static final int SQLITE_ACCESS_READ = 2;
+    public static final int SQLITE_CONFIG_SINGLETHREAD = 1;  /* nil */
+    public static final int SQLITE_CONFIG_MULTITHREAD = 2;  /* nil */
+    public static final int SQLITE_CONFIG_SERIALIZED = 3;  /* nil */
+    public static final int SQLITE_CONFIG_MALLOC = 4;  /* sqlite3_mem_methods* */
+    public static final int SQLITE_CONFIG_GETMALLOC = 5;  /* sqlite3_mem_methods* */
+    public static final int SQLITE_CONFIG_SCRATCH = 6;  /* void*, int sz, int N */
+    public static final int SQLITE_CONFIG_PAGECACHE = 7;  /* void*, int sz, int N */
+    public static final int SQLITE_CONFIG_HEAP = 8;  /* void*, int nByte, int min */
+    public static final int SQLITE_CONFIG_MEMSTATUS = 9;  /* boolean */
+    public static final int SQLITE_CONFIG_MUTEX = 10;  /* sqlite3_mutex_methods* */
+    public static final int SQLITE_CONFIG_GETMUTEX = 11;  /* sqlite3_mutex_methods* */
+    public static final int SQLITE_CONFIG_LOOKASIDE = 13;  /* int int */
+    public static final int SQLITE_CONFIG_PCACHE = 14;  /* sqlite3_pcache_methods* */
+    public static final int SQLITE_CONFIG_GETPCACHE = 15;  /* sqlite3_pcache_methods* */
+    public static final int SQLITE_DBCONFIG_LOOKASIDE = 1001;  /* void* int int */
+    public static final int SQLITE_DENY = 1;   /* Abort the SQL statement with an error */
+    public static final int SQLITE_IGNORE = 2;   /* Don't allow access, but don't generate an error */
+    public static final int SQLITE_CREATE_INDEX = 1;   /* Index Name      Table Name      */
+    public static final int SQLITE_CREATE_TABLE = 2;   /* Table Name      NULL            */
+    public static final int SQLITE_CREATE_TEMP_INDEX = 3;   /* Index Name      Table Name      */
+    public static final int SQLITE_CREATE_TEMP_TABLE = 4;   /* Table Name      NULL            */
+    public static final int SQLITE_CREATE_TEMP_TRIGGER = 5;   /* Trigger Name    Table Name      */
+    public static final int SQLITE_CREATE_TEMP_VIEW = 6;   /* View Name       NULL            */
+    public static final int SQLITE_CREATE_TRIGGER = 7;   /* Trigger Name    Table Name      */
+    public static final int SQLITE_CREATE_VIEW = 8;   /* View Name       NULL            */
+    public static final int SQLITE_DELETE = 9;   /* Table Name      NULL            */
+    public static final int SQLITE_DROP_INDEX = 10;   /* Index Name      Table Name      */
+    public static final int SQLITE_DROP_TABLE = 11;   /* Table Name      NULL            */
+    public static final int SQLITE_DROP_TEMP_INDEX = 12;   /* Index Name      Table Name      */
+    public static final int SQLITE_DROP_TEMP_TABLE = 13;   /* Table Name      NULL            */
+    public static final int SQLITE_DROP_TEMP_TRIGGER = 14;   /* Trigger Name    Table Name      */
+    public static final int SQLITE_DROP_TEMP_VIEW = 15;   /* View Name       NULL            */
+    public static final int SQLITE_DROP_TRIGGER = 16;   /* Trigger Name    Table Name      */
+    public static final int SQLITE_DROP_VIEW = 17;   /* View Name       NULL            */
+    public static final int SQLITE_INSERT = 18;   /* Table Name      NULL            */
+    public static final int SQLITE_PRAGMA = 19;   /* Pragma Name     1st arg or NULL */
+    public static final int SQLITE_READ = 20;   /* Table Name      Column Name     */
+    public static final int SQLITE_SELECT = 21;   /* NULL            NULL            */
+    public static final int SQLITE_TRANSACTION = 22;   /* Operation       NULL            */
+    public static final int SQLITE_UPDATE = 23;   /* Table Name      Column Name     */
+    public static final int SQLITE_ATTACH = 24;   /* Filename        NULL            */
+    public static final int SQLITE_DETACH = 25;   /* Database Name   NULL            */
+    public static final int SQLITE_ALTER_TABLE = 26;   /* Database Name   Table Name      */
+    public static final int SQLITE_REINDEX = 27;   /* Index Name      NULL            */
+    public static final int SQLITE_ANALYZE = 28;   /* Table Name      NULL            */
+    public static final int SQLITE_CREATE_VTABLE = 29;   /* Table Name      Module Name     */
+    public static final int SQLITE_DROP_VTABLE = 30;   /* Table Name      Module Name     */
+    public static final int SQLITE_FUNCTION = 31;   /* NULL            Function Name   */
+    public static final int SQLITE_SAVEPOINT = 32;   /* Operation       Savepoint Name  */
+    public static final int SQLITE_COPY = 0;   /* No longer used */
+    public static final int SQLITE_LIMIT_LENGTH = 0;
+    public static final int SQLITE_LIMIT_SQL_LENGTH = 1;
+    public static final int SQLITE_LIMIT_COLUMN = 2;
+    public static final int SQLITE_LIMIT_EXPR_DEPTH = 3;
+    public static final int SQLITE_LIMIT_COMPOUND_SELECT = 4;
+    public static final int SQLITE_LIMIT_VDBE_OP = 5;
+    public static final int SQLITE_LIMIT_FUNCTION_ARG = 6;
+    public static final int SQLITE_LIMIT_ATTACHED = 7;
+    public static final int SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8;
+    public static final int SQLITE_LIMIT_VARIABLE_NUMBER = 9;
+    public static final int SQLITE_LIMIT_TRIGGER_DEPTH = 10;
     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;
+    public static final int SQLITE_UTF8 = 1;
+    public static final int SQLITE_UTF16LE = 2;
+    public static final int SQLITE_UTF16BE = 3;
+    public static final int SQLITE_UTF16 = 4;    /* Use native byte order */
+    public static final int SQLITE_ANY = 5;    /* sqlite3_create_function only */
+    public static final int SQLITE_UTF16_ALIGNED = 8;    /* sqlite3_create_collation only */
+    public static final int SQLITE_INDEX_CONSTRAINT_EQ = 2;
+    public static final int SQLITE_INDEX_CONSTRAINT_GT = 4;
+    public static final int SQLITE_INDEX_CONSTRAINT_LE = 8;
+    public static final int SQLITE_INDEX_CONSTRAINT_LT = 16;
+    public static final int SQLITE_INDEX_CONSTRAINT_GE = 32;
+    public static final int SQLITE_INDEX_CONSTRAINT_MATCH = 64;
+    public static final int SQLITE_MUTEX_FAST = 0;
+    public static final int SQLITE_MUTEX_RECURSIVE = 1;
+    public static final int SQLITE_MUTEX_STATIC_MASTER = 2;
+    public static final int SQLITE_MUTEX_STATIC_MEM = 3;  /* sqlite3_malloc() */
+    public static final int SQLITE_MUTEX_STATIC_MEM2 = 4;  /* NOT USED */
+    public static final int SQLITE_MUTEX_STATIC_OPEN = 4;  /* sqlite3BtreeOpen() */
+    public static final int SQLITE_MUTEX_STATIC_PRNG = 5;  /* sqlite3_random() */
+    public static final int SQLITE_MUTEX_STATIC_LRU = 6;  /* lru page list */
+    public static final int SQLITE_MUTEX_STATIC_LRU2 = 7;  /* lru page list */
+    public static final int SQLITE_TESTCTRL_FIRST = 5;
+    public static final int SQLITE_TESTCTRL_PRNG_SAVE = 5;
+    public static final int SQLITE_TESTCTRL_PRNG_RESTORE = 6;
+    public static final int SQLITE_TESTCTRL_PRNG_RESET = 7;
+    public static final int SQLITE_TESTCTRL_BITVEC_TEST = 8;
+    public static final int SQLITE_TESTCTRL_FAULT_INSTALL = 9;
+    public static final int SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS = 10;
+    public static final int SQLITE_TESTCTRL_PENDING_BYTE = 11;
+    public static final int SQLITE_TESTCTRL_ASSERT = 12;
+    public static final int SQLITE_TESTCTRL_ALWAYS = 13;
+    public static final int SQLITE_TESTCTRL_RESERVE = 14;
+    public static final int SQLITE_TESTCTRL_OPTIMIZATIONS = 15;
+    public static final int SQLITE_TESTCTRL_ISKEYWORD = 16;
+    public static final int SQLITE_TESTCTRL_LAST = 16;
+    public static final int SQLITE_STATUS_MEMORY_USED = 0;
+    public static final int SQLITE_STATUS_PAGECACHE_USED = 1;
+    public static final int SQLITE_STATUS_PAGECACHE_OVERFLOW = 2;
+    public static final int SQLITE_STATUS_SCRATCH_USED = 3;
+    public static final int SQLITE_STATUS_SCRATCH_OVERFLOW = 4;
+    public static final int SQLITE_STATUS_MALLOC_SIZE = 5;
+    public static final int SQLITE_STATUS_PARSER_STACK = 6;
+    public static final int SQLITE_STATUS_PAGECACHE_SIZE = 7;
+    public static final int SQLITE_STATUS_SCRATCH_SIZE = 8;
+    public static final int SQLITE_DBSTATUS_LOOKASIDE_USED = 0;
+    public static final int SQLITE_STMTSTATUS_FULLSCAN_STEP = 1;
+    public static final int SQLITE_STMTSTATUS_SORT = 2;
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Database.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Database.java
index fbb5d29..8178836 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Database.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Database.java
@@ -22,17 +22,102 @@
      * Open an SQLite database file.
      *
      * @param filename the name of the database file
-     * @param mode open mode, currently ignored
+     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
      */
 
     public void open(String filename, int mode) throws SQLite.Exception {
-    synchronized(this) {
-        _open(filename, mode);
-    }
+	if ((mode & 0200) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
+		   SQLite.Constants.SQLITE_OPEN_CREATE;
+	} else if ((mode & 0400) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
+	}
+	synchronized(this) {
+	    try {
+		_open4(filename, mode, null, false);
+	    } catch (SQLite.Exception se) {
+		throw se;
+	    } catch (java.lang.OutOfMemoryError me) {
+		throw me;
+	    } catch (Throwable t) {
+		_open(filename, mode);
+	    }
+	}
     }
 
+    /**
+     * Open an SQLite database file.
+     *
+     * @param filename the name of the database file
+     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
+     * @param vfs VFS name (for SQLite >= 3.5)
+     */
+
+    public void open(String filename, int mode, String vfs)
+	throws SQLite.Exception {
+	if ((mode & 0200) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
+		   SQLite.Constants.SQLITE_OPEN_CREATE;
+	} else if ((mode & 0400) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
+	}
+	synchronized(this) {
+	    try {
+		_open4(filename, mode, vfs, false);
+	    } catch (SQLite.Exception se) {
+		throw se;
+	    } catch (java.lang.OutOfMemoryError me) {
+		throw me;
+	    } catch (Throwable t) {
+		_open(filename, mode);
+	    }
+	}
+    }
+
+    /**
+     * Open an SQLite database file.
+     *
+     * @param filename the name of the database file
+     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
+     * @param vfs VFS name (for SQLite >= 3.5)
+     * @param ver2 flag to force version on create (false = SQLite3, true = SQLite2)
+     */
+
+    public void open(String filename, int mode, String vfs, boolean ver2)
+	throws SQLite.Exception {
+	if ((mode & 0200) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
+		   SQLite.Constants.SQLITE_OPEN_CREATE;
+	} else if ((mode & 0400) != 0) {
+	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
+	}
+	synchronized(this) {
+	    try {
+		_open4(filename, mode, vfs, ver2);
+	    } catch (SQLite.Exception se) {
+		throw se;
+	    } catch (java.lang.OutOfMemoryError me) {
+		throw me;
+	    } catch (Throwable t) {
+		_open(filename, mode);
+	    }
+	}
+    }
+
+    /*
+     * For backward compatibility to older sqlite.jar, sqlite_jni
+     */
+
     private native void _open(String filename, int mode)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
+
+    /*
+     * Newer full interface
+     */
+
+    private native void _open4(String filename, int mode, String vfs,
+			       boolean ver2)
+	throws SQLite.Exception;
 
     /**
      * Open SQLite auxiliary database file for temporary
@@ -42,22 +127,22 @@
      */
 
     public void open_aux_file(String filename) throws SQLite.Exception {
-    synchronized(this) {
-        _open_aux_file(filename);
-    }
+	synchronized(this) {
+	    _open_aux_file(filename);
+	}
     }
 
     private native void _open_aux_file(String filename)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Destructor for object.
      */
 
     protected void finalize() {
-    synchronized(this) {
-        _finalize();
-    }
+	synchronized(this) {
+	    _finalize();
+	}
     }
 
     private native void _finalize();
@@ -66,14 +151,14 @@
      * Close the underlying SQLite database file.
      */
 
-    public void close()    throws SQLite.Exception {
-    synchronized(this) {
-        _close();
-    }
+    public void close()	throws SQLite.Exception {
+	synchronized(this) {
+	    _close();
+	}
     }
 
     private native void _close()
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Execute an SQL statement and invoke callback methods
@@ -88,13 +173,13 @@
      */
 
     public void exec(String sql, SQLite.Callback cb) throws SQLite.Exception {
-    synchronized(this) {
-        _exec(sql, cb);
-    }
+	synchronized(this) {
+	    _exec(sql, cb);
+	}
     }
 
     private native void _exec(String sql, SQLite.Callback cb)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Execute an SQL statement and invoke callback methods
@@ -120,14 +205,14 @@
      */
 
     public void exec(String sql, SQLite.Callback cb,
-             String args[]) throws SQLite.Exception {
-    synchronized(this) {
-        _exec(sql, cb, args);
-    }
+		     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;
+	throws SQLite.Exception;
 
     /**
      * Return the row identifier of the last inserted
@@ -135,9 +220,9 @@
      */
 
     public long last_insert_rowid() {
-    synchronized(this) {
-        return _last_insert_rowid();
-    }
+	synchronized(this) {
+	    return _last_insert_rowid();
+	}
     }
 
     private native long _last_insert_rowid();
@@ -147,9 +232,9 @@
      */
 
     public void interrupt() {
-    synchronized(this) {
-        _interrupt();
-    }
+	synchronized(this) {
+	    _interrupt();
+	}
     }
 
     private native void _interrupt();
@@ -159,9 +244,9 @@
      */
 
     public long changes() {
-    synchronized(this) {
-        return _changes();
-    }
+	synchronized(this) {
+	    return _changes();
+	}
     }
 
     private native long _changes();
@@ -174,9 +259,9 @@
      */
 
     public void busy_handler(SQLite.BusyHandler bh) {
-    synchronized(this) {
-        _busy_handler(bh);
-    }
+	synchronized(this) {
+	    _busy_handler(bh);
+	}
     }
 
     private native void _busy_handler(SQLite.BusyHandler bh);
@@ -189,9 +274,9 @@
      */
 
     public void busy_timeout(int ms) {
-    synchronized(this) {
-        _busy_timeout(ms);
-    }
+	synchronized(this) {
+	    _busy_timeout(ms);
+	}
     }
 
     private native void _busy_timeout(int ms);
@@ -201,25 +286,92 @@
      * set into memory.
      *
      * @param sql the SQL statement to be executed
+     * @param maxrows the max. number of rows to retrieve
+     * @return result set
+     */
+
+    public TableResult get_table(String sql, int maxrows)
+	throws SQLite.Exception {
+	TableResult ret = new TableResult(maxrows);
+	if (!is3()) {
+	    try {
+		exec(sql, ret);
+	    } catch (SQLite.Exception e) {
+		if (maxrows <= 0 || !ret.atmaxrows) {
+		    throw e;
+		}
+	    }
+	} else {
+	    synchronized(this) {
+		/* only one statement !!! */
+		Vm vm = compile(sql);
+		set_last_error(vm.error_code);
+		if (ret.maxrows > 0) {
+		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
+			set_last_error(vm.error_code);
+		    }
+		} else {
+		    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
      * @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 get_table(sql, 0);
     }
-    return ret;
+
+    /**
+     * Convenience method to retrieve an entire result
+     * set into memory.
+     *
+     * @param sql the SQL statement to be executed
+     * @param maxrows the max. number of rows to retrieve
+     * @param args arguments for the SQL statement, '%q' substitution
+     * @return result set
+     */
+
+    public TableResult get_table(String sql, int maxrows, String args[])
+	throws SQLite.Exception {
+	TableResult ret = new TableResult(maxrows);
+	if (!is3()) {
+	    try {
+		exec(sql, ret, args);
+	    } catch (SQLite.Exception e) {
+		if (maxrows <= 0 || !ret.atmaxrows) {
+		    throw e;
+		}
+	    }
+	} else {
+	    synchronized(this) {
+		/* only one statement !!! */
+		Vm vm = compile(sql, args);
+		set_last_error(vm.error_code);
+		if (ret.maxrows > 0) {
+		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
+			set_last_error(vm.error_code);
+		    }
+		} else {
+		    while (vm.step(ret)) {
+			set_last_error(vm.error_code);
+		    }
+		}
+		vm.finalize();
+	    }
+	}
+	return ret;
     }
 
     /**
@@ -232,22 +384,8 @@
      */
 
     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;
+	throws SQLite.Exception {
+	return get_table(sql, 0, args);
     }
 
     /**
@@ -261,19 +399,32 @@
      */
 
     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();
-        }
-    }
+	throws SQLite.Exception {
+	tbl.clear();
+	if (!is3()) {
+	    try {
+		exec(sql, tbl, args);
+	    } catch (SQLite.Exception e) {
+		if (tbl.maxrows <= 0 || !tbl.atmaxrows) {
+		    throw e;
+		}
+	    }
+	} else {
+	    synchronized(this) {
+		/* only one statement !!! */
+		Vm vm = compile(sql, args);
+		if (tbl.maxrows > 0) {
+		    while (tbl.nrows < tbl.maxrows && vm.step(tbl)) {
+			set_last_error(vm.error_code);
+		    }
+		} else {
+		    while (vm.step(tbl)) {
+			set_last_error(vm.error_code);
+		    }
+		}
+		vm.finalize();
+	    }
+	}
     }
 
     /**
@@ -285,7 +436,7 @@
      */
 
     public synchronized static boolean complete(String sql) {
-    return _complete(sql);
+	return _complete(sql);
     }
 
     private native static boolean _complete(String sql);
@@ -314,9 +465,9 @@
      */
 
     public void create_function(String name, int nargs, Function f) {
-    synchronized(this) {
-        _create_function(name, nargs, f);
-    }
+	synchronized(this) {
+	    _create_function(name, nargs, f);
+	}
     }
 
     private native void _create_function(String name, int nargs, Function f);
@@ -330,9 +481,9 @@
      */
 
     public void create_aggregate(String name, int nargs, Function f) {
-    synchronized(this) {
-        _create_aggregate(name, nargs, f);
-    }
+	synchronized(this) {
+	    _create_aggregate(name, nargs, f);
+	}
     }
 
     private native void _create_aggregate(String name, int nargs, Function f);
@@ -346,9 +497,9 @@
      */
 
     public void function_type(String name, int type) {
-    synchronized(this) {
-        _function_type(name, type);
-    }
+	synchronized(this) {
+	    _function_type(name, type);
+	}
     }
 
     private native void _function_type(String name, int type);
@@ -364,7 +515,7 @@
      */
 
     public int last_error() {
-    return error_code;
+	return error_code;
     }
 
     /**
@@ -373,7 +524,7 @@
      */
 
     protected void set_last_error(int error_code) {
-    this.error_code = error_code;
+	this.error_code = error_code;
     }
 
     /**
@@ -383,9 +534,9 @@
      */
 
     public String error_message() {
-    synchronized(this) {
-        return _errmsg();
-    }
+	synchronized(this) {
+	    return _errmsg();
+	}
     }
 
     private native String _errmsg();
@@ -405,13 +556,13 @@
      */
 
     public void set_encoding(String enc) throws SQLite.Exception {
-    synchronized(this) {
-        _set_encoding(enc);
-    }
+	synchronized(this) {
+	    _set_encoding(enc);
+	}
     }
 
     private native void _set_encoding(String enc)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Set authorizer function. Only available in SQLite 2.7.6 and
@@ -421,9 +572,9 @@
      */
 
     public void set_authorizer(Authorizer auth) {
-    synchronized(this) {
-        _set_authorizer(auth);
-    }
+	synchronized(this) {
+	    _set_authorizer(auth);
+	}
     }
 
     private native void _set_authorizer(Authorizer auth);
@@ -436,9 +587,9 @@
      */
 
     public void trace(Trace tr) {
-    synchronized(this) {
-        _trace(tr);
-    }
+	synchronized(this) {
+	    _trace(tr);
+	}
     }
 
     private native void _trace(Trace tr);
@@ -452,11 +603,11 @@
      */
 
     public Vm compile(String sql) throws SQLite.Exception {
-    synchronized(this) {
-        Vm vm = new Vm();
-        vm_compile(sql, vm);
-        return vm;
-    }
+	synchronized(this) {
+	    Vm vm = new Vm();
+	    vm_compile(sql, vm);
+	    return vm;
+	}
     }
 
     /**
@@ -469,11 +620,11 @@
      */
 
     public Vm compile(String sql, String args[]) throws SQLite.Exception {
-    synchronized(this) {
-        Vm vm = new Vm();
-        vm_compile_args(sql, vm, args);
-        return vm;
-    }
+	synchronized(this) {
+	    Vm vm = new Vm();
+	    vm_compile_args(sql, vm, args);
+	    return vm;
+	}
     }
 
     /**
@@ -485,11 +636,11 @@
      */
 
     public Stmt prepare(String sql) throws SQLite.Exception {
-    synchronized(this) {
-        Stmt stmt = new Stmt();
-        stmt_prepare(sql, stmt);
-        return stmt;
-    }
+	synchronized(this) {
+	    Stmt stmt = new Stmt();
+	    stmt_prepare(sql, stmt);
+	    return stmt;
+	}
     }
 
     /**
@@ -503,12 +654,12 @@
      */
 
     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;
-    }
+			  long row, boolean rw) throws SQLite.Exception {
+	synchronized(this) {
+	    Blob blob = new Blob();
+	    _open_blob(db, table, column, row, rw, blob);
+	    return blob;
+	}
     }
 
     /**
@@ -525,7 +676,7 @@
      */
 
     private native void vm_compile(String sql, Vm vm)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Internal compile method, SQLite 3.0 only.
@@ -535,7 +686,7 @@
      */
 
     private native void vm_compile_args(String sql, Vm vm, String args[])
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Internal SQLite3 prepare method.
@@ -544,7 +695,7 @@
      */
 
     private native void stmt_prepare(String sql, Stmt stmt)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Internal SQLite open blob method.
@@ -557,8 +708,8 @@
      */
 
     private native void _open_blob(String db, String table, String column,
-                   long row, boolean rw, Blob blob)
-    throws SQLite.Exception;
+				   long row, boolean rw, Blob blob)
+	throws SQLite.Exception;
 
     /**
      * Establish a progress callback method which gets called after
@@ -569,47 +720,186 @@
      */
 
     public void progress_handler(int n, SQLite.ProgressHandler p) {
-    synchronized(this) {
-        _progress_handler(n, p);
-    }
+	synchronized(this) {
+	    _progress_handler(n, p);
+	}
     }
 
     private native void _progress_handler(int n, SQLite.ProgressHandler p);
 
     /**
+     * Specify key for encrypted database. To be called
+     * right after open() on SQLite3 databases.
+     * Not available in public releases of SQLite.
+     *
+     * @param ekey the key as byte array
+     */
+
+    public void key(byte[] ekey) throws SQLite.Exception {
+	synchronized(this) {
+	    _key(ekey);
+	}
+    }
+
+    /**
+     * Specify key for encrypted database. To be called
+     * right after open() on SQLite3 databases.
+     * Not available in public releases of SQLite.
+     *
+     * @param skey the key as String
+     */
+
+    public void key(String skey) throws SQLite.Exception {
+	synchronized(this) {
+	    byte ekey[] = null;
+	    if (skey != null && skey.length() > 0) {
+		ekey = new byte[skey.length()];
+		for (int i = 0; i< skey.length(); i++) {
+		    char c = skey.charAt(i);
+		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
+		}
+	    }
+	    _key(ekey);
+	}
+    }
+
+    private native void _key(byte[] ekey);
+
+    /**
+     * Change the key of a encrypted database. The
+     * SQLite3 database must have been open()ed.
+     * Not available in public releases of SQLite.
+     *
+     * @param ekey the key as byte array
+     */
+
+    public void rekey(byte[] ekey) throws SQLite.Exception {
+	synchronized(this) {
+	    _rekey(ekey);
+	}
+    }
+
+    /**
+     * Change the key of a encrypted database. The
+     * SQLite3 database must have been open()ed.
+     * Not available in public releases of SQLite.
+     *
+     * @param skey the key as String
+     */
+
+    public void rekey(String skey) throws SQLite.Exception {
+	synchronized(this) {
+	    byte ekey[] = null;
+	    if (skey != null && skey.length() > 0) {
+		ekey = new byte[skey.length()];
+		for (int i = 0; i< skey.length(); i++) {
+		    char c = skey.charAt(i);
+		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
+		}
+	    }
+	    _rekey(ekey);
+	}
+    }
+
+    private native void _rekey(byte[] ekey);
+
+    /**
+     * Enable/disable shared cache mode (SQLite 3.x only).
+     *
+     * @param onoff boolean to enable or disable shared cache
+     * @return boolean when true, function supported/succeeded
+     */
+
+    protected static native boolean _enable_shared_cache(boolean onoff);
+
+    /**
      * Internal native initializer.
      */
 
     private static native void internal_init();
 
     /**
+     * Make long value from julian date for java.lang.Date
+     *
+     * @param d double value (julian date in SQLite3 format)
+     * @return long
+     */
+
+    public static long long_from_julian(double d) {
+	d -= 2440587.5;
+	d *= 86400000.0;
+	return (long) d;
+    }
+
+    /**
+     * Make long value from julian date for java.lang.Date
+     *
+     * @param s string (double value) (julian date in SQLite3 format)
+     * @return long
+     */
+
+    public static long long_from_julian(String s) throws SQLite.Exception {
+	try {
+	    double d = Double.valueOf(s).doubleValue();
+	    return long_from_julian(d);
+	} catch (java.lang.Exception ee) {
+	    throw new SQLite.Exception("not a julian date");
+	}
+    }
+
+    /**
+     * Make julian date value from java.lang.Date
+     *
+     * @param ms millisecond value of java.lang.Date
+     * @return double
+     */
+
+    public static double julian_from_long(long ms) {
+	double adj = (ms < 0) ? 0 : 0.5;
+	double d = (ms + adj) / 86400000.0 + 2440587.5;
+	return d;
+    }
+
+    /**
      * 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);
-        }
+	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.err.println("Unable to load sqlite_jni from" +
+				       "SQLite.library.path=" + path +
+				       ", trying system default: " + t);
+		    System.loadLibrary("sqlite_jni");
+		}
+	    }
+	} catch (Throwable t) {
+	    System.err.println("Unable to load sqlite_jni: " + t);
+	}
+	/*
+	 * Call native initializer functions now, since the
+	 * native part could have been linked statically, i.e.
+	 * the try/catch above would have failed in that case.
+	 */
+	try {
+	    internal_init();
+	    new FunctionContext();
+	} catch (java.lang.Exception e) {
+	}
     }
 }
 
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Exception.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Exception.java
index cc26b99..589fa4b 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Exception.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Exception.java
@@ -13,6 +13,6 @@
      */
 
     public Exception(String string) {
-    super(string);
+	super(string);
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java b/libcore/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java
index d0b5182..8509b4d 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/FunctionContext.java
@@ -77,6 +77,6 @@
     private static native void internal_init();
 
     static {
-    internal_init();
+	internal_init();
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java
index 20c98e3..67e95da 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCConnection.java
@@ -22,6 +22,11 @@
     protected String enc;
 
     /**
+     * SQLite 3 VFS to use.
+     */
+    protected String vfs;
+
+    /**
      * Autocommit flag, true means autocommit.
      */
     protected boolean autocommit = true;
@@ -38,6 +43,11 @@
     protected int timeout = 1000000;
 
     /**
+     * Use double/julian date representation.
+     */
+    protected boolean useJulian = false;
+
+    /**
      * File name of database.
      */
     private String dbfile = null;
@@ -57,344 +67,398 @@
      */
     private boolean readonly = false;
 
+    /**
+     * Transaction isolation mode.
+     */
+    private int trmode = TRANSACTION_SERIALIZABLE;
 
     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;
+	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);
+	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;
+	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;
+	DatabaseX dbx = null;
+	try {
+	    dbx = new DatabaseX();
+	    dbx.open(dbfile, readonly ? SQLite.Constants.SQLITE_OPEN_READONLY :
+		     (SQLite.Constants.SQLITE_OPEN_READWRITE |
+		      SQLite.Constants.SQLITE_OPEN_CREATE), vfs);
+	    dbx.set_encoding(enc);
+	} catch (SQLite.Exception e) {
+	    throw new SQLException(e.toString());
+	}
+	int loop = 0;
+	while (true) {
+	    try {
+		dbx.exec("PRAGMA short_column_names = off;", null);
+		dbx.exec("PRAGMA full_column_names = on;", null);
+		dbx.exec("PRAGMA empty_result_callbacks = on;", null);
+		if (SQLite.Database.version().compareTo("2.6.0") >= 0) {
+		    dbx.exec("PRAGMA show_datatypes = on;", null);
+		}
+	    } catch (SQLite.Exception e) {
+		if (dbx.last_error() != SQLite.Constants.SQLITE_BUSY ||
+		    !busy0(dbx, ++loop)) {
+		    try {
+			dbx.close();
+		    } catch (SQLite.Exception ee) {
+		    }
+		    throw new SQLException(e.toString());
+		}
+		continue;
+	    }
+	    break;
+	}
+	return dbx;
     }
 
-    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;
-    }
+    public JDBCConnection(String url, String enc, String pwd, String drep,
+			  String vfs)
+	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;
+	this.vfs = vfs;
+	try {
+	    db = open(readonly);
+	    try {
+		if (pwd != null && pwd.length() > 0) {
+		    db.key(pwd);
+		}
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("error while setting key");
+	    }
+	    db.busy_handler(this);
+	} catch (SQLException e) {
+	    if (db != null) {
+		try {
+		    db.close();
+		} catch (SQLite.Exception ee) {
+		}
+	    }
+	    throw e;
+	}
+	useJulian = drep != null &&
+	    (drep.startsWith("j") || drep.startsWith("J"));
     }
 
     /* non-standard */
     public SQLite.Database getSQLiteDatabase() {
-    return (SQLite.Database) db;
+	return (SQLite.Database) db;
     }
   
     public Statement createStatement() {
-    JDBCStatement s = new JDBCStatement(this);
-    return s;
+	JDBCStatement s = new JDBCStatement(this);
+	return s;
     }
-  
+
     public Statement createStatement(int resultSetType,
-                     int resultSetConcurrency)
-    throws SQLException {
-    JDBCStatement s = new JDBCStatement(this);
-    return s;
+				     int resultSetConcurrency)
+	throws SQLException {
+	if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
+	    resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
+	    resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    throw new SQLException("unsupported result set type");
+	}
+	if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
+	    resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
+	    throw new SQLException("unsupported result set concurrency");
+	}
+	JDBCStatement s = new JDBCStatement(this);
+	return s;
     }
-    
+	
     public DatabaseMetaData getMetaData() throws SQLException {
-    if (meta == null) {
-        meta = new JDBCDatabaseMetaData(this);
-    }
-    return meta;
+	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());
-        }
-    }
+	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;
+	return db == null;
     }
 
     public boolean isReadOnly() throws SQLException {
-    return readonly;
+	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());
-    }
+	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;
+	return autocommit;
     }
 
     public String getCatalog() throws SQLException {
-    return null;
+	return null;
     }
 
     public int getTransactionIsolation() throws SQLException {
-    return TRANSACTION_SERIALIZABLE;
+	return trmode;
     }
 
     public SQLWarning getWarnings() throws SQLException {
-    return null;
+	return null;
     }
 
     public String nativeSQL(String sql) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public CallableStatement prepareCall(String sql) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public CallableStatement prepareCall(String sql, int x, int y)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public PreparedStatement prepareStatement(String sql) throws SQLException {
-    JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
-    return s;
+	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;
+					      int resultSetConcurrency)
+	throws SQLException {
+	if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
+	    resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
+	    resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    throw new SQLException("unsupported result set type");
+	}
+	if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
+	    resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
+	    throw new SQLException("unsupported result set concurrency");
+	}
+	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());
-    }
+	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;
+	if (ac && intrans && db != null) {
+	    try {
+		db.exec("ROLLBACK", null);
+	    } catch (SQLite.Exception e) {
+		throw new SQLException(e.toString());
+	    } finally {
+		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());
-        }
-    }
+	if (intrans) {
+	    throw new SQLException("incomplete transaction");
+	}
+	if (ro != readonly) {
+	    DatabaseX dbx = null;
+	    try {
+		dbx = open(ro);
+		db.close();
+		db = dbx;
+		dbx = null;
+		readonly = ro;
+	    } catch (SQLException e) {
+		throw e;
+	    } catch (SQLite.Exception ee) {
+		if (dbx != null) {
+		    try {
+			dbx.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");
-    }
+	if (db.is3() && SQLite.JDBCDriver.sharedCache) {
+	    String flag = null;
+	    if (level == TRANSACTION_READ_UNCOMMITTED &&
+		trmode != TRANSACTION_READ_UNCOMMITTED) {
+		flag = "on";
+	    } else if (level == TRANSACTION_SERIALIZABLE &&
+		       trmode != TRANSACTION_SERIALIZABLE) {
+		flag = "off";
+	    }
+	    if (flag != null) {
+		try {
+		    db.exec("PRAGMA read_uncommitted = " + flag + ";", null);
+		    trmode = level;
+		} catch (java.lang.Exception e) {
+		}
+	    }
+	}
+	if (level != trmode) {
+	    throw new SQLException("not supported");
+	}
     }
 
     public java.util.Map<String, Class<?>> getTypeMap() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setTypeMap(java.util.Map map) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
   
     public int getHoldability() throws SQLException {
-    return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+	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");
+	if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+	    return;
+	}
+	throw new SQLException("not supported");
     }
 
     public Savepoint setSavepoint() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Savepoint setSavepoint(String name) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void rollback(Savepoint x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void releaseSavepoint(Savepoint x) throws SQLException {
-    throw new SQLException("not supported");
+	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);
+				     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);
+					      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");
+	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);
+	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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public PreparedStatement prepareStatement(String sql, String columns[])
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
 }
@@ -404,49 +468,49 @@
     static Object lock = new Object();
 
     public DatabaseX() {
-    super();
+	super();
     }
 
     void wait(int ms) {
-    try {
-        synchronized (lock) {
-        lock.wait(ms);
-        }
-    } catch (java.lang.Exception e) {
-    }
+	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();
-    }
+	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();
-    }
+	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;
+	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();
-    }
+	throws SQLite.Exception {
+	super.get_table(sql, args, tbl);
+	synchronized (lock) {
+	    lock.notifyAll();
+	}
     }
 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
index 8c14d1d..878e06e 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
@@ -8,1571 +8,1640 @@
     private JDBCConnection conn;
 
     public JDBCDatabaseMetaData(JDBCConnection conn) {
-    this.conn = conn;
+	this.conn = conn;
     }
 
     public boolean allProceduresAreCallable() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean allTablesAreSelectable() throws SQLException {
-    return true;
+	return true;
     }
 
     public String getURL() throws SQLException {
-    return conn.url;
+	return conn.url;
     }
 
     public String getUserName() throws SQLException {
-    return "";
+	return "";
     }
 
     public boolean isReadOnly() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean nullsAreSortedHigh() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean nullsAreSortedLow() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean nullsAreSortedAtStart() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean nullsAreSortedAtEnd() throws SQLException {
-    return false;
+	return false;
     }
 
     public String getDatabaseProductName() throws SQLException {
-    return "SQLite";
+	return "SQLite";
     }
 
     public String getDatabaseProductVersion() throws SQLException {
-    return SQLite.Database.version();
+	return SQLite.Database.version();
     }
 
     public String getDriverName() throws SQLException {
-    return "SQLite/JDBC";
+	return "SQLite/JDBC";
     }
 
     public String getDriverVersion() throws SQLException {
-    return "" + SQLite.JDBCDriver.MAJORVERSION + "." +
-        SQLite.JDBCDriver.MINORVERSION;
+	return "" + SQLite.JDBCDriver.MAJORVERSION + "." +
+	    SQLite.Constants.drv_minor;
     }
 
     public int getDriverMajorVersion() {
-    return SQLite.JDBCDriver.MAJORVERSION;
+	return SQLite.JDBCDriver.MAJORVERSION;
     }
 
     public int getDriverMinorVersion() {
-    return SQLite.JDBCDriver.MINORVERSION;
+	return SQLite.Constants.drv_minor;
     }
 
     public boolean usesLocalFiles() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean usesLocalFilePerTable() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsMixedCaseIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesUpperCaseIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesLowerCaseIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesMixedCaseIdentifiers() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
-    return true;
+	return true;
     }
 
     public String getIdentifierQuoteString() throws SQLException {
-    return "\"";
+	return "\"";
     }
 
     public String getSQLKeywords() throws SQLException {
-    return "SELECT,UPDATE,CREATE,TABLE,VIEW,DELETE,FROM,WHERE" +
-        ",COMMIT,ROLLBACK,TRIGGER";
+	return "SELECT,UPDATE,CREATE,TABLE,VIEW,DELETE,FROM,WHERE" +
+	    ",COMMIT,ROLLBACK,TRIGGER";
     }
 
     public String getNumericFunctions() throws SQLException {
-    return ""; 
+	return ""; 
     }
 
     public String getStringFunctions() throws SQLException {
-    return "";
+	return "";
     }
 
     public String getSystemFunctions() throws SQLException {
-    return "";
+	return "";
     }
 
     public String getTimeDateFunctions() throws SQLException {
-    return "";
+	return "";
     }
 
     public String getSearchStringEscape() throws SQLException {
-    return "\\";
+	return "\\";
     }
 
     public String getExtraNameCharacters() throws SQLException {
-    return "";
+	return "";
     }
 
     public boolean supportsAlterTableWithAddColumn() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsAlterTableWithDropColumn() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsColumnAliasing() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean nullPlusNonNullIsNull() throws SQLException {
-    return false;
+	return false;
     }
     
     public boolean supportsConvert() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsConvert(int fromType, int toType)
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean supportsTableCorrelationNames() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsDifferentTableCorrelationNames()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean supportsExpressionsInOrderBy() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsOrderByUnrelated() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsGroupBy() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsGroupByUnrelated() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsGroupByBeyondSelect() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsLikeEscapeClause() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsMultipleResultSets() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsMultipleTransactions() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsNonNullableColumns() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsMinimumSQLGrammar() throws SQLException {
-    return true;
+	return true;
     } 
 
     public boolean supportsCoreSQLGrammar() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsExtendedSQLGrammar() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsANSI92EntryLevelSQL() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsANSI92IntermediateSQL() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsANSI92FullSQL() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsIntegrityEnhancementFacility()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean supportsOuterJoins() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsFullOuterJoins() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsLimitedOuterJoins() throws SQLException {
-    return false;
+	return false;
     }
 
     public String getSchemaTerm() throws SQLException {
-    return "";
+	return "";
     }
 
     public String getProcedureTerm() throws SQLException {
-    return "";
+	return "";
     }
 
     public String getCatalogTerm() throws SQLException {
-    return "";
+	return "";
     }
 
     public boolean isCatalogAtStart() throws SQLException {
-    return false;
+	return false;
     }
 
     public String getCatalogSeparator() throws SQLException {
-    return "";
+	return "";
     }
 
     public boolean supportsSchemasInDataManipulation() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsSchemasInProcedureCalls() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsSchemasInTableDefinitions() throws SQLException {
-    return false;
+	return false;
     }
     
     public boolean supportsSchemasInIndexDefinitions() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsSchemasInPrivilegeDefinitions()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean supportsCatalogsInDataManipulation() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsCatalogsInProcedureCalls() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsCatalogsInTableDefinitions() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsCatalogsInPrivilegeDefinitions()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean supportsPositionedDelete() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsPositionedUpdate() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsSelectForUpdate() throws SQLException {
-    return true;
+	return false;
     }
 
     public boolean supportsStoredProcedures() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsSubqueriesInComparisons() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsSubqueriesInExists() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsSubqueriesInIns() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsSubqueriesInQuantifieds() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsCorrelatedSubqueries() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsUnion() throws SQLException {
-    return false;
+	return true;
     }
 
     public boolean supportsUnionAll() throws SQLException {
-    return false;
+	return true;
     }
 
     public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
-    return false;
+	return false;
     }
 
     public int getMaxBinaryLiteralLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxCharLiteralLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnsInGroupBy() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnsInIndex() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnsInOrderBy() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnsInSelect() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxColumnsInTable() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxConnections() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxCursorNameLength() throws SQLException {
-    return 8;
+	return 8;
     }
 
     public int getMaxIndexLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxSchemaNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxProcedureNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxCatalogNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxRowSize() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
-    return true;
+	return true;
     }
 
     public int getMaxStatementLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxStatements() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxTableNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxTablesInSelect() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getMaxUserNameLength() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public int getDefaultTransactionIsolation() throws SQLException {
-    return Connection.TRANSACTION_SERIALIZABLE;
+	return Connection.TRANSACTION_SERIALIZABLE;
     }
 
     public boolean supportsTransactions() throws SQLException {
-    return true;
+	return true;
     }
 
     public boolean supportsTransactionIsolationLevel(int level)
-    throws SQLException {
-    return level == Connection.TRANSACTION_SERIALIZABLE;
+	throws SQLException {
+	return level == Connection.TRANSACTION_SERIALIZABLE;
     }
 
     public boolean supportsDataDefinitionAndDataManipulationTransactions()
-    throws SQLException {
-    return true;
+	throws SQLException {
+	return true;
     }
 
     public boolean supportsDataManipulationTransactionsOnly()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean dataDefinitionCausesTransactionCommit()
-    throws SQLException {
-    return false;
+	throws SQLException {
+	return false;
     }
 
     public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
-    return false;
+	return false;
     }
 
     public ResultSet getProcedures(String catalog, String schemaPattern,
-                   String procedureNamePattern)
-    throws SQLException {
-    return null;
+				   String procedureNamePattern)
+	throws SQLException {
+	return null;
     }
 
     public ResultSet getProcedureColumns(String catalog,
-                     String schemaPattern,
-                     String procedureNamePattern, 
-                     String columnNamePattern)
-    throws SQLException {
-    return null;
+					 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;
+			       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;
+	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;
+	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;
+	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;
+				String tableNamePattern,
+				String columnNamePattern)
+	throws SQLException {
+	if (conn.db == null) {
+	    throw new SQLException("connection closed");
+	}
+	JDBCStatement s = new JDBCStatement(conn);
+	JDBCResultSet rs0 = null;
+	try {
+	    try {
+		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("schema reload failed");
+	    }
+	    rs0 = (JDBCResultSet)
+		(s.executeQuery("PRAGMA table_info(" +
+				SQLite.Shell.sql_quote(tableNamePattern) +
+				")"));
+	    s.close();
+	} catch (SQLException e) {
+	    throw e;
+	} finally {
+	    s.close();
+	}
+	if (rs0.tr.nrows < 1) {
+	    throw new SQLException("no such table: " + tableNamePattern);
+	}
+	String cols[] = {
+	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+	    "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME",
+	    "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS",
+	    "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;
+					 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;
+					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;
+					  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 {
+	    try {
+		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("schema reload failed");
+	    }
+	    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;
+				       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;
+				    String table) throws SQLException {
+	JDBCStatement s0 = new JDBCStatement(conn);
+	JDBCResultSet rs0 = null;
+	try {
+	    try {
+		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("schema reload failed");
+	    }
+	    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();
+		    row[4]  = "" + (Integer.valueOf(r1[col]).intValue() + 1);
+		    row[5]  = iname;
+		    tr.newrow(row);
+		}
+	    }
+	}
+	if (tr.nrows > 0) {
+	    return rs;
+	}
+	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();
+		row[4] = "" + (Integer.valueOf(r0[col]).intValue() + 1);
+		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);
-    }
+				      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 fkcol = r0[col];
+	    col = ((Integer) h0.get("to")).intValue();
+	    String pkcol = 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;
+	    row[8]  = "" + ((Integer.valueOf(seq)).intValue() + 1);
+	    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;
+				     String table) throws SQLException {
+	JDBCStatement s0 = new JDBCStatement(conn);
+	JDBCResultSet rs0 = null;
+	try {
+	    try {
+		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("schema reload failed");
+	    }
+	    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;
+				     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;
+				       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 {
+		try {
+		    conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+		} catch (SQLite.Exception se) {
+		    throw new SQLException("schema reload failed");
+		}
+		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;
+	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);
+	String row12[] = {
+	    "REAL", "" + Types.REAL, "16",
+	    null, null, null,
+	    "" + typeNullable, "0", "" + typeSearchable,
+	    "0", "0", "1",
+	    null, "0", "0",
+	    "0", "0", "10"
+	};
+	tr.newrow(row12);
+	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;
+				  boolean unique, boolean approximate)
+	throws SQLException {
+	JDBCStatement s0 = new JDBCStatement(conn);
+	JDBCResultSet rs0 = null;
+	try {
+	    try {
+		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
+	    } catch (SQLite.Exception se) {
+		throw new SQLException("schema reload failed");
+	    }
+	    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();
+		    row[7]  = "" + (Integer.valueOf(r1[col]).intValue() + 1);
+		    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;
+	return type == ResultSet.TYPE_FORWARD_ONLY ||
+	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
+	    type == ResultSet.TYPE_SCROLL_SENSITIVE;
     }
 
     public boolean supportsResultSetConcurrency(int type, int concurrency)
-    throws SQLException {
-    return false;
+	throws SQLException {
+	if (type == ResultSet.TYPE_FORWARD_ONLY ||
+	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
+	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    return concurrency == ResultSet.CONCUR_READ_ONLY ||
+		concurrency == ResultSet.CONCUR_UPDATABLE;
+	}
+	return false;
     }
 
     public boolean ownUpdatesAreVisible(int type) throws SQLException {
-    return false;
+	if (type == ResultSet.TYPE_FORWARD_ONLY ||
+	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
+	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    return true;
+	}
+	return false;
     }
 
     public boolean ownDeletesAreVisible(int type) throws SQLException {
-    return false;
+	if (type == ResultSet.TYPE_FORWARD_ONLY ||
+	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
+	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    return true;
+	}
+	return false;
     }
 
     public boolean ownInsertsAreVisible(int type) throws SQLException {
-    return false;
+	if (type == ResultSet.TYPE_FORWARD_ONLY ||
+	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
+	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
+	    return true;
+	}
+	return false;
     }
 
     public boolean othersUpdatesAreVisible(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean othersDeletesAreVisible(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean othersInsertsAreVisible(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean updatesAreDetected(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean deletesAreDetected(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean insertsAreDetected(int type) throws SQLException {
-    return false;
+	return false;
     }
 
     public boolean supportsBatchUpdates() throws SQLException {
-    return false;
+	return true;
     }
 
     public ResultSet getUDTs(String catalog, String schemaPattern, 
-              String typeNamePattern, int[] types) 
-    throws SQLException {
-    return null;
+		      String typeNamePattern, int[] types) 
+	throws SQLException {
+	return null;
     }
 
     public Connection getConnection() throws SQLException {
-    return conn;
+	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";
+	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";
+	case Types.REAL:	return "real";
+	}
+	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;
+	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;
+	}
+	if (type.startsWith("real")) {
+	    return Types.REAL;
+	}
+	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;
+	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.REAL:
+	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;
+	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.REAL:
+	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;
+	return false;
     }
 
     public boolean supportsNamedParameters() {
-    return false;
+	return false;
     }
 
     public boolean supportsMultipleOpenResults() {
-    return false;
+	return false;
     }
 
     public boolean supportsGetGeneratedKeys() {
-    return false;
+	return false;
     }
 
     public boolean supportsResultSetHoldability(int x) {
-    return false;
+	return false;
     }
 
     public boolean supportsStatementPooling() {
-    return false;
+	return false;
     }
 
     public boolean locatorsUpdateCopy() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public ResultSet getSuperTypes(String catalog, String schemaPattern,
-                String typeNamePattern)
-    throws SQLException {
-    throw new SQLException("not supported");
+			    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");
+				    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");
+				   String typeNamePattern,
+				   String attributeNamePattern)
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public int getResultSetHoldability() throws SQLException {
-    return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+	return ResultSet.HOLD_CURSORS_OVER_COMMIT;
     }
 
     public int getDatabaseMajorVersion() {
-    return SQLite.JDBCDriver.MAJORVERSION;
+	return SQLite.JDBCDriver.MAJORVERSION;
     }
 
     public int getDatabaseMinorVersion() {
-    return SQLite.JDBCDriver.MINORVERSION;
+	return SQLite.Constants.drv_minor;
     }
 
     public int getJDBCMajorVersion() {
-    return 1;
+	return 1;
     }
     
     public int getJDBCMinorVersion() {
-    return 0;
+	return 0;
     }
 
     public int getSQLStateType() throws SQLException {
-    return sqlStateXOpen;
+	return sqlStateXOpen;
     }
 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
index ab81867..3d5b045 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
@@ -9,12 +9,12 @@
     boolean blob;
 
     BatchArg(String arg, boolean blob) {
-    if (arg == null) {
-        this.arg = null;
-    } else {
-        this.arg = new String(arg);
-    }
-    this.blob = blob;
+	if (arg == null) {
+	    this.arg = null;
+	} else {
+	    this.arg = new String(arg);
+	}
+	this.blob = blob;
     }
 }
 
@@ -26,727 +26,756 @@
     private boolean blobs[];
     private ArrayList<BatchArg> batch;
     private static final boolean nullrepl =
-    SQLite.Database.version().compareTo("2.5.0") < 0;
+	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);
+	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) {
+	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 == '\'') {
+		    if (nextChar == '\'') {
                         sb.append(c);
                         sb.append(nextChar);
                         i++;
                     } else {
-            inq = false;
+			inq = false;
                         sb.append(c);
                     }
-        } else {
-            inq = true;
+		} 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();
+		}
+	    } 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();
+	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);
+	return executeQuery(fixup2(sql), args, false);
     }
 
     public int executeUpdate() throws SQLException {
-    executeQuery(fixup2(sql), args, true);
-    return updcnt;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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;
+	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);
-        }
-    }
+	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;
+	throws SQLException {
+	if (parameterIndex < 1 || parameterIndex > args.length) {
+	    throw new SQLException("bad parameter index");
+	}
+	if (x == null) {
+	    args[parameterIndex - 1] = nullrepl ? "" : null;
+	} else {
+	    if (conn.useJulian) {
+		args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime()));
+	    } 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;
+	throws SQLException {
+	if (parameterIndex < 1 || parameterIndex > args.length) {
+	    throw new SQLException("bad parameter index");
+	}
+	if (x == null) {
+	    args[parameterIndex - 1] = nullrepl ? "" : null;
+	} else {
+	    if (conn.useJulian) {
+		args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime()));
+	    } 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;
+	throws SQLException {
+	if (parameterIndex < 1 || parameterIndex > args.length) {
+	    throw new SQLException("bad parameter index");
+	}
+	if (x == null) {
+	    args[parameterIndex - 1] = nullrepl ? "" : null;
+	} else {
+	    if (conn.useJulian) {
+		args[parameterIndex - 1] = java.lang.Double.toString(SQLite.Database.julian_from_long(x.getTime()));
+	    } 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");
+			       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");
+				 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");
+				int length) throws SQLException {
+	try {
+	    byte[] data = new byte[length];
+	    x.read(data, 0, length);
+	    setBytes(parameterIndex, data);
+	} catch (java.io.IOException e) {
+	    throw new SQLException("I/O failed");
+	}
     }
 
     public void clearParameters() throws SQLException {
-    for (int i = 0; i < args.length; i++) {
-        args[i] = nullrepl ? "" : null;
-        blobs[i] = false;
-    }
+	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;
+			  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;
+	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;
+	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;
+	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]));
-    }
+	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++);
+	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;
+		args[k] = b.arg;
+		blobs[k] = 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;
+	if (batch != null) {
+	    batch.clear();
+	    batch = null;
+	}
     }
+
+    public void close() throws SQLException {
+    	clearBatch();
+	super.close();
     }
 
     public void setCharacterStream(int parameterIndex,
-                   java.io.Reader reader,
-                   int length) throws SQLException {
-    throw new SQLException("not supported");
+				   java.io.Reader reader,
+				   int length) throws SQLException {
+	try {
+	    char[] data = new char[length];
+	    reader.read(data);
+	    setString(parameterIndex, new String(data));
+	} catch (java.io.IOException e) {
+	    throw new SQLException("I/O failed");
+	}
     }
 
     public void setRef(int i, Ref x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setBlob(int i, Blob x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setClob(int i, Clob x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setArray(int i, Array x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public ResultSetMetaData getMetaData() throws SQLException {
-    return rs.getMetaData();
+	return rs.getMetaData();
     }
 
     public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
-    throws SQLException {
-    setDate(parameterIndex, x);
+	throws SQLException {
+	setDate(parameterIndex, x);
     }
 
     public void setTime(int parameterIndex, java.sql.Time x, Calendar cal)
-    throws SQLException {
-    setTime(parameterIndex, x);
+	throws SQLException {
+	setTime(parameterIndex, x);
     }
 
     public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
-                 Calendar cal) throws SQLException {
-    setTimestamp(parameterIndex, x);
+			     Calendar cal) throws SQLException {
+	setTimestamp(parameterIndex, x);
     }
 
     public void setNull(int parameterIndex, int sqlType, String typeName)
-    throws SQLException {
-    setNull(parameterIndex, sqlType);
+	throws SQLException {
+	setNull(parameterIndex, sqlType);
     }
 
     public ParameterMetaData getParameterMetaData() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void registerOutputParameter(String parameterName, int sqlType)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void registerOutputParameter(String parameterName, int sqlType,
-                    int scale)
-    throws SQLException {
-    throw new SQLException("not supported");
+					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");
+					String typeName)
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.net.URL getURL(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setURL(int parameterIndex, java.net.URL url)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setNull(String parameterName, int sqlType)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setBoolean(String parameterName, boolean val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setByte(String parameterName, byte val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setShort(String parameterName, short val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setInt(String parameterName, int val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setLong(String parameterName, long val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setFloat(String parameterName, float val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setDouble(String parameterName, double val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setBigDecimal(String parameterName, BigDecimal val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setString(String parameterName, String val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setBytes(String parameterName, byte val[])
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setDate(String parameterName, java.sql.Date val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setTime(String parameterName, java.sql.Time val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setTimestamp(String parameterName, java.sql.Timestamp val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	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");
+			       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");
+				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");
+			  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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void setObject(String parameterName, Object val)
-    throws SQLException {
-    throw new SQLException("not supported");
+	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");
+				   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");
+			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");
+			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");
+			     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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public String getString(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public boolean getBoolean(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public byte getByte(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public short getShort(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public int getInt(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public long getLong(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public float getFloat(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public double getDouble(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public byte[] getBytes(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Date getDate(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Time getTime(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Timestamp getTimestamp(String parameterName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public Object getObject(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Object getObject(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public BigDecimal getBigDecimal(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Object getObject(String parameterName, Map map)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public Object getObject(int parameterIndex, Map map)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public Ref getRef(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Ref getRef(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Blob getBlob(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Blob getBlob(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Clob getClob(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Clob getClob(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Array getArray(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public Array getArray(int parameterIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Date getDate(String parameterName, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Date getDate(int parameterIndex, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Time getTime(String parameterName, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Time getTime(int parameterIndex, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.net.URL getURL(String parameterName) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
index 06384eb..1ecd846 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
@@ -23,910 +23,1292 @@
     /**
      * Meta data for result set or null.
      */
-    private JDBCResultSetMetaData m;
+    private JDBCResultSetMetaData md;
 
     /**
      * Last result cell retrieved or null.
      */
     private String lastg;
 
+    /**
+     * Updatability of this result set.
+     */
+    private int updatable;
+
+    /**
+     * When updatable this is the table name.
+     */
+    private String uptable;
+
+    /**
+     * When updatable these are the PK column names of uptable.
+     */
+    private String pkcols[];
+
+    /**
+     * When updatable these are the PK column indices (0-based) of uptable.
+     */
+    private int pkcoli[];
+
+    /*
+     * Constants to reflect updateability.
+     */
+    private final static int UPD_UNKNOWN = -1;
+    private final static int UPD_NO = 0;
+    private final static int UPD_INS = 1;
+    private final static int UPD_INSUPDDEL = 2;
+
+    /**
+     * Flag for cursor being (not) on insert row.
+     */
+    private boolean oninsrow;
+
+    /**
+     * Row buffer for insert/update row.
+     */
+    private String rowbuf[];
+
+    private static final boolean nullrepl =
+        SQLite.Database.version().compareTo("2.5.0") < 0;
 
     public JDBCResultSet(SQLite.TableResult tr, JDBCStatement s) {
-    this.tr = tr;
-    this.s = s;
-    this.m = null;
-    this.lastg = null;
-    this.row = -1;
+	this.tr = tr;
+	this.s = s;
+	this.md = null;
+	this.lastg = null;
+	this.row = -1;
+	this.updatable = UPD_UNKNOWN;
+	this.oninsrow = false;
+	this.rowbuf = null;
+    }
+
+    public boolean isUpdatable() throws SQLException {
+	if (updatable == UPD_UNKNOWN) {
+	    try {
+		JDBCResultSetMetaData m =
+		    (JDBCResultSetMetaData) getMetaData();
+		java.util.HashSet<String> h = new java.util.HashSet<String>();
+		String lastt = null;
+		for (int i = 1; i <= tr.ncolumns; i++) {
+		    lastt = m.getTableName(i);
+		    h.add(lastt);
+		}
+		if (h.size() > 1 || lastt == null) {
+		    updatable = UPD_NO;
+		    throw new SQLException("view or join");
+		}
+		updatable = UPD_INS;
+		uptable = lastt;
+		JDBCResultSet pk = (JDBCResultSet)
+		    s.conn.getMetaData().getPrimaryKeys(null, null, uptable);
+		if (pk.tr.nrows > 0) {
+		    boolean colnotfound = false;
+		    pkcols = new String[pk.tr.nrows];
+		    pkcoli = new int[pk.tr.nrows];
+		    for (int i = 0; i < pk.tr.nrows; i++) {
+			String rd[] = (String []) pk.tr.rows.elementAt(i);
+			pkcols[i] = rd[3];
+			try {
+			    pkcoli[i] = findColumn(pkcols[i]) - 1;
+			} catch (SQLException ee) {
+			    colnotfound = true;
+			}
+		    }
+		    if (!colnotfound) {
+			updatable = UPD_INSUPDDEL;
+		    }
+		}
+		pk.close();
+	    } catch (SQLException e) {
+		updatable = UPD_NO;
+	    }
+	}
+	if (updatable < UPD_INS) {
+	    throw new SQLException("result set not updatable");
+	}
+	return true;
+    }
+
+    public void fillRowbuf() throws SQLException {
+	if (rowbuf == null) {
+	    if (row < 0) {
+		throw new SQLException("cursor outside of result set");
+	    }
+	    rowbuf = new String[tr.ncolumns];
+	    System.arraycopy((String []) tr.rows.elementAt(row), 0,
+			     rowbuf, 0, tr.ncolumns);
+	}
     }
 
     public boolean next() throws SQLException {
-    if (tr == null) {
-        return false;
-    }
-    row++;
-    return row < tr.nrows;
+	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);
+	JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+	return m.findColByName(columnName);
     }
   
     public int getRow() throws SQLException {
-    if (tr == null) {
-        throw new SQLException("no rows");
-    }
-    return row + 1;
+	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;
+	if (tr == null) {
+	    // BEGIN android-changed: throw rather than return false.
+	    throw new SQLException("ResultSet already closed");
+	    // END android-changed
+	}
+	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;
+	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;
+	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");
+	if (dir != ResultSet.FETCH_FORWARD) {
+	    throw new SQLException("not supported");
+	}
     }
 
     public int getFetchDirection() throws SQLException {
-    throw new SQLException("not supported");
+	return ResultSet.FETCH_FORWARD;
     }
 
     public void setFetchSize(int fsize) throws SQLException {
-    throw new SQLException("not supported");
+	if (fsize != 1) {
+	    throw new SQLException("not supported");
+	}
     }
 
     public int getFetchSize() throws SQLException {
-    throw new SQLException("not supported");
+	return 1;
     }
 
     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;
+	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);
+	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;
+	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;
+	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);
+	int col = findColumn(columnName);
+	return getInt(col);
     }
 
     public boolean getBoolean(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	return getInt(columnIndex) == 1 ||
+	    Boolean.valueOf(getString(columnIndex)).booleanValue();
     }
 
     public boolean getBoolean(String columnName) throws SQLException {
-    throw new SQLException("not supported");
+	int col = findColumn(columnName);
+	return getBoolean(col);
     }
 
     public ResultSetMetaData getMetaData() throws SQLException {
-    if (m == null) {
-        m = new JDBCResultSetMetaData(this);
-    }
-    return m;
+	if (md == null) {
+	    md = new JDBCResultSetMetaData(this);
+	}
+	return md;
     }
 
     public short getShort(int columnIndex) throws SQLException {
-    Short s = internalGetShort(columnIndex);
-    if (s != null) {
-        return s.shortValue();
-    }
-    return 0;
+	Short sh = internalGetShort(columnIndex);
+	if (sh != null) {
+	    return sh.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;
+	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);
+	int col = findColumn(columnName);
+	return getShort(col);
     }
 
     public java.sql.Time getTime(int columnIndex) throws SQLException {
-    return internalGetTime(columnIndex, null);
+	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;
+					  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 {
+	    if (s.conn.useJulian) {
+		try {
+		    return new java.sql.Time(SQLite.Database.long_from_julian(lastg));
+		} catch (java.lang.Exception ee) {
+		    return java.sql.Time.valueOf(lastg);
+		}
+	    } else {
+		try {
+		    return java.sql.Time.valueOf(lastg);
+		} catch (java.lang.Exception ee) {
+		    return new java.sql.Time(SQLite.Database.long_from_julian(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);
+	int col = findColumn(columnName);
+	return getTime(col);
     }
 
     public java.sql.Time getTime(int columnIndex, java.util.Calendar cal)
-    throws SQLException {
-    return internalGetTime(columnIndex, 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);
+	throws SQLException{
+	int col = findColumn(columnName);
+	return getTime(col, cal);
     }
 
     public java.sql.Timestamp getTimestamp(int columnIndex)
-    throws SQLException{
-    return internalGetTimestamp(columnIndex, null);
+	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;
+						    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 {
+	    if (s.conn.useJulian) {
+		try {
+		    return new java.sql.Timestamp(SQLite.Database.long_from_julian(lastg));
+		} catch (java.lang.Exception ee) {
+		    return java.sql.Timestamp.valueOf(lastg);
+		}
+	    } else {
+		try {
+		    return java.sql.Timestamp.valueOf(lastg);
+		} catch (java.lang.Exception ee) {
+		    return new java.sql.Timestamp(SQLite.Database.long_from_julian(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);
+	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);
+					   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);
+					   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);
+	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;
+					  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 {
+	    if (s.conn.useJulian) {
+		try {
+		    return new java.sql.Date(SQLite.Database.long_from_julian(lastg));
+		} catch (java.lang.Exception ee) {
+		    return java.sql.Date.valueOf(lastg);
+		}
+	    } else {
+		try {
+		    return java.sql.Date.valueOf(lastg);
+		} catch (java.lang.Exception ee) {
+		    return new java.sql.Date(SQLite.Database.long_from_julian(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);
+	int col = findColumn(columnName);
+	return getDate(col);
     }
 
     public java.sql.Date getDate(int columnIndex, java.util.Calendar cal)
-    throws SQLException{
-    return internalGetDate(columnIndex, 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);
+	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;
+	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;
+	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);
+	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;
+	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;
+	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);
+	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;
+	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;
+	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);
+	int col = findColumn(columnName);
+	return getLong(col);
     }
 
     @Deprecated
     public java.io.InputStream getUnicodeStream(int columnIndex)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     @Deprecated
     public java.io.InputStream getUnicodeStream(String columnName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.io.InputStream getAsciiStream(String columnName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.io.InputStream getAsciiStream(int columnIndex)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public BigDecimal getBigDecimal(String columnName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.io.InputStream getBinaryStream(int columnIndex)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	byte data[] = getBytes(columnIndex);
+	if (data != null) {
+	    return new java.io.ByteArrayInputStream(data);
+	}
+	return null;
     }
 
     public java.io.InputStream getBinaryStream(String columnName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	byte data[] = getBytes(columnName);
+	if (data != null) {
+	    return new java.io.ByteArrayInputStream(data);
+	}
+	return null;
     }
 
     public byte getByte(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public byte getByte(String columnName) throws SQLException {
-    throw new SQLException("not supported");
+	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;
+	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);
+	int col = findColumn(columnName);
+	return getBytes(col);
     }
 
     public String getCursorName() throws SQLException {
-    return null;
+	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;
+	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);
+	int col = findColumn(columnName);
+	return getObject(col);
     }
 
     public Object getObject(int columnIndex, java.util.Map map) 
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public Object getObject(String columnIndex, java.util.Map map)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public java.sql.Ref getRef(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Ref getRef(String columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Blob getBlob(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Blob getBlob(String columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Clob getClob(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Clob getClob(String columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Array getArray(int columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.sql.Array getArray(String columnIndex) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public java.io.Reader getCharacterStream(int columnIndex)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	String data = getString(columnIndex);
+	if (data != null) {
+	    char[] cdata = data.toCharArray();
+	    return new java.io.CharArrayReader(cdata);
+	}
+	return null;
     }
 
     public java.io.Reader getCharacterStream(String columnName)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	String data = getString(columnName);
+	if (data != null) {
+	    char[] cdata = data.toCharArray();
+	    return new java.io.CharArrayReader(cdata);
+	}
+	return null;
     }
 
     public SQLWarning getWarnings() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public boolean wasNull() throws SQLException {
-    return lastg == null;
+	return lastg == null;
     }
-    
+	
     public void clearWarnings() throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public boolean isFirst() throws SQLException {
-    if (tr == null) {
-        return true;
-    }
-    return row == 0;
+	if (tr == null) {
+	    return true;
+	}
+	return row == 0;
     }
 
     public boolean isBeforeFirst() throws SQLException {
-    if (tr == null || tr.nrows <= 0) {
-        return false;
-    }
-    return row < 0;
+	if (tr == null || tr.nrows <= 0) {
+	    return false;
+	}
+	return row < 0;
     }
 
     public void beforeFirst() throws SQLException {
-    if (tr == null) {
-        return;
-    }
-    row = -1;
+	if (tr == null) {
+	    return;
+	}
+	row = -1;
     }
 
     public boolean first() throws SQLException {
-    if (tr == null || tr.nrows <= 0) {
-        return false;
-    }
-    row = 0;
-    return true;
+	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;
+	if (tr == null || tr.nrows <= 0) {
+	    return false;
+	}
+	return row >= tr.nrows;
     }
 
     public void afterLast() throws SQLException {
-    if (tr == null) {
-        return;
-    }
-    row = tr.nrows;
+	if (tr == null) {
+	    return;
+	}
+	row = tr.nrows;
     }
 
     public boolean isLast() throws SQLException {
-    if (tr == null) {
-        return true;
-    }
-    return row == tr.nrows - 1;
+	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;
+	if (tr == null || tr.nrows <= 0) {
+	    return false;
+	}
+	row = tr.nrows -1;
+	return true;
     }
 
     public int getType() throws SQLException {
-    return TYPE_SCROLL_INSENSITIVE;
+	return TYPE_SCROLL_SENSITIVE;
     }
 
     public int getConcurrency() throws SQLException {
-    return CONCUR_READ_ONLY;
+	return CONCUR_UPDATABLE;
     }
 
     public boolean rowUpdated() throws SQLException {
-    throw new SQLException("not supported");
+	return false;
     }
 
     public boolean rowInserted() throws SQLException {
-    throw new SQLException("not supported");
+	return false;
     }
 
     public boolean rowDeleted() throws SQLException {
-    throw new SQLException("not supported");
+	return false;
     }
 
     public void insertRow() throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (!oninsrow || rowbuf == null) {
+	    throw new SQLException("no insert data provided");
+	}
+	JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+	StringBuffer sb = new StringBuffer();
+	sb.append("INSERT INTO ");
+	sb.append(SQLite.Shell.sql_quote_dbl(uptable));
+	sb.append("(");
+	for (int i = 0; i < tr.ncolumns; i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(m.getColumnName(i + 1)));
+	    if (i < tr.ncolumns - 1) {
+		sb.append(",");
+	    }
+	}
+	sb.append(") VALUES(");
+	for (int i = 0; i < tr.ncolumns; i++) {
+	    sb.append(nullrepl ? "'%q'" : "%Q");
+	    if (i < tr.ncolumns - 1) {
+		sb.append(",");
+	    }
+	}
+	sb.append(")");
+	try {
+	    this.s.conn.db.exec(sb.toString(), null, rowbuf);
+	} catch (SQLite.Exception e) {
+	    throw new SQLException(e.getMessage());
+	}
+	tr.newrow(rowbuf);
+	rowbuf = null;
+	oninsrow = false;
+	last();
     }
 
     public void updateRow() throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (rowbuf == null) {
+	    throw new SQLException("no update data provided");
+	}
+	if (oninsrow) {
+	    throw new SQLException("cursor on insert row");
+	}
+	if (updatable < UPD_INSUPDDEL) {
+	    throw new SQLException("no primary key on table defined");
+	}
+	String rd[] = (String []) tr.rows.elementAt(row);
+	JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+	String args[] = new String[tr.ncolumns + pkcols.length];
+	StringBuffer sb = new StringBuffer();
+	sb.append("UPDATE ");
+	sb.append(SQLite.Shell.sql_quote_dbl(uptable));
+	sb.append(" SET ");
+	int i;
+	for (i = 0; i < tr.ncolumns; i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(m.getColumnName(i + 1)));
+	    sb.append(" = " + (nullrepl ? "'%q'" : "%Q"));
+	    if (i < tr.ncolumns - 1) {
+		sb.append(",");
+	    }
+	    args[i] = rowbuf[i];
+	}
+	sb. append(" WHERE ");
+	for (int k = 0; k < pkcols.length; k++, i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(pkcols[k]));
+	    sb.append(" = " + (nullrepl ? "'%q'" : "%Q"));
+	    if (k < pkcols.length - 1) {
+		sb.append(" AND ");
+	    }
+	    args[i] = rd[pkcoli[k]];
+	}
+	try {
+	    this.s.conn.db.exec(sb.toString(), null, args);
+	} catch (SQLite.Exception e) {
+	    throw new SQLException(e.getMessage());
+	}
+	System.arraycopy(rowbuf, 0, rd, 0, rowbuf.length);
+	rowbuf = null;
     }
 
     public void deleteRow() throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (oninsrow) {
+	    throw new SQLException("cursor on insert row");
+	}
+	if (updatable < UPD_INSUPDDEL) {
+	    throw new SQLException("no primary key on table defined");
+	}
+	fillRowbuf();
+	StringBuffer sb = new StringBuffer();
+	sb.append("DELETE FROM ");
+	sb.append(SQLite.Shell.sql_quote_dbl(uptable));
+	sb.append(" WHERE ");
+	String args[] = new String[pkcols.length];
+	for (int i = 0; i < pkcols.length; i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(pkcols[i]));
+	    sb.append(" = " + (nullrepl ? "'%q'" : "%Q"));
+	    if (i < pkcols.length - 1) {
+		sb.append(" AND ");
+	    }
+	    args[i] = rowbuf[pkcoli[i]];
+	}
+	try {
+	    this.s.conn.db.exec(sb.toString(), null, args);
+	} catch (SQLite.Exception e) {
+	    throw new SQLException(e.getMessage());
+	}
+	rowbuf = null;
     }
 
     public void refreshRow() throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (oninsrow) {
+	    throw new SQLException("cursor on insert row");
+	}
+	if (updatable < UPD_INSUPDDEL) {
+	    throw new SQLException("no primary key on table defined");
+	}
+	JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+	String rd[] = (String []) tr.rows.elementAt(row);
+	StringBuffer sb = new StringBuffer();
+	sb.append("SELECT ");
+	for (int i = 0; i < tr.ncolumns; i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(m.getColumnName(i + 1)));
+	    if (i < tr.ncolumns - 1) {
+		sb.append(",");
+	    }
+	}
+	sb.append(" FROM ");
+	sb.append(SQLite.Shell.sql_quote_dbl(uptable));
+	sb.append(" WHERE ");
+	String args[] = new String[pkcols.length];
+	for (int i = 0; i < pkcols.length; i++) {
+	    sb.append(SQLite.Shell.sql_quote_dbl(pkcols[i]));
+	    sb.append(" = " + (nullrepl ? "'%q'" : "%Q"));
+	    if (i < pkcols.length - 1) {
+		sb.append(" AND ");
+	    }
+	    args[i] = rd[pkcoli[i]];
+	}
+	SQLite.TableResult trnew = null;
+	try {
+	    trnew = this.s.conn.db.get_table(sb.toString(), args);
+	} catch (SQLite.Exception e) {
+	    throw new SQLException(e.getMessage());
+	}
+	if (trnew.nrows != 1) {
+	    throw new SQLException("wrong size of result set");
+	}
+	rowbuf = null;
+	tr.rows.setElementAt(trnew.rows.elementAt(0), row);
     }
 
     public void cancelRowUpdates() throws SQLException {
-    throw new SQLException("not supported");
+	rowbuf = null;
     }
 
     public void moveToInsertRow() throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (!oninsrow) {
+	    oninsrow = true;
+	    rowbuf = new String[tr.nrows];
+	}
     }
 
     public void moveToCurrentRow() throws SQLException {
-    throw new SQLException("not supported");
+	if (oninsrow) {
+	    oninsrow = false;
+	    rowbuf = null;
+	}
     }
 
     public void updateNull(int colIndex) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = null;
     }
 
     public void updateBoolean(int colIndex, boolean b) throws SQLException {
-    throw new SQLException("not supported");
+	updateString(colIndex, b ? "1" : "0");
     }
 
     public void updateByte(int colIndex, byte b) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void updateShort(int colIndex, short b) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = Short.toString(b);
     }
 
     public void updateInt(int colIndex, int b) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = Integer.toString(b);
     }
 
     public void updateLong(int colIndex, long b) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = Long.toString(b);
     }
 
     public void updateFloat(int colIndex, float f) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = Float.toString(f);
     }
 
     public void updateDouble(int colIndex, double f) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = Double.toString(f);
     }
 
     public void updateBigDecimal(int colIndex, BigDecimal f)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void updateString(int colIndex, String s) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = s;
     }
 
     public void updateBytes(int colIndex, byte[] s) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	if (this.s.conn.db.is3()) {
+	    rowbuf[colIndex - 1] = SQLite.StringEncoder.encodeX(s);
+	} else {
+	    rowbuf[colIndex - 1] = SQLite.StringEncoder.encode(s);
+	}
     }
 
     public void updateDate(int colIndex, java.sql.Date d) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = d.toString();
     }
 
     public void updateTime(int colIndex, java.sql.Time t) throws SQLException {
-    throw new SQLException("not supported");
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = t.toString();
     }
 
     public void updateTimestamp(int colIndex, java.sql.Timestamp t)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	isUpdatable();
+	if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+	    throw new SQLException("column " + colIndex + " not found");
+	}
+	fillRowbuf();
+	rowbuf[colIndex - 1] = t.toString();
     }
 
     public void updateAsciiStream(int colIndex, java.io.InputStream in, int s)
-    throws SQLException {
-    throw new SQLException("not supported");
+	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");
+	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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public void updateObject(int colIndex, Object obj) throws SQLException {
-    throw new SQLException("not supported");
+	updateString(colIndex, obj.toString());
     }
 
     public void updateObject(int colIndex, Object obj, int s)
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	updateString(colIndex, obj.toString());
     }
 
-    public void updateNull(String colIndex) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateNull(String colName) throws SQLException {
+	int col = findColumn(colName);
+	updateNull(col);
     }
 
-    public void updateBoolean(String colIndex, boolean b) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateBoolean(String colName, boolean b) throws SQLException {
+	int col = findColumn(colName);
+	updateBoolean(col, b);
     }
 
-    public void updateByte(String colIndex, byte b) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateByte(String colName, 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 updateShort(String colName, short b) throws SQLException {
+	int col = findColumn(colName);
+	updateShort(col, b);
     }
 
-    public void updateInt(String colIndex, int b) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateInt(String colName, int b) throws SQLException {
+	int col = findColumn(colName);
+	updateInt(col, b);
     }
 
-    public void updateLong(String colIndex, long b) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateLong(String colName, long b) throws SQLException {
+	int col = findColumn(colName);
+	updateLong(col, b);
     }
 
-    public void updateFloat(String colIndex, float f) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateFloat(String colName, float f) throws SQLException {
+	int col = findColumn(colName);
+	updateFloat(col, f);
     }
 
-    public void updateDouble(String colIndex, double f) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateDouble(String colName, double f) throws SQLException {
+	int col = findColumn(colName);
+	updateDouble(col, f);
     }
 
-    public void updateBigDecimal(String colIndex, BigDecimal f)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateBigDecimal(String colName, 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 updateString(String colName, String s) throws SQLException {
+	int col = findColumn(colName);
+	updateString(col, s);
     }
 
-    public void updateBytes(String colIndex, byte[] s) throws SQLException {
-    throw new SQLException("not supported");
+    public void updateBytes(String colName, byte[] s) throws SQLException {
+	int col = findColumn(colName);
+	updateBytes(col, s);
     }
 
-    public void updateDate(String colIndex, java.sql.Date d)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateDate(String colName, java.sql.Date d)
+	throws SQLException {
+	int col = findColumn(colName);
+	updateDate(col, d);
     }
 
-    public void updateTime(String colIndex, java.sql.Time t)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateTime(String colName, java.sql.Time t)
+	throws SQLException {
+	int col = findColumn(colName);
+	updateTime(col, t);
     }
 
-    public void updateTimestamp(String colIndex, java.sql.Timestamp t)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateTimestamp(String colName, java.sql.Timestamp t)
+	throws SQLException {
+	int col = findColumn(colName);
+	updateTimestamp(col, t);
     }
 
-    public void updateAsciiStream(String colIndex, java.io.InputStream in,
-                  int s)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateAsciiStream(String colName, 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 updateBinaryStream(String colName, 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 updateCharacterStream(String colName, 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 colName, Object obj)
+	throws SQLException {
+	int col = findColumn(colName);
+	updateObject(col, obj);
     }
 
-    public void updateObject(String colIndex, Object obj, int s)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateObject(String colName, Object obj, int s)
+	throws SQLException {
+	int col = findColumn(colName);
+	updateObject(col, obj, s);
     }
 
     public Statement getStatement() throws SQLException {
-    if (s == null) {
-        throw new SQLException("stale result set");
-    }
-    return s;
+	if (s == null) {
+	    throw new SQLException("stale result set");
+	}
+	return s;
     }
 
     public void close() throws SQLException {
-    s = null;
-    tr = null;
-    lastg = null;
-    row = -1;
+	s = null;
+	tr = null;
+	lastg = null;
+	oninsrow = false;
+	rowbuf = 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;
+	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 java.net.URL getURL(String colName) throws SQLException {
+	int col = findColumn(colName);
+	return getURL(col);
     }
 
     public void updateRef(int colIndex, java.sql.Ref x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
-    public void updateRef(String colIndex, java.sql.Ref x)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateRef(String colName, 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");
+	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 updateBlob(String colName, 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");
+	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 updateClob(String colName, 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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
-    public void updateArray(String colIndex, java.sql.Array x)
-    throws SQLException {
-    throw new SQLException("not supported");
+    public void updateArray(String colName, java.sql.Array x)
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
index 934ca78..40be126 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
@@ -5,208 +5,210 @@
 public class JDBCResultSetMetaData implements java.sql.ResultSetMetaData {
 
     private JDBCResultSet r;
-    
+	
     public JDBCResultSetMetaData(JDBCResultSet r) {
-    this.r = r;
+	this.r = r;
     }
  
     public String getCatalogName(int column) throws java.sql.SQLException {
-    return null;
+	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;
+	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.REAL:
+		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;
+	if (r != null && r.tr != null) {
+	    return r.tr.ncolumns;
+	}
+	return 0;
     }
 
     public int getColumnDisplaySize(int column) throws java.sql.SQLException {
-    return 0;
+	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;
+	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;
+	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");
+	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");
+	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";
+		    case Types.REAL:		return "real";
+		    /* defaults to varchar below */
+		    }
+		}
+		return "varchar";
+	    }
+	}
+	throw new SQLException("bad column index");
     }
 
     public int getPrecision(int column) throws java.sql.SQLException {
-    return 0;
+	return 0;
     }
 
     public int getScale(int column) throws java.sql.SQLException {
-    return 0;
+	return 0;
     }
 
     public String getSchemaName(int column) throws java.sql.SQLException {
-    return null;
+	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;
+	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;
+	return false;
     }
 
     public boolean isCaseSensitive(int column) throws java.sql.SQLException {
-    return false;
+	return false;
     }
 
     public boolean isCurrency(int column) throws java.sql.SQLException {
-    return false;
+	return false;
     }
 
     public boolean isDefinitelyWritable(int column) 
-    throws java.sql.SQLException {
-    return true;
+	throws java.sql.SQLException {
+	return true;
     }
 
     public int isNullable(int column) throws java.sql.SQLException {
-    return columnNullableUnknown;
+	return columnNullableUnknown;
     }
 
     public boolean isReadOnly(int column) throws java.sql.SQLException {
-    return false;
+	return false;
     }
 
     public boolean isSearchable(int column) throws java.sql.SQLException {
-    return true;
+	return true;
     }
 
     public boolean isSigned(int column) throws java.sql.SQLException {
-    return false;
+	return false;
     }
 
     public boolean isWritable(int column) throws java.sql.SQLException {
-    return true;
+	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");
+	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/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java
index 99d12d3..48efa08 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/JDBCStatement.java
@@ -8,280 +8,286 @@
     protected JDBCConnection conn;
     protected JDBCResultSet rs;
     protected int updcnt;
+    protected int maxrows = 0;
     private ArrayList<String> batch;
 
     public JDBCStatement(JDBCConnection conn) {
-    this.conn = conn;
-    this.updcnt = 0;
-    this.rs = null;
-    this.batch = null;    
+	this.conn = conn;
+	this.updcnt = 0;
+	this.rs = null;
+	this.batch = null;	
     }
 
     public void setFetchSize(int fetchSize) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public int getFetchSize() throws SQLException {
-    return 1;
+	return 1;
     }
 
     public int getMaxRows() throws SQLException {
-    return 0;
+	return maxrows;
     }
 
     public void setMaxRows(int max) throws SQLException {
-    throw new SQLException("not supported");
+        // BEGIN android-added:
+        if (max < 0) {
+            throw new SQLException("max must be >= 0 (was " + max + ")");
+        }
+        // END android-added
+	maxrows = max;
     }
 
     public void setFetchDirection(int fetchDirection) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public int getFetchDirection() throws SQLException {
-    return ResultSet.FETCH_UNKNOWN;
+	return ResultSet.FETCH_UNKNOWN;
     }
 
     public int getResultSetConcurrency() throws SQLException {
-    return ResultSet.CONCUR_READ_ONLY;
+	return ResultSet.CONCUR_READ_ONLY;
     }
 
     public int getResultSetType() throws SQLException {
-    return ResultSet.TYPE_SCROLL_INSENSITIVE;
+	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;
-    }
+	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;
+	return conn.timeout;
     }
 
     public ResultSet getResultSet() throws SQLException {
-    return rs;
+	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;
+	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, maxrows);
+		    }
+		} else {
+		    if (updonly) {
+			conn.db.exec(sql, null, args);
+		    } else {
+			tr = conn.db.get_table(sql, maxrows, 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);
+	return executeQuery(sql, null, false);
     }
 
     public boolean execute(String sql) throws SQLException {
-    return executeQuery(sql) != null;
+	return executeQuery(sql) != null;
     }
 
     public void cancel() throws SQLException {
-    if (conn == null || conn.db == null) {
-        throw new SQLException("stale connection");
-    }
-    conn.db.interrupt();
+	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;
+	return conn;
     }
 
     public void addBatch(String sql) throws SQLException {
-    if (batch == null) {
-        batch = new ArrayList<String>(1);
-    }
-    batch.add(sql);
+	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;
+	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;
-    }
+	if (batch != null) {
+	    batch.clear();
+	    batch = null;
+	}
     }
 
     public void close() throws SQLException {
-    clearBatch();
-    conn = null;
+	clearBatch();
+	conn = null;
     }
 
     public int executeUpdate(String sql) throws SQLException {
-    executeQuery(sql, null, true);
-    return updcnt;
+	executeQuery(sql, null, true);
+	return updcnt;
     }
 
     public int getMaxFieldSize() throws SQLException {
-    return 0;
+	return 0;
     }
 
     public boolean getMoreResults() throws SQLException {
-    if (rs != null) {
-        rs.close();
-        rs = null;
-    }
-    return false;
+	if (rs != null) {
+	    rs.close();
+	    rs = null;
+	}
+	return false;
     }
 
     public int getUpdateCount() throws SQLException {
-    return updcnt;
+	return updcnt;
     }
 
     public SQLWarning getWarnings() throws SQLException {
-    return null;
+	return null;
     }
 
     public void setCursorName(String name) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setEscapeProcessing(boolean enable) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public void setMaxFieldSize(int max) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public boolean getMoreResults(int x) throws SQLException {
-    throw new SQLException("not supported");
+	throw new SQLException("not supported");
     }
 
     public ResultSet getGeneratedKeys() throws SQLException {
-    throw new SQLException("not supported");
+	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);
+	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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public int executeUpdate(String sql, String colIndexes[])
-    throws SQLException {
-    throw new SQLException("not supported");
+	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);
+	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");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public boolean execute(String sql, String colIndexes[])
-    throws SQLException {
-    throw new SQLException("not supported");
+	throws SQLException {
+	throw new SQLException("not supported");
     }
 
     public int getResultSetHoldability() throws SQLException {
-    return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+	return ResultSet.HOLD_CURSORS_OVER_COMMIT;
     }
 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java
index 205372f..1414fc0 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBC2y/TableResultX.java
@@ -7,31 +7,40 @@
     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;
+	super();
+	sql_type = new int[this.ncolumns];
+	for (int i = 0; i < this.ncolumns; i++) {
+	    sql_type[i] = Types.VARCHAR;
+	}
     }
+
+    public TableResultX(int maxrows) {
+	super(maxrows);
+	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]);
-        }
-    }    
+	this.column = tr.column;
+	this.rows = tr.rows;
+	this.ncolumns = tr.ncolumns;
+	this.nrows = tr.nrows;
+	this.types = tr.types;
+	this.maxrows = tr.maxrows;
+	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;
+	sql_type = types;
     } 
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java
index 63b95ee..c90035d 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/JDBCDriver.java
@@ -6,104 +6,139 @@
 public class JDBCDriver implements java.sql.Driver {
 
     public static final int MAJORVERSION = 1;
-    public static final int MINORVERSION = 2;
+
+    public static boolean sharedCache = false;
+
+    public static String vfs = null;
 
     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);
-    }
+	try {
+	    Class connClass = null;
+	    Class args[] = new Class[5];
+	    args[0] = Class.forName("java.lang.String");
+	    args[1] = args[0];
+	    args[2] = args[0];
+	    args[3] = args[0];
+	    args[4] = 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());
+	    try {
+		String shcache =
+		    java.lang.System.getProperty("SQLite.sharedcache");
+		if (shcache != null &&
+		    (shcache.startsWith("y") || shcache.startsWith("Y"))) {
+		    sharedCache = SQLite.Database._enable_shared_cache(true);
+		}
+	    } catch (java.lang.Exception e) {
+	    }
+	    try {
+		String tvfs = 
+		    java.lang.System.getProperty("SQLite.vfs");
+		if (tvfs != null) {
+		    vfs = tvfs;
+		}
+	    } catch (java.lang.Exception e) {
+	    }
+	} 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:/");
+	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;
+	throws SQLException {
+	if (!acceptsURL(url)) {
+	    return null;
+	}
+	Object args[] = new Object[5];
+	args[0] = url;
+	if (info != null) {
+	    args[1] = info.getProperty("encoding");
+	    args[2] = info.getProperty("password");
+	    args[3] = info.getProperty("daterepr");
+	    args[4] = info.getProperty("vfs");
+	}
+	if (args[1] == null) {
+	    args[1] = java.lang.System.getProperty("SQLite.encoding");
+	}
+	if (args[4] == null) {
+	    args[4] = vfs;
+	}
+	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;
+	return MAJORVERSION;
     }
 
     public int getMinorVersion() {
-    return MINORVERSION;
+	return Constants.drv_minor;
     }
 
     public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
-    throws SQLException {
-    DriverPropertyInfo p[] = new DriverPropertyInfo[1];
-    DriverPropertyInfo pp = new DriverPropertyInfo("encoding", "");
-    p[0] = pp;
-    return p;
+	throws SQLException {
+	DriverPropertyInfo p[] = new DriverPropertyInfo[4];
+	DriverPropertyInfo pp = new DriverPropertyInfo("encoding", "");
+	p[0] = pp;
+	pp = new DriverPropertyInfo("password", "");
+	p[1] = pp;
+	pp = new DriverPropertyInfo("daterepr", "normal");
+	p[2] = pp;
+	pp = new DriverPropertyInfo("vfs", vfs);
+	p[3] = pp;
+	return p;
     }
 
     public boolean jdbcCompliant() {
-    return false;
+	return false;
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/Shell.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Shell.java
index 78d37a1..b25e8ca 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Shell.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Shell.java
@@ -38,537 +38,562 @@
     static final int MODE_Insert2 = 6;
 
     public Shell(PrintWriter pw, PrintWriter err) {
-    this.pw = pw;
-    this.err = err;
+	this.pw = pw;
+	this.err = err;
     }
 
     public Shell(PrintStream ps, PrintStream errs) {
-    pw = new PrintWriter(ps);
-    err = new PrintWriter(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;
+	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();
+	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();
+	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();
+	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;
+	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);
+	if (str == null) {
+	    tableName = "";
+	    return;
+	}
+	if (db.is3()) {
+	    tableName = Shell.sql_quote_dbl(str);
+	} else {
+	    tableName = Shell.sql_quote(str);
+	}
     }
 
     public void columns(String args[]) {
-    cols = args;
+	cols = args;
     }
 
     public void types(String args[]) {
-    /* Empty body to satisfy SQLite.Callback interface. */
+	/* 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;
+	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();
+	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;
+	}
+	if (cmd.compareTo(".rekey") == 0) {
+	    try {
+		db.rekey(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;
-    }
+	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();
-    }
+	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;
-    }
+	    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();
-        }
-    }
+	    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) {
-    }
+	String key = null;
+	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 (args[i].compareTo("-key") == 0) {
+		++i;
+		key = args[i];
+	    } 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 (key != null) {
+	    try {
+		s.db.key(key);
+	    } catch (Exception e) {
+		System.err.println("Unable to set key: " + e);
+		System.exit(1);
+	    }
+	}
+	if (sql != null) {
+	    s.do_cmd(sql);
+	    s.pw.flush();
+	} else {
+	    BufferedReader is =
+		new BufferedReader(new InputStreamReader(System.in));
+	    s.do_input(is);
+	    s.pw.flush();
+	}
+	try {
+	    s.db.close();
+	} catch (Exception ee) {
+	}
     }
 }
 
@@ -584,86 +609,86 @@
 
     DBDump(Shell s, String tables[]) {
         this.s = s;
-    s.pw.println("BEGIN TRANSACTION;");
+	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;");
+	    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. */
+	/* Empty body to satisfy SQLite.Callback interface. */
     }
 
     public void types(String args[]) {
-    /* Empty body to satisfy SQLite.Callback interface. */
+	/* 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 = "";
+	    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;
+			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/libcore/sqlite-jdbc/src/main/java/SQLite/Stmt.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Stmt.java
index c4f72ed..d60e6b0 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Stmt.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Stmt.java
@@ -141,7 +141,7 @@
      */
 
     public native void bind_zeroblob(int pos, int length)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
     /**
      * Return number of parameters in compiled SQLite3 statement.
@@ -165,7 +165,7 @@
      */
 
     public native int bind_parameter_index(String name)
-    throws SQLite.Exception;
+	throws SQLite.Exception;
 
 
     /**
@@ -226,16 +226,16 @@
 
     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;
+	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;
     }
 
     /**
@@ -283,6 +283,6 @@
     private static native void internal_init();
 
     static {
-    internal_init();
+	internal_init();
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java b/libcore/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java
index c2f20ad..f02e77b 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/StringEncoder.java
@@ -40,55 +40,55 @@
      */
 
     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();
+	// 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();
     }
 
     /**
@@ -102,53 +102,96 @@
      */
 
     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;
+	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;
+		switch (a[i]) {
+		case '0': tmp = 0; break;
+		case '1': tmp = 1; break;
+		case '2': tmp = 2; break;
+		case '3': tmp = 3; break;
+		case '4': tmp = 4; break;
+		case '5': tmp = 5; break;
+		case '6': tmp = 6; break;
+		case '7': tmp = 7; break;
+		case '8': tmp = 8; break;
+		case '9': tmp = 9; break;
+		case 'A':
+		case 'a': tmp = 10; break;
+		case 'B':
+		case 'b': tmp = 11; break;
+		case 'C':
+		case 'c': tmp = 12; break;
+		case 'D':
+		case 'd': tmp = 13; break;
+		case 'E':
+		case 'e': tmp = 14; break;
+		case 'F':
+		case 'f': tmp = 15; break;
+		default:  tmp = 0; break;
+		}
+		result[k] = (byte) (tmp << 4);
+		switch (a[i+1]) {
+		case '0': tmp = 0; break;
+		case '1': tmp = 1; break;
+		case '2': tmp = 2; break;
+		case '3': tmp = 3; break;
+		case '4': tmp = 4; break;
+		case '5': tmp = 5; break;
+		case '6': tmp = 6; break;
+		case '7': tmp = 7; break;
+		case '8': tmp = 8; break;
+		case '9': tmp = 9; break;
+		case 'A':
+		case 'a': tmp = 10; break;
+		case 'B':
+		case 'b': tmp = 11; break;
+		case 'C':
+		case 'c': tmp = 12; break;
+		case 'D':
+		case 'd': tmp = 13; break;
+		case 'E':
+		case 'e': tmp = 14; break;
+		case 'F':
+		case 'f': tmp = 15; break;
+		default:  tmp = 0; break;
+		}
+		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;
     }
 
     /**
@@ -162,17 +205,17 @@
      */
 
     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;
+				   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'
+	'0', '1', '2', '3', '4', '5', '6', '7',
+	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
     };
 
     /**
@@ -183,19 +226,19 @@
      */
 
     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();
+	// check input
+	if (a == null || a.length == 0) {
+	    return "X''";
+	}
+	int outLen = a.length * 2 + 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) & 0x0F]);
+	    out.append(xdigits[a[i] & 0x0F]);
+	}
+	out.append('\'');
+	return out.toString();
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/java/SQLite/TableResult.java b/libcore/sqlite-jdbc/src/main/java/SQLite/TableResult.java
index 1a7fb57..14337aa 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/TableResult.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/TableResult.java
@@ -60,11 +60,32 @@
     public Vector rows;
 
     /**
+     * Maximum number of rows to hold in the table.
+     */
+
+    public int maxrows = 0;
+
+    /**
+     * Flag to indicate Maximum number of rows condition.
+     */
+
+    public boolean atmaxrows;
+
+    /**
      * Create an empty result set.
      */
 
     public TableResult() {
-    clear();
+	clear();
+    }
+
+    /**
+     * Create an empty result set with maximum number of rows.
+     */
+
+    public TableResult(int maxrows) {
+	this.maxrows = maxrows;
+	clear();
     }
 
     /**
@@ -72,10 +93,11 @@
      */
 
     public void clear() {
-    column = new String[0];
-    types = null;
-    rows = new Vector();
-    ncolumns = nrows = 0;
+	column = new String[0];
+	types = null;
+	rows = new Vector();
+	ncolumns = nrows = 0;
+	atmaxrows = false;
     }
 
     /**
@@ -83,8 +105,8 @@
      */
 
     public void columns(String coldata[]) {
-    column = coldata;
-    ncolumns = column.length;
+	column = coldata;
+	ncolumns = column.length;
     }
 
     /**
@@ -92,7 +114,7 @@
      */
 
     public void types(String types[]) {
-    this.types = types;
+	this.types = types;
     }
 
     /**
@@ -100,11 +122,15 @@
      */
 
     public boolean newrow(String rowdata[]) {
-    if (rowdata != null) {
-        rows.addElement(rowdata);
-        nrows++;
-    }
-    return false;
+	if (rowdata != null) {
+	    if (maxrows > 0 && nrows >= maxrows) {
+		atmaxrows = true;
+		return true;
+	    }
+	    rows.addElement(rowdata);
+	    nrows++;
+	}
+	return false;
     }
 
     /**
@@ -112,22 +138,22 @@
      */
 
     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();
+	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/libcore/sqlite-jdbc/src/main/java/SQLite/Vm.java b/libcore/sqlite-jdbc/src/main/java/SQLite/Vm.java
index 9856ed0..f47e12f 100644
--- a/libcore/sqlite-jdbc/src/main/java/SQLite/Vm.java
+++ b/libcore/sqlite-jdbc/src/main/java/SQLite/Vm.java
@@ -73,6 +73,6 @@
     private static native void internal_init();
 
     static {
-    internal_init();
+	internal_init();
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/native/sqlite_jni.c b/libcore/sqlite-jdbc/src/main/native/sqlite_jni.c
index 1333d24..bb5e2da 100644
--- a/libcore/sqlite-jdbc/src/main/native/sqlite_jni.c
+++ b/libcore/sqlite-jdbc/src/main/native/sqlite_jni.c
@@ -30,7 +30,9 @@
 #define HAVE_BOTH_SQLITE 1
 #endif
 
-#define CANT_PASS_VALIST_AS_CHARPTR
+#ifndef HAVE_SQLITE3_SHARED_CACHE
+#define HAVE_SQLITE3_SHARED_CACHE 0
+#endif
 
 #include "sqlite_jni.h"
 
@@ -181,7 +183,7 @@
     int len = 0;
 
     if (jstr) {
-        while (*jstr++) {
+	while (*jstr++) {
 	    len++;
 	}
     }
@@ -332,6 +334,7 @@
     dest->result = 0;
     dest->tofree = 0;
     if (haveutf) {
+        // BEGIN android-changed: leak/error reporting/simplification/performance.
         const jsize utfLength = (*env)->GetStringUTFLength(env, src);
         dest->result = dest->tofree = malloc(utfLength + 1);
         if (!dest->tofree) {
@@ -340,6 +343,7 @@
         }
         (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
         return dest->result;
+        // END android-changed
     }
     if (enc) {
 	bytes = (*env)->CallObjectMethod(env, src,
@@ -417,7 +421,7 @@
 					    "(Ljava/lang/String;I)Z");
 
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return ret;
 	}
 	trans2utf(env, h->haveutf, h->enc, table, &tabstr);
@@ -425,7 +429,7 @@
 					(jint) count)
 	      != JNI_FALSE;
 	(*env)->DeleteLocalRef(env, tabstr.jstr);
-	(*env)->DeleteLocalRef(env, cls);
+	(*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
     }
     return ret;
 }
@@ -445,12 +449,12 @@
 					    "(Ljava/lang/String;I)Z");
 
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return ret;
 	}
 	ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count)
 	    != JNI_FALSE;
-	(*env)->DeleteLocalRef(env, cls);
+	(*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
     }
     return ret;
 }
@@ -468,11 +472,11 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z");
 
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return ret;
 	}
 	ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE;
-	(*env)->DeleteLocalRef(env, cls);
+	(*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
     }
     return ret;
 }
@@ -690,41 +694,39 @@
 #endif
 #endif
 	}
-	mid = (*env)->GetMethodID(env, cls, "newrow",
-				  "([Ljava/lang/String;)Z");
-	if (mid) {
-	    jboolean rc;
+	if (data) {
+	    mid = (*env)->GetMethodID(env, cls, "newrow",
+				      "([Ljava/lang/String;)Z");
+	    if (mid) {
+		jboolean rc;
 
-	    if (data) {
 		arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
-	    } else {
-		arr = 0;
-	    }
-	    for (i = 0; arr && i < ncol; i++) {
-		if (data[i]) {
-		    transstr dats;
+		for (i = 0; arr && i < ncol; i++) {
+		    if (data[i]) {
+			transstr dats;
 
-		    trans2utf(env, h->haveutf, h->enc, data[i], &dats);
-		    (*env)->SetObjectArrayElement(env, arr, i, dats.jstr);
-		    exc = (*env)->ExceptionOccurred(env);
-		    if (exc) {
-			(*env)->DeleteLocalRef(env, exc);
-			return 1;
+			trans2utf(env, h->haveutf, h->enc, data[i], &dats);
+			(*env)->SetObjectArrayElement(env, arr, i, dats.jstr);
+			exc = (*env)->ExceptionOccurred(env);
+			if (exc) {
+			    (*env)->DeleteLocalRef(env, exc);
+			    return 1;
+			}
+			(*env)->DeleteLocalRef(env, dats.jstr);
 		    }
-		    (*env)->DeleteLocalRef(env, dats.jstr);
 		}
+		rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr);
+		exc = (*env)->ExceptionOccurred(env);
+		if (exc) {
+		    (*env)->DeleteLocalRef(env, exc);
+		    return 1;
+		}
+		if (arr) {
+		    (*env)->DeleteLocalRef(env, arr);
+		}
+		(*env)->DeleteLocalRef(env, cls);
+		return rc != JNI_FALSE;
 	    }
-	    rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr);
-	    exc = (*env)->ExceptionOccurred(env);
-	    if (exc) {
-		(*env)->DeleteLocalRef(env, exc);
-		return 1;
-	    }
-	    if (arr) {
-		(*env)->DeleteLocalRef(env, arr);
-	    }
-	    (*env)->DeleteLocalRef(env, cls);
-	    return rc != JNI_FALSE;
 	}
     }
     return 0;
@@ -803,7 +805,7 @@
 	    bl->next = 0;
 	    bl->h = 0;
 	    if (bl->blob) {
-	        sqlite3_blob_close(bl->blob);
+		sqlite3_blob_close(bl->blob);
 	    }
 	    bl->blob = 0;
 	}
@@ -996,13 +998,21 @@
 }
 
 JNIEXPORT void JNICALL
-Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode)
+Java_SQLite_Database__1open4(JNIEnv *env, jobject obj, jstring file, jint mode,
+			     jstring vfs, jboolean ver2)
 {
     handle *h = gethandle(env, obj);
     jthrowable exc;
     char *err = 0;
     transstr filename;
     int maj, min, lev;
+#if HAVE_SQLITE3_OPEN_V2
+    transstr vfsname;
+
+    vfsname.result = 0;
+    vfsname.tofree = 0;
+    vfsname.jstr = 0;
+#endif
 
     if (h) {
 	if (h->sqlite) {
@@ -1066,6 +1076,17 @@
 	(*env)->DeleteLocalRef(env, exc);
 	return;
     }
+#if HAVE_SQLITE3_OPEN_V2
+    if (vfs) {
+	trans2iso(env, 1, h->enc, vfs, &vfsname);
+	exc = (*env)->ExceptionOccurred(env);
+	if (exc) {
+	    transfree(&filename);
+	    (*env)->DeleteLocalRef(env, exc);
+	    return;
+	}
+    }
+#endif
 #if HAVE_BOTH_SQLITE
     {
 	FILE *f = fopen(filename.result, "rb");
@@ -1075,8 +1096,13 @@
 	    c_0 = fgetc(f);
 	    fclose(f);
 	}
-	if (c_0 != '*') {
+	if (c_0 != '*' && ver2 == JNI_FALSE) {
+#if HAVE_SQLITE3_OPEN_V2
+	    int rc = sqlite3_open_v2(filename.result, (sqlite3 **) &h->sqlite,
+				     (int) mode, vfsname.result);
+#else
 	    int rc = sqlite3_open(filename.result, (sqlite3 **) &h->sqlite);
+#endif
 
 	    if (rc == SQLITE_OK) {
 		h->is3 = 1;
@@ -1094,7 +1120,13 @@
     h->sqlite = (void *) sqlite_open(filename.result, (int) mode, &err);
 #endif
 #if HAVE_SQLITE3
-    if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK) {
+#if HAVE_SQLITE3_OPEN_V2
+    if (sqlite3_open_v2(filename.result, (sqlite3 **) &h->sqlite,
+			(int) mode, vfsname.result) != SQLITE_OK)
+#else
+    if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK)
+#endif
+    {
         if (h->sqlite) {
 	    sqlite3_close((sqlite3 *) h->sqlite);
 	    h->sqlite = 0;
@@ -1103,6 +1135,9 @@
 #endif
 #endif
     transfree(&filename);
+#if HAVE_SQLITE3_OPEN_V2
+    transfree(&vfsname);
+#endif
     exc = (*env)->ExceptionOccurred(env);
     if (exc) {
 	(*env)->DeleteLocalRef(env, exc);
@@ -1145,6 +1180,9 @@
 #if HAVE_BOTH_SQLITE
 	if (h->is3) {
 	    sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
+#if HAVE_SQLITE3_LOAD_EXTENSION
+	    sqlite3_enable_load_extension((sqlite3 *) h->sqlite, 1);
+#endif
 	} else {
 	    sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
 	}
@@ -1154,6 +1192,9 @@
 #endif
 #if HAVE_SQLITE3
 	sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
+#if HAVE_SQLITE3_LOAD_EXTENSION
+	sqlite3_enable_load_extension((sqlite3 *) h->sqlite, 1);
+#endif
 #endif
 #endif
 	h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF);
@@ -1168,6 +1209,12 @@
 }
 
 JNIEXPORT void JNICALL
+Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode)
+{
+    Java_SQLite_Database__1open4(env, obj, file, mode, 0, 0);
+}
+
+JNIEXPORT void JNICALL
 Java_SQLite_Database__1open_1aux_1file(JNIEnv *env, jobject obj, jstring file)
 {
     handle *h = gethandle(env, obj);
@@ -1339,7 +1386,7 @@
 	    jthrowable exc;
 	    int rc = SQLITE_ERROR, nargs, i;
 	    char *err = 0, *p;
-	    const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
+	    const char *str = (*env)->GetStringUTFChars(env, sql, NULL); // android-changed: unused variable
 	    transstr sqlstr;
 	    struct args {
 		char *arg;
@@ -1615,7 +1662,7 @@
 	int i;
 
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return;
 	}
 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
@@ -1664,7 +1711,7 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
 					    "(LSQLite/FunctionContext;)V");
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return;
 	}
 	f->sf = sf;
@@ -1691,7 +1738,7 @@
 	int i;
 
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return;
 	}
 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
@@ -1741,7 +1788,7 @@
 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
 					    "(LSQLite/FunctionContext;)V");
 	if (mid == 0) {
-	    (*env)->DeleteLocalRef(env, cls);
+	    (*env)->DeleteLocalRef(env, cls); // android-changed: plug leak
 	    return;
 	}
 	f->sf = sf;
@@ -2520,7 +2567,8 @@
 
     if (v && v->vm && v->h) {
 	jthrowable exc;
-	int ret, ncol = 0;
+	int ret, tmp;
+	long ncol = 0;
 #if HAVE_SQLITE3
 	freemem *freeproc = 0;
 	const char **blob = 0;
@@ -2531,7 +2579,29 @@
 #if HAVE_BOTH_SQLITE
 	if (v->is3) {
 	    ret = sqlite3_step((sqlite3_stmt *) v->vm);
-	    if (ret == SQLITE_ROW) {
+	    if (ret == SQLITE_DONE && v->hh.row1) {
+		ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+		if (ncol > 0) {
+		    data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
+		    if (data) {
+			data[0] = (const char *) ncol;
+			++data;
+			cols = data + ncol + 1;
+			blob = cols + ncol + 1;
+			freeproc = free_tab;
+		    } else {
+			ret = SQLITE_NOMEM;
+		    }
+		}
+		if (ret != SQLITE_NOMEM) {
+		    int i;
+
+		    for (i = 0; i < ncol; i++) {
+			cols[i] =
+			    sqlite3_column_name((sqlite3_stmt *) v->vm, i);
+		    }
+		}
+	    } else if (ret == SQLITE_ROW) {
 		ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
 		if (ncol > 0) {
 		    data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
@@ -2584,15 +2654,41 @@
 		}
 	    }
 	} else {
-	    ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
+	    tmp = 0;
+	    ret = sqlite_step((sqlite_vm *) v->vm, &tmp, &data, &cols);
+	    ncol = tmp;
 	}
 #else
 #if HAVE_SQLITE2
-	ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
+	tmp = 0;
+	ret = sqlite_step((sqlite_vm *) v->vm, &tmp, &data, &cols);
+	ncol = tmp;
 #endif
 #if HAVE_SQLITE3
 	ret = sqlite3_step((sqlite3_stmt *) v->vm);
-	if (ret == SQLITE_ROW) {
+	if (ret == SQLITE_DONE && v->hh.row1) {
+	    ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+	    if (ncol > 0) {
+		data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
+		if (data) {
+		    data[0] = (const char *) ncol;
+		    ++data;
+		    cols = data + ncol + 1;
+		    blob = cols + ncol + 1;
+		    freeproc = free_tab;
+		} else {
+		    ret = SQLITE_NOMEM;
+		}
+	    }
+	    if (ret != SQLITE_NOMEM) {
+		int i;
+
+		for (i = 0; i < ncol; i++) {
+		    cols[i] =
+			sqlite3_column_name((sqlite3_stmt *) v->vm, i);
+		}
+	    }
+	} else if (ret == SQLITE_ROW) {
 	    ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
 	    if (ncol > 0) {
 		data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
@@ -2670,6 +2766,29 @@
 	    return JNI_TRUE;
 	} else if (ret == SQLITE_DONE) {
 dofin:
+	    if (v->hh.row1 && cols) {
+		v->hh.cb = cb;
+		v->hh.env = env;
+#if HAVE_BOTH_SQLITE
+		if (v->is3) {
+		    v->hh.stmt = (sqlite3_stmt *) v->vm;
+		}
+#else
+#if HAVE_SQLITE3
+		v->hh.stmt = (sqlite3_stmt *) v->vm;
+#endif
+#endif
+		callback((void *) &v->hh, ncol, (char **) 0, (char **) cols);
+#if HAVE_SQLITE3
+		if (data && freeproc) {
+		    freeproc((void *) data);
+		}
+#endif
+		exc = (*env)->ExceptionOccurred(env);
+		if (exc) {
+		    (*env)->DeleteLocalRef(env, exc);
+		}
+	    }
 #if HAVE_BOTH_SQLITE
 	    if (v->is3) {
 		sqlite3_finalize((sqlite3_stmt *) v->vm);
@@ -2720,6 +2839,9 @@
     hvm *v = gethvm(env, obj);
     void *svm = 0;
     char *err = 0;
+#ifdef HAVE_SQLITE2
+    char *errfr = 0;
+#endif
     const char *tail;
     int ret;
 
@@ -2759,11 +2881,13 @@
 		    sqlite3_finalize((sqlite3_stmt *) svm);
 		    svm = 0;
 		}
+		err = (char *) sqlite3_errmsg((sqlite3 *) v->h->sqlite);
 	    }
 	} else {
 	    ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
-				 &tail, (sqlite_vm **) &svm, &err);
+				 &tail, (sqlite_vm **) &svm, &errfr);
 	    if (ret != SQLITE_OK) {
+		err = errfr;
 		if (svm) {
 		    sqlite_finalize((sqlite_vm *) svm, 0);
 		    svm = 0;
@@ -2773,8 +2897,9 @@
 #else
 #if HAVE_SQLITE2
 	ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
-			     &tail, (sqlite_vm **) &svm, &err);
+			     &tail, (sqlite_vm **) &svm, &errfr);
 	if (ret != SQLITE_OK) {
+	    err = errfr;
 	    if (svm) {
 		sqlite_finalize((sqlite_vm *) svm, 0);
 		svm = 0;
@@ -2794,6 +2919,7 @@
 		sqlite3_finalize((sqlite3_stmt *) svm);
 		svm = 0;
 	    }
+	    err = (char *) sqlite3_errmsg((sqlite3 *) v->h->sqlite);
 	}
 #endif
 #endif
@@ -2802,15 +2928,15 @@
 	    v->tail = 0;
 	    throwex(env, err ? err : "error in compile/prepare");
 #if HAVE_SQLITE2
-	    if (err) {
-		sqlite_freemem(err);
+	    if (errfr) {
+		sqlite_freemem(errfr);
 	    }
 #endif
 	    return JNI_FALSE;
 	}
 #if HAVE_SQLITE2
-	if (err) {
-	    sqlite_freemem(err);
+	if (errfr) {
+	    sqlite_freemem(errfr);
 	}
 #endif
 	if (!svm) {
@@ -2838,6 +2964,9 @@
     void *svm = 0;
     hvm *v;
     char *err = 0;
+#if HAVE_SQLITE2
+    char *errfr = 0;
+#endif
     const char *tail;
     transstr tr;
     jvalue vv;
@@ -2877,11 +3006,13 @@
 		sqlite3_finalize((sqlite3_stmt *) svm);
 		svm = 0;
 	    }
+	    err = (char *) sqlite3_errmsg((sqlite3 *) h->sqlite);
 	}
     } else {
 	ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
-			     (sqlite_vm **) &svm, &err);
+			     (sqlite_vm **) &svm, &errfr);
 	if (ret != SQLITE_OK) {
+	    err = errfr;
 	    if (svm) {
 		sqlite_finalize((sqlite_vm *) svm, 0);
 	    }
@@ -2890,8 +3021,9 @@
 #else
 #if HAVE_SQLITE2
     ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
-			 (sqlite_vm **) &svm, &err);
+			 (sqlite_vm **) &svm, &errfr);
     if (ret != SQLITE_OK) {
+	err = errfr;
 	if (svm) {
 	    sqlite_finalize((sqlite_vm *) svm, 0);
 	    svm = 0;
@@ -2911,6 +3043,7 @@
 	    sqlite3_finalize((sqlite3_stmt *) svm);
 	    svm = 0;
 	}
+	err = (char *) sqlite3_errmsg((sqlite3 *) h->sqlite);
     }
 #endif
 #endif
@@ -2919,15 +3052,15 @@
 	setvmerr(env, vm, ret);
 	throwex(env, err ? err : "error in prepare/compile");
 #if HAVE_SQLITE2
-	if (err) {
-	    sqlite_freemem(err);
+	if (errfr) {
+	    sqlite_freemem(errfr);
 	}
 #endif
 	return;
     }
 #if HAVE_SQLITE2
-    if (err) {
-	sqlite_freemem(err);
+    if (errfr) {
+	sqlite_freemem(errfr);
     }
 #endif
     if (!svm) {
@@ -3019,7 +3152,7 @@
 	jthrowable exc;
 	int rc = SQLITE_ERROR, nargs, i;
 	char *p;
-	const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
+	const char *str = (*env)->GetStringUTFChars(env, sql, NULL); // android-changed: unused variable
 	const char *tail;
 	transstr sqlstr;
 	struct args {
@@ -3408,7 +3541,7 @@
 	return;
     }
     len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
-    if (len16 < (jsize) sizeof (jchar)) {
+    if (len16 < (jsize) sizeof (jchar)) { // android-changed: signed/unsigned comparison
         len16 = sizeof (jchar);
     }
     v = malloc(sizeof (hvm) + len16);
@@ -3681,6 +3814,7 @@
 	    return;
 	}
 	if (val) {
+	    // BEGIN android-changed: simplification/performance.
 	    const jsize charCount = (*env)->GetStringLength(env, val);
 	    len = charCount * sizeof(jchar);
 	    if (len > 0) {
@@ -3697,6 +3831,7 @@
 	        ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, pos, "", 0,
 					  SQLITE_STATIC);
 	    }
+	    // END android-changed
 	} else {
 	    ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
 	}
@@ -4312,6 +4447,108 @@
 #endif
 }
 
+JNIEXPORT void
+JNICALL Java_SQLite_Database__1key(JNIEnv *env, jobject obj, jbyteArray key)
+{
+    jsize len;
+    jbyte *data;
+#if HAVE_SQLITE3_KEY
+    handle *h = gethandle(env, obj);
+#endif
+
+    len = (*env)->GetArrayLength(env, key);
+    data = (*env)->GetByteArrayElements(env, key, 0);
+    if (len == 0) {
+	data = 0;
+    }
+    if (!data) {
+	len = 0;
+    }
+#if HAVE_SQLITE3_KEY
+    if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+	if (!h->is3) {
+	    if (data) {
+		memset(data, 0, len);
+	    }
+	    throwex(env, "unsupported");
+	}
+#endif
+	sqlite3_key((sqlite3 *) h->sqlite, data, len);
+	if (data) {
+	    memset(data, 0, len);
+	}
+    } else {
+	if (data) {
+	    memset(data, 0, len);
+	}
+	throwclosed(env);
+    }
+#else
+    if (data) {
+	memset(data, 0, len);
+    }
+    /* no error */
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1rekey(JNIEnv *env, jobject obj, jbyteArray key)
+{
+    jsize len;
+    jbyte *data;
+#if HAVE_SQLITE3_KEY
+    handle *h = gethandle(env, obj);
+#endif
+
+    len = (*env)->GetArrayLength(env, key);
+    data = (*env)->GetByteArrayElements(env, key, 0);
+    if (len == 0) {
+	data = 0;
+    }
+    if (!data) {
+	len = 0;
+    }
+#if HAVE_SQLITE3_KEY
+    if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+	if (!h->is3) {
+	    if (data) {
+		memset(data, 0, len);
+	    }
+	    throwex(env, "unsupported");
+	}
+#endif
+	sqlite3_rekey((sqlite3 *) h->sqlite, data, len);
+	if (data) {
+	    memset(data, 0, len);
+	}
+    } else {
+	if (data) {
+	    memset(data, 0, len);
+	}
+	throwclosed(env);
+    }
+#else
+    if (data) {
+	memset(data, 0, len);
+    }
+    throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Database__1enable_1shared_1cache(JNIEnv *env, jclass cls,
+					     jboolean onoff)
+{
+#if HAVE_SQLITE3_SHARED_CACHE
+    return (sqlite3_enable_shared_cache(onoff == JNI_TRUE) == SQLITE_OK) ?
+	   JNI_TRUE : JNI_FALSE;
+#else
+    return JNI_FALSE;
+#endif
+}
+
 JNIEXPORT void JNICALL
 Java_SQLite_Stmt_internal_1init(JNIEnv *env, jclass cls)
 {
@@ -4342,11 +4579,13 @@
 JNIEXPORT void JNICALL
 Java_SQLite_Database_internal_1init(JNIEnv *env, jclass cls)
 {
-//#ifndef JNI_VERSION_1_2
-    jclass jls = (*env)->FindClass(env, "java/lang/String");
+#if defined(DONT_USE_JNI_ONLOAD) || !defined(JNI_VERSION_1_2)
+    while (C_java_lang_String == 0) {
+	jclass jls = (*env)->FindClass(env, "java/lang/String");
 
-    C_java_lang_String = (*env)->NewGlobalRef(env, jls);
-//#endif
+	C_java_lang_String = (*env)->NewGlobalRef(env, jls);
+    }
+#endif
     F_SQLite_Database_handle =
 	(*env)->GetFieldID(env, cls, "handle", "J");
     F_SQLite_Database_error_code =
@@ -4363,7 +4602,7 @@
 			    "([BLjava/lang/String;)V");
 }
 
-#ifdef JNI_VERSION_1_2
+#if !defined(DONT_USE_JNI_ONLOAD) && defined(JNI_VERSION_1_2)
 JNIEXPORT jint JNICALL
 JNI_OnLoad(JavaVM *vm, void *reserved)
 {
@@ -4384,7 +4623,7 @@
     if (!cls) {
 	return JNI_ERR;
     }
-    C_java_lang_String = (*env)->NewWeakGlobalRef(env, cls);
+    C_java_lang_String = (*env)->NewGlobalRef(env, cls); // android-changed: bug
     return JNI_VERSION_1_2;
 }
 
@@ -4397,7 +4636,7 @@
 	return;
     }
     if (C_java_lang_String) {
-	(*env)->DeleteWeakGlobalRef(env, C_java_lang_String);
+	(*env)->DeleteGlobalRef(env, C_java_lang_String); // android-changed: bug
 	C_java_lang_String = 0;
     }
 }
diff --git a/libcore/sqlite-jdbc/src/main/native/sqlite_jni_defs.h b/libcore/sqlite-jdbc/src/main/native/sqlite_jni_defs.h
index 91b2378..d21bf16 100644
--- a/libcore/sqlite-jdbc/src/main/native/sqlite_jni_defs.h
+++ b/libcore/sqlite-jdbc/src/main/native/sqlite_jni_defs.h
@@ -36,4 +36,4 @@
 #define HAVE_SQLITE3_RESULT_ZEROBLOB 0
 #define HAVE_SQLITE3_INCRBLOBIO 0
 
-
+#define CANT_PASS_VALIST_AS_CHARPTR