Introduced DISABLE_COMPATIBILITY_WAL flag
If set, Compatibility WAL will not be used.
Currently this flag is set if SQLiteOpenHelper.setWriteAheadLogging(false)
is called before opening the database. Previously this call was ignored
since ENABLE_WRITE_AHEAD_LOGGING flag is only set when setWriteAheadLogging(true)
Test: CtsDatabaseTestCases
Bug: 74116447
Change-Id: Ic486e178b9da5d747840be739303a2685b91f35b
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 7717b8d..2a791ec 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -292,8 +292,10 @@
final boolean walEnabled =
(mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
// Use compatibility WAL unless an app explicitly set journal/synchronous mode
+ // or DISABLE_COMPATIBILITY_WAL flag is set
final boolean useCompatibilityWal = mConfiguration.journalMode == null
- && mConfiguration.syncMode == null && mConfiguration.useCompatibilityWal;
+ && mConfiguration.syncMode == null
+ && (mConfiguration.openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
if (walEnabled || useCompatibilityWal) {
setJournalMode("WAL");
if (useCompatibilityWal && SQLiteCompatibilityWalFlags.areFlagsSet()) {
@@ -423,8 +425,8 @@
boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled
!= mConfiguration.foreignKeyConstraintsEnabled;
boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
- & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0
- || configuration.useCompatibilityWal != mConfiguration.useCompatibilityWal;
+ & (SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING
+ | SQLiteDatabase.DISABLE_COMPATIBILITY_WAL)) != 0;
boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
// Update configuration parameters.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index dc60612..dadb95b 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -315,7 +315,12 @@
}
}
- if (mConfiguration.openFlags != configuration.openFlags) {
+ // We should do in-place switching when transitioning from compatibility WAL
+ // to rollback journal. Otherwise transient connection state will be lost
+ boolean onlyCompatWalChanged = (mConfiguration.openFlags ^ configuration.openFlags)
+ == SQLiteDatabase.DISABLE_COMPATIBILITY_WAL;
+
+ if (!onlyCompatWalChanged && mConfiguration.openFlags != configuration.openFlags) {
// If we are changing open flags and WAL mode at the same time, then
// we have no choice but to close the primary connection beforehand
// because there can only be one connection open when we change WAL mode.
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index ae1f57d..b463d8d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -253,6 +253,13 @@
public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
/**
+ * Open flag: Flag for {@link #openDatabase} to disable Compatibility WAL when opening database.
+ *
+ * @hide
+ */
+ public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000;
+
+ /**
* Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
*
* Each prepared-statement is between 1K - 6K, depending on the complexity of the
@@ -288,10 +295,10 @@
mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
mConfigurationLocked.journalMode = journalMode;
mConfigurationLocked.syncMode = syncMode;
- mConfigurationLocked.useCompatibilityWal = SQLiteGlobal.isCompatibilityWalSupported();
- if (!mConfigurationLocked.isInMemoryDb() && SQLiteCompatibilityWalFlags.areFlagsSet()) {
- mConfigurationLocked.useCompatibilityWal = SQLiteCompatibilityWalFlags
- .isCompatibilityWalSupported();
+ if (!SQLiteGlobal.isCompatibilityWalSupported() || (
+ SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
+ .isCompatibilityWalSupported())) {
+ mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
}
}
@@ -2082,21 +2089,21 @@
synchronized (mLock) {
throwIfNotOpenLocked();
- final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal;
final int oldFlags = mConfigurationLocked.openFlags;
- if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
+ final boolean walDisabled = (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0;
+ final boolean compatibilityWalDisabled = (oldFlags & DISABLE_COMPATIBILITY_WAL) != 0;
+ if (walDisabled && compatibilityWalDisabled) {
return;
}
mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
- // If an app explicitly disables WAL, do not even use compatibility mode
- mConfigurationLocked.useCompatibilityWal = false;
+ // If an app explicitly disables WAL, compatibility mode should be disabled too
+ mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.openFlags = oldFlags;
- mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal;
throw ex;
}
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index a14df1e..275043f 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -111,15 +111,6 @@
public long idleConnectionTimeoutMs = Long.MAX_VALUE;
/**
- * Enables compatibility WAL mode. Applications cannot explicitly choose compatibility WAL mode,
- * therefore it is not exposed as a flag.
- *
- * <p>In this mode, only database journal mode will be changed, connection pool
- * size will still be limited to a single connection.
- */
- public boolean useCompatibilityWal;
-
- /**
* Journal mode to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} is not set.
* <p>Default is returned by {@link SQLiteGlobal#getDefaultJournalMode()}
*/
@@ -191,7 +182,6 @@
lookasideSlotSize = other.lookasideSlotSize;
lookasideSlotCount = other.lookasideSlotCount;
idleConnectionTimeoutMs = other.idleConnectionTimeoutMs;
- useCompatibilityWal = other.useCompatibilityWal;
journalMode = other.journalMode;
syncMode = other.syncMode;
}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 64e9e5d..7ff6635 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -197,6 +197,8 @@
}
mOpenParamsBuilder.setWriteAheadLoggingEnabled(enabled);
}
+ // Compatibility WAL is disabled if an app disables or enables WAL
+ mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.DISABLE_COMPATIBILITY_WAL);
}
}