Loading core/java/android/database/sqlite/SQLiteDatabase.java +14 −32 Original line number Diff line number Diff line Loading @@ -343,25 +343,14 @@ public class SQLiteDatabase extends SQLiteClosable { private static final String MEMORY_DB_PATH = ":memory:"; /** * @param closable */ void addSQLiteClosable(SQLiteClosable closable) { lock(); try { synchronized void addSQLiteClosable(SQLiteClosable closable) { // mPrograms is per instance of SQLiteDatabase and it doesn't actually touch the database // itself. so, there is no need to lock(). mPrograms.put(closable, null); } finally { unlock(); } } void removeSQLiteClosable(SQLiteClosable closable) { lock(); try { synchronized void removeSQLiteClosable(SQLiteClosable closable) { mPrograms.remove(closable); } finally { unlock(); } } @Override Loading Loading @@ -1261,6 +1250,8 @@ public class SQLiteDatabase extends SQLiteClosable { * statement and fill in those values with {@link SQLiteProgram#bindString} * and {@link SQLiteProgram#bindLong} each time you want to run the * statement. Statements may not return result sets larger than 1x1. *<p> * No two threads should be using the same {@link SQLiteStatement} at the same time. * * @param sql The raw SQL statement, may contain ? for unknown values to be * bound later. Loading @@ -1269,19 +1260,7 @@ public class SQLiteDatabase extends SQLiteClosable { */ public SQLiteStatement compileStatement(String sql) throws SQLException { verifyDbIsOpen(); String prefixSql = sql.trim().substring(0, 6); SQLiteDatabase db = this; // get a pooled database connection handle to use, if this is a query if (prefixSql.equalsIgnoreCase("SELECT")) { db = getDbConnection(sql); } db.lock(); try { return new SQLiteStatement(db, sql); } finally { releaseDbConnection(db); db.unlock(); } return new SQLiteStatement(this, sql); } /** Loading Loading @@ -2354,7 +2333,10 @@ public class SQLiteDatabase extends SQLiteClosable { return true; } private synchronized void disableWriteAheadLogging() { /** * package visibility only for testing purposes */ /* package */ synchronized void disableWriteAheadLogging() { if (mConnectionPool == null) { return; } Loading Loading @@ -2394,7 +2376,7 @@ public class SQLiteDatabase extends SQLiteClosable { return this.mConnectionNum > 0; } private SQLiteDatabase getDbConnection(String sql) { /* package */ SQLiteDatabase getDbConnection(String sql) { verifyDbIsOpen(); // use the current connection handle if Loading core/java/android/database/sqlite/SQLiteProgram.java +39 −14 Original line number Diff line number Diff line Loading @@ -64,11 +64,16 @@ public abstract class SQLiteProgram extends SQLiteClosable { protected int nStatement = 0; /* package */ SQLiteProgram(SQLiteDatabase db, String sql) { mDatabase = db; this(db, sql, true); } /* package */ SQLiteProgram(SQLiteDatabase db, String sql, boolean compileFlag) { mSql = sql.trim(); attachObjectToDatabase(db); if (compileFlag) { compileSql(); } } private void compileSql() { if (nStatement > 0) { Loading Loading @@ -139,6 +144,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { private synchronized void attachObjectToDatabase(SQLiteDatabase db) { db.acquireReference(); db.addSQLiteClosable(this); mDatabase = db; nHandle = db.mNativeHandle; } Loading @@ -147,6 +153,26 @@ public abstract class SQLiteProgram extends SQLiteClosable { mDatabase.releaseReference(); } /* package */ synchronized void verifyDbAndCompileSql() { mDatabase.verifyDbIsOpen(); // use pooled database connection handles for SELECT SQL statements SQLiteDatabase db = (getSqlStatementType(mSql) != SELECT_STMT) ? mDatabase : mDatabase.getDbConnection(mSql); if (!db.equals(mDatabase)) { // the database connection handle to be used is not the same as the one supplied // in the constructor. do some housekeeping. detachObjectFromDatabase(); attachObjectToDatabase(db); } // compile the sql statement mDatabase.lock(); try { compileSql(); } finally { mDatabase.unlock(); } } @Override protected void onAllReferencesReleased() { releaseCompiledSqlIfNotInCache(); Loading @@ -159,7 +185,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { mDatabase.releaseReference(); } private void releaseCompiledSqlIfNotInCache() { /* package */ synchronized void releaseCompiledSqlIfNotInCache() { if (mCompiledSql == null) { return; } Loading Loading @@ -222,7 +248,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindNull(int index) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_null(index); Loading @@ -241,7 +267,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindLong(int index, long value) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_long(index, value); Loading @@ -260,7 +286,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindDouble(int index, double value) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_double(index, value); Loading @@ -282,7 +308,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { throw new IllegalArgumentException("the bind value at index " + index + " is null"); } synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_string(index, value); Loading @@ -304,7 +330,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { throw new IllegalArgumentException("the bind value at index " + index + " is null"); } synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_blob(index, value); Loading @@ -319,6 +345,9 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void clearBindings() { synchronized (this) { if (this.nStatement == 0) { return; } mDatabase.verifyDbIsOpen(); acquireReference(); try { Loading @@ -334,14 +363,10 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void close() { synchronized (this) { if (nStatement == 0 || nHandle == 0 || !mDatabase.isOpen()) { if (nHandle == 0 || !mDatabase.isOpen()) { return; } releaseReference(); // set all database objects to null/0, so that the user can't use a closed Object. mCompiledSql = null; nStatement = 0; nHandle = 0; } } Loading @@ -366,6 +391,6 @@ public abstract class SQLiteProgram extends SQLiteClosable { protected final native void native_bind_double(int index, double value); protected final native void native_bind_string(int index, String value); protected final native void native_bind_blob(int index, byte[] value); private final native void native_clear_bindings(); /* package */ final native void native_clear_bindings(); } core/java/android/database/sqlite/SQLiteStatement.java +7 −2 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import dalvik.system.BlockGuard; * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple * threads should perform its own synchronization when using the SQLiteStatement. */ @SuppressWarnings("deprecation") public class SQLiteStatement extends SQLiteProgram { private static final boolean READ = true; Loading @@ -41,7 +42,7 @@ public class SQLiteStatement extends SQLiteProgram * @param sql */ /* package */ SQLiteStatement(SQLiteDatabase db, String sql) { super(db, sql); super(db, sql, false /* don't compile sql statement */); } /** Loading Loading @@ -134,7 +135,7 @@ public class SQLiteStatement extends SQLiteProgram * methods in this class. */ private long acquireAndLock(boolean rwFlag) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); if (rwFlag == WRITE) { BlockGuard.getThreadPolicy().onWriteToDisk(); } else { Loading @@ -153,6 +154,10 @@ public class SQLiteStatement extends SQLiteProgram private void releaseAndUnlock() { releaseReference(); mDatabase.unlock(); clearBindings(); // release the compiled sql statement so that the caller's SQLiteStatement no longer // has a hard reference to a database object that may get deallocated at any point. releaseCompiledSqlIfNotInCache(); } private final native void native_execute(); Loading core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java +26 −14 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { @SmallTest public void testEnableWriteAheadLogging() { mDatabase.disableWriteAheadLogging(); assertNull(mDatabase.mConnectionPool); mDatabase.enableWriteAheadLogging(); DatabaseConnectionPool pool = mDatabase.mConnectionPool; Loading Loading @@ -280,6 +281,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { @SmallTest public void testLruCachingOfSqliteCompiledSqlObjs() { mDatabase.disableWriteAheadLogging(); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); mDatabase.execSQL("insert into test values(1,1);"); // set cache size Loading @@ -292,9 +294,10 @@ public class SQLiteDatabaseTest extends AndroidTestCase { ArrayList<String> sqlStrings = new ArrayList<String>(); SQLiteStatement stmt0 = null; for (int i = 0; i < N+1; i++) { String s = "select * from test where i = " + i; String s = "select * from test where i = " + i + " and j = ?"; sqlStrings.add(s); SQLiteStatement c = mDatabase.compileStatement(s); c.bindLong(1, 1); stmtObjs.add(i, c.getSqlStatementId()); if (i == 0) { // save thie SQLiteStatement obj. we want to make sure it is thrown out of Loading @@ -307,6 +310,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { assertEquals(0, stmt0.getSqlStatementId()); for (int i = 1; i < N+1; i++) { SQLiteCompiledSql compSql = mDatabase.getCompiledStatementForSql(sqlStrings.get(i)); assertNotNull(compSql); assertTrue(stmtObjs.contains(compSql.nStatement)); } } Loading @@ -317,9 +321,11 @@ public class SQLiteDatabaseTest extends AndroidTestCase { "num1 INTEGER, num2 INTEGER, image BLOB);"); final String statement = "DELETE FROM test WHERE _id=?;"; SQLiteStatement statementDoNotClose = mDatabase.compileStatement(statement); // SQl statement is compiled only at find bind or execute call assertTrue(statementDoNotClose.getSqlStatementId() == 0); statementDoNotClose.bindLong(1, 1); assertTrue(statementDoNotClose.getSqlStatementId() > 0); int nStatement = statementDoNotClose.getSqlStatementId(); assertTrue(statementDoNotClose.getSqlStatementId() == nStatement); /* do not close statementDoNotClose object. * That should leave it in SQLiteDatabase.mPrograms. * mDatabase.close() in tearDown() should release it. Loading @@ -332,24 +338,26 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @SmallTest public void testStatementClose() { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase\ int N = 26; mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; int stmt0Id = 0; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1, 1); // keep track of 0th entry if (i == 0) { stmt0Id = stmt.getSqlStatementId(); } stmt.executeInsert(); stmt.close(); } // add one more to the cache - and the above 'stmt0Id' should fall out of cache SQLiteStatement stmt1 = mDatabase.compileStatement("select * from test where i = 1;"); SQLiteStatement stmt1 = mDatabase.compileStatement("select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); // the above close() should have queuedUp the statement for finalization Loading @@ -369,7 +377,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @LargeTest public void testStatementCloseDiffThread() throws InterruptedException { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase in a thread Thread t1 = new Thread() { @Override public void run() { Loading @@ -377,12 +385,13 @@ public class SQLiteDatabaseTest extends AndroidTestCase { mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1,1); // keep track of 0th entry if (i == 0) { setStmt0Id(stmt.getSqlStatementId()); } stmt.executeInsert(); stmt.close(); } } Loading @@ -396,7 +405,8 @@ public class SQLiteDatabaseTest extends AndroidTestCase { Thread t2 = new Thread() { @Override public void run() { SQLiteStatement stmt1 = mDatabase.compileStatement( "select * from test where i = 1;"); "select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); } }; Loading Loading @@ -438,7 +448,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @LargeTest public void testStatementCloseByDbClose() throws InterruptedException { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase in a thread Thread t1 = new Thread() { @Override public void run() { Loading @@ -446,12 +456,13 @@ public class SQLiteDatabaseTest extends AndroidTestCase { mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1, 1); // keep track of 0th entry if (i == 0) { setStmt0Id(stmt.getSqlStatementId()); } stmt.executeInsert(); stmt.close(); } } Loading @@ -465,7 +476,8 @@ public class SQLiteDatabaseTest extends AndroidTestCase { Thread t2 = new Thread() { @Override public void run() { SQLiteStatement stmt1 = mDatabase.compileStatement( "select * from test where i = 1;"); "select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); } }; Loading core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java +158 −62 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/database/sqlite/SQLiteDatabase.java +14 −32 Original line number Diff line number Diff line Loading @@ -343,25 +343,14 @@ public class SQLiteDatabase extends SQLiteClosable { private static final String MEMORY_DB_PATH = ":memory:"; /** * @param closable */ void addSQLiteClosable(SQLiteClosable closable) { lock(); try { synchronized void addSQLiteClosable(SQLiteClosable closable) { // mPrograms is per instance of SQLiteDatabase and it doesn't actually touch the database // itself. so, there is no need to lock(). mPrograms.put(closable, null); } finally { unlock(); } } void removeSQLiteClosable(SQLiteClosable closable) { lock(); try { synchronized void removeSQLiteClosable(SQLiteClosable closable) { mPrograms.remove(closable); } finally { unlock(); } } @Override Loading Loading @@ -1261,6 +1250,8 @@ public class SQLiteDatabase extends SQLiteClosable { * statement and fill in those values with {@link SQLiteProgram#bindString} * and {@link SQLiteProgram#bindLong} each time you want to run the * statement. Statements may not return result sets larger than 1x1. *<p> * No two threads should be using the same {@link SQLiteStatement} at the same time. * * @param sql The raw SQL statement, may contain ? for unknown values to be * bound later. Loading @@ -1269,19 +1260,7 @@ public class SQLiteDatabase extends SQLiteClosable { */ public SQLiteStatement compileStatement(String sql) throws SQLException { verifyDbIsOpen(); String prefixSql = sql.trim().substring(0, 6); SQLiteDatabase db = this; // get a pooled database connection handle to use, if this is a query if (prefixSql.equalsIgnoreCase("SELECT")) { db = getDbConnection(sql); } db.lock(); try { return new SQLiteStatement(db, sql); } finally { releaseDbConnection(db); db.unlock(); } return new SQLiteStatement(this, sql); } /** Loading Loading @@ -2354,7 +2333,10 @@ public class SQLiteDatabase extends SQLiteClosable { return true; } private synchronized void disableWriteAheadLogging() { /** * package visibility only for testing purposes */ /* package */ synchronized void disableWriteAheadLogging() { if (mConnectionPool == null) { return; } Loading Loading @@ -2394,7 +2376,7 @@ public class SQLiteDatabase extends SQLiteClosable { return this.mConnectionNum > 0; } private SQLiteDatabase getDbConnection(String sql) { /* package */ SQLiteDatabase getDbConnection(String sql) { verifyDbIsOpen(); // use the current connection handle if Loading
core/java/android/database/sqlite/SQLiteProgram.java +39 −14 Original line number Diff line number Diff line Loading @@ -64,11 +64,16 @@ public abstract class SQLiteProgram extends SQLiteClosable { protected int nStatement = 0; /* package */ SQLiteProgram(SQLiteDatabase db, String sql) { mDatabase = db; this(db, sql, true); } /* package */ SQLiteProgram(SQLiteDatabase db, String sql, boolean compileFlag) { mSql = sql.trim(); attachObjectToDatabase(db); if (compileFlag) { compileSql(); } } private void compileSql() { if (nStatement > 0) { Loading Loading @@ -139,6 +144,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { private synchronized void attachObjectToDatabase(SQLiteDatabase db) { db.acquireReference(); db.addSQLiteClosable(this); mDatabase = db; nHandle = db.mNativeHandle; } Loading @@ -147,6 +153,26 @@ public abstract class SQLiteProgram extends SQLiteClosable { mDatabase.releaseReference(); } /* package */ synchronized void verifyDbAndCompileSql() { mDatabase.verifyDbIsOpen(); // use pooled database connection handles for SELECT SQL statements SQLiteDatabase db = (getSqlStatementType(mSql) != SELECT_STMT) ? mDatabase : mDatabase.getDbConnection(mSql); if (!db.equals(mDatabase)) { // the database connection handle to be used is not the same as the one supplied // in the constructor. do some housekeeping. detachObjectFromDatabase(); attachObjectToDatabase(db); } // compile the sql statement mDatabase.lock(); try { compileSql(); } finally { mDatabase.unlock(); } } @Override protected void onAllReferencesReleased() { releaseCompiledSqlIfNotInCache(); Loading @@ -159,7 +185,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { mDatabase.releaseReference(); } private void releaseCompiledSqlIfNotInCache() { /* package */ synchronized void releaseCompiledSqlIfNotInCache() { if (mCompiledSql == null) { return; } Loading Loading @@ -222,7 +248,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindNull(int index) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_null(index); Loading @@ -241,7 +267,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindLong(int index, long value) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_long(index, value); Loading @@ -260,7 +286,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void bindDouble(int index, double value) { synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_double(index, value); Loading @@ -282,7 +308,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { throw new IllegalArgumentException("the bind value at index " + index + " is null"); } synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_string(index, value); Loading @@ -304,7 +330,7 @@ public abstract class SQLiteProgram extends SQLiteClosable { throw new IllegalArgumentException("the bind value at index " + index + " is null"); } synchronized (this) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); acquireReference(); try { native_bind_blob(index, value); Loading @@ -319,6 +345,9 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void clearBindings() { synchronized (this) { if (this.nStatement == 0) { return; } mDatabase.verifyDbIsOpen(); acquireReference(); try { Loading @@ -334,14 +363,10 @@ public abstract class SQLiteProgram extends SQLiteClosable { */ public void close() { synchronized (this) { if (nStatement == 0 || nHandle == 0 || !mDatabase.isOpen()) { if (nHandle == 0 || !mDatabase.isOpen()) { return; } releaseReference(); // set all database objects to null/0, so that the user can't use a closed Object. mCompiledSql = null; nStatement = 0; nHandle = 0; } } Loading @@ -366,6 +391,6 @@ public abstract class SQLiteProgram extends SQLiteClosable { protected final native void native_bind_double(int index, double value); protected final native void native_bind_string(int index, String value); protected final native void native_bind_blob(int index, byte[] value); private final native void native_clear_bindings(); /* package */ final native void native_clear_bindings(); }
core/java/android/database/sqlite/SQLiteStatement.java +7 −2 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import dalvik.system.BlockGuard; * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple * threads should perform its own synchronization when using the SQLiteStatement. */ @SuppressWarnings("deprecation") public class SQLiteStatement extends SQLiteProgram { private static final boolean READ = true; Loading @@ -41,7 +42,7 @@ public class SQLiteStatement extends SQLiteProgram * @param sql */ /* package */ SQLiteStatement(SQLiteDatabase db, String sql) { super(db, sql); super(db, sql, false /* don't compile sql statement */); } /** Loading Loading @@ -134,7 +135,7 @@ public class SQLiteStatement extends SQLiteProgram * methods in this class. */ private long acquireAndLock(boolean rwFlag) { mDatabase.verifyDbIsOpen(); verifyDbAndCompileSql(); if (rwFlag == WRITE) { BlockGuard.getThreadPolicy().onWriteToDisk(); } else { Loading @@ -153,6 +154,10 @@ public class SQLiteStatement extends SQLiteProgram private void releaseAndUnlock() { releaseReference(); mDatabase.unlock(); clearBindings(); // release the compiled sql statement so that the caller's SQLiteStatement no longer // has a hard reference to a database object that may get deallocated at any point. releaseCompiledSqlIfNotInCache(); } private final native void native_execute(); Loading
core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java +26 −14 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { @SmallTest public void testEnableWriteAheadLogging() { mDatabase.disableWriteAheadLogging(); assertNull(mDatabase.mConnectionPool); mDatabase.enableWriteAheadLogging(); DatabaseConnectionPool pool = mDatabase.mConnectionPool; Loading Loading @@ -280,6 +281,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { @SmallTest public void testLruCachingOfSqliteCompiledSqlObjs() { mDatabase.disableWriteAheadLogging(); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); mDatabase.execSQL("insert into test values(1,1);"); // set cache size Loading @@ -292,9 +294,10 @@ public class SQLiteDatabaseTest extends AndroidTestCase { ArrayList<String> sqlStrings = new ArrayList<String>(); SQLiteStatement stmt0 = null; for (int i = 0; i < N+1; i++) { String s = "select * from test where i = " + i; String s = "select * from test where i = " + i + " and j = ?"; sqlStrings.add(s); SQLiteStatement c = mDatabase.compileStatement(s); c.bindLong(1, 1); stmtObjs.add(i, c.getSqlStatementId()); if (i == 0) { // save thie SQLiteStatement obj. we want to make sure it is thrown out of Loading @@ -307,6 +310,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { assertEquals(0, stmt0.getSqlStatementId()); for (int i = 1; i < N+1; i++) { SQLiteCompiledSql compSql = mDatabase.getCompiledStatementForSql(sqlStrings.get(i)); assertNotNull(compSql); assertTrue(stmtObjs.contains(compSql.nStatement)); } } Loading @@ -317,9 +321,11 @@ public class SQLiteDatabaseTest extends AndroidTestCase { "num1 INTEGER, num2 INTEGER, image BLOB);"); final String statement = "DELETE FROM test WHERE _id=?;"; SQLiteStatement statementDoNotClose = mDatabase.compileStatement(statement); // SQl statement is compiled only at find bind or execute call assertTrue(statementDoNotClose.getSqlStatementId() == 0); statementDoNotClose.bindLong(1, 1); assertTrue(statementDoNotClose.getSqlStatementId() > 0); int nStatement = statementDoNotClose.getSqlStatementId(); assertTrue(statementDoNotClose.getSqlStatementId() == nStatement); /* do not close statementDoNotClose object. * That should leave it in SQLiteDatabase.mPrograms. * mDatabase.close() in tearDown() should release it. Loading @@ -332,24 +338,26 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @SmallTest public void testStatementClose() { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase\ int N = 26; mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; int stmt0Id = 0; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1, 1); // keep track of 0th entry if (i == 0) { stmt0Id = stmt.getSqlStatementId(); } stmt.executeInsert(); stmt.close(); } // add one more to the cache - and the above 'stmt0Id' should fall out of cache SQLiteStatement stmt1 = mDatabase.compileStatement("select * from test where i = 1;"); SQLiteStatement stmt1 = mDatabase.compileStatement("select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); // the above close() should have queuedUp the statement for finalization Loading @@ -369,7 +377,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @LargeTest public void testStatementCloseDiffThread() throws InterruptedException { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase in a thread Thread t1 = new Thread() { @Override public void run() { Loading @@ -377,12 +385,13 @@ public class SQLiteDatabaseTest extends AndroidTestCase { mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1,1); // keep track of 0th entry if (i == 0) { setStmt0Id(stmt.getSqlStatementId()); } stmt.executeInsert(); stmt.close(); } } Loading @@ -396,7 +405,8 @@ public class SQLiteDatabaseTest extends AndroidTestCase { Thread t2 = new Thread() { @Override public void run() { SQLiteStatement stmt1 = mDatabase.compileStatement( "select * from test where i = 1;"); "select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); } }; Loading Loading @@ -438,7 +448,7 @@ public class SQLiteDatabaseTest extends AndroidTestCase { */ @LargeTest public void testStatementCloseByDbClose() throws InterruptedException { mDatabase.execSQL("CREATE TABLE test (i int);"); mDatabase.execSQL("CREATE TABLE test (i int, j int);"); // fill up statement cache in mDatabase in a thread Thread t1 = new Thread() { @Override public void run() { Loading @@ -446,12 +456,13 @@ public class SQLiteDatabaseTest extends AndroidTestCase { mDatabase.setMaxSqlCacheSize(N); SQLiteStatement stmt; for (int i = 0; i < N; i ++) { stmt = mDatabase.compileStatement("insert into test values(" + i + ");"); stmt.executeInsert(); stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);"); stmt.bindLong(1, 1); // keep track of 0th entry if (i == 0) { setStmt0Id(stmt.getSqlStatementId()); } stmt.executeInsert(); stmt.close(); } } Loading @@ -465,7 +476,8 @@ public class SQLiteDatabaseTest extends AndroidTestCase { Thread t2 = new Thread() { @Override public void run() { SQLiteStatement stmt1 = mDatabase.compileStatement( "select * from test where i = 1;"); "select * from test where i = ?;"); stmt1.bindLong(1, 1); stmt1.close(); } }; Loading
core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java +158 −62 File changed.Preview size limit exceeded, changes collapsed. Show changes