Merge "Revert "Add API support for sqlite3_set_authorizer().""
This commit is contained in:
@@ -14205,46 +14205,6 @@ package android.database.sqlite {
|
||||
ctor public SQLiteAccessPermException(String);
|
||||
}
|
||||
|
||||
public interface SQLiteAuthorizer {
|
||||
method public int onAuthorize(int, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
|
||||
field public static final int SQLITE_ACTION_ALTER_TABLE = 26; // 0x1a
|
||||
field public static final int SQLITE_ACTION_ANALYZE = 28; // 0x1c
|
||||
field public static final int SQLITE_ACTION_ATTACH = 24; // 0x18
|
||||
field public static final int SQLITE_ACTION_CREATE_INDEX = 1; // 0x1
|
||||
field public static final int SQLITE_ACTION_CREATE_TABLE = 2; // 0x2
|
||||
field public static final int SQLITE_ACTION_CREATE_TEMP_INDEX = 3; // 0x3
|
||||
field public static final int SQLITE_ACTION_CREATE_TEMP_TABLE = 4; // 0x4
|
||||
field public static final int SQLITE_ACTION_CREATE_TEMP_TRIGGER = 5; // 0x5
|
||||
field public static final int SQLITE_ACTION_CREATE_TEMP_VIEW = 6; // 0x6
|
||||
field public static final int SQLITE_ACTION_CREATE_TRIGGER = 7; // 0x7
|
||||
field public static final int SQLITE_ACTION_CREATE_VIEW = 8; // 0x8
|
||||
field public static final int SQLITE_ACTION_CREATE_VTABLE = 29; // 0x1d
|
||||
field public static final int SQLITE_ACTION_DELETE = 9; // 0x9
|
||||
field public static final int SQLITE_ACTION_DETACH = 25; // 0x19
|
||||
field public static final int SQLITE_ACTION_DROP_INDEX = 10; // 0xa
|
||||
field public static final int SQLITE_ACTION_DROP_TABLE = 11; // 0xb
|
||||
field public static final int SQLITE_ACTION_DROP_TEMP_INDEX = 12; // 0xc
|
||||
field public static final int SQLITE_ACTION_DROP_TEMP_TABLE = 13; // 0xd
|
||||
field public static final int SQLITE_ACTION_DROP_TEMP_TRIGGER = 14; // 0xe
|
||||
field public static final int SQLITE_ACTION_DROP_TEMP_VIEW = 15; // 0xf
|
||||
field public static final int SQLITE_ACTION_DROP_TRIGGER = 16; // 0x10
|
||||
field public static final int SQLITE_ACTION_DROP_VIEW = 17; // 0x11
|
||||
field public static final int SQLITE_ACTION_DROP_VTABLE = 30; // 0x1e
|
||||
field public static final int SQLITE_ACTION_FUNCTION = 31; // 0x1f
|
||||
field public static final int SQLITE_ACTION_INSERT = 18; // 0x12
|
||||
field public static final int SQLITE_ACTION_PRAGMA = 19; // 0x13
|
||||
field public static final int SQLITE_ACTION_READ = 20; // 0x14
|
||||
field public static final int SQLITE_ACTION_RECURSIVE = 33; // 0x21
|
||||
field public static final int SQLITE_ACTION_REINDEX = 27; // 0x1b
|
||||
field public static final int SQLITE_ACTION_SAVEPOINT = 32; // 0x20
|
||||
field public static final int SQLITE_ACTION_SELECT = 21; // 0x15
|
||||
field public static final int SQLITE_ACTION_TRANSACTION = 22; // 0x16
|
||||
field public static final int SQLITE_ACTION_UPDATE = 23; // 0x17
|
||||
field public static final int SQLITE_AUTHORIZER_RESULT_DENY = 1; // 0x1
|
||||
field public static final int SQLITE_AUTHORIZER_RESULT_IGNORE = 2; // 0x2
|
||||
field public static final int SQLITE_AUTHORIZER_RESULT_OK = 0; // 0x0
|
||||
}
|
||||
|
||||
public class SQLiteBindOrColumnIndexOutOfRangeException extends android.database.sqlite.SQLiteException {
|
||||
ctor public SQLiteBindOrColumnIndexOutOfRangeException();
|
||||
ctor public SQLiteBindOrColumnIndexOutOfRangeException(String);
|
||||
@@ -14301,7 +14261,6 @@ package android.database.sqlite {
|
||||
method public void beginTransactionWithListenerNonExclusive(@Nullable android.database.sqlite.SQLiteTransactionListener);
|
||||
method public void beginTransactionWithListenerReadOnly(@Nullable android.database.sqlite.SQLiteTransactionListener);
|
||||
method public android.database.sqlite.SQLiteStatement compileStatement(String) throws android.database.SQLException;
|
||||
method @NonNull public android.database.sqlite.SQLiteStatement compileStatement(@NonNull String, @NonNull android.database.sqlite.SQLiteAuthorizer) throws android.database.SQLException;
|
||||
method @NonNull public static android.database.sqlite.SQLiteDatabase create(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
|
||||
method @NonNull public static android.database.sqlite.SQLiteDatabase createInMemory(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
|
||||
method public int delete(String, String, String[]);
|
||||
@@ -14312,7 +14271,6 @@ package android.database.sqlite {
|
||||
method public void execPerConnectionSQL(@NonNull String, @Nullable Object[]) throws android.database.SQLException;
|
||||
method public void execSQL(String) throws android.database.SQLException;
|
||||
method public void execSQL(String, Object[]) throws android.database.SQLException;
|
||||
method public void execSQL(@NonNull String, @Nullable Object[], @NonNull android.database.sqlite.SQLiteAuthorizer) throws android.database.SQLException;
|
||||
method public static String findEditTable(String);
|
||||
method public java.util.List<android.util.Pair<java.lang.String,java.lang.String>> getAttachedDbs();
|
||||
method public long getMaximumSize();
|
||||
@@ -14324,7 +14282,6 @@ package android.database.sqlite {
|
||||
method public long insert(String, String, android.content.ContentValues);
|
||||
method public long insertOrThrow(String, String, android.content.ContentValues) throws android.database.SQLException;
|
||||
method public long insertWithOnConflict(String, String, android.content.ContentValues, int);
|
||||
method public boolean isAuthorizerSupportEnabled();
|
||||
method public boolean isDatabaseIntegrityOk();
|
||||
method public boolean isDbLockedByCurrentThread();
|
||||
method @Deprecated public boolean isDbLockedByOtherThreads();
|
||||
@@ -14351,7 +14308,6 @@ package android.database.sqlite {
|
||||
method public android.database.Cursor rawQuery(String, String[], android.os.CancellationSignal);
|
||||
method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, String, String[], String);
|
||||
method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, String, String[], String, android.os.CancellationSignal);
|
||||
method @NonNull public android.database.Cursor rawQueryWithFactory(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory, @NonNull String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal, @NonNull android.database.sqlite.SQLiteAuthorizer);
|
||||
method public static int releaseMemory();
|
||||
method public long replace(String, String, android.content.ContentValues);
|
||||
method public long replaceOrThrow(String, String, android.content.ContentValues) throws android.database.SQLException;
|
||||
@@ -14368,7 +14324,6 @@ package android.database.sqlite {
|
||||
method public int update(String, android.content.ContentValues, String, String[]);
|
||||
method public int updateWithOnConflict(String, android.content.ContentValues, String, String[], int);
|
||||
method public void validateSql(@NonNull String, @Nullable android.os.CancellationSignal);
|
||||
method public void validateSql(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull android.database.sqlite.SQLiteAuthorizer);
|
||||
method @Deprecated public boolean yieldIfContended();
|
||||
method public boolean yieldIfContendedSafely();
|
||||
method public boolean yieldIfContendedSafely(long);
|
||||
@@ -14417,9 +14372,7 @@ package android.database.sqlite {
|
||||
ctor public SQLiteDatabase.OpenParams.Builder(android.database.sqlite.SQLiteDatabase.OpenParams);
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder addOpenFlags(int);
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams build();
|
||||
method public boolean isAuthorizerSupportEnabled();
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setAuthorizerSupportEnabled(boolean);
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
|
||||
method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(@Nullable android.database.DatabaseErrorHandler);
|
||||
method @Deprecated @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(@IntRange(from=0) long);
|
||||
|
||||
@@ -1303,7 +1303,6 @@ package android.database.sqlite {
|
||||
|
||||
public final class SQLiteDirectCursorDriver implements android.database.sqlite.SQLiteCursorDriver {
|
||||
ctor public SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal);
|
||||
ctor public SQLiteDirectCursorDriver(@NonNull android.database.sqlite.SQLiteDatabase, @Nullable android.database.sqlite.SQLiteAuthorizer, @NonNull String, @Nullable String, @Nullable android.os.CancellationSignal);
|
||||
method public void cursorClosed();
|
||||
method public void cursorDeactivated();
|
||||
method public void cursorRequeried(android.database.Cursor);
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Authorizer which is consulted during compilation of a SQL statement.
|
||||
* <p>
|
||||
* During compilation, this callback will be invoked to determine if each action
|
||||
* requested by the SQL statement is allowed.
|
||||
* <p>
|
||||
* This can be useful to dynamically block interaction with private, internal,
|
||||
* or otherwise sensitive columns or tables inside a database, such as when
|
||||
* compiling an untrusted SQL statement.
|
||||
*/
|
||||
public interface SQLiteAuthorizer {
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "SQLITE_AUTHORIZER_RESULT_" }, value = {
|
||||
SQLITE_AUTHORIZER_RESULT_OK,
|
||||
SQLITE_AUTHORIZER_RESULT_DENY,
|
||||
SQLITE_AUTHORIZER_RESULT_IGNORE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface AuthorizerResult {}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "SQLITE_ACTION_" }, value = {
|
||||
SQLITE_ACTION_CREATE_INDEX,
|
||||
SQLITE_ACTION_CREATE_TABLE,
|
||||
SQLITE_ACTION_CREATE_TEMP_INDEX,
|
||||
SQLITE_ACTION_CREATE_TEMP_TABLE,
|
||||
SQLITE_ACTION_CREATE_TEMP_TRIGGER,
|
||||
SQLITE_ACTION_CREATE_TEMP_VIEW,
|
||||
SQLITE_ACTION_CREATE_TRIGGER,
|
||||
SQLITE_ACTION_CREATE_VIEW,
|
||||
SQLITE_ACTION_DELETE,
|
||||
SQLITE_ACTION_DROP_INDEX,
|
||||
SQLITE_ACTION_DROP_TABLE,
|
||||
SQLITE_ACTION_DROP_TEMP_INDEX,
|
||||
SQLITE_ACTION_DROP_TEMP_TABLE,
|
||||
SQLITE_ACTION_DROP_TEMP_TRIGGER,
|
||||
SQLITE_ACTION_DROP_TEMP_VIEW,
|
||||
SQLITE_ACTION_DROP_TRIGGER,
|
||||
SQLITE_ACTION_DROP_VIEW,
|
||||
SQLITE_ACTION_INSERT,
|
||||
SQLITE_ACTION_PRAGMA,
|
||||
SQLITE_ACTION_READ,
|
||||
SQLITE_ACTION_SELECT,
|
||||
SQLITE_ACTION_TRANSACTION,
|
||||
SQLITE_ACTION_UPDATE,
|
||||
SQLITE_ACTION_ATTACH,
|
||||
SQLITE_ACTION_DETACH,
|
||||
SQLITE_ACTION_ALTER_TABLE,
|
||||
SQLITE_ACTION_REINDEX,
|
||||
SQLITE_ACTION_ANALYZE,
|
||||
SQLITE_ACTION_CREATE_VTABLE,
|
||||
SQLITE_ACTION_DROP_VTABLE,
|
||||
SQLITE_ACTION_FUNCTION,
|
||||
SQLITE_ACTION_SAVEPOINT,
|
||||
SQLITE_ACTION_RECURSIVE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface AuthorizerAction {}
|
||||
|
||||
/** Successful result */
|
||||
int SQLITE_AUTHORIZER_RESULT_OK = 0;
|
||||
/** Abort the SQL statement with an error */
|
||||
int SQLITE_AUTHORIZER_RESULT_DENY = 1;
|
||||
/** Don't allow access, but don't generate an error */
|
||||
int SQLITE_AUTHORIZER_RESULT_IGNORE = 2;
|
||||
|
||||
/** Authorizer action for {@code CREATE INDEX} */
|
||||
int SQLITE_ACTION_CREATE_INDEX = 1;
|
||||
/** Authorizer action for {@code CREATE TABLE} */
|
||||
int SQLITE_ACTION_CREATE_TABLE = 2;
|
||||
/** Authorizer action for {@code CREATE TEMP INDEX} */
|
||||
int SQLITE_ACTION_CREATE_TEMP_INDEX = 3;
|
||||
/** Authorizer action for {@code CREATE TEMP TABLE} */
|
||||
int SQLITE_ACTION_CREATE_TEMP_TABLE = 4;
|
||||
/** Authorizer action for {@code CREATE TEMP TRIGGER} */
|
||||
int SQLITE_ACTION_CREATE_TEMP_TRIGGER = 5;
|
||||
/** Authorizer action for {@code CREATE TEMP VIEW} */
|
||||
int SQLITE_ACTION_CREATE_TEMP_VIEW = 6;
|
||||
/** Authorizer action for {@code CREATE TRIGGER} */
|
||||
int SQLITE_ACTION_CREATE_TRIGGER = 7;
|
||||
/** Authorizer action for {@code CREATE VIEW} */
|
||||
int SQLITE_ACTION_CREATE_VIEW = 8;
|
||||
/** Authorizer action for {@code DELETE} */
|
||||
int SQLITE_ACTION_DELETE = 9;
|
||||
/** Authorizer action for {@code DROP INDEX} */
|
||||
int SQLITE_ACTION_DROP_INDEX = 10;
|
||||
/** Authorizer action for {@code DROP TABLE} */
|
||||
int SQLITE_ACTION_DROP_TABLE = 11;
|
||||
/** Authorizer action for {@code DROP TEMP INDEX} */
|
||||
int SQLITE_ACTION_DROP_TEMP_INDEX = 12;
|
||||
/** Authorizer action for {@code DROP TEMP TABLE} */
|
||||
int SQLITE_ACTION_DROP_TEMP_TABLE = 13;
|
||||
/** Authorizer action for {@code DROP TEMP TRIGGER} */
|
||||
int SQLITE_ACTION_DROP_TEMP_TRIGGER = 14;
|
||||
/** Authorizer action for {@code DROP TEMP VIEW} */
|
||||
int SQLITE_ACTION_DROP_TEMP_VIEW = 15;
|
||||
/** Authorizer action for {@code DROP TRIGGER} */
|
||||
int SQLITE_ACTION_DROP_TRIGGER = 16;
|
||||
/** Authorizer action for {@code DROP VIEW} */
|
||||
int SQLITE_ACTION_DROP_VIEW = 17;
|
||||
/** Authorizer action for {@code INSERT} */
|
||||
int SQLITE_ACTION_INSERT = 18;
|
||||
/** Authorizer action for {@code PRAGMA} */
|
||||
int SQLITE_ACTION_PRAGMA = 19;
|
||||
/** Authorizer action for read access on a specific table and column */
|
||||
int SQLITE_ACTION_READ = 20;
|
||||
/** Authorizer action for {@code SELECT} */
|
||||
int SQLITE_ACTION_SELECT = 21;
|
||||
/** Authorizer action for transaction operations */
|
||||
int SQLITE_ACTION_TRANSACTION = 22;
|
||||
/** Authorizer action for {@code UPDATE} */
|
||||
int SQLITE_ACTION_UPDATE = 23;
|
||||
/** Authorizer action for {@code ATTACH} */
|
||||
int SQLITE_ACTION_ATTACH = 24;
|
||||
/** Authorizer action for {@code DETACH} */
|
||||
int SQLITE_ACTION_DETACH = 25;
|
||||
/** Authorizer action for {@code ALTER TABLE} */
|
||||
int SQLITE_ACTION_ALTER_TABLE = 26;
|
||||
/** Authorizer action for {@code REINDEX} */
|
||||
int SQLITE_ACTION_REINDEX = 27;
|
||||
/** Authorizer action for {@code ANALYZE} */
|
||||
int SQLITE_ACTION_ANALYZE = 28;
|
||||
/** Authorizer action for {@code CREATE VIRTUAL TABLE} */
|
||||
int SQLITE_ACTION_CREATE_VTABLE = 29;
|
||||
/** Authorizer action for {@code DROP VIRTUAL TABLE} */
|
||||
int SQLITE_ACTION_DROP_VTABLE = 30;
|
||||
/** Authorizer action for invocation of a function */
|
||||
int SQLITE_ACTION_FUNCTION = 31;
|
||||
/** Authorizer action for savepoint operations */
|
||||
int SQLITE_ACTION_SAVEPOINT = 32;
|
||||
/** Authorizer action for recursive operations */
|
||||
int SQLITE_ACTION_RECURSIVE = 33;
|
||||
|
||||
/**
|
||||
* Test if the given action should be allowed.
|
||||
*
|
||||
* @param action The action requested by the SQL statement currently being
|
||||
* compiled.
|
||||
* @param arg3 Optional argument relevant to the given action.
|
||||
* @param arg4 Optional argument relevant to the given action.
|
||||
* @param arg5 Optional argument relevant to the given action.
|
||||
* @param arg6 Optional argument relevant to the given action.
|
||||
* @return {@link SQLiteConstants#SQLITE_AUTHORIZER_RESULT_OK} to allow the action,
|
||||
* {@link SQLiteConstants#SQLITE_AUTHORIZER_RESULT_IGNORE} to disallow the specific
|
||||
* action but allow the SQL statement to continue to be compiled, or
|
||||
* {@link SQLiteConstants#SQLITE_AUTHORIZER_RESULT_DENY} to cause the entire SQL
|
||||
* statement to be rejected with an error.
|
||||
* @see <a href="https://www.sqlite.org/c3ref/c_alter_table.html">Upstream
|
||||
* SQLite documentation</a> that describes possible actions and their
|
||||
* arguments.
|
||||
*/
|
||||
@AuthorizerResult int onAuthorize(@AuthorizerAction int action, @Nullable String arg3,
|
||||
@Nullable String arg4, @Nullable String arg5, @Nullable String arg6);
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWindow;
|
||||
import android.database.DatabaseUtils;
|
||||
@@ -33,10 +33,8 @@ import android.util.Log;
|
||||
import android.util.LruCache;
|
||||
import android.util.Pair;
|
||||
import android.util.Printer;
|
||||
|
||||
import dalvik.system.BlockGuard;
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
@@ -130,10 +128,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
private int mCancellationSignalAttachCount;
|
||||
|
||||
private static native long nativeOpen(String path, int openFlags, String label,
|
||||
int lookasideSlotSize, int lookasideSlotCount);
|
||||
boolean enableTrace, boolean enableProfile, int lookasideSlotSize,
|
||||
int lookasideSlotCount);
|
||||
private static native void nativeClose(long connectionPtr);
|
||||
private static native void nativeSetAuthorizer(long connectionPtr,
|
||||
SQLiteAuthorizer authorizer);
|
||||
private static native void nativeRegisterCustomScalarFunction(long connectionPtr,
|
||||
String name, UnaryOperator<String> function);
|
||||
private static native void nativeRegisterCustomAggregateFunction(long connectionPtr,
|
||||
@@ -228,7 +225,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final String file = mConfiguration.path;
|
||||
final int cookie = mRecentOperations.beginOperation("open", null, null);
|
||||
try {
|
||||
mConnectionPtr = nativeOpen(file, mConfiguration.openFlags, mConfiguration.label,
|
||||
mConnectionPtr = nativeOpen(file, mConfiguration.openFlags,
|
||||
mConfiguration.label,
|
||||
NoPreloadHolder.DEBUG_SQL_STATEMENTS, NoPreloadHolder.DEBUG_SQL_TIME,
|
||||
mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
|
||||
} catch (SQLiteCantOpenDatabaseException e) {
|
||||
final StringBuilder message = new StringBuilder("Cannot open database '")
|
||||
@@ -302,9 +301,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
private void setPageSize() {
|
||||
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
|
||||
final long newValue = SQLiteGlobal.getDefaultPageSize();
|
||||
long value = executeForLong(null, "PRAGMA page_size", null, null);
|
||||
long value = executeForLong("PRAGMA page_size", null, null);
|
||||
if (value != newValue) {
|
||||
execute(null, "PRAGMA page_size=" + newValue, null, null);
|
||||
execute("PRAGMA page_size=" + newValue, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,9 +311,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
private void setAutoCheckpointInterval() {
|
||||
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
|
||||
final long newValue = SQLiteGlobal.getWALAutoCheckpoint();
|
||||
long value = executeForLong(null, "PRAGMA wal_autocheckpoint", null, null);
|
||||
long value = executeForLong("PRAGMA wal_autocheckpoint", null, null);
|
||||
if (value != newValue) {
|
||||
executeForLong(null, "PRAGMA wal_autocheckpoint=" + newValue, null, null);
|
||||
executeForLong("PRAGMA wal_autocheckpoint=" + newValue, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,9 +321,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
private void setJournalSizeLimit() {
|
||||
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
|
||||
final long newValue = SQLiteGlobal.getJournalSizeLimit();
|
||||
long value = executeForLong(null, "PRAGMA journal_size_limit", null, null);
|
||||
long value = executeForLong("PRAGMA journal_size_limit", null, null);
|
||||
if (value != newValue) {
|
||||
executeForLong(null, "PRAGMA journal_size_limit=" + newValue, null, null);
|
||||
executeForLong("PRAGMA journal_size_limit=" + newValue, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,9 +331,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
private void setForeignKeyModeFromConfiguration() {
|
||||
if (!mIsReadOnlyConnection) {
|
||||
final long newValue = mConfiguration.foreignKeyConstraintsEnabled ? 1 : 0;
|
||||
long value = executeForLong(null, "PRAGMA foreign_keys", null, null);
|
||||
long value = executeForLong("PRAGMA foreign_keys", null, null);
|
||||
if (value != newValue) {
|
||||
execute(null, "PRAGMA foreign_keys=" + newValue, null, null);
|
||||
execute("PRAGMA foreign_keys=" + newValue, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,7 +386,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
Log.i(TAG, walFile.getAbsolutePath() + " " + size + " bytes: Bigger than "
|
||||
+ threshold + "; truncating");
|
||||
try {
|
||||
executeForString(null, "PRAGMA wal_checkpoint(TRUNCATE)", null, null);
|
||||
executeForString("PRAGMA wal_checkpoint(TRUNCATE)", null, null);
|
||||
mConfiguration.shouldTruncateWalFile = false;
|
||||
} catch (SQLiteException e) {
|
||||
Log.w(TAG, "Failed to truncate the -wal file", e);
|
||||
@@ -399,10 +398,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
// No change to the sync mode is intended
|
||||
return;
|
||||
}
|
||||
String value = executeForString(null, "PRAGMA synchronous", null, null);
|
||||
String value = executeForString("PRAGMA synchronous", null, null);
|
||||
if (!canonicalizeSyncMode(value).equalsIgnoreCase(
|
||||
canonicalizeSyncMode(newValue))) {
|
||||
execute(null, "PRAGMA synchronous=" + newValue, null, null);
|
||||
execute("PRAGMA synchronous=" + newValue, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,11 +420,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
// No change to the journal mode is intended
|
||||
return;
|
||||
}
|
||||
String value = executeForString(null, "PRAGMA journal_mode", null, null);
|
||||
String value = executeForString("PRAGMA journal_mode", null, null);
|
||||
if (!value.equalsIgnoreCase(newValue)) {
|
||||
try {
|
||||
String result = executeForString(null, "PRAGMA journal_mode=" + newValue,
|
||||
null, null);
|
||||
String result = executeForString("PRAGMA journal_mode=" + newValue, null, null);
|
||||
if (result.equalsIgnoreCase(newValue)) {
|
||||
return;
|
||||
}
|
||||
@@ -477,26 +475,26 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
|
||||
try {
|
||||
// Ensure the android metadata table exists.
|
||||
execute(null, "CREATE TABLE IF NOT EXISTS android_metadata (locale TEXT)", null, null);
|
||||
execute("CREATE TABLE IF NOT EXISTS android_metadata (locale TEXT)", null, null);
|
||||
|
||||
// Check whether the locale was actually changed.
|
||||
final String oldLocale = executeForString(null, "SELECT locale FROM android_metadata "
|
||||
final String oldLocale = executeForString("SELECT locale FROM android_metadata "
|
||||
+ "UNION SELECT NULL ORDER BY locale DESC LIMIT 1", null, null);
|
||||
if (oldLocale != null && oldLocale.equals(newLocale)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go ahead and update the indexes using the new locale.
|
||||
execute(null, "BEGIN", null, null);
|
||||
execute("BEGIN", null, null);
|
||||
boolean success = false;
|
||||
try {
|
||||
execute(null, "DELETE FROM android_metadata", null, null);
|
||||
execute(null, "INSERT INTO android_metadata (locale) VALUES(?)",
|
||||
execute("DELETE FROM android_metadata", null, null);
|
||||
execute("INSERT INTO android_metadata (locale) VALUES(?)",
|
||||
new Object[] { newLocale }, null);
|
||||
execute(null, "REINDEX LOCALIZED", null, null);
|
||||
execute("REINDEX LOCALIZED", null, null);
|
||||
success = true;
|
||||
} finally {
|
||||
execute(null, success ? "COMMIT" : "ROLLBACK", null, null);
|
||||
execute(success ? "COMMIT" : "ROLLBACK", null, null);
|
||||
}
|
||||
} catch (SQLiteException ex) {
|
||||
throw ex;
|
||||
@@ -525,10 +523,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final int type = DatabaseUtils.getSqlStatementType(statement.first);
|
||||
switch (type) {
|
||||
case DatabaseUtils.STATEMENT_SELECT:
|
||||
executeForString(null, statement.first, statement.second, null);
|
||||
executeForString(statement.first, statement.second, null);
|
||||
break;
|
||||
case DatabaseUtils.STATEMENT_PRAGMA:
|
||||
execute(null, statement.first, statement.second, null);
|
||||
execute(statement.first, statement.second, null);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
@@ -545,10 +543,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final File checkFile = new File(mConfiguration.path
|
||||
+ SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX);
|
||||
|
||||
final boolean hasMetadataTable = executeForLong(null,
|
||||
final boolean hasMetadataTable = executeForLong(
|
||||
"SELECT count(*) FROM sqlite_master"
|
||||
+ " WHERE type='table' AND name='android_metadata'",
|
||||
null, null) > 0;
|
||||
+ " WHERE type='table' AND name='android_metadata'", null, null) > 0;
|
||||
final boolean hasCheckFile = checkFile.exists();
|
||||
|
||||
if (!mIsReadOnlyConnection && !hasCheckFile) {
|
||||
@@ -670,15 +667,14 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
*
|
||||
* @throws SQLiteException if an error occurs, such as a syntax error.
|
||||
*/
|
||||
public void prepare(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable SQLiteStatementInfo outStatementInfo) {
|
||||
public void prepare(String sql, SQLiteStatementInfo outStatementInfo) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
final int cookie = mRecentOperations.beginOperation("prepare", sql, null);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
if (outStatementInfo != null) {
|
||||
outStatementInfo.numParameters = statement.mNumParameters;
|
||||
@@ -718,9 +714,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public void execute(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public void execute(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -729,7 +724,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
try {
|
||||
final boolean isPragmaStmt =
|
||||
DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_PRAGMA;
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -764,15 +759,15 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public long executeForLong(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable Object[] bindArgs, @Nullable CancellationSignal cancellationSignal) {
|
||||
public long executeForLong(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
final int cookie = mRecentOperations.beginOperation("executeForLong", sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -809,15 +804,15 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public String executeForString(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable Object[] bindArgs, @Nullable CancellationSignal cancellationSignal) {
|
||||
public String executeForString(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
final int cookie = mRecentOperations.beginOperation("executeForString", sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -856,9 +851,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public ParcelFileDescriptor executeForBlobFileDescriptor(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public ParcelFileDescriptor executeForBlobFileDescriptor(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -866,7 +860,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final int cookie = mRecentOperations.beginOperation("executeForBlobFileDescriptor",
|
||||
sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -903,9 +897,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public int executeForChangedRowCount(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public int executeForChangedRowCount(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -914,7 +907,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final int cookie = mRecentOperations.beginOperation("executeForChangedRowCount",
|
||||
sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -953,9 +946,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public long executeForLastInsertedRowId(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public long executeForLastInsertedRowId(String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -963,7 +955,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final int cookie = mRecentOperations.beginOperation("executeForLastInsertedRowId",
|
||||
sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -1008,10 +1000,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public int executeForCursorWindow(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable Object[] bindArgs, @NonNull CursorWindow window,
|
||||
int startPos, int requiredPos, boolean countAllRows,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public int executeForCursorWindow(String sql, Object[] bindArgs,
|
||||
CursorWindow window, int startPos, int requiredPos, boolean countAllRows,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -1027,7 +1018,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
final int cookie = mRecentOperations.beginOperation("executeForCursorWindow",
|
||||
sql, bindArgs);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
try {
|
||||
throwIfStatementForbidden(statement);
|
||||
bindArguments(statement, bindArgs);
|
||||
@@ -1065,19 +1056,13 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a {@link #PreparedStatement}, possibly from the cache.
|
||||
*/
|
||||
private PreparedStatement acquirePreparedStatement(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql) {
|
||||
PreparedStatement acquirePreparedStatement(String sql) {
|
||||
++mPool.mTotalPrepareStatements;
|
||||
// Custom per-statement authorizers are typically used for incoming
|
||||
// untrusted custom SQL, which is likely to have low cache hit ratios,
|
||||
// so we compile them every time. This leaves the prepared statement
|
||||
// cache for statements using the default authorizer.
|
||||
boolean skipCache = (authorizer != null);
|
||||
PreparedStatement statement = skipCache ? null : mPreparedStatementCache.get(sql);
|
||||
PreparedStatement statement = mPreparedStatementCache.get(sql);
|
||||
boolean skipCache = false;
|
||||
if (statement != null) {
|
||||
if (!statement.mInUse) {
|
||||
return statement;
|
||||
@@ -1088,12 +1073,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
skipCache = true;
|
||||
}
|
||||
++mPool.mTotalPrepareStatementCacheMiss;
|
||||
if (authorizer != null) {
|
||||
nativeSetAuthorizer(mConnectionPtr, authorizer);
|
||||
}
|
||||
long statementPtr = 0;
|
||||
final long statementPtr = nativePrepareStatement(mConnectionPtr, sql);
|
||||
try {
|
||||
statementPtr = nativePrepareStatement(mConnectionPtr, sql);
|
||||
final int numParameters = nativeGetParameterCount(mConnectionPtr, statementPtr);
|
||||
final int type = DatabaseUtils.getSqlStatementType(sql);
|
||||
final boolean readOnly = nativeIsReadOnly(mConnectionPtr, statementPtr);
|
||||
@@ -1105,15 +1086,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
} catch (RuntimeException ex) {
|
||||
// Finalize the statement if an exception occurred and we did not add
|
||||
// it to the cache. If it is already in the cache, then leave it there.
|
||||
// It is safe to call finalize on a NULL, if nativePrepare failed.
|
||||
if (statement == null || !statement.mInCache) {
|
||||
nativeFinalizeStatement(mConnectionPtr, statementPtr);
|
||||
}
|
||||
throw ex;
|
||||
} finally {
|
||||
if (authorizer != null) {
|
||||
nativeSetAuthorizer(mConnectionPtr, null);
|
||||
}
|
||||
}
|
||||
statement.mInUse = true;
|
||||
return statement;
|
||||
@@ -1154,11 +1130,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
* Return a prepared statement for use by {@link SQLiteRawStatement}. This throws if the
|
||||
* prepared statement is incompatible with this connection.
|
||||
*/
|
||||
PreparedStatement acquirePersistentStatement(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql) {
|
||||
PreparedStatement acquirePersistentStatement(@NonNull String sql) {
|
||||
final int cookie = mRecentOperations.beginOperation("prepare", sql, null);
|
||||
try {
|
||||
final PreparedStatement statement = acquirePreparedStatement(authorizer, sql);
|
||||
final PreparedStatement statement = acquirePreparedStatement(sql);
|
||||
throwIfStatementForbidden(statement);
|
||||
return statement;
|
||||
} catch (RuntimeException e) {
|
||||
@@ -1353,8 +1328,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
long pageCount = 0;
|
||||
long pageSize = 0;
|
||||
try {
|
||||
pageCount = executeForLong(null, "PRAGMA page_count;", null, null);
|
||||
pageSize = executeForLong(null, "PRAGMA page_size;", null, null);
|
||||
pageCount = executeForLong("PRAGMA page_count;", null, null);
|
||||
pageSize = executeForLong("PRAGMA page_size;", null, null);
|
||||
} catch (SQLiteException ex) {
|
||||
// Ignore.
|
||||
}
|
||||
@@ -1365,15 +1340,15 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
|
||||
// the main database which we have already described.
|
||||
CursorWindow window = new CursorWindow("collectDbStats");
|
||||
try {
|
||||
executeForCursorWindow(null, "PRAGMA database_list;", null, window, 0, 0, false, null);
|
||||
executeForCursorWindow("PRAGMA database_list;", null, window, 0, 0, false, null);
|
||||
for (int i = 1; i < window.getNumRows(); i++) {
|
||||
String name = window.getString(i, 1);
|
||||
String path = window.getString(i, 2);
|
||||
pageCount = 0;
|
||||
pageSize = 0;
|
||||
try {
|
||||
pageCount = executeForLong(null, "PRAGMA " + name + ".page_count;", null, null);
|
||||
pageSize = executeForLong(null, "PRAGMA " + name + ".page_size;", null, null);
|
||||
pageCount = executeForLong("PRAGMA " + name + ".page_count;", null, null);
|
||||
pageSize = executeForLong("PRAGMA " + name + ".page_size;", null, null);
|
||||
} catch (SQLiteException ex) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
@@ -44,12 +44,10 @@ import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Printer;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import dalvik.annotation.optimization.NeverCompile;
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
@@ -255,13 +253,6 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
*/
|
||||
public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
|
||||
|
||||
/** @hide */
|
||||
public static final int ENABLE_TRACE = 0x00000100;
|
||||
/** @hide */
|
||||
public static final int ENABLE_PROFILE = 0x00000200;
|
||||
/** @hide */
|
||||
public static final int ENABLE_AUTHORIZER = 0x00000400;
|
||||
|
||||
/**
|
||||
* Open flag: Flag for {@link #openDatabase} to create the database file if it does not
|
||||
* already exist.
|
||||
@@ -1462,38 +1453,9 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
* {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
|
||||
*/
|
||||
public SQLiteStatement compileStatement(String sql) throws SQLException {
|
||||
return compileStatementInternal(sql, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an SQL statement into a reusable pre-compiled statement object.
|
||||
* The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
|
||||
* 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.
|
||||
* Must configure: {@link OpenParams.Builder#setAuthorizerSupportEnabled(boolean)}.
|
||||
*
|
||||
* @param sql The raw SQL statement, may contain ? for unknown values to be
|
||||
* bound later.
|
||||
* @param authorizer The sql authorizer attached to the statement.
|
||||
* @return A pre-compiled {@link SQLiteStatement} object. Note that
|
||||
* {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
|
||||
*/
|
||||
public @NonNull SQLiteStatement compileStatement(@NonNull String sql,
|
||||
@NonNull SQLiteAuthorizer authorizer) throws SQLException {
|
||||
return compileStatementInternal(sql, authorizer);
|
||||
}
|
||||
|
||||
private @NonNull SQLiteStatement compileStatementInternal(@NonNull String sql,
|
||||
@Nullable SQLiteAuthorizer authorizer) throws SQLException {
|
||||
if (authorizer != null) {
|
||||
throwIfNotAuthorizerEnabled();
|
||||
}
|
||||
acquireReference();
|
||||
try {
|
||||
return new SQLiteStatement(this, authorizer, sql, null);
|
||||
return new SQLiteStatement(this, sql, null);
|
||||
} finally {
|
||||
releaseReference();
|
||||
}
|
||||
@@ -1790,8 +1752,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
public Cursor rawQueryWithFactory(
|
||||
CursorFactory cursorFactory, String sql, String[] selectionArgs,
|
||||
String editTable) {
|
||||
return rawQueryWithFactoryInternal(cursorFactory, sql, selectionArgs,
|
||||
editTable, null, null);
|
||||
return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1812,52 +1773,17 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
public Cursor rawQueryWithFactory(
|
||||
CursorFactory cursorFactory, String sql, String[] selectionArgs,
|
||||
String editTable, CancellationSignal cancellationSignal) {
|
||||
return rawQueryWithFactoryInternal(cursorFactory, sql, selectionArgs, editTable,
|
||||
cancellationSignal, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the provided SQL and returns a cursor over the result set.
|
||||
* Must configure: {@link OpenParams.Builder#setAuthorizerSupportEnabled(boolean)}.
|
||||
*
|
||||
* @param cursorFactory the cursor factory to use, or null for the default factory
|
||||
* @param sql the SQL query. The SQL string must not be ; terminated
|
||||
* @param selectionArgs You may include ?s in where clause in the query,
|
||||
* which will be replaced by the values from selectionArgs. The
|
||||
* values will be bound as Strings.
|
||||
* @param editTable the name of the first table, which is editable
|
||||
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
|
||||
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
|
||||
* when the query is executed.
|
||||
* @param authorizer The sql authorizer attached to the query.
|
||||
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
|
||||
* {@link Cursor}s are not synchronized, see the documentation for more details.
|
||||
*/
|
||||
public @NonNull Cursor rawQueryWithFactory(@Nullable CursorFactory cursorFactory,
|
||||
@NonNull String sql, @SuppressLint("ArrayReturn") @Nullable String[] selectionArgs,
|
||||
@Nullable String editTable, @Nullable CancellationSignal cancellationSignal,
|
||||
@NonNull SQLiteAuthorizer authorizer) {
|
||||
return rawQueryWithFactoryInternal(cursorFactory, sql, selectionArgs, editTable,
|
||||
cancellationSignal, authorizer);
|
||||
}
|
||||
|
||||
private @NonNull Cursor rawQueryWithFactoryInternal(@Nullable CursorFactory cursorFactory,
|
||||
@NonNull String sql, @SuppressLint("ArrayReturn") @Nullable String[] selectionArgs,
|
||||
@Nullable String editTable, @Nullable CancellationSignal cancellationSignal,
|
||||
@Nullable SQLiteAuthorizer authorizer) {
|
||||
if (authorizer != null) {
|
||||
throwIfNotAuthorizerEnabled();
|
||||
}
|
||||
acquireReference();
|
||||
try {
|
||||
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, authorizer, sql,
|
||||
editTable, cancellationSignal);
|
||||
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
|
||||
cancellationSignal);
|
||||
return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
|
||||
selectionArgs);
|
||||
} finally {
|
||||
releaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for inserting a row into the database.
|
||||
*
|
||||
@@ -2005,8 +1931,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
}
|
||||
sql.append(')');
|
||||
|
||||
// Custom authorizers can be applied through SQLiteQueryBuilder
|
||||
SQLiteStatement statement = new SQLiteStatement(this, null, sql.toString(), bindArgs);
|
||||
SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
|
||||
try {
|
||||
return statement.executeInsert();
|
||||
} finally {
|
||||
@@ -2033,9 +1958,8 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
public int delete(String table, String whereClause, String[] whereArgs) {
|
||||
acquireReference();
|
||||
try {
|
||||
// Custom authorizers can be applied through SQLiteQueryBuilder
|
||||
SQLiteStatement statement = new SQLiteStatement(this, null, "DELETE FROM " + table
|
||||
+ (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
|
||||
SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
|
||||
(!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
|
||||
try {
|
||||
return statement.executeUpdateDelete();
|
||||
} finally {
|
||||
@@ -2112,8 +2036,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
sql.append(whereClause);
|
||||
}
|
||||
|
||||
// Custom authorizers can be applied through SQLiteQueryBuilder
|
||||
SQLiteStatement statement = new SQLiteStatement(this, null, sql.toString(), bindArgs);
|
||||
SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
|
||||
try {
|
||||
return statement.executeUpdateDelete();
|
||||
} finally {
|
||||
@@ -2150,7 +2073,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
* @throws SQLException if the SQL string is invalid
|
||||
*/
|
||||
public void execSQL(String sql) throws SQLException {
|
||||
executeSql(null, sql, null);
|
||||
executeSql(sql, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2203,72 +2126,14 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
* @throws SQLException if the SQL string is invalid
|
||||
*/
|
||||
public void execSQL(String sql, Object[] bindArgs) throws SQLException {
|
||||
executeSql(null, sql, bindArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
|
||||
* Must configure: {@link OpenParams.Builder#setAuthorizerSupportEnabled(boolean)}.
|
||||
* <p>
|
||||
* For INSERT statements, use any of the following instead.
|
||||
* <ul>
|
||||
* <li>{@link #insert(String, String, ContentValues)}</li>
|
||||
* <li>{@link #insertOrThrow(String, String, ContentValues)}</li>
|
||||
* <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For UPDATE statements, use any of the following instead.
|
||||
* <ul>
|
||||
* <li>{@link #update(String, ContentValues, String, String[])}</li>
|
||||
* <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For DELETE statements, use any of the following instead.
|
||||
* <ul>
|
||||
* <li>{@link #delete(String, String, String[])}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the following are good candidates for using this method:
|
||||
* <ul>
|
||||
* <li>ALTER TABLE</li>
|
||||
* <li>CREATE or DROP table / trigger / view / index / virtual table</li>
|
||||
* <li>REINDEX</li>
|
||||
* <li>RELEASE</li>
|
||||
* <li>SAVEPOINT</li>
|
||||
* <li>PRAGMA that returns no data</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* When using {@link #enableWriteAheadLogging()}, journal_mode is
|
||||
* automatically managed by this class. So, do not set journal_mode
|
||||
* using "PRAGMA journal_mode'<value>" statement if your app is using
|
||||
* {@link #enableWriteAheadLogging()}
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that {@code PRAGMA} values which apply on a per-connection basis
|
||||
* should <em>not</em> be configured using this method; you should instead
|
||||
* use {@link #execPerConnectionSQL} to ensure that they are uniformly
|
||||
* applied to all current and future connections.
|
||||
* </p>
|
||||
*
|
||||
* @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
|
||||
* not supported.
|
||||
* @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
|
||||
* @param authorizer The sql authorizer attached to the query.
|
||||
* @throws SQLException if the SQL string is invalid
|
||||
*/
|
||||
public void execSQL(@NonNull String sql,
|
||||
@SuppressLint("ArrayReturn") @Nullable Object[] bindArgs,
|
||||
@NonNull SQLiteAuthorizer authorizer) throws SQLException {
|
||||
if (authorizer != null) {
|
||||
throwIfNotAuthorizerEnabled();
|
||||
if (bindArgs == null) {
|
||||
throw new IllegalArgumentException("Empty bindArgs");
|
||||
}
|
||||
executeSql(authorizer, sql, bindArgs);
|
||||
executeSql(sql, bindArgs);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public int executeSql(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable Object[] bindArgs) throws SQLException {
|
||||
public int executeSql(String sql, Object[] bindArgs) throws SQLException {
|
||||
acquireReference();
|
||||
try {
|
||||
final int statementType = DatabaseUtils.getSqlStatementType(sql);
|
||||
@@ -2286,7 +2151,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
}
|
||||
}
|
||||
|
||||
try (SQLiteStatement statement = new SQLiteStatement(this, authorizer, sql, bindArgs)) {
|
||||
try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
|
||||
return statement.executeUpdateDelete();
|
||||
} finally {
|
||||
// If schema was updated, close non-primary connections, otherwise they might
|
||||
@@ -2300,25 +2165,6 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link SQLiteRawStatement} connected to the database. A transaction must be in
|
||||
* progress or an exception will be thrown. The resulting object will be closed automatically
|
||||
* when the current transaction closes.
|
||||
* Must configure: {@link OpenParams.Builder#setAuthorizerSupportEnabled(boolean)}.
|
||||
* @param sql The SQL string to be compiled into a prepared statement.
|
||||
* @param authorizer The sql authorizer attached to the statement.
|
||||
* @return A {@link SQLiteRawStatement} holding the compiled SQL.
|
||||
* @throws IllegalStateException if a transaction is not in progress.
|
||||
* @throws SQLiteException if the SQL cannot be compiled.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public SQLiteRawStatement createRawStatement(@NonNull String sql,
|
||||
@NonNull SQLiteAuthorizer authorizer) {
|
||||
Objects.requireNonNull(sql);
|
||||
return new SQLiteRawStatement(this, sql, authorizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link SQLiteRawStatement} connected to the database. A transaction must be in
|
||||
* progress or an exception will be thrown. The resulting object will be closed automatically
|
||||
@@ -2332,8 +2178,9 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
@NonNull
|
||||
public SQLiteRawStatement createRawStatement(@NonNull String sql) {
|
||||
Objects.requireNonNull(sql);
|
||||
return createRawStatement(sql, null);
|
||||
return new SQLiteRawStatement(this, sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the "rowid" of the last row to be inserted on the current connection. See the
|
||||
* SQLite documentation for the specific details. This method must only be called when inside
|
||||
@@ -2359,33 +2206,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
* @throws SQLiteException if {@code sql} is invalid
|
||||
*/
|
||||
public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
|
||||
validateSqlInternal(sql, cancellationSignal, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a SQL SELECT statement is valid by compiling it.
|
||||
* If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
|
||||
* Must configure: {@link OpenParams.Builder#setAuthorizerSupportEnabled(boolean)}.
|
||||
*
|
||||
* @param sql SQL to be validated
|
||||
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
|
||||
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
|
||||
* when the query is executed.
|
||||
* @param authorizer The sql authorizer attached to the query.
|
||||
* @throws SQLiteException if {@code sql} is invalid
|
||||
*/
|
||||
public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal,
|
||||
@NonNull SQLiteAuthorizer authorizer) {
|
||||
validateSqlInternal(sql, cancellationSignal, authorizer);
|
||||
}
|
||||
|
||||
private void validateSqlInternal(@NonNull String sql,
|
||||
@Nullable CancellationSignal cancellationSignal,
|
||||
@Nullable SQLiteAuthorizer authorizer) {
|
||||
if (authorizer != null) {
|
||||
throwIfNotAuthorizerEnabled();
|
||||
}
|
||||
getThreadSession().prepare(authorizer, sql,
|
||||
getThreadSession().prepare(sql,
|
||||
getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
|
||||
}
|
||||
|
||||
@@ -2404,21 +2225,6 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the database is opened with authorizer support enabled.
|
||||
*
|
||||
* @return True if authorizer support is enabled.
|
||||
*/
|
||||
public boolean isAuthorizerSupportEnabled() {
|
||||
synchronized (mLock) {
|
||||
return isAuthorizerSupportEnabledLocked();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAuthorizerSupportEnabledLocked() {
|
||||
return (mConfigurationLocked.openFlags & ENABLE_AUTHORIZER) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the database is in-memory db.
|
||||
*
|
||||
@@ -3004,13 +2810,6 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
return "SQLiteDatabase: " + getPath();
|
||||
}
|
||||
|
||||
private void throwIfNotAuthorizerEnabled() {
|
||||
if ((mConfigurationLocked.openFlags & ENABLE_AUTHORIZER) == 0) {
|
||||
throw new IllegalStateException("The database '" + mConfigurationLocked.label
|
||||
+ "' does not have authorizer support enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
private void throwIfNotOpenLocked() {
|
||||
if (mConnectionPoolLocked == null) {
|
||||
throw new IllegalStateException("The database '" + mConfigurationLocked.label
|
||||
@@ -3274,39 +3073,6 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if support for {@link SQLiteAuthorizer} is enabled.
|
||||
*
|
||||
* @see SQLiteDatabase#compileStatement(String, SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#execSQL(String, Object[], SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#validateSql(String, CancellationSignal,
|
||||
* SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#rawQueryWithFactory(CursorFactory, String,
|
||||
* String[], String, CancellationSignal, SQLiteAuthorizer)
|
||||
*/
|
||||
public boolean isAuthorizerSupportEnabled() {
|
||||
return (mOpenFlags & ENABLE_AUTHORIZER) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables support for {@link SQLiteAuthorizer}.
|
||||
*
|
||||
* @see SQLiteDatabase#compileStatement(String, SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#execSQL(String, Object[], SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#validateSql(String, CancellationSignal,
|
||||
* SQLiteAuthorizer)
|
||||
* @see SQLiteDatabase#rawQueryWithFactory(CursorFactory, String,
|
||||
* String[], String, CancellationSignal, SQLiteAuthorizer)
|
||||
*/
|
||||
public @NonNull Builder setAuthorizerSupportEnabled(boolean enabled) {
|
||||
if (enabled) {
|
||||
addOpenFlags(SQLiteDatabase.ENABLE_AUTHORIZER);
|
||||
} else {
|
||||
removeOpenFlags(SQLiteDatabase.ENABLE_AUTHORIZER);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an optional factory class that is called to instantiate a cursor when query
|
||||
* is called.
|
||||
@@ -3408,8 +3174,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
|
||||
OPEN_READONLY,
|
||||
CREATE_IF_NECESSARY,
|
||||
NO_LOCALIZED_COLLATORS,
|
||||
ENABLE_WRITE_AHEAD_LOGGING,
|
||||
ENABLE_AUTHORIZER
|
||||
ENABLE_WRITE_AHEAD_LOGGING
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface DatabaseOpenFlags {}
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.database.sqlite.SQLiteDebug.NoPreloadHolder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BinaryOperator;
|
||||
@@ -157,13 +155,6 @@ public final class SQLiteDatabaseConfiguration {
|
||||
throw new IllegalArgumentException("path must not be null.");
|
||||
}
|
||||
|
||||
if (NoPreloadHolder.DEBUG_SQL_STATEMENTS) {
|
||||
openFlags |= SQLiteDatabase.ENABLE_PROFILE;
|
||||
}
|
||||
if (NoPreloadHolder.DEBUG_SQL_TIME) {
|
||||
openFlags |= SQLiteDatabase.ENABLE_TRACE;
|
||||
}
|
||||
|
||||
this.path = path;
|
||||
label = stripPathForLogs(path);
|
||||
this.openFlags = openFlags;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
@@ -31,7 +29,6 @@ import android.os.CancellationSignal;
|
||||
@TestApi
|
||||
public final class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
|
||||
private final SQLiteDatabase mDatabase;
|
||||
private final SQLiteAuthorizer mAuthorizer;
|
||||
private final String mEditTable;
|
||||
private final String mSql;
|
||||
private final CancellationSignal mCancellationSignal;
|
||||
@@ -39,22 +36,14 @@ public final class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
|
||||
|
||||
public SQLiteDirectCursorDriver(SQLiteDatabase db, String sql, String editTable,
|
||||
CancellationSignal cancellationSignal) {
|
||||
this(db, null, sql, editTable, cancellationSignal);
|
||||
}
|
||||
|
||||
public SQLiteDirectCursorDriver(@NonNull SQLiteDatabase db,
|
||||
@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable String editTable, @Nullable CancellationSignal cancellationSignal) {
|
||||
mDatabase = db;
|
||||
mAuthorizer = authorizer;
|
||||
mEditTable = editTable;
|
||||
mSql = sql;
|
||||
mCancellationSignal = cancellationSignal;
|
||||
}
|
||||
|
||||
public Cursor query(CursorFactory factory, String[] selectionArgs) {
|
||||
final SQLiteQuery query = new SQLiteQuery(mDatabase,
|
||||
mAuthorizer, mSql, mCancellationSignal);
|
||||
final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
|
||||
final Cursor cursor;
|
||||
try {
|
||||
query.bindAllArgsAsStrings(selectionArgs);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.os.Build;
|
||||
@@ -35,7 +33,6 @@ public abstract class SQLiteProgram extends SQLiteClosable {
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private final SQLiteDatabase mDatabase;
|
||||
private final SQLiteAuthorizer mAuthorizer;
|
||||
@UnsupportedAppUsage
|
||||
private final String mSql;
|
||||
private final boolean mReadOnly;
|
||||
@@ -44,11 +41,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
private final Object[] mBindArgs;
|
||||
|
||||
SQLiteProgram(@NonNull SQLiteDatabase db, @Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs,
|
||||
@Nullable CancellationSignal cancellationSignalForPrepare) {
|
||||
SQLiteProgram(SQLiteDatabase db, String sql, Object[] bindArgs,
|
||||
CancellationSignal cancellationSignalForPrepare) {
|
||||
mDatabase = db;
|
||||
mAuthorizer = authorizer;
|
||||
mSql = sql.trim();
|
||||
|
||||
int n = DatabaseUtils.getSqlStatementType(mSql);
|
||||
@@ -64,7 +59,7 @@ public abstract class SQLiteProgram extends SQLiteClosable {
|
||||
default:
|
||||
boolean assumeReadOnly = (n == DatabaseUtils.STATEMENT_SELECT);
|
||||
SQLiteStatementInfo info = new SQLiteStatementInfo();
|
||||
db.getThreadSession().prepare(mAuthorizer, mSql,
|
||||
db.getThreadSession().prepare(mSql,
|
||||
db.getThreadDefaultConnectionFlags(assumeReadOnly),
|
||||
cancellationSignalForPrepare, info);
|
||||
mReadOnly = info.readOnly;
|
||||
@@ -93,10 +88,6 @@ public abstract class SQLiteProgram extends SQLiteClosable {
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
final SQLiteAuthorizer getAuthorizer() {
|
||||
return mAuthorizer;
|
||||
}
|
||||
|
||||
final String getSql() {
|
||||
return mSql;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.database.CursorWindow;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.OperationCanceledException;
|
||||
@@ -35,9 +33,8 @@ public final class SQLiteQuery extends SQLiteProgram {
|
||||
|
||||
private final CancellationSignal mCancellationSignal;
|
||||
|
||||
SQLiteQuery(@NonNull SQLiteDatabase db, @Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String query, @Nullable CancellationSignal cancellationSignal) {
|
||||
super(db, authorizer, query, null, cancellationSignal);
|
||||
SQLiteQuery(SQLiteDatabase db, String query, CancellationSignal cancellationSignal) {
|
||||
super(db, query, null, cancellationSignal);
|
||||
|
||||
mCancellationSignal = cancellationSignal;
|
||||
}
|
||||
@@ -62,9 +59,9 @@ public final class SQLiteQuery extends SQLiteProgram {
|
||||
try {
|
||||
window.acquireReference();
|
||||
try {
|
||||
int numRows = getSession().executeForCursorWindow(getAuthorizer(), getSql(),
|
||||
getBindArgs(), window, startPos, requiredPos, countAllRows,
|
||||
getConnectionFlags(), mCancellationSignal);
|
||||
int numRows = getSession().executeForCursorWindow(getSql(), getBindArgs(),
|
||||
window, startPos, requiredPos, countAllRows, getConnectionFlags(),
|
||||
mCancellationSignal);
|
||||
return numRows;
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import dalvik.annotation.optimization.FastNative;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -136,15 +138,14 @@ public final class SQLiteRawStatement implements Closeable {
|
||||
* {@link IllegalStateException} if a transaction is not in progress. Clients should call
|
||||
* {@link SQLiteDatabase.createRawStatement} to create a new instance.
|
||||
*/
|
||||
SQLiteRawStatement(@NonNull SQLiteDatabase db, @NonNull String sql,
|
||||
@Nullable SQLiteAuthorizer authorizer) throws SQLiteException {
|
||||
SQLiteRawStatement(@NonNull SQLiteDatabase db, @NonNull String sql) throws SQLiteException {
|
||||
mThread = Thread.currentThread();
|
||||
mDatabase = db;
|
||||
mSession = mDatabase.getThreadSession();
|
||||
mSession.throwIfNoTransaction();
|
||||
mSql = sql;
|
||||
// Acquire a connection and prepare the statement.
|
||||
mPreparedStatement = mSession.acquirePersistentStatement(authorizer, mSql, this);
|
||||
mPreparedStatement = mSession.acquirePersistentStatement(mSql, this);
|
||||
mStatement = mPreparedStatement.mStatementPtr;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.database.CursorWindow;
|
||||
import android.database.DatabaseUtils;
|
||||
@@ -80,7 +80,7 @@ import java.util.ArrayDeque;
|
||||
* specifying the desired transaction mode. Once an explicit transaction has begun,
|
||||
* all subsequent database operations will be performed as part of that transaction.
|
||||
* To end an explicit transaction, first call {@link #setTransactionSuccessful} if the
|
||||
* transaction was successful, then call {@link #endTransaction}. If the transaction was
|
||||
* transaction was successful, then call {@link #end}. If the transaction was
|
||||
* marked successful, its changes will be committed, otherwise they will be rolled back.
|
||||
* </p><p>
|
||||
* Explicit transactions can also be nested. A nested explicit transaction is
|
||||
@@ -309,12 +309,12 @@ public final class SQLiteSession {
|
||||
CancellationSignal cancellationSignal) {
|
||||
throwIfTransactionMarkedSuccessful();
|
||||
beginTransactionUnchecked(transactionMode, transactionListener, connectionFlags,
|
||||
cancellationSignal);
|
||||
cancellationSignal);
|
||||
}
|
||||
|
||||
private void beginTransactionUnchecked(int transactionMode,
|
||||
SQLiteTransactionListener transactionListener, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (cancellationSignal != null) {
|
||||
cancellationSignal.throwIfCanceled();
|
||||
}
|
||||
@@ -329,21 +329,20 @@ public final class SQLiteSession {
|
||||
// Execute SQL might throw a runtime exception.
|
||||
switch (transactionMode) {
|
||||
case TRANSACTION_MODE_IMMEDIATE:
|
||||
mConnection.execute(null, "BEGIN IMMEDIATE;", null,
|
||||
mConnection.execute("BEGIN IMMEDIATE;", null,
|
||||
cancellationSignal); // might throw
|
||||
break;
|
||||
case TRANSACTION_MODE_EXCLUSIVE:
|
||||
mConnection.execute(null, "BEGIN EXCLUSIVE;", null,
|
||||
mConnection.execute("BEGIN EXCLUSIVE;", null,
|
||||
cancellationSignal); // might throw
|
||||
break;
|
||||
case TRANSACTION_MODE_DEFERRED:
|
||||
mConnection.execute(null, "BEGIN DEFERRED;", null,
|
||||
mConnection.execute("BEGIN DEFERRED;", null,
|
||||
cancellationSignal); // might throw
|
||||
break;
|
||||
default:
|
||||
// Per SQLite documentation, this executes in DEFERRED mode.
|
||||
mConnection.execute(null, "BEGIN;",
|
||||
null, cancellationSignal); // might throw
|
||||
mConnection.execute("BEGIN;", null, cancellationSignal); // might throw
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -354,8 +353,7 @@ public final class SQLiteSession {
|
||||
transactionListener.onBegin(); // might throw
|
||||
} catch (RuntimeException ex) {
|
||||
if (mTransactionStack == null) {
|
||||
mConnection.execute(null, "ROLLBACK;", null,
|
||||
cancellationSignal); // might throw
|
||||
mConnection.execute("ROLLBACK;", null, cancellationSignal); // might throw
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
@@ -417,14 +415,14 @@ public final class SQLiteSession {
|
||||
* @see #setTransactionSuccessful
|
||||
* @see #yieldTransaction
|
||||
*/
|
||||
public void endTransaction(@Nullable CancellationSignal cancellationSignal) {
|
||||
public void endTransaction(CancellationSignal cancellationSignal) {
|
||||
throwIfNoTransaction();
|
||||
assert mConnection != null;
|
||||
|
||||
endTransactionUnchecked(cancellationSignal, false);
|
||||
}
|
||||
|
||||
private void endTransactionUnchecked(@Nullable CancellationSignal cancellationSignal,
|
||||
boolean yielding) {
|
||||
private void endTransactionUnchecked(CancellationSignal cancellationSignal, boolean yielding) {
|
||||
if (cancellationSignal != null) {
|
||||
cancellationSignal.throwIfCanceled();
|
||||
}
|
||||
@@ -462,11 +460,9 @@ public final class SQLiteSession {
|
||||
|
||||
try {
|
||||
if (successful) {
|
||||
mConnection.execute(null, "COMMIT;", null,
|
||||
cancellationSignal); // might throw
|
||||
mConnection.execute("COMMIT;", null, cancellationSignal); // might throw
|
||||
} else {
|
||||
mConnection.execute(null, "ROLLBACK;", null,
|
||||
cancellationSignal); // might throw
|
||||
mConnection.execute("ROLLBACK;", null, cancellationSignal); // might throw
|
||||
}
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
@@ -603,9 +599,8 @@ public final class SQLiteSession {
|
||||
* @throws SQLiteException if an error occurs, such as a syntax error.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public void prepare(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
int connectionFlags, @Nullable CancellationSignal cancellationSignal,
|
||||
@Nullable SQLiteStatementInfo outStatementInfo) {
|
||||
public void prepare(String sql, int connectionFlags, CancellationSignal cancellationSignal,
|
||||
SQLiteStatementInfo outStatementInfo) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -616,7 +611,7 @@ public final class SQLiteSession {
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
mConnection.prepare(authorizer, sql, outStatementInfo); // might throw
|
||||
mConnection.prepare(sql, outStatementInfo); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
}
|
||||
@@ -635,20 +630,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public void execute(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public void execute(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
mConnection.execute(authorizer, sql, bindArgs, cancellationSignal); // might throw
|
||||
mConnection.execute(sql, bindArgs, cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
}
|
||||
@@ -669,21 +663,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public long executeForLong(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public long executeForLong(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForLong(authorizer, sql, bindArgs,
|
||||
cancellationSignal); // might throw
|
||||
return mConnection.executeForLong(sql, bindArgs, cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
}
|
||||
@@ -704,21 +696,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public String executeForString(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public String executeForString(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForString(authorizer, sql, bindArgs,
|
||||
cancellationSignal); // might throw
|
||||
return mConnection.executeForString(sql, bindArgs, cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
}
|
||||
@@ -741,20 +731,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public ParcelFileDescriptor executeForBlobFileDescriptor(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public ParcelFileDescriptor executeForBlobFileDescriptor(String sql, Object[] bindArgs,
|
||||
int connectionFlags, CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForBlobFileDescriptor(authorizer, sql, bindArgs,
|
||||
return mConnection.executeForBlobFileDescriptor(sql, bindArgs,
|
||||
cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
@@ -776,20 +765,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public int executeForChangedRowCount(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public int executeForChangedRowCount(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForChangedRowCount(authorizer, sql, bindArgs,
|
||||
return mConnection.executeForChangedRowCount(sql, bindArgs,
|
||||
cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
@@ -811,20 +799,19 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public long executeForLastInsertedRowId(@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public long executeForLastInsertedRowId(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForLastInsertedRowId(authorizer, sql, bindArgs,
|
||||
return mConnection.executeForLastInsertedRowId(sql, bindArgs,
|
||||
cancellationSignal); // might throw
|
||||
} finally {
|
||||
releaseConnection(); // might throw
|
||||
@@ -855,10 +842,9 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
public int executeForCursorWindow(@Nullable SQLiteAuthorizer authorizer, @NonNull String sql,
|
||||
@Nullable Object[] bindArgs, @NonNull CursorWindow window, int startPos,
|
||||
int requiredPos, boolean countAllRows, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
public int executeForCursorWindow(String sql, Object[] bindArgs,
|
||||
CursorWindow window, int startPos, int requiredPos, boolean countAllRows,
|
||||
int connectionFlags, CancellationSignal cancellationSignal) {
|
||||
if (sql == null) {
|
||||
throw new IllegalArgumentException("sql must not be null.");
|
||||
}
|
||||
@@ -866,14 +852,14 @@ public final class SQLiteSession {
|
||||
throw new IllegalArgumentException("window must not be null.");
|
||||
}
|
||||
|
||||
if (executeSpecial(sql, connectionFlags, cancellationSignal)) {
|
||||
if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) {
|
||||
window.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
acquireConnection(sql, connectionFlags, cancellationSignal); // might throw
|
||||
try {
|
||||
return mConnection.executeForCursorWindow(authorizer, sql, bindArgs,
|
||||
return mConnection.executeForCursorWindow(sql, bindArgs,
|
||||
window, startPos, requiredPos, countAllRows,
|
||||
cancellationSignal); // might throw
|
||||
} finally {
|
||||
@@ -902,8 +888,8 @@ public final class SQLiteSession {
|
||||
* or invalid number of bind arguments.
|
||||
* @throws OperationCanceledException if the operation was canceled.
|
||||
*/
|
||||
private boolean executeSpecial(@NonNull String sql, int connectionFlags,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
private boolean executeSpecial(String sql, Object[] bindArgs, int connectionFlags,
|
||||
CancellationSignal cancellationSignal) {
|
||||
if (cancellationSignal != null) {
|
||||
cancellationSignal.throwIfCanceled();
|
||||
}
|
||||
@@ -956,14 +942,13 @@ public final class SQLiteSession {
|
||||
* method is called when the transaction is closed.
|
||||
*/
|
||||
@NonNull
|
||||
SQLiteConnection.PreparedStatement acquirePersistentStatement(
|
||||
@Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String query, @NonNull Closeable dependent) {
|
||||
SQLiteConnection.PreparedStatement acquirePersistentStatement(@NonNull String query,
|
||||
@NonNull Closeable dependent) {
|
||||
throwIfNoTransaction();
|
||||
throwIfTransactionMarkedSuccessful();
|
||||
mOpenDependents.addFirst(dependent);
|
||||
try {
|
||||
return mConnection.acquirePersistentStatement(authorizer, query);
|
||||
return mConnection.acquirePersistentStatement(query);
|
||||
} catch (Throwable e) {
|
||||
mOpenDependents.remove(dependent);
|
||||
throw e;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.database.sqlite;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
@@ -34,12 +32,7 @@ import android.os.ParcelFileDescriptor;
|
||||
public final class SQLiteStatement extends SQLiteProgram {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) {
|
||||
super(db, null, sql, bindArgs, null);
|
||||
}
|
||||
|
||||
SQLiteStatement(@NonNull SQLiteDatabase db, @Nullable SQLiteAuthorizer authorizer,
|
||||
@NonNull String sql, @Nullable Object[] bindArgs) {
|
||||
super(db, authorizer, sql, bindArgs, null);
|
||||
super(db, sql, bindArgs, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,8 +45,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
public void execute() {
|
||||
acquireReference();
|
||||
try {
|
||||
getSession().execute(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSession().execute(getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
@@ -74,7 +66,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
acquireReference();
|
||||
try {
|
||||
return getSession().executeForChangedRowCount(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
@@ -96,7 +88,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
acquireReference();
|
||||
try {
|
||||
return getSession().executeForLastInsertedRowId(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
@@ -117,7 +109,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
acquireReference();
|
||||
try {
|
||||
return getSession().executeForLong(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
@@ -138,7 +130,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
acquireReference();
|
||||
try {
|
||||
return getSession().executeForString(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
@@ -159,7 +151,7 @@ public final class SQLiteStatement extends SQLiteProgram {
|
||||
acquireReference();
|
||||
try {
|
||||
return getSession().executeForBlobFileDescriptor(
|
||||
getAuthorizer(), getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
getSql(), getBindArgs(), getConnectionFlags(), null);
|
||||
} catch (SQLiteDatabaseCorruptException ex) {
|
||||
onCorruption();
|
||||
throw ex;
|
||||
|
||||
@@ -58,10 +58,6 @@ namespace android {
|
||||
*/
|
||||
static const int BUSY_TIMEOUT_MS = 2500;
|
||||
|
||||
static struct {
|
||||
jmethodID onAuthorize;
|
||||
} gAuthorizer;
|
||||
|
||||
static struct {
|
||||
jmethodID apply;
|
||||
} gUnaryOperator;
|
||||
@@ -74,14 +70,11 @@ struct SQLiteConnection {
|
||||
// Open flags.
|
||||
// Must be kept in sync with the constants defined in SQLiteDatabase.java.
|
||||
enum {
|
||||
OPEN_READWRITE = 0x00000000,
|
||||
OPEN_READONLY = 0x00000001,
|
||||
OPEN_READ_MASK = 0x00000001,
|
||||
NO_LOCALIZED_COLLATORS = 0x00000010,
|
||||
ENABLE_TRACE = 0x00000100,
|
||||
ENABLE_PROFILE = 0x00000200,
|
||||
ENABLE_AUTHORIZER = 0x00000400,
|
||||
CREATE_IF_NECESSARY = 0x10000000,
|
||||
OPEN_READWRITE = 0x00000000,
|
||||
OPEN_READONLY = 0x00000001,
|
||||
OPEN_READ_MASK = 0x00000001,
|
||||
NO_LOCALIZED_COLLATORS = 0x00000010,
|
||||
CREATE_IF_NECESSARY = 0x10000000,
|
||||
};
|
||||
|
||||
sqlite3* const db;
|
||||
@@ -90,15 +83,9 @@ struct SQLiteConnection {
|
||||
const String8 label;
|
||||
|
||||
volatile bool canceled;
|
||||
volatile jobject authorizer;
|
||||
|
||||
SQLiteConnection(sqlite3* db, int openFlags, const String8& path, const String8& label)
|
||||
: db(db),
|
||||
openFlags(openFlags),
|
||||
path(path),
|
||||
label(label),
|
||||
canceled(false),
|
||||
authorizer(NULL) {}
|
||||
SQLiteConnection(sqlite3* db, int openFlags, const String8& path, const String8& label) :
|
||||
db(db), openFlags(openFlags), path(path), label(label), canceled(false) { }
|
||||
};
|
||||
|
||||
// Called each time a statement begins execution, when tracing is enabled.
|
||||
@@ -121,34 +108,10 @@ static int sqliteProgressHandlerCallback(void* data) {
|
||||
return connection->canceled;
|
||||
}
|
||||
|
||||
static int sqliteAuthorizerCallback(void* data, int action, const char* arg3, const char* arg4,
|
||||
const char* arg5, const char* arg6) {
|
||||
SQLiteConnection* connection = static_cast<SQLiteConnection*>(data);
|
||||
if (connection->authorizer) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
ScopedLocalRef<jobject> authorizerObj(env, env->NewLocalRef(connection->authorizer));
|
||||
ScopedLocalRef<jstring> arg3String(env, env->NewStringUTF(arg3));
|
||||
ScopedLocalRef<jstring> arg4String(env, env->NewStringUTF(arg4));
|
||||
ScopedLocalRef<jstring> arg5String(env, env->NewStringUTF(arg5));
|
||||
ScopedLocalRef<jstring> arg6String(env, env->NewStringUTF(arg6));
|
||||
int res = env->CallIntMethod(authorizerObj.get(), gAuthorizer.onAuthorize, action,
|
||||
arg3String.get(), arg4String.get(), arg5String.get(),
|
||||
arg6String.get());
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("Exception thrown by authorizer");
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
return SQLITE_DENY;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags,
|
||||
jstring labelStr, jint lookasideSz, jint lookasideCnt) {
|
||||
jstring labelStr, jboolean enableTrace, jboolean enableProfile, jint lookasideSz,
|
||||
jint lookasideCnt) {
|
||||
int sqliteFlags;
|
||||
if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) {
|
||||
sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
@@ -209,16 +172,13 @@ static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFla
|
||||
// Create wrapper object.
|
||||
SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label);
|
||||
|
||||
// Enable optional features if requested.
|
||||
if (openFlags & SQLiteConnection::ENABLE_TRACE) {
|
||||
// Enable tracing and profiling if requested.
|
||||
if (enableTrace) {
|
||||
sqlite3_trace(db, &sqliteTraceCallback, connection);
|
||||
}
|
||||
if (openFlags & SQLiteConnection::ENABLE_PROFILE) {
|
||||
if (enableProfile) {
|
||||
sqlite3_profile(db, &sqliteProfileCallback, connection);
|
||||
}
|
||||
if (openFlags & SQLiteConnection::ENABLE_AUTHORIZER) {
|
||||
sqlite3_set_authorizer(db, &sqliteAuthorizerCallback, connection);
|
||||
}
|
||||
|
||||
ALOGV("Opened connection %p with label '%s'", db, label.string());
|
||||
return reinterpret_cast<jlong>(connection);
|
||||
@@ -228,11 +188,6 @@ static void nativeClose(JNIEnv* env, jclass clazz, jlong connectionPtr) {
|
||||
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
|
||||
|
||||
if (connection) {
|
||||
if (connection->authorizer) {
|
||||
env->DeleteGlobalRef(connection->authorizer);
|
||||
connection->authorizer = NULL;
|
||||
}
|
||||
|
||||
ALOGV("Closing connection %p", connection->db);
|
||||
int err = sqlite3_close(connection->db);
|
||||
if (err != SQLITE_OK) {
|
||||
@@ -246,20 +201,6 @@ static void nativeClose(JNIEnv* env, jclass clazz, jlong connectionPtr) {
|
||||
}
|
||||
}
|
||||
|
||||
static void nativeSetAuthorizer(JNIEnv* env, jclass clazz, jlong connectionPtr,
|
||||
jobject authorizerObj) {
|
||||
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
|
||||
|
||||
if (connection->authorizer) {
|
||||
env->DeleteGlobalRef(connection->authorizer);
|
||||
connection->authorizer = NULL;
|
||||
}
|
||||
if (authorizerObj) {
|
||||
jobject authorizerObjGlobal = env->NewGlobalRef(authorizerObj);
|
||||
connection->authorizer = authorizerObjGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
static void sqliteCustomScalarFunctionCallback(sqlite3_context *context,
|
||||
int argc, sqlite3_value **argv) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
@@ -944,53 +885,69 @@ static jint nativeLastInsertRowId(JNIEnv* env, jclass, jlong connectionPtr) {
|
||||
return sqlite3_last_insert_rowid(connection->db);
|
||||
}
|
||||
|
||||
static const JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"nativeOpen", "(Ljava/lang/String;ILjava/lang/String;II)J", (void*)nativeOpen},
|
||||
{"nativeClose", "(J)V", (void*)nativeClose},
|
||||
{"nativeSetAuthorizer", "(JLandroid/database/sqlite/SQLiteAuthorizer;)V",
|
||||
(void*)nativeSetAuthorizer},
|
||||
{"nativeRegisterCustomScalarFunction",
|
||||
"(JLjava/lang/String;Ljava/util/function/UnaryOperator;)V",
|
||||
(void*)nativeRegisterCustomScalarFunction},
|
||||
{"nativeRegisterCustomAggregateFunction",
|
||||
"(JLjava/lang/String;Ljava/util/function/BinaryOperator;)V",
|
||||
(void*)nativeRegisterCustomAggregateFunction},
|
||||
{"nativeRegisterLocalizedCollators", "(JLjava/lang/String;)V",
|
||||
(void*)nativeRegisterLocalizedCollators},
|
||||
{"nativePrepareStatement", "(JLjava/lang/String;)J", (void*)nativePrepareStatement},
|
||||
{"nativeFinalizeStatement", "(JJ)V", (void*)nativeFinalizeStatement},
|
||||
{"nativeGetParameterCount", "(JJ)I", (void*)nativeGetParameterCount},
|
||||
{"nativeIsReadOnly", "(JJ)Z", (void*)nativeIsReadOnly},
|
||||
{"nativeGetColumnCount", "(JJ)I", (void*)nativeGetColumnCount},
|
||||
{"nativeGetColumnName", "(JJI)Ljava/lang/String;", (void*)nativeGetColumnName},
|
||||
{"nativeBindNull", "(JJI)V", (void*)nativeBindNull},
|
||||
{"nativeBindLong", "(JJIJ)V", (void*)nativeBindLong},
|
||||
{"nativeBindDouble", "(JJID)V", (void*)nativeBindDouble},
|
||||
{"nativeBindString", "(JJILjava/lang/String;)V", (void*)nativeBindString},
|
||||
{"nativeBindBlob", "(JJI[B)V", (void*)nativeBindBlob},
|
||||
{"nativeResetStatementAndClearBindings", "(JJ)V",
|
||||
(void*)nativeResetStatementAndClearBindings},
|
||||
{"nativeExecute", "(JJZ)V", (void*)nativeExecute},
|
||||
{"nativeExecuteForLong", "(JJ)J", (void*)nativeExecuteForLong},
|
||||
{"nativeExecuteForString", "(JJ)Ljava/lang/String;", (void*)nativeExecuteForString},
|
||||
{"nativeExecuteForBlobFileDescriptor", "(JJ)I", (void*)nativeExecuteForBlobFileDescriptor},
|
||||
{"nativeExecuteForChangedRowCount", "(JJ)I", (void*)nativeExecuteForChangedRowCount},
|
||||
{"nativeExecuteForLastInsertedRowId", "(JJ)J", (void*)nativeExecuteForLastInsertedRowId},
|
||||
{"nativeExecuteForCursorWindow", "(JJJIIZ)J", (void*)nativeExecuteForCursorWindow},
|
||||
{"nativeGetDbLookaside", "(J)I", (void*)nativeGetDbLookaside},
|
||||
{"nativeCancel", "(J)V", (void*)nativeCancel},
|
||||
{"nativeResetCancel", "(JZ)V", (void*)nativeResetCancel},
|
||||
static const JNINativeMethod sMethods[] =
|
||||
{
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZII)J",
|
||||
(void*)nativeOpen },
|
||||
{ "nativeClose", "(J)V",
|
||||
(void*)nativeClose },
|
||||
{ "nativeRegisterCustomScalarFunction", "(JLjava/lang/String;Ljava/util/function/UnaryOperator;)V",
|
||||
(void*)nativeRegisterCustomScalarFunction },
|
||||
{ "nativeRegisterCustomAggregateFunction", "(JLjava/lang/String;Ljava/util/function/BinaryOperator;)V",
|
||||
(void*)nativeRegisterCustomAggregateFunction },
|
||||
{ "nativeRegisterLocalizedCollators", "(JLjava/lang/String;)V",
|
||||
(void*)nativeRegisterLocalizedCollators },
|
||||
{ "nativePrepareStatement", "(JLjava/lang/String;)J",
|
||||
(void*)nativePrepareStatement },
|
||||
{ "nativeFinalizeStatement", "(JJ)V",
|
||||
(void*)nativeFinalizeStatement },
|
||||
{ "nativeGetParameterCount", "(JJ)I",
|
||||
(void*)nativeGetParameterCount },
|
||||
{ "nativeIsReadOnly", "(JJ)Z",
|
||||
(void*)nativeIsReadOnly },
|
||||
{ "nativeGetColumnCount", "(JJ)I",
|
||||
(void*)nativeGetColumnCount },
|
||||
{ "nativeGetColumnName", "(JJI)Ljava/lang/String;",
|
||||
(void*)nativeGetColumnName },
|
||||
{ "nativeBindNull", "(JJI)V",
|
||||
(void*)nativeBindNull },
|
||||
{ "nativeBindLong", "(JJIJ)V",
|
||||
(void*)nativeBindLong },
|
||||
{ "nativeBindDouble", "(JJID)V",
|
||||
(void*)nativeBindDouble },
|
||||
{ "nativeBindString", "(JJILjava/lang/String;)V",
|
||||
(void*)nativeBindString },
|
||||
{ "nativeBindBlob", "(JJI[B)V",
|
||||
(void*)nativeBindBlob },
|
||||
{ "nativeResetStatementAndClearBindings", "(JJ)V",
|
||||
(void*)nativeResetStatementAndClearBindings },
|
||||
{ "nativeExecute", "(JJZ)V",
|
||||
(void*)nativeExecute },
|
||||
{ "nativeExecuteForLong", "(JJ)J",
|
||||
(void*)nativeExecuteForLong },
|
||||
{ "nativeExecuteForString", "(JJ)Ljava/lang/String;",
|
||||
(void*)nativeExecuteForString },
|
||||
{ "nativeExecuteForBlobFileDescriptor", "(JJ)I",
|
||||
(void*)nativeExecuteForBlobFileDescriptor },
|
||||
{ "nativeExecuteForChangedRowCount", "(JJ)I",
|
||||
(void*)nativeExecuteForChangedRowCount },
|
||||
{ "nativeExecuteForLastInsertedRowId", "(JJ)J",
|
||||
(void*)nativeExecuteForLastInsertedRowId },
|
||||
{ "nativeExecuteForCursorWindow", "(JJJIIZ)J",
|
||||
(void*)nativeExecuteForCursorWindow },
|
||||
{ "nativeGetDbLookaside", "(J)I",
|
||||
(void*)nativeGetDbLookaside },
|
||||
{ "nativeCancel", "(J)V",
|
||||
(void*)nativeCancel },
|
||||
{ "nativeResetCancel", "(JZ)V",
|
||||
(void*)nativeResetCancel },
|
||||
|
||||
{"nativeLastInsertRowId", "(J)I", (void*)nativeLastInsertRowId}};
|
||||
{ "nativeLastInsertRowId", "(J)I", (void*) nativeLastInsertRowId }
|
||||
};
|
||||
|
||||
int register_android_database_SQLiteConnection(JNIEnv *env)
|
||||
{
|
||||
jclass authorizerClazz = FindClassOrDie(env, "android/database/sqlite/SQLiteAuthorizer");
|
||||
gAuthorizer.onAuthorize = GetMethodIDOrDie(env, authorizerClazz, "onAuthorize",
|
||||
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/"
|
||||
"String;Ljava/lang/String;)I");
|
||||
|
||||
jclass unaryClazz = FindClassOrDie(env, "java/util/function/UnaryOperator");
|
||||
gUnaryOperator.apply = GetMethodIDOrDie(env, unaryClazz,
|
||||
"apply", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
|
||||
Reference in New Issue
Block a user