Skip to content

Commit a492040

Browse files
committed
change rawExecSQL to allow execution of SELECT operations
1 parent b49f977 commit a492040

File tree

7 files changed

+96
-15
lines changed

7 files changed

+96
-15
lines changed

sqlcipher/src/androidTest/java/net/zetetic/database/sqlcipher_cts/ImportUnencryptedDatabaseTest.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ public void shouldImportUnencryptedPlaintextDatabase(){
2121
try {
2222
database.close();
2323
unencryptedDatabasePath = extractAssetToDatabaseDirectory("unencrypted.db");
24-
database = SQLiteDatabase.openDatabase(unencryptedDatabasePath.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE);
24+
database = SQLiteDatabase.openDatabase(unencryptedDatabasePath.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_NECESSARY);
2525
database.execSQL("ATTACH DATABASE ? as encrypted KEY ?;",
2626
new Object[]{encryptedDatabasePath.getAbsolutePath(), "foo"});
27-
database.execSQL("SELECT sqlcipher_export('encrypted');");
27+
database.rawExecSQL("SELECT sqlcipher_export('encrypted');");
2828
database.execSQL("DETACH DATABASE encrypted;");
2929
database.close();
30-
3130
database = SQLiteDatabase.openDatabase(encryptedDatabasePath.getAbsolutePath(), "foo",
3231
null, SQLiteDatabase.OPEN_READWRITE, null);
3332
Cursor cursor = database.rawQuery("select * from t1", new String[]{});
@@ -37,15 +36,13 @@ public void shouldImportUnencryptedPlaintextDatabase(){
3736
cursor.close();
3837
}
3938
database.close();
40-
assertThat(a, is("one for the money"));
41-
assertThat(b, is("two for the show"));
42-
4339
} catch (Exception ex){
44-
40+
throw ex;
4541
} finally {
42+
assertThat(a, is("one for the money"));
43+
assertThat(b, is("two for the show"));
4644
delete(unencryptedDatabasePath);
4745
delete(encryptedDatabasePath);
4846
}
4947
}
50-
5148
}

sqlcipher/src/androidTest/java/net/zetetic/database/sqlcipher_cts/SQLCipherDatabaseTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ public void shouldPerformRollbackToSavepoint(){
401401
assertThat(count, is(1L));
402402
}
403403

