From 48b72ed67269392ae1b5762811449b4dc7b9888d Mon Sep 17 00:00:00 2001 From: Daniel Santiago Rivera Date: Mon, 6 Mar 2023 15:36:52 -0500 Subject: [PATCH] Clear statement cache if schema changes. If DDL statement is executed then the prepared statement cache must be cleaned up on active connections, otherwise their column result information can be outdated. Bug: 183028015 Test: atest CtsDatabaseTestCases Change-Id: I7e51007afb029c0591e48eaa0be908bcb92df576 --- .../java/android/database/sqlite/SQLiteConnection.java | 4 ++++ .../android/database/sqlite/SQLiteConnectionPool.java | 10 ++++++++++ core/java/android/database/sqlite/SQLiteDatabase.java | 6 ++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index 4b3eb3a000ff6..45326610fbd00 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -1392,6 +1392,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen return sql.replaceAll("[\\s]*\\n+[\\s]*", " "); } + void clearPreparedStatementCache() { + mPreparedStatementCache.evictAll(); + } + /** * Holder type for a prepared statement. * diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java index 069c264313e79..6023d66b9c883 100644 --- a/core/java/android/database/sqlite/SQLiteConnectionPool.java +++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java @@ -1126,6 +1126,16 @@ public final class SQLiteConnectionPool implements Closeable { mConnectionWaiterPool = waiter; } + void clearAcquiredConnectionsPreparedStatementCache() { + synchronized (mLock) { + if (!mAcquiredConnections.isEmpty()) { + for (SQLiteConnection connection : mAcquiredConnections.keySet()) { + connection.clearPreparedStatementCache(); + } + } + } + } + /** * Dumps debugging information about this connection pool. * diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index c08294f42c45d..db898c3b7b5d2 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -2088,10 +2088,12 @@ public final class SQLiteDatabase extends SQLiteClosable { try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) { return statement.executeUpdateDelete(); } finally { - // If schema was updated, close non-primary connections, otherwise they might - // have outdated schema information + // If schema was updated, close non-primary connections and clear prepared + // statement caches of active connections, otherwise they might have outdated + // schema information. if (statementType == DatabaseUtils.STATEMENT_DDL) { mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions(); + mConnectionPoolLocked.clearAcquiredConnectionsPreparedStatementCache(); } } } finally {