don't compile statement for certain SQL statements

SQL statements such as Create table, Pragma, Begin, Commit, Rollback
etc don't need a compiled statement.

Change-Id: I55f5e4e6cbb41cbe83e592e25ba852fe23e2b39f
This commit is contained in:
Vasu Nori
2010-09-15 18:40:49 -07:00
parent 7553cf74e6
commit 4e874edf69
5 changed files with 126 additions and 20 deletions

View File

@@ -64538,7 +64538,29 @@
visibility="public"
>
</field>
<field name="STATEMENT_DDL"
type="int"
transient="false"
volatile="false"
value="8"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="STATEMENT_OTHER"
type="int"
transient="false"
volatile="false"
value="99"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="STATEMENT_PRAGMA"
type="int"
transient="false"
volatile="false"
@@ -64560,6 +64582,17 @@
visibility="public"
>
</field>
<field name="STATEMENT_UNPREPARED"
type="int"
transient="false"
volatile="false"
value="9"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="STATEMENT_UPDATE"
type="int"
transient="false"

View File

@@ -66,7 +66,13 @@ public class DatabaseUtils {
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_ABORT = 6;
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_OTHER = 7;
public static final int STATEMENT_PRAGMA = 7;
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_DDL = 8;
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_UNPREPARED = 9;
/** One of the values returned by {@link #getSqlStatementType(String)}. */
public static final int STATEMENT_OTHER = 99;
/**
* Special function for writing an exception result at the header of
@@ -1255,6 +1261,13 @@ public class DatabaseUtils {
return STATEMENT_ABORT;
} else if (prefixSql.equals("BEG")) {
return STATEMENT_BEGIN;
} else if (prefixSql.equals("PRA")) {
return STATEMENT_PRAGMA;
} else if (prefixSql.equals("CRE") || prefixSql.equals("DRO") ||
prefixSql.equals("ALT")) {
return STATEMENT_DDL;
} else if (prefixSql.equals("ANA") || prefixSql.equals("DET")) {
return STATEMENT_UNPREPARED;
}
return STATEMENT_OTHER;
}

View File

@@ -86,6 +86,10 @@ public abstract class SQLiteProgram extends SQLiteClosable {
*/
/* package */ HashMap<Integer, Object> mBindArgs = null;
/* package */ final int mStatementType;
/* package */ static final int STATEMENT_CACHEABLE = 16;
/* package */ static final int STATEMENT_DONT_PREPARE = 32;
/* package */ static final int STATEMENT_USE_POOLED_CONN = 64;
/* package */ static final int STATEMENT_TYPE_MASK = 0x0f;
/* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
this(db, sql, null, true);
@@ -94,7 +98,25 @@ public abstract class SQLiteProgram extends SQLiteClosable {
/* package */ SQLiteProgram(SQLiteDatabase db, String sql, Object[] bindArgs,
boolean compileFlag) {
mSql = sql.trim();
mStatementType = DatabaseUtils.getSqlStatementType(mSql);
int n = DatabaseUtils.getSqlStatementType(mSql);
switch (n) {
case DatabaseUtils.STATEMENT_UPDATE:
mStatementType = n | STATEMENT_CACHEABLE;
break;
case DatabaseUtils.STATEMENT_SELECT:
mStatementType = n | STATEMENT_CACHEABLE | STATEMENT_USE_POOLED_CONN;
break;
case DatabaseUtils.STATEMENT_ATTACH:
case DatabaseUtils.STATEMENT_BEGIN:
case DatabaseUtils.STATEMENT_COMMIT:
case DatabaseUtils.STATEMENT_ABORT:
case DatabaseUtils.STATEMENT_DDL:
case DatabaseUtils.STATEMENT_UNPREPARED:
mStatementType = n | STATEMENT_DONT_PREPARE;
break;
default:
mStatementType = n;
}
db.acquireReference();
db.addSQLiteClosable(this);
mDatabase = db;
@@ -112,8 +134,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
private void compileSql() {
// only cache CRUD statements
if (mStatementType != DatabaseUtils.STATEMENT_SELECT &&
mStatementType != DatabaseUtils.STATEMENT_UPDATE) {
if ((mStatementType & STATEMENT_CACHEABLE) == 0) {
mCompiledSql = new SQLiteCompiledSql(mDatabase, mSql);
nStatement = mCompiledSql.nStatement;
// since it is not in the cache, no need to acquire() it.
@@ -163,14 +184,19 @@ public abstract class SQLiteProgram extends SQLiteClosable {
if (mCompiledSql == null) {
return;
}
synchronized(mDatabase.mCompiledQueries) {
if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) {
// it is NOT in compiled-sql cache. i.e., responsibility of
// releasing this statement is on me.
mCompiledSql.releaseSqlStatement();
} else {
// it is in compiled-sql cache. reset its CompiledSql#mInUse flag
mCompiledSql.release();
if ((mStatementType & STATEMENT_CACHEABLE) == 0) {
// this SQL statement was never in cache
mCompiledSql.releaseSqlStatement();
} else {
synchronized(mDatabase.mCompiledQueries) {
if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) {
// it is NOT in compiled-sql cache. i.e., responsibility of
// releasing this statement is on me.
mCompiledSql.releaseSqlStatement();
} else {
// it is in compiled-sql cache. reset its CompiledSql#mInUse flag
mCompiledSql.release();
}
}
}
mCompiledSql = null;
@@ -347,6 +373,16 @@ public abstract class SQLiteProgram extends SQLiteClosable {
}
/* package */ synchronized void compileAndbindAllArgs() {
if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) {
// no need to prepare this SQL statement
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
if (mBindArgs != null) {
throw new IllegalArgumentException("no need to pass bindargs for this sql :" +
mSql);
}
}
return;
}
if (nStatement == 0) {
// SQL statement is not compiled yet. compile it now.
compileSql();

View File

@@ -71,7 +71,7 @@ public class SQLiteStatement extends SQLiteProgram
}
/**
* Execute this SQL statement, if the the number of rows affected by exection of this SQL
* Execute this SQL statement, if the the number of rows affected by execution of this SQL
* statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
*
* @return the number of rows affected by this SQL statement execution.
@@ -82,7 +82,15 @@ public class SQLiteStatement extends SQLiteProgram
synchronized(this) {
try {
long timeStart = acquireAndLock(WRITE);
int numChanges = native_execute();
int numChanges = 0;
if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) {
// since the statement doesn't have to be prepared,
// call the following native method which will not prepare
// the query plan
native_executeSql(mSql);
} else {
numChanges = native_execute();
}
mDatabase.logTimeStat(mSql, timeStart);
return numChanges;
} finally {
@@ -199,8 +207,8 @@ public class SQLiteStatement extends SQLiteProgram
mState = 0;
// use pooled database connection handles for SELECT SQL statements
mDatabase.verifyDbIsOpen();
SQLiteDatabase db = (mStatementType != DatabaseUtils.STATEMENT_SELECT) ? mDatabase
: mDatabase.getDbConnection(mSql);
SQLiteDatabase db = ((mStatementType & SQLiteProgram.STATEMENT_USE_POOLED_CONN) > 0)
? mDatabase.getDbConnection(mSql) : mDatabase;
// use the database connection obtained above
mOrigDb = mDatabase;
mDatabase = db;
@@ -217,13 +225,14 @@ public class SQLiteStatement extends SQLiteProgram
* beginTransaction() methods in SQLiteDatabase call lockForced() before
* calling execSQL("BEGIN transaction").
*/
if (mStatementType == DatabaseUtils.STATEMENT_BEGIN) {
if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == DatabaseUtils.STATEMENT_BEGIN) {
if (!mDatabase.isDbLockedByCurrentThread()) {
// transaction is NOT started by calling beginTransaction() methods in
// SQLiteDatabase
mDatabase.setTransactionUsingExecSqlFlag();
}
} else if (mStatementType == DatabaseUtils.STATEMENT_UPDATE) {
} else if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) ==
DatabaseUtils.STATEMENT_UPDATE) {
// got update SQL statement. if there is NO pending transaction, start one
if (!mDatabase.inTransaction()) {
mDatabase.beginTransactionNonExclusive();
@@ -257,8 +266,10 @@ public class SQLiteStatement extends SQLiteProgram
} else if (mState == LOCK_ACQUIRED) {
mDatabase.unlock();
}
if (mStatementType == DatabaseUtils.STATEMENT_COMMIT ||
mStatementType == DatabaseUtils.STATEMENT_ABORT) {
if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) ==
DatabaseUtils.STATEMENT_COMMIT ||
(mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) ==
DatabaseUtils.STATEMENT_ABORT) {
mDatabase.resetTransactionUsingExecSqlFlag();
}
clearBindings();
@@ -275,4 +286,5 @@ public class SQLiteStatement extends SQLiteProgram
private final native long native_1x1_long();
private final native String native_1x1_string();
private final native ParcelFileDescriptor native_1x1_blob_ashmem() throws IOException;
private final native void native_executeSql(String sql);
}

View File

@@ -239,6 +239,17 @@ static jobject native_1x1_blob_ashmem(JNIEnv* env, jobject object)
return value;
}
static void native_executeSql(JNIEnv* env, jobject object, jstring sql)
{
char const* sqlString = env->GetStringUTFChars(sql, NULL);
sqlite3 * handle = GET_HANDLE(env, object);
int err = sqlite3_exec(handle, sqlString, NULL, NULL, NULL);
if (err != SQLITE_OK) {
throw_sqlite3_exception(env, handle);
}
env->ReleaseStringUTFChars(sql, sqlString);
}
static JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
@@ -247,6 +258,7 @@ static JNINativeMethod sMethods[] =
{"native_1x1_long", "()J", (void *)native_1x1_long},
{"native_1x1_string", "()Ljava/lang/String;", (void *)native_1x1_string},
{"native_1x1_blob_ashmem", "()Landroid/os/ParcelFileDescriptor;", (void *)native_1x1_blob_ashmem},
{"native_executeSql", "(Ljava/lang/String;)V", (void *)native_executeSql},
};
int register_android_database_SQLiteStatement(JNIEnv * env)