404-
@Test(expected = SQLiteException.class)
405-
public void shouldThrowExceptionWithSelectStatementUsingRawExecSQL(){
404+
@Test
405+
public void shouldNotThrowExceptionWithSelectStatementUsingRawExecSQL(){
406406
database.rawExecSQL("SELECT count(*) FROM sqlite_schema;");
407407
}
408408

sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteConnection.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ private static native void nativeResetStatementAndClearBindings(
152152
private static native String nativeExecuteForString(long connectionPtr, long statementPtr);
153153
private static native int nativeExecuteForBlobFileDescriptor(
154154
long connectionPtr, long statementPtr);
155+
private static native void nativeExecuteRaw(long connectionPtr, long statementPtr);
155156
private static native int nativeExecuteForChangedRowCount(long connectionPtr, long statementPtr);
156157
private static native long nativeExecuteForLastInsertedRowId(
157158
long connectionPtr, long statementPtr);
@@ -737,6 +738,53 @@ public ParcelFileDescriptor executeForBlobFileDescriptor(String sql, Object[] bi
737738
}
738739
}
739740

741+
/**
742+
* Executes a statement that returns a count of the number of rows
743+
* that were changed. Use for UPDATE or DELETE SQL statements.
744+
*
745+
* @param sql The SQL statement to execute.
746+
* @param bindArgs The arguments to bind, or null if none.
747+
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
748+
* @return The number of rows that were changed.
749+
*
750+
* @throws SQLiteException if an error occurs, such as a syntax error
751+
* or invalid number of bind arguments.
752+
* @throws OperationCanceledException if the operation was canceled.
753+
*/
754+
public void executeRaw(String sql, Object[] bindArgs,
755+
CancellationSignal cancellationSignal) {
756+
if (sql == null) {
757+
throw new IllegalArgumentException("sql must not be null.");
758+
}
759+
760+
final int cookie = mRecentOperations.beginOperation("executeRaw",
761+
sql, bindArgs);
762+
try {
763+
final PreparedStatement statement = acquirePreparedStatement(sql);
764+
try {
765+
throwIfStatementForbidden(statement);
766+
bindArguments(statement, bindArgs);
767+
applyBlockGuardPolicy(statement);
768+
attachCancellationSignal(cancellationSignal);
769+
try {
770+
nativeExecuteRaw(
771+
mConnectionPtr, statement.mStatementPtr);
772+
} finally {
773+
detachCancellationSignal(cancellationSignal);
774+
}
775+
} finally {
776+
releasePreparedStatement(statement);
777+
}
778+
} catch (RuntimeException ex) {
779+
mRecentOperations.failOperation(cookie, ex);
780+
throw ex;
781+
} finally {
782+
if (mRecentOperations.endOperationDeferLog(cookie)) {
783+
mRecentOperations.logOperation(cookie, "");
784+
}
785+
}
786+
}
787+
740788
/**
741789
* Executes a statement that returns a count of the number of rows
742790
* that were changed. Use for UPDATE or DELETE SQL statements.

sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteDatabase.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,16 +1957,15 @@ public void execSQL(String sql, Object[] bindArgs) throws SQLException {
19571957
* @param bindArgs The arguments to bind.
19581958
* @return The number of rows that were changed.
19591959
*/
1960-
public int rawExecSQL(String sql, Object...bindArgs) throws SQLException {
1960+
public void rawExecSQL(String sql, Object...bindArgs) throws SQLException {
19611961
acquireReference();
19621962
try {
19631963
SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
19641964
try {
1965-
return statement.executeUpdateDeleteRaw();
1965+
statement.executeRaw();
19661966
} finally {
19671967
statement.close();
19681968
}
1969-
19701969
} finally {
19711970
releaseReference();
19721971
}

sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteSession.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,15 +778,15 @@ public int executeForChangedRowCount(String sql, Object[] bindArgs, int connecti
778778
* or invalid number of bind arguments.
779779
* @throws OperationCanceledException if the operation was canceled.
780780
*/
781-
public int executeForChangedRowCountRaw(String sql, Object[] bindArgs, int connectionFlags,
781+
public void executeRaw(String sql, Object[] bindArgs, int connectionFlags,
782782
CancellationSignal cancellationSignal) {
783783
if (sql == null) {
784784
throw new IllegalArgumentException("sql must not be null.");
785785
}
786786

787787
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
788788
try {
789-
return mConnection.executeForChangedRowCount(sql, bindArgs,
789+
mConnection.executeRaw(sql, bindArgs,
790790
cancellationSignal); // might throw
791791
} finally {
792792
releaseConnection(); // might throw

sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteStatement.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ public final class SQLiteStatement extends SQLiteProgram implements SupportSQLit
3838
super(db, sql, bindArgs, null);
3939
}
4040

41+
/**
42+
* Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
43+
* CREATE / DROP table, view, trigger, index etc.
44+
*
45+
* @throws android.database.SQLException If the SQL string is invalid for
46+
* some reason
47+
*/
48+
public void executeRaw() {
49+
acquireReference();
50+
try {
51+
getSession().executeRaw(getSql(), getBindArgs(), getConnectionFlags(), null);
52+
} catch (SQLiteDatabaseCorruptException ex) {
53+
onCorruption();
54+
throw ex;
55+
} finally {
56+
releaseReference();
57+
}
58+
}
59+
4160
/**
4261
* Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
4362
* CREATE / DROP table, view, trigger, index etc.

sqlcipher/src/main/jni/sqlcipher/android_database_SQLiteConnection.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,22 @@ static void nativeResetStatementAndClearBindings(JNIEnv* env, jclass clazz, jlon
497497
}
498498
}
499499

500+
static int executeNonQueryRaw(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) {
501+
int err;
502+
do {
503+
err = sqlite3_step(statement);
504+
} while(err == SQLITE_ROW);
505+
return err;
506+
}
507+
508+
static void nativeExecuteRaw(JNIEnv* env, jclass clazz, jlong connectionPtr,
509+
jlong statementPtr) {
510+
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
511+
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
512+
513+
executeNonQueryRaw(env, connection, statement);
514+
}
515+
500516
static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) {
501517
int err = sqlite3_step(statement);
502518
if (err == SQLITE_ROW) {
@@ -905,6 +921,8 @@ static JNINativeMethod sMethods[] =
905921
(void*)nativeBindBlob },
906922
{ "nativeResetStatementAndClearBindings", "(JJ)V",
907923
(void*)nativeResetStatementAndClearBindings },
924+
{ "nativeExecuteRaw", "(JJ)V",
925+
(void*)nativeExecuteRaw },
908926
{ "nativeExecute", "(JJ)V",
909927
(void*)nativeExecute },
910928
{ "nativeExecuteForLong", "(JJ)J",

0 commit comments

Comments
 (0)