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:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user