summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/database/sqlite/SQLiteProgram.java147
-rw-r--r--core/java/android/database/sqlite/SQLiteStatement.java78
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java93
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java102
4 files changed, 216 insertions, 204 deletions
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 4df6ad102d6e..017b65f97ec5 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -17,6 +17,9 @@
package android.database.sqlite;
import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
/**
* A base class for compiled SQLite programs.
@@ -29,7 +32,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
private static final String TAG = "SQLiteProgram";
/** the type of sql statement being processed by this object */
- private static final int SELECT_STMT = 1;
+ /* package */ static final int SELECT_STMT = 1;
private static final int UPDATE_STMT = 2;
private static final int OTHER_STMT = 3;
@@ -63,13 +66,40 @@ public abstract class SQLiteProgram extends SQLiteClosable {
@Deprecated
protected int nStatement = 0;
+ /**
+ * In the case of {@link SQLiteStatement}, this member stores the bindargs passed
+ * to the following methods, instead of actually doing the binding.
+ * <ul>
+ * <li>{@link #bindBlob(int, byte[])}</li>
+ * <li>{@link #bindDouble(int, double)}</li>
+ * <li>{@link #bindLong(int, long)}</li>
+ * <li>{@link #bindNull(int)}</li>
+ * <li>{@link #bindString(int, String)}</li>
+ * </ul>
+ * <p>
+ * Each entry in the array is a Pair of
+ * <ol>
+ * <li>bind arg position number</li>
+ * <li>the value to be bound to the bindarg</li>
+ * </ol>
+ * <p>
+ * It is lazily initialized in the above bind methods
+ * and it is cleared in {@link #clearBindings()} method.
+ * <p>
+ * It is protected (in multi-threaded environment) by {@link SQLiteProgram}.this
+ */
+ private ArrayList<Pair<Integer, Object>> bindArgs = null;
+
/* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
this(db, sql, true);
}
/* package */ SQLiteProgram(SQLiteDatabase db, String sql, boolean compileFlag) {
mSql = sql.trim();
- attachObjectToDatabase(db);
+ db.acquireReference();
+ db.addSQLiteClosable(this);
+ mDatabase = db;
+ nHandle = db.mNativeHandle;
if (compileFlag) {
compileSql();
}
@@ -120,7 +150,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
nStatement = mCompiledSql.nStatement;
}
- private int getSqlStatementType(String sql) {
+ /* package */ int getSqlStatementType(String sql) {
if (mSql.length() < 6) {
return OTHER_STMT;
}
@@ -136,46 +166,11 @@ public abstract class SQLiteProgram extends SQLiteClosable {
return OTHER_STMT;
}
- private synchronized void attachObjectToDatabase(SQLiteDatabase db) {
- db.acquireReference();
- db.addSQLiteClosable(this);
- mDatabase = db;
- nHandle = db.mNativeHandle;
- }
-
- private synchronized void detachObjectFromDatabase() {
- mDatabase.removeSQLiteClosable(this);
- 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
- if (nStatement > 0) {
- // already compiled.
- return;
- }
- mDatabase.lock();
- try {
- compileSql();
- } finally {
- mDatabase.unlock();
- }
- }
-
@Override
protected void onAllReferencesReleased() {
releaseCompiledSqlIfNotInCache();
- detachObjectFromDatabase();
+ mDatabase.removeSQLiteClosable(this);
+ mDatabase.releaseReference();
}
@Override
@@ -246,11 +241,17 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param index The 1-based index to the parameter to bind null to
*/
public void bindNull(int index) {
+ mDatabase.verifyDbIsOpen();
synchronized (this) {
- verifyDbAndCompileSql();
acquireReference();
try {
- native_bind_null(index);
+ if (this.nStatement == 0) {
+ // since the SQL statement is not compiled, don't do the binding yet.
+ // can be done before executing the SQL statement
+ addToBindArgs(index, null);
+ } else {
+ native_bind_null(index);
+ }
} finally {
releaseReference();
}
@@ -265,11 +266,15 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindLong(int index, long value) {
+ mDatabase.verifyDbIsOpen();
synchronized (this) {
- verifyDbAndCompileSql();
acquireReference();
try {
- native_bind_long(index, value);
+ if (this.nStatement == 0) {
+ addToBindArgs(index, value);
+ } else {
+ native_bind_long(index, value);
+ }
} finally {
releaseReference();
}
@@ -284,11 +289,15 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindDouble(int index, double value) {
+ mDatabase.verifyDbIsOpen();
synchronized (this) {
- verifyDbAndCompileSql();
acquireReference();
try {
- native_bind_double(index, value);
+ if (this.nStatement == 0) {
+ addToBindArgs(index, value);
+ } else {
+ native_bind_double(index, value);
+ }
} finally {
releaseReference();
}
@@ -306,11 +315,15 @@ public abstract class SQLiteProgram extends SQLiteClosable {
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
+ mDatabase.verifyDbIsOpen();
synchronized (this) {
- verifyDbAndCompileSql();
acquireReference();
try {
- native_bind_string(index, value);
+ if (this.nStatement == 0) {
+ addToBindArgs(index, value);
+ } else {
+ native_bind_string(index, value);
+ }
} finally {
releaseReference();
}
@@ -328,11 +341,15 @@ public abstract class SQLiteProgram extends SQLiteClosable {
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
+ mDatabase.verifyDbIsOpen();
synchronized (this) {
- verifyDbAndCompileSql();
acquireReference();
try {
- native_bind_blob(index, value);
+ if (this.nStatement == 0) {
+ addToBindArgs(index, value);
+ } else {
+ native_bind_blob(index, value);
+ }
} finally {
releaseReference();
}
@@ -344,6 +361,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
*/
public void clearBindings() {
synchronized (this) {
+ bindArgs = null;
if (this.nStatement == 0) {
return;
}
@@ -362,6 +380,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
*/
public void close() {
synchronized (this) {
+ bindArgs = null;
if (nHandle == 0 || !mDatabase.isOpen()) {
return;
}
@@ -369,6 +388,34 @@ public abstract class SQLiteProgram extends SQLiteClosable {
}
}
+ private synchronized void addToBindArgs(int index, Object value) {
+ if (bindArgs == null) {
+ bindArgs = new ArrayList<Pair<Integer, Object>>();
+ }
+ bindArgs.add(new Pair<Integer, Object>(index, value));
+ }
+
+ /* package */ synchronized void compileAndbindAllArgs() {
+ assert nStatement == 0;
+ compileSql();
+ if (bindArgs == null) {
+ return;
+ }
+ for (Pair<Integer, Object> p : bindArgs) {
+ if (p.second == null) {
+ native_bind_null(p.first);
+ } else if (p.second instanceof Long) {
+ native_bind_long(p.first, (Long)p.second);
+ } else if (p.second instanceof Double) {
+ native_bind_double(p.first, (Double)p.second);
+ } else if (p.second instanceof byte[]) {
+ native_bind_blob(p.first, (byte[])p.second);
+ } else {
+ native_bind_string(p.first, (String)p.second);
+ }
+ }
+ }
+
/**
* @deprecated This method is deprecated and must not be used.
* Compiles SQL into a SQLite program.
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 966459389623..b90280307ad6 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -35,6 +35,8 @@ public class SQLiteStatement extends SQLiteProgram
private static final boolean READ = true;
private static final boolean WRITE = false;
+ private SQLiteDatabase mOrigDb;
+
/**
* Don't use SQLiteStatement constructor directly, please use
* {@link SQLiteDatabase#compileStatement(String)}
@@ -53,12 +55,14 @@ public class SQLiteStatement extends SQLiteProgram
* some reason
*/
public void execute() {
- long timeStart = acquireAndLock(WRITE);
- try {
- native_execute();
- mDatabase.logTimeStat(mSql, timeStart);
- } finally {
- releaseAndUnlock();
+ synchronized(this) {
+ long timeStart = acquireAndLock(WRITE);
+ try {
+ native_execute();
+ mDatabase.logTimeStat(mSql, timeStart);
+ } finally {
+ releaseAndUnlock();
+ }
}
}
@@ -72,13 +76,15 @@ public class SQLiteStatement extends SQLiteProgram
* some reason
*/
public long executeInsert() {
- long timeStart = acquireAndLock(WRITE);
- try {
- native_execute();
- mDatabase.logTimeStat(mSql, timeStart);
- return (mDatabase.lastChangeCount() > 0) ? mDatabase.lastInsertRow() : -1;
- } finally {
- releaseAndUnlock();
+ synchronized(this) {
+ long timeStart = acquireAndLock(WRITE);
+ try {
+ native_execute();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return (mDatabase.lastChangeCount() > 0) ? mDatabase.lastInsertRow() : -1;
+ } finally {
+ releaseAndUnlock();
+ }
}
}
@@ -91,13 +97,15 @@ public class SQLiteStatement extends SQLiteProgram
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
*/
public long simpleQueryForLong() {
- long timeStart = acquireAndLock(READ);
- try {
- long retValue = native_1x1_long();
- mDatabase.logTimeStat(mSql, timeStart);
- return retValue;
- } finally {
- releaseAndUnlock();
+ synchronized(this) {
+ long timeStart = acquireAndLock(READ);
+ try {
+ long retValue = native_1x1_long();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return retValue;
+ } finally {
+ releaseAndUnlock();
+ }
}
}
@@ -110,13 +118,15 @@ public class SQLiteStatement extends SQLiteProgram
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
*/
public String simpleQueryForString() {
- long timeStart = acquireAndLock(READ);
- try {
- String retValue = native_1x1_string();
- mDatabase.logTimeStat(mSql, timeStart);
- return retValue;
- } finally {
- releaseAndUnlock();
+ synchronized(this) {
+ long timeStart = acquireAndLock(READ);
+ try {
+ String retValue = native_1x1_string();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return retValue;
+ } finally {
+ releaseAndUnlock();
+ }
}
}
@@ -125,6 +135,7 @@ public class SQLiteStatement extends SQLiteProgram
* this method does the following:
* <ul>
* <li>make sure the database is open</li>
+ * <li>get a database connection from the connection pool,if possible</li>
* <li>notifies {@link BlockGuard} of read/write</li>
* <li>get lock on the database</li>
* <li>acquire reference on this object</li>
@@ -135,7 +146,14 @@ public class SQLiteStatement extends SQLiteProgram
* methods in this class.
*/
private long acquireAndLock(boolean rwFlag) {
- verifyDbAndCompileSql();
+ // use pooled database connection handles for SELECT SQL statements
+ mDatabase.verifyDbIsOpen();
+ SQLiteDatabase db = (getSqlStatementType(mSql) != SELECT_STMT) ? mDatabase
+ : mDatabase.getDbConnection(mSql);
+ // use the database connection obtained above
+ mOrigDb = mDatabase;
+ mDatabase = db;
+ nHandle = mDatabase.mNativeHandle;
if (rwFlag == WRITE) {
BlockGuard.getThreadPolicy().onWriteToDisk();
} else {
@@ -145,6 +163,7 @@ public class SQLiteStatement extends SQLiteProgram
mDatabase.lock();
acquireReference();
mDatabase.closePendingStatements();
+ compileAndbindAllArgs();
return startTime;
}
@@ -158,6 +177,9 @@ public class SQLiteStatement extends SQLiteProgram
// 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();
+ // restore the database connection handle to the original value
+ mDatabase = mOrigDb;
+ nHandle = mDatabase.mNativeHandle;
}
private final native void native_execute();
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
index ca8dac13efd6..91ef0b7a3afc 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
@@ -279,11 +279,24 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
}
}
+ private static class ClassToTestSqlCompilationAndCaching extends SQLiteProgram {
+ private ClassToTestSqlCompilationAndCaching(SQLiteDatabase db, String sql) {
+ super(db, sql);
+ }
+ private static ClassToTestSqlCompilationAndCaching create(SQLiteDatabase db, String sql) {
+ db.lock();
+ try {
+ return new ClassToTestSqlCompilationAndCaching(db, sql);
+ } finally {
+ db.unlock();
+ }
+ }
+ }
+
@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
int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE;
mDatabase.setMaxSqlCacheSize(N);
@@ -292,22 +305,24 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
// insertion of (N+1)th entry, make sure 0th entry is closed
ArrayList<Integer> stmtObjs = new ArrayList<Integer>();
ArrayList<String> sqlStrings = new ArrayList<String>();
- SQLiteStatement stmt0 = null;
+ int stmt0 = 0;
for (int i = 0; i < N+1; i++) {
- String s = "select * from test where i = " + i + " and j = ?";
+ String s = "insert into test values(" + i + ",?);";
sqlStrings.add(s);
- SQLiteStatement c = mDatabase.compileStatement(s);
- c.bindLong(1, 1);
- stmtObjs.add(i, c.getSqlStatementId());
+ ClassToTestSqlCompilationAndCaching c =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase, s);
+ int n = c.getSqlStatementId();
+ stmtObjs.add(i, n);
if (i == 0) {
- // save thie SQLiteStatement obj. we want to make sure it is thrown out of
- // the cache and its handle is 0'ed.
- stmt0 = c;
+ // save the statementId of this obj. we want to make sure it is thrown out of
+ // the cache at the end of this test.
+ stmt0 = n;
}
c.close();
}
- // is 0'th entry out of the cache?
- assertEquals(0, stmt0.getSqlStatementId());
+ // is 0'th entry out of the cache? it should be in the list of statementIds
+ // corresponding to the pre-compiled sql statements to be finalized.
+ assertTrue(mDatabase.getQueuedUpStmtList().contains(stmt0));
for (int i = 1; i < N+1; i++) {
SQLiteCompiledSql compSql = mDatabase.getCompiledStatementForSql(sqlStrings.get(i));
assertNotNull(compSql);
@@ -321,11 +336,7 @@ 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();
/* do not close statementDoNotClose object.
* That should leave it in SQLiteDatabase.mPrograms.
* mDatabase.close() in tearDown() should release it.
@@ -340,24 +351,25 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
public void testStatementClose() {
mDatabase.execSQL("CREATE TABLE test (i int, j int);");
// fill up statement cache in mDatabase\
- int N = 26;
+ int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE;
mDatabase.setMaxSqlCacheSize(N);
SQLiteStatement stmt;
int stmt0Id = 0;
for (int i = 0; i < N; i ++) {
- stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);");
- stmt.bindLong(1, 1);
+ ClassToTestSqlCompilationAndCaching c =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(" + i + ", ?);");
// keep track of 0th entry
if (i == 0) {
- stmt0Id = stmt.getSqlStatementId();
+ stmt0Id = c.getSqlStatementId();
}
- stmt.executeInsert();
- stmt.close();
+ c.close();
}
// add one more to the cache - and the above 'stmt0Id' should fall out of cache
- SQLiteStatement stmt1 = mDatabase.compileStatement("insert into test values(100, ?);");
- stmt1.bindLong(1, 1);
+ ClassToTestSqlCompilationAndCaching stmt1 =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(100, ?);");
stmt1.close();
// the above close() should have queuedUp the statement for finalization
@@ -381,18 +393,18 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
// fill up statement cache in mDatabase in a thread
Thread t1 = new Thread() {
@Override public void run() {
- int N = 26;
+ int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE;
mDatabase.setMaxSqlCacheSize(N);
SQLiteStatement stmt;
for (int i = 0; i < N; i ++) {
- stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);");
- stmt.bindLong(1,1);
+ ClassToTestSqlCompilationAndCaching c =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(" + i + ", ?);");
// keep track of 0th entry
if (i == 0) {
- setStmt0Id(stmt.getSqlStatementId());
+ stmt0Id = c.getSqlStatementId();
}
- stmt.executeInsert();
- stmt.close();
+ c.close();
}
}
};
@@ -404,9 +416,9 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
// just for the heck of it, do it in a separate thread
Thread t2 = new Thread() {
@Override public void run() {
- SQLiteStatement stmt1 = mDatabase.compileStatement(
- "insert into test values(100, ?);");
- stmt1.bindLong(1, 1);
+ ClassToTestSqlCompilationAndCaching stmt1 =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(100, ?);");
stmt1.close();
}
};
@@ -452,18 +464,18 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
// fill up statement cache in mDatabase in a thread
Thread t1 = new Thread() {
@Override public void run() {
- int N = 26;
+ int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE;
mDatabase.setMaxSqlCacheSize(N);
SQLiteStatement stmt;
for (int i = 0; i < N; i ++) {
- stmt = mDatabase.compileStatement("insert into test values(" + i + ", ?);");
- stmt.bindLong(1, 1);
+ ClassToTestSqlCompilationAndCaching c =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(" + i + ", ?);");
// keep track of 0th entry
if (i == 0) {
- setStmt0Id(stmt.getSqlStatementId());
+ stmt0Id = c.getSqlStatementId();
}
- stmt.executeInsert();
- stmt.close();
+ c.close();
}
}
};
@@ -475,8 +487,9 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
// just for the heck of it, do it in a separate thread
Thread t2 = new Thread() {
@Override public void run() {
- SQLiteStatement stmt1 = mDatabase.compileStatement(
- "insert into test values(100, ?);");
+ ClassToTestSqlCompilationAndCaching stmt1 =
+ ClassToTestSqlCompilationAndCaching.create(mDatabase,
+ "insert into test values(100, ?);");
stmt1.bindLong(1, 1);
stmt1.close();
}
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java
index eb27551b0add..217545f9cf6c 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteStatementTest.java
@@ -158,14 +158,16 @@ public class SQLiteStatementTest extends AndroidTestCase {
assertEquals(0, stmt.getSqlStatementId());
int colValue = new Random().nextInt();
stmt.bindLong(1, colValue);
- // verify that the sql statement is now compiled
- int n = stmt.nStatement;
- assertTrue(n > 0);
- assertEquals(n, stmt.getSqlStatementId());
+ // verify that the sql statement is still not compiled
+ assertEquals(0, stmt.getSqlStatementId());
// should still be using the mDatabase connection - verify
assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
+ assertEquals(mDatabase, stmt.mDatabase);
stmt.bindString(2, "blah" + colValue);
- assertEquals(n, stmt.nStatement);
+ // verify that the sql statement is still not compiled
+ assertEquals(0, stmt.getSqlStatementId());
+ assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
+ assertEquals(mDatabase, stmt.mDatabase);
stmt.executeInsert();
// now that the statement is executed, pre-compiled statement should be released
assertEquals(0, stmt.nStatement);
@@ -187,97 +189,25 @@ public class SQLiteStatementTest extends AndroidTestCase {
assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
assertEquals(mDatabase, stmt.mDatabase);
stmt.bindString(1, "blah" + colValue);
- // verify that the sql statement is now compiled
- n = stmt.nStatement;
- assertTrue(n > 0);
- assertEquals(n, stmt.getSqlStatementId());
- SQLiteDatabase dbUsed = mDatabase;
- if (wal) {
- // if wal is set, should be using a pooled connection handle
- dbUsed = mDatabase.mConnectionPool.getConnectionList().get(0);
- assertTrue(mDatabase.mNativeHandle != dbUsed.mNativeHandle);
- }
- assertEquals(dbUsed.mNativeHandle, stmt.nHandle);
- assertEquals(dbUsed, stmt.mDatabase);
+ // verify that the sql statement is still not compiled
+ assertEquals(0, stmt.nStatement);
+ assertEquals(0, stmt.getSqlStatementId());
+ assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
+ assertEquals(mDatabase, stmt.mDatabase);
// execute the statement
Long l = stmt.simpleQueryForLong();
assertEquals(colValue, l.intValue());
// now that the statement is executed, pre-compiled statement should be released
assertEquals(0, stmt.nStatement);
assertEquals(0, stmt.getSqlStatementId());
- // but the database handle should still remain attached to the statement
- assertEquals(dbUsed.mNativeHandle, stmt.nHandle);
- assertEquals(dbUsed, stmt.mDatabase);
+ assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
+ assertEquals(mDatabase, stmt.mDatabase);
stmt.close();
// pre-compiled SQL statement should still remain released from this object
assertEquals(0, stmt.nStatement);
assertEquals(0, stmt.getSqlStatementId());
// but the database handle should still remain attached to the statement
- assertEquals(dbUsed, stmt.mDatabase);
- }
-
- /**
- * test to make sure SqliteStatement.nStatement is populated only during bind and execute calls.
- */
- public void testGetSqlStatementId() {
- mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
- "num1 INTEGER, num2 INTEGER, image BLOB);");
- final String statement = "DELETE FROM test WHERE _id=?;";
- SQLiteStatement statementOne = mDatabase.compileStatement(statement);
- // sql statement is NOT compiled until the bind or execute call.
- statementOne.bindLong(1, 1);
- SQLiteStatement statementTwo = mDatabase.compileStatement(statement);
- statementTwo.bindLong(1, 1);
- // since the same compiled statement is being accessed at the same time by 2 different
- // objects, they each get their own statement id
- assertTrue(statementOne.getSqlStatementId() != statementTwo.getSqlStatementId());
- statementOne.close();
- statementTwo.close();
-
- // two SQLiteStatements referring to the same SQL statement should refer to the same
- // pre-compiled SQl statement id if the SQLiteStatement objects are NOT in use at the same
- // time
- statementOne = mDatabase.compileStatement(statement);
- statementOne.bindLong(1, 1);
- // now that the SQL statement is compiled, get its pre-compiled SQL statement id
- int n = statementOne.getSqlStatementId();
- statementOne.close();
- statementTwo = mDatabase.compileStatement(statement);
- statementTwo.bindLong(1, 2); // use different value for bindarg, just for the heck of it
- assertEquals(n, statementTwo.getSqlStatementId());
- statementTwo.close();
-
- // now try to compile 2 different statements and they should have different uniquerIds.
- SQLiteStatement statement1 = mDatabase.compileStatement("DELETE FROM test WHERE _id > ?;");
- statement1.bindLong(1, 1);
- SQLiteStatement statement2 = mDatabase.compileStatement("DELETE FROM test WHERE _id < ?;");
- statement2.bindLong(1, 11);
- assertTrue(statement1.getSqlStatementId() != statement2.getSqlStatementId());
- statement1.close();
- statement2.close();
- }
-
- public void testOnAllReferencesReleased() {
- mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
- "num1 INTEGER, num2 INTEGER, image BLOB);");
- final String statement = "DELETE FROM test WHERE _id=?;";
- SQLiteStatement statementOne = mDatabase.compileStatement(statement);
- statementOne.bindLong(1, 1);
- assertTrue(statementOne.getSqlStatementId() > 0);
- statementOne.releaseReference();
- assertEquals(0, statementOne.getSqlStatementId());
- statementOne.close();
- }
-
- public void testOnAllReferencesReleasedFromContainer() {
- mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
- "num1 INTEGER, num2 INTEGER, image BLOB);");
- final String statement = "DELETE FROM test WHERE _id=?;";
- SQLiteStatement statementOne = mDatabase.compileStatement(statement);
- statementOne.bindLong(1, 1);
- assertTrue(statementOne.getSqlStatementId() > 0);
- statementOne.releaseReferenceFromContainer();
- assertEquals(0, statementOne.getSqlStatementId());
- statementOne.close();
+ assertEquals(mDatabase.mNativeHandle, stmt.nHandle);
+ assertEquals(mDatabase, stmt.mDatabase);
}
}