Close available secondary connections if schema changes
If DDL statement is executed on one connection, the schema change is
not always visible to other connections due to sqlite3_column_count()
API limitation. We have to close secondary connections to prevent the
issue.
Test: cts/SQLiteOpenHelperTest
Bug: 33695159
Change-Id: I862da71ecec5b1edc880dbfadf22efb2274ca10a
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 8b0fef4..5adb119 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -570,6 +570,16 @@
mAvailableNonPrimaryConnections.clear();
}
+ /**
+ * Close non-primary connections that are not currently in use. This method is safe to use
+ * in finalize block as it doesn't throw RuntimeExceptions.
+ */
+ void closeAvailableNonPrimaryConnectionsAndLogExceptions() {
+ synchronized (mLock) {
+ closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
+ }
+ }
+
// Can't throw.
private void closeExcessConnectionsAndLogExceptionsLocked() {
int availableCount = mAvailableNonPrimaryConnections.size();
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 863fb19..09bb9c6 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1740,7 +1740,8 @@
private int executeSql(String sql, Object[] bindArgs) throws SQLException {
acquireReference();
try {
- if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
+ final int statementType = DatabaseUtils.getSqlStatementType(sql);
+ if (statementType == DatabaseUtils.STATEMENT_ATTACH) {
boolean disableWal = false;
synchronized (mLock) {
if (!mHasAttachedDbsLocked) {
@@ -1754,11 +1755,14 @@
}
}
- SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
- try {
+ try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) {
return statement.executeUpdateDelete();
} finally {
- statement.close();
+ // If schema was updated, close non-primary connections, otherwise they might
+ // have outdated schema information
+ if (statementType == DatabaseUtils.STATEMENT_DDL) {
+ mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions();
+ }
}
} finally {
releaseReference();