Changeset 209096 in webkit


Ignore:
Timestamp:
Nov 29, 2016 3:28:00 PM (7 years ago)
Author:
beidson@apple.com
Message:

IndexedDB 2.0: Cache and reuse SQLiteStatements in the SQLite backend.
https://bugs.webkit.org/show_bug.cgi?id=164974

Reviewed by Alex Christensen.

No new tests (No behavior change other than being faster).

Instead of building new SQLiteStatements from scratch each time they're needed and then
finalizing them after used for a single operation, cache them.

For tests that do puts and/or gets in tight loops, this shows up as a 5%-20% speedup on profiles.

  • Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:

(WebCore::IDBServer::SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo):
(WebCore::IDBServer::SQLiteIDBBackingStore::getOrEstablishDatabaseInfo):
(WebCore::IDBServer::SQLiteIDBBackingStore::createObjectStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::deleteObjectStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::renameObjectStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::clearObjectStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::createIndex):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedHasIndexRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::deleteIndex):
(WebCore::IDBServer::SQLiteIDBBackingStore::renameIndex):
(WebCore::IDBServer::SQLiteIDBBackingStore::keyExistsInObjectStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::deleteUnusedBlobFileRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::deleteRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::addRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::getBlobRecordsForObjectStoreRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::getAllObjectStoreRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetKeyGeneratorValue):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedSetKeyGeneratorValue):
(WebCore::IDBServer::SQLiteIDBBackingStore::deleteBackingStore):
(WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatement):
(WebCore::IDBServer::SQLiteIDBBackingStore::closeSQLiteDB):
(WebCore::IDBServer::queryForGetAllObjectStoreRecords): Deleted.

  • Modules/indexeddb/server/SQLiteIDBBackingStore.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r209092 r209096  
     12016-11-29  Brady Eidson  <beidson@apple.com>
     2
     3        IndexedDB 2.0: Cache and reuse SQLiteStatements in the SQLite backend.
     4        https://bugs.webkit.org/show_bug.cgi?id=164974
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (No behavior change other than being faster).
     9
     10        Instead of building new SQLiteStatements from scratch each time they're needed and then
     11        finalizing them after used for a single operation, cache them.
     12
     13        For tests that do puts and/or gets in tight loops, this shows up as a 5%-20% speedup on profiles.
     14
     15        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
     16        (WebCore::IDBServer::SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo):
     17        (WebCore::IDBServer::SQLiteIDBBackingStore::getOrEstablishDatabaseInfo):
     18        (WebCore::IDBServer::SQLiteIDBBackingStore::createObjectStore):
     19        (WebCore::IDBServer::SQLiteIDBBackingStore::deleteObjectStore):
     20        (WebCore::IDBServer::SQLiteIDBBackingStore::renameObjectStore):
     21        (WebCore::IDBServer::SQLiteIDBBackingStore::clearObjectStore):
     22        (WebCore::IDBServer::SQLiteIDBBackingStore::createIndex):
     23        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedHasIndexRecord):
     24        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexRecord):
     25        (WebCore::IDBServer::SQLiteIDBBackingStore::deleteIndex):
     26        (WebCore::IDBServer::SQLiteIDBBackingStore::renameIndex):
     27        (WebCore::IDBServer::SQLiteIDBBackingStore::keyExistsInObjectStore):
     28        (WebCore::IDBServer::SQLiteIDBBackingStore::deleteUnusedBlobFileRecords):
     29        (WebCore::IDBServer::SQLiteIDBBackingStore::deleteRecord):
     30        (WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
     31        (WebCore::IDBServer::SQLiteIDBBackingStore::addRecord):
     32        (WebCore::IDBServer::SQLiteIDBBackingStore::getBlobRecordsForObjectStoreRecord):
     33        (WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
     34        (WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
     35        (WebCore::IDBServer::SQLiteIDBBackingStore::getAllObjectStoreRecords):
     36        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetKeyGeneratorValue):
     37        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedSetKeyGeneratorValue):
     38        (WebCore::IDBServer::SQLiteIDBBackingStore::deleteBackingStore):
     39        (WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatement):
     40        (WebCore::IDBServer::SQLiteIDBBackingStore::closeSQLiteDB):
     41        (WebCore::IDBServer::queryForGetAllObjectStoreRecords): Deleted.
     42        * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
     43
    1442016-11-22  Jiewen Tan  <jiewen_tan@apple.com>
    245
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp

    r209069 r209096  
    491491    if (!m_sqliteDB->executeCommand("CREATE TABLE IDBDatabaseInfo (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL);")) {
    492492        LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    493         m_sqliteDB = nullptr;
     493        closeSQLiteDB();
    494494        return nullptr;
    495495    }
     
    497497    if (!m_sqliteDB->executeCommand("CREATE TABLE ObjectStoreInfo (id INTEGER PRIMARY KEY NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL, name TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL, keyPath BLOB NOT NULL ON CONFLICT FAIL, autoInc INTEGER NOT NULL ON CONFLICT FAIL, maxIndexID INTEGER NOT NULL ON CONFLICT FAIL);")) {
    498498        LOG_ERROR("Could not create ObjectStoreInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    499         m_sqliteDB = nullptr;
     499        closeSQLiteDB();
    500500        return nullptr;
    501501    }
     
    503503    if (!m_sqliteDB->executeCommand("CREATE TABLE IndexInfo (id INTEGER NOT NULL ON CONFLICT FAIL, name TEXT NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, keyPath BLOB NOT NULL ON CONFLICT FAIL, isUnique INTEGER NOT NULL ON CONFLICT FAIL, multiEntry INTEGER NOT NULL ON CONFLICT FAIL);")) {
    504504        LOG_ERROR("Could not create IndexInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    505         m_sqliteDB = nullptr;
     505        closeSQLiteDB();
    506506        return nullptr;
    507507    }
     
    509509    if (!m_sqliteDB->executeCommand("CREATE TABLE KeyGenerators (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, currentKey INTEGER NOT NULL ON CONFLICT FAIL);")) {
    510510        LOG_ERROR("Could not create KeyGenerators table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    511         m_sqliteDB = nullptr;
     511        closeSQLiteDB();
    512512        return nullptr;
    513513    }
     
    519519            || sql.step() != SQLITE_DONE) {
    520520            LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    521             m_sqliteDB = nullptr;
     521            closeSQLiteDB();
    522522            return nullptr;
    523523        }
     
    529529            || sql.step() != SQLITE_DONE) {
    530530            LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    531             m_sqliteDB = nullptr;
     531            closeSQLiteDB();
    532532            return nullptr;
    533533        }
     
    541541            || sql.step() != SQLITE_DONE) {
    542542            LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    543             m_sqliteDB = nullptr;
     543            closeSQLiteDB();
    544544            return nullptr;
    545545        }
     
    548548    if (!m_sqliteDB->executeCommand(ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MaxObjectStoreID', 1);"))) {
    549549        LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    550         m_sqliteDB = nullptr;
     550        closeSQLiteDB();
    551551        return nullptr;
    552552    }
     
    722722    if (!m_sqliteDB->open(dbFilename)) {
    723723        LOG_ERROR("Failed to open SQLite database at path '%s'", dbFilename.utf8().data());
    724         m_sqliteDB = nullptr;
     724        closeSQLiteDB();
    725725    }
    726726
     
    734734    if (!ensureValidRecordsTable()) {
    735735        LOG_ERROR("Error creating or migrating Records table in database");
    736         m_sqliteDB = nullptr;
     736        closeSQLiteDB();
    737737        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error creating or migrating Records table in database") };
    738738    }
     
    740740    if (!ensureValidIndexRecordsTable()) {
    741741        LOG_ERROR("Error creating or migrating Index Records table in database");
    742         m_sqliteDB = nullptr;
     742        closeSQLiteDB();
    743743        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error creating or migrating Index Records table in database") };
    744744    }
     
    746746    if (!ensureValidBlobTables()) {
    747747        LOG_ERROR("Error creating or confirming Blob Records tables in database");
    748         m_sqliteDB = nullptr;
     748        closeSQLiteDB();
    749749        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error creating or confirming Blob Records tables in database") };
    750750    }
     
    756756    if (!databaseInfo) {
    757757        LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());
    758         m_sqliteDB = nullptr;
     758        closeSQLiteDB();
    759759        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to establish IDB database file") };
    760760    }
     
    863863
    864864    {
    865         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO ObjectStoreInfo VALUES (?, ?, ?, ?, ?);"));
    866         if (sql.prepare() != SQLITE_OK
    867             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    868             || sql.bindText(2, info.name()) != SQLITE_OK
    869             || sql.bindBlob(3, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
    870             || sql.bindInt(4, info.autoIncrement()) != SQLITE_OK
    871             || sql.bindInt64(5, info.maxIndexID()) != SQLITE_OK
    872             || sql.step() != SQLITE_DONE) {
     865        auto* sql = cachedStatement(SQL::CreateObjectStoreInfo, ASCIILiteral("INSERT INTO ObjectStoreInfo VALUES (?, ?, ?, ?, ?);"));
     866        if (!sql
     867            || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     868            || sql->bindText(2, info.name()) != SQLITE_OK
     869            || sql->bindBlob(3, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
     870            || sql->bindInt(4, info.autoIncrement()) != SQLITE_OK
     871            || sql->bindInt64(5, info.maxIndexID()) != SQLITE_OK
     872            || sql->step() != SQLITE_DONE) {
    873873            LOG_ERROR("Could not add object store '%s' to ObjectStoreInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    874874            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not create object store") };
     
    877877
    878878    {
    879         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, 0);"));
    880         if (sql.prepare() != SQLITE_OK
    881             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    882             || sql.step() != SQLITE_DONE) {
     879        auto* sql = cachedStatement(SQL::CreateObjectStoreKeyGenerator, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, 0);"));
     880        if (!sql
     881            || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     882            || sql->step() != SQLITE_DONE) {
    883883            LOG_ERROR("Could not seed initial key generator value for ObjectStoreInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    884884            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not seed initial key generator value for object store") };
     
    910910    // Delete the ObjectStore record
    911911    {
    912         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM ObjectStoreInfo WHERE id = ?;"));
    913         if (sql.prepare() != SQLITE_OK
    914             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
    915             || sql.step() != SQLITE_DONE) {
     912        auto* sql = cachedStatement(SQL::DeleteObjectStoreInfo, ASCIILiteral("DELETE FROM ObjectStoreInfo WHERE id = ?;"));
     913        if (!sql
     914            || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
     915            || sql->step() != SQLITE_DONE) {
    916916            LOG_ERROR("Could not delete object store id %" PRIi64 " from ObjectStoreInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    917917            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete object store") };
     
    921921    // Delete the ObjectStore's key generator record if there is one.
    922922    {
    923         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM KeyGenerators WHERE objectStoreID = ?;"));
    924         if (sql.prepare() != SQLITE_OK
    925             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
    926             || sql.step() != SQLITE_DONE) {
     923        auto* sql = cachedStatement(SQL::DeleteObjectStoreKeyGenerator, ASCIILiteral("DELETE FROM KeyGenerators WHERE objectStoreID = ?;"));
     924        if (!sql
     925            || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
     926            || sql->step() != SQLITE_DONE) {
    927927            LOG_ERROR("Could not delete object store from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    928928            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete key generator for deleted object store") };
     
    932932    // Delete all associated records
    933933    {
    934         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
    935         if (sql.prepare() != SQLITE_OK
    936             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
    937             || sql.step() != SQLITE_DONE) {
     934        auto* sql = cachedStatement(SQL::DeleteObjectStoreRecords, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
     935        if (!sql
     936            || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
     937            || sql->step() != SQLITE_DONE) {
    938938            LOG_ERROR("Could not delete records for object store %" PRIi64 " (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    939939            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete records for deleted object store") };
     
    943943    // Delete all associated Indexes
    944944    {
    945         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE objectStoreID = ?;"));
    946         if (sql.prepare() != SQLITE_OK
    947             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
    948             || sql.step() != SQLITE_DONE) {
     945        auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexInfo, ASCIILiteral("DELETE FROM IndexInfo WHERE objectStoreID = ?;"));
     946        if (!sql
     947            || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
     948            || sql->step() != SQLITE_DONE) {
    949949            LOG_ERROR("Could not delete index from IndexInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    950950            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete IDBIndex for deleted object store") };
     
    954954    // Delete all associated Index records
    955955    {
    956         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
    957         if (sql.prepare() != SQLITE_OK
    958             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
    959             || sql.step() != SQLITE_DONE) {
     956        auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecords, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
     957        if (!sql
     958            || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
     959            || sql->step() != SQLITE_DONE) {
    960960            LOG_ERROR("Could not delete index records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    961961            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete IDBIndex records for deleted object store") };
     
    965965    // Delete all unused Blob URL records.
    966966    {
    967         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM BlobRecords WHERE objectStoreRow NOT IN (SELECT recordID FROM Records)"));
    968         if (sql.prepare() != SQLITE_OK
    969             || sql.step() != SQLITE_DONE) {
     967        auto* sql = cachedStatement(SQL::DeleteObjectStoreBlobRecords, ASCIILiteral("DELETE FROM BlobRecords WHERE objectStoreRow NOT IN (SELECT recordID FROM Records)"));
     968        if (!sql
     969            || sql->step() != SQLITE_DONE) {
    970970            LOG_ERROR("Could not delete Blob URL records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    971971            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete stored blob records for deleted object store") };
     
    10011001
    10021002    {
    1003         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("UPDATE ObjectStoreInfo SET name = ? WHERE id = ?;"));
    1004         if (sql.prepare() != SQLITE_OK
    1005             || sql.bindText(1, newName) != SQLITE_OK
    1006             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
    1007             || sql.step() != SQLITE_DONE) {
     1003        auto* sql = cachedStatement(SQL::RenameObjectStore, ASCIILiteral("UPDATE ObjectStoreInfo SET name = ? WHERE id = ?;"));
     1004        if (!sql
     1005            || sql->bindText(1, newName) != SQLITE_OK
     1006            || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
     1007            || sql->step() != SQLITE_DONE) {
    10081008            LOG_ERROR("Could not update name for object store id %" PRIi64 " in ObjectStoreInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    10091009            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not rename object store") };
     
    10341034
    10351035    {
    1036         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
    1037         if (sql.prepare() != SQLITE_OK
    1038             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1039             || sql.step() != SQLITE_DONE) {
     1036        auto* sql = cachedStatement(SQL::ClearObjectStoreRecords, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
     1037        if (!sql
     1038            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1039            || sql->step() != SQLITE_DONE) {
    10401040            LOG_ERROR("Could not clear records from object store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    10411041            return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to clear object store") };
     
    10441044
    10451045    {
    1046         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
    1047         if (sql.prepare() != SQLITE_OK
    1048             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1049             || sql.step() != SQLITE_DONE) {
     1046        auto* sql = cachedStatement(SQL::ClearObjectStoreIndexRecords, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
     1047        if (!sql
     1048            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1049            || sql->step() != SQLITE_DONE) {
    10501050            LOG_ERROR("Could not delete records from index record store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    10511051            return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to delete index records while clearing object store") };
     
    10801080    }
    10811081
    1082     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);"));
    1083     if (sql.prepare() != SQLITE_OK
    1084         || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    1085         || sql.bindText(2, info.name()) != SQLITE_OK
    1086         || sql.bindInt64(3, info.objectStoreIdentifier()) != SQLITE_OK
    1087         || sql.bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
    1088         || sql.bindInt(5, info.unique()) != SQLITE_OK
    1089         || sql.bindInt(6, info.multiEntry()) != SQLITE_OK
    1090         || sql.step() != SQLITE_DONE) {
     1082    auto* sql = cachedStatement(SQL::CreateIndexInfo, ASCIILiteral("INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);"));
     1083    if (!sql
     1084        || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     1085        || sql->bindText(2, info.name()) != SQLITE_OK
     1086        || sql->bindInt64(3, info.objectStoreIdentifier()) != SQLITE_OK
     1087        || sql->bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
     1088        || sql->bindInt(5, info.unique()) != SQLITE_OK
     1089        || sql->bindInt(6, info.multiEntry()) != SQLITE_OK
     1090        || sql->step() != SQLITE_DONE) {
    10911091        LOG_ERROR("Could not add index '%s' to IndexInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    10921092        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to create index in database") };
     
    11091109        IDBError error = updateOneIndexForAddRecord(info, key, valueBuffer);
    11101110        if (!error.isNull()) {
    1111             SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
    1112             if (sql.prepare() != SQLITE_OK
    1113                 || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    1114                 || sql.bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
    1115                 || sql.step() != SQLITE_DONE) {
     1111            auto* sql = cachedStatement(SQL::DeleteIndexInfo, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
     1112            if (!sql
     1113                || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     1114                || sql->bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
     1115                || sql->step() != SQLITE_DONE) {
    11161116                LOG_ERROR("Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database");
    11171117                return { IDBDatabaseException::UnknownError, ASCIILiteral("Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database") };
     
    11441144    }
    11451145
    1146     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT rowid FROM IndexRecords WHERE indexID = ? AND objectStoreID = ? AND key = CAST(? AS TEXT);"));
    1147     if (sql.prepare() != SQLITE_OK
    1148         || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    1149         || sql.bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
    1150         || sql.bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK) {
     1146    auto* sql = cachedStatement(SQL::HasIndexRecord, ASCIILiteral("SELECT rowid FROM IndexRecords WHERE indexID = ? AND objectStoreID = ? AND key = CAST(? AS TEXT);"));
     1147    if (!sql
     1148        || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     1149        || sql->bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
     1150        || sql->bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK) {
    11511151        LOG_ERROR("Error checking for index record in database");
    11521152        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error checking for index record in database") };
    11531153    }
    11541154
    1155     int sqlResult = sql.step();
     1155    int sqlResult = sql->step();
    11561156    if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
    11571157        return { };
     
    12211221
    12221222    {
    1223         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT));"));
    1224         if (sql.prepare() != SQLITE_OK
    1225             || sql.bindInt64(1, indexID) != SQLITE_OK
    1226             || sql.bindInt64(2, objectStoreID) != SQLITE_OK
    1227             || sql.bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK
    1228             || sql.bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLITE_OK
    1229             || sql.step() != SQLITE_DONE) {
     1223        auto* sql = cachedStatement(SQL::PutIndexRecord, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT));"));
     1224        if (!sql
     1225            || sql->bindInt64(1, indexID) != SQLITE_OK
     1226            || sql->bindInt64(2, objectStoreID) != SQLITE_OK
     1227            || sql->bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK
     1228            || sql->bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLITE_OK
     1229            || sql->step() != SQLITE_DONE) {
    12301230            LOG_ERROR("Could not put index record for index %" PRIi64 " in object store %" PRIi64 " in Records table (%i) - %s", indexID, objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    12311231            return { IDBDatabaseException::UnknownError, ASCIILiteral("Error putting index record into database") };
     
    12561256
    12571257    {
    1258         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
    1259         if (sql.prepare() != SQLITE_OK
    1260             || sql.bindInt64(1, indexIdentifier) != SQLITE_OK
    1261             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
    1262             || sql.step() != SQLITE_DONE) {
     1258        auto* sql = cachedStatement(SQL::DeleteIndexInfo, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
     1259        if (!sql
     1260            || sql->bindInt64(1, indexIdentifier) != SQLITE_OK
     1261            || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
     1262            || sql->step() != SQLITE_DONE) {
    12631263            LOG_ERROR("Could not delete index id %" PRIi64 " from IndexInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    12641264            return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting index from database") };
     
    12671267
    12681268    {
    1269         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE indexID = ? AND objectStoreID = ?;"));
    1270         if (sql.prepare() != SQLITE_OK
    1271             || sql.bindInt64(1, indexIdentifier) != SQLITE_OK
    1272             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
    1273             || sql.step() != SQLITE_DONE) {
     1269        auto* sql = cachedStatement(SQL::DeleteIndexRecords, ASCIILiteral("DELETE FROM IndexRecords WHERE indexID = ? AND objectStoreID = ?;"));
     1270        if (!sql
     1271            || sql->bindInt64(1, indexIdentifier) != SQLITE_OK
     1272            || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
     1273            || sql->step() != SQLITE_DONE) {
    12741274            LOG_ERROR("Could not delete index records for index id %" PRIi64 " from IndexRecords table (%i) - %s", indexIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    12751275            return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting index records from database") };
     
    13111311
    13121312    {
    1313         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("UPDATE IndexInfo SET name = ? WHERE objectStoreID = ? AND id = ?;"));
    1314         if (sql.prepare() != SQLITE_OK
    1315             || sql.bindText(1, newName) != SQLITE_OK
    1316             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
    1317             || sql.bindInt64(3, indexIdentifier) != SQLITE_OK
    1318             || sql.step() != SQLITE_DONE) {
     1313        auto* sql = cachedStatement(SQL::RenameIndex, ASCIILiteral("UPDATE IndexInfo SET name = ? WHERE objectStoreID = ? AND id = ?;"));
     1314        if (!sql
     1315            || sql->bindText(1, newName) != SQLITE_OK
     1316            || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
     1317            || sql->bindInt64(3, indexIdentifier) != SQLITE_OK
     1318            || sql->step() != SQLITE_DONE) {
    13191319            LOG_ERROR("Could not update name for index id (%" PRIi64 ", %" PRIi64 ") in IndexInfo table (%i) - %s", objectStoreIdentifier, indexIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    13201320            return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not rename index") };
     
    13471347        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKey to check for existence in object store") };
    13481348    }
    1349     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT key FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT) LIMIT 1;"));
    1350     if (sql.prepare() != SQLITE_OK
    1351         || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1352         || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
     1349    auto* sql = cachedStatement(SQL::KeyExistsInObjectStore, ASCIILiteral("SELECT key FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT) LIMIT 1;"));
     1350    if (!sql
     1351        || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1352        || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
    13531353        LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    13541354        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to check for existence of IDBKey in object store") };
    13551355    }
    13561356
    1357     int sqlResult = sql.step();
     1357    int sqlResult = sql->step();
    13581358    if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
    13591359        return { };
     
    13761376    HashSet<String> removedBlobFilenames;
    13771377    {
    1378         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"));
    1379 
    1380         if (sql.prepare() != SQLITE_OK) {
     1378        auto* sql = cachedStatement(SQL::GetUnusedBlobFilenames, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"));
     1379
     1380        if (!sql) {
    13811381            LOG_ERROR("Error deleting stored blobs (%i) (Could not gather unused blobURLs) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    13821382            return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting stored blobs") };
    13831383        }
    13841384
    1385         int result = sql.step();
     1385        int result = sql->step();
    13861386        while (result == SQLITE_ROW) {
    1387             removedBlobFilenames.add(sql.getColumnText(0));
    1388             result = sql.step();
     1387            removedBlobFilenames.add(sql->getColumnText(0));
     1388            result = sql->step();
    13891389        }
    13901390
     
    13971397    // Remove the blob records that are no longer in use.
    13981398    if (!removedBlobFilenames.isEmpty()) {
    1399         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"));
    1400 
    1401         if (sql.prepare() != SQLITE_OK
    1402             || sql.step() != SQLITE_DONE) {
     1399        auto* sql = cachedStatement(SQL::DeleteUnusedBlobs, ASCIILiteral("DELETE FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"));
     1400
     1401        if (!sql
     1402            || sql->step() != SQLITE_DONE) {
    14031403            LOG_ERROR("Error deleting stored blobs (%i) (Could not delete blobFile records) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    14041404            return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting stored blobs") };
     
    14311431    int64_t recordID;
    14321432    {
    1433         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT recordID FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
    1434 
    1435         if (sql.prepare() != SQLITE_OK
    1436             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1437             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
     1433        auto* sql = cachedStatement(SQL::GetObjectStoreRecordID, ASCIILiteral("SELECT recordID FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
     1434
     1435        if (!sql
     1436            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1437            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
    14381438            LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    14391439            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete record from object store") };
    14401440        }
    14411441
    1442         int result = sql.step();
     1442        int result = sql->step();
    14431443
    14441444        // If there's no record ID, there's no record to delete.
     
    14511451        }
    14521452
    1453         recordID = sql.getColumnInt64(0);
     1453        recordID = sql->getColumnInt64(0);
    14541454    }
    14551455
     
    14611461    // Delete the blob records for this object store record.
    14621462    {
    1463         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM BlobRecords WHERE objectStoreRow = ?;"));
    1464 
    1465         if (sql.prepare() != SQLITE_OK
    1466             || sql.bindInt64(1, recordID) != SQLITE_OK
    1467             || sql.step() != SQLITE_DONE) {
     1463        auto* sql = cachedStatement(SQL::DeleteBlobRecord, ASCIILiteral("DELETE FROM BlobRecords WHERE objectStoreRow = ?;"));
     1464
     1465        if (!sql
     1466            || sql->bindInt64(1, recordID) != SQLITE_OK
     1467            || sql->step() != SQLITE_DONE) {
    14681468            LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) (Could not delete BlobRecords records) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    14691469            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete record from object store") };
     
    14771477    // Delete record from object store
    14781478    {
    1479         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
    1480 
    1481         if (sql.prepare() != SQLITE_OK
    1482             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1483             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
    1484             || sql.step() != SQLITE_DONE) {
     1479        auto* sql = cachedStatement(SQL::DeleteObjectStoreRecord, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
     1480
     1481        if (!sql
     1482            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1483            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
     1484            || sql->step() != SQLITE_DONE) {
    14851485            LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    14861486            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete record from object store") };
     
    14901490    // Delete record from indexes store
    14911491    {
    1492         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
    1493 
    1494         if (sql.prepare() != SQLITE_OK
    1495             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1496             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
    1497             || sql.step() != SQLITE_DONE) {
     1492        auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecord, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
     1493
     1494        if (!sql
     1495            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1496            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
     1497            || sql->step() != SQLITE_DONE) {
    14981498            LOG_ERROR("Could not delete record from indexes for object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    14991499            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete index entries for object store record") };
     
    16071607        RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(key);
    16081608
    1609         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
    1610 
    1611         if (sql.prepare() != SQLITE_OK
    1612             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
    1613             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
    1614             || sql.step() != SQLITE_DONE) {
     1609        auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecord, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
     1610
     1611        if (!sql
     1612            || sql->bindInt64(1, info.identifier()) != SQLITE_OK
     1613            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
     1614            || sql->step() != SQLITE_DONE) {
    16151615            LOG_ERROR("Adding one Index record failed, but failed to remove all others that previously succeeded");
    16161616            return { IDBDatabaseException::UnknownError, ASCIILiteral("Adding one Index record failed, but failed to remove all others that previously succeeded") };
     
    16481648    int64_t recordID = 0;
    16491649    {
    1650         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO Records VALUES (?, CAST(? AS TEXT), ?, NULL);"));
    1651         if (sql.prepare() != SQLITE_OK
    1652             || sql.bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
    1653             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
    1654             || sql.bindBlob(3, value.data().data()->data(), value.data().data()->size()) != SQLITE_OK
    1655             || sql.step() != SQLITE_DONE) {
     1650        auto* sql = cachedStatement(SQL::AddObjectStoreRecord, ASCIILiteral("INSERT INTO Records VALUES (?, CAST(? AS TEXT), ?, NULL);"));
     1651        if (!sql
     1652            || sql->bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
     1653            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
     1654            || sql->bindBlob(3, value.data().data()->data(), value.data().data()->size()) != SQLITE_OK
     1655            || sql->step() != SQLITE_DONE) {
    16561656            LOG_ERROR("Could not put record for object store %" PRIi64 " in Records table (%i) - %s", objectStoreInfo.identifier(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    16571657            return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to store record in object store") };
     
    16641664
    16651665    if (!error.isNull()) {
    1666         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
    1667         if (sql.prepare() != SQLITE_OK
    1668             || sql.bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
    1669             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
    1670             || sql.step() != SQLITE_DONE) {
     1666        auto* sql = cachedStatement(SQL::DeleteObjectStoreRecord, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
     1667        if (!sql
     1668            || sql->bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
     1669            || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
     1670            || sql->step() != SQLITE_DONE) {
    16711671            LOG_ERROR("Indexing new object store record failed, but unable to remove the object store record itself");
    16721672            return { IDBDatabaseException::UnknownError, ASCIILiteral("Indexing new object store record failed, but unable to remove the object store record itself") };
     
    16811681        auto& url = blobURLs[i];
    16821682        {
    1683             SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO BlobRecords VALUES (?, ?);"));
    1684             if (sql.prepare() != SQLITE_OK
    1685                 || sql.bindInt64(1, recordID) != SQLITE_OK
    1686                 || sql.bindText(2, url) != SQLITE_OK
    1687                 || sql.step() != SQLITE_DONE) {
     1683            auto* sql = cachedStatement(SQL::AddBlobRecord, ASCIILiteral("INSERT INTO BlobRecords VALUES (?, ?);"));
     1684            if (!sql
     1685                || sql->bindInt64(1, recordID) != SQLITE_OK
     1686                || sql->bindText(2, url) != SQLITE_OK
     1687                || sql->step() != SQLITE_DONE) {
    16881688                LOG_ERROR("Unable to record Blob record in database");
    16891689                return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to record Blob record in database") };
     
    16941694        // If we already have a file for this blobURL, nothing left to do.
    16951695        {
    1696             SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL = ?;"));
    1697             if (sql.prepare() != SQLITE_OK
    1698                 || sql.bindText(1, url) != SQLITE_OK) {
     1696            auto* sql = cachedStatement(SQL::BlobFilenameForBlobURL, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL = ?;"));
     1697            if (!sql
     1698                || sql->bindText(1, url) != SQLITE_OK) {
    16991699                LOG_ERROR("Unable to examine Blob filenames in database");
    17001700                return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to examine Blob filenames in database") };
    17011701            }
    17021702
    1703             int result = sql.step();
     1703            int result = sql->step();
    17041704            if (result != SQLITE_ROW && result != SQLITE_DONE) {
    17051705                LOG_ERROR("Unable to examine Blob filenames in database");
     
    17141714        String storedFilename = String::format("%" PRId64 ".blob", potentialFileNameInteger);
    17151715        {
    1716             SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO BlobFiles VALUES (?, ?);"));
    1717             if (sql.prepare() != SQLITE_OK
    1718                 || sql.bindText(1, url) != SQLITE_OK
    1719                 || sql.bindText(2, storedFilename) != SQLITE_OK
    1720                 || sql.step() != SQLITE_DONE) {
     1716            auto* sql = cachedStatement(SQL::AddBlobFilename, ASCIILiteral("INSERT INTO BlobFiles VALUES (?, ?);"));
     1717            if (!sql
     1718                || sql->bindText(1, url) != SQLITE_OK
     1719                || sql->bindText(2, storedFilename) != SQLITE_OK
     1720                || sql->step() != SQLITE_DONE) {
    17211721                LOG_ERROR("Unable to record Blob file record in database");
    17221722                return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to record Blob file record in database") };
     
    17381738    HashSet<String> blobURLSet;
    17391739    {
    1740         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT blobURL FROM BlobRecords WHERE objectStoreRow = ?"));
    1741         if (sql.prepare() != SQLITE_OK
    1742             || sql.bindInt64(1, objectStoreRecord) != SQLITE_OK) {
     1740        auto* sql = cachedStatement(SQL::GetBlobURL, ASCIILiteral("SELECT blobURL FROM BlobRecords WHERE objectStoreRow = ?"));
     1741        if (!sql
     1742            || sql->bindInt64(1, objectStoreRecord) != SQLITE_OK) {
    17431743            LOG_ERROR("Could not prepare statement to fetch blob URLs for object store record (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    17441744            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up blobURL records in object store by key range") };
    17451745        }
    17461746
    1747         int sqlResult = sql.step();
     1747        int sqlResult = sql->step();
    17481748        if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE) {
    17491749            // There are no blobURLs in the database for this object store record.
     
    17521752
    17531753        while (sqlResult == SQLITE_ROW) {
    1754             blobURLSet.add(sql.getColumnText(0));
    1755             sqlResult = sql.step();
     1754            blobURLSet.add(sql->getColumnText(0));
     1755            sqlResult = sql->step();
    17561756        }
    17571757
     
    17651765    String databaseDirectory = fullDatabaseDirectory();
    17661766    for (auto& blobURL : blobURLSet) {
    1767         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL = ?"));
    1768         if (sql.prepare() != SQLITE_OK
    1769             || sql.bindText(1, blobURL) != SQLITE_OK) {
     1767        auto* sql = cachedStatement(SQL::BlobFilenameForBlobURL, ASCIILiteral("SELECT fileName FROM BlobFiles WHERE blobURL = ?;"));
     1768        if (!sql
     1769            || sql->bindText(1, blobURL) != SQLITE_OK) {
    17701770            LOG_ERROR("Could not prepare statement to fetch blob filename for object store record (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    17711771            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up blobURL records in object store by key range") };
    17721772        }
    17731773
    1774         if (sql.step() != SQLITE_ROW) {
     1774        if (sql->step() != SQLITE_ROW) {
    17751775            LOG_ERROR("Entry for blob filename for blob url %s does not exist (%i) - %s", blobURL.utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    17761776            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up blobURL records in object store by key range") };
     
    17791779        blobURLs.append(blobURL);
    17801780
    1781         String fileName = sql.getColumnText(0);
     1781        String fileName = sql->getColumnText(0);
    17821782        blobFilePaths.append(pathByAppendingComponent(databaseDirectory, fileName));
    17831783    }
     
    18201820    ThreadSafeDataBuffer resultBuffer;
    18211821    {
    1822         static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1823         static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    1824         static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1825         static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    1826 
    1827         const ASCIILiteral* query = nullptr;
    1828 
     1822        static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1823        static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1824        static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1825        static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1826
     1827        SQLiteStatement* sql = nullptr;
    18291828        if (keyRange.lowerOpen) {
    18301829            if (keyRange.upperOpen)
    1831                 query = &lowerOpenUpperOpen.get();
     1830                sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpen.get());
    18321831            else
    1833                 query = &lowerOpenUpperClosed.get();
     1832                sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosed.get());
    18341833        } else {
    18351834            if (keyRange.upperOpen)
    1836                 query = &lowerClosedUpperOpen.get();
     1835                sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpen.get());
    18371836            else
    1838                 query = &lowerClosedUpperClosed.get();
    1839         }
    1840 
    1841         ASSERT(query);
    1842 
    1843         SQLiteStatement sql(*m_sqliteDB, *query);
    1844         if (sql.prepare() != SQLITE_OK
    1845             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    1846             || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
    1847             || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
     1837                sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosed.get());
     1838        }
     1839
     1840        if (!sql
     1841            || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     1842            || sql->bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
     1843            || sql->bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
    18481844            LOG_ERROR("Could not get key range record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    18491845            return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up record in object store by key range") };
    18501846        }
    18511847
    1852         int sqlResult = sql.step();
     1848        int sqlResult = sql->step();
    18531849
    18541850        if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE) {
     
    18631859
    18641860        Vector<uint8_t> buffer;
    1865         sql.getColumnBlobAsVector(0, buffer);
     1861        sql->getColumnBlobAsVector(0, buffer);
    18661862        resultBuffer = ThreadSafeDataBuffer::adoptVector(buffer);
    18671863
    1868         recordID = sql.getColumnInt64(1);
     1864        recordID = sql->getColumnInt64(1);
    18691865    }
    18701866
     
    18861882}
    18871883
    1888 static const ASCIILiteral& queryForGetAllObjectStoreRecords(const IDBGetAllRecordsData& getAllRecordsData)
    1889 {
    1890     static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1891     static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    1892     static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1893     static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    1894     static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1895     static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    1896     static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
    1897     static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1884SQLiteStatement* SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords(const IDBGetAllRecordsData& getAllRecordsData)
     1885{
     1886    static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1887    static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1888    static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1889    static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1890    static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1891    static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
     1892    static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
     1893    static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
    18981894
    18991895    if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
    19001896        if (getAllRecordsData.keyRangeData.lowerOpen) {
    19011897            if (getAllRecordsData.keyRangeData.upperOpen)
    1902                 return lowerOpenUpperOpenKey.get();
    1903             return lowerOpenUpperClosedKey.get();
     1898                return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKey.get());
     1899            return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKey.get());
    19041900        }
    19051901
    19061902        if (getAllRecordsData.keyRangeData.upperOpen)
    1907             return lowerClosedUpperOpenKey.get();
    1908         return lowerClosedUpperClosedKey.get();
     1903            return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKey.get());
     1904        return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKey.get());
    19091905    }
    19101906
    19111907    if (getAllRecordsData.keyRangeData.lowerOpen) {
    19121908        if (getAllRecordsData.keyRangeData.upperOpen)
    1913             return lowerOpenUpperOpenValue.get();
    1914         return lowerOpenUpperClosedValue.get();
     1909            return cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpenValue.get());
     1910        return cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosedValue.get());
    19151911    }
    19161912
    19171913    if (getAllRecordsData.keyRangeData.upperOpen)
    1918         return lowerClosedUpperOpenValue.get();
    1919     return lowerClosedUpperClosedValue.get();
     1914        return cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpenValue.get());
     1915    return cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosedValue.get());
    19201916}
    19211917
     
    19511947    }
    19521948
    1953     SQLiteStatement sql(*m_sqliteDB, queryForGetAllObjectStoreRecords(getAllRecordsData));
    1954     if (sql.prepare() != SQLITE_OK
    1955         || sql.bindInt64(1, getAllRecordsData.objectStoreIdentifier) != SQLITE_OK
    1956         || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
    1957         || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
     1949    auto* sql = cachedStatementForGetAllObjectStoreRecords(getAllRecordsData);
     1950    if (!sql
     1951        || sql->bindInt64(1, getAllRecordsData.objectStoreIdentifier) != SQLITE_OK
     1952        || sql->bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
     1953        || sql->bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
    19581954        LOG_ERROR("Could not get key range record from object store %" PRIi64 " from Records table (%i) - %s", getAllRecordsData.objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    19591955        return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up record in object store by key range") };
     
    19681964        targetResults = std::numeric_limits<uint32_t>::max();
    19691965
    1970     int sqlResult = sql.step();
     1966    int sqlResult = sql->step();
    19711967    uint32_t returnedResults = 0;
    19721968
     
    19741970        if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values) {
    19751971            Vector<uint8_t> buffer;
    1976             sql.getColumnBlobAsVector(0, buffer);
     1972            sql->getColumnBlobAsVector(0, buffer);
    19771973            ThreadSafeDataBuffer resultBuffer = ThreadSafeDataBuffer::adoptVector(buffer);
    19781974
    1979             auto recordID = sql.getColumnInt64(1);
     1975            auto recordID = sql->getColumnInt64(1);
    19801976
    19811977            ASSERT(recordID);
     
    19911987            Vector<uint8_t> keyData;
    19921988            IDBKeyData key;
    1993             sql.getColumnBlobAsVector(0, keyData);
     1989            sql->getColumnBlobAsVector(0, keyData);
    19941990
    19951991            if (!deserializeIDBKeyData(keyData.data(), keyData.size(), key)) {
     
    20021998
    20031999        ++returnedResults;
    2004         sqlResult = sql.step();
     2000        sqlResult = sql->step();
    20052001    }
    20062002
     
    21272123IDBError SQLiteIDBBackingStore::uncheckedGetKeyGeneratorValue(int64_t objectStoreID, uint64_t& outValue)
    21282124{
    2129     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT currentKey FROM KeyGenerators WHERE objectStoreID = ?;"));
    2130     if (sql.prepare() != SQLITE_OK
    2131         || sql.bindInt64(1, objectStoreID) != SQLITE_OK) {
     2125    auto* sql = cachedStatement(SQL::GetKeyGeneratorValue, ASCIILiteral("SELECT currentKey FROM KeyGenerators WHERE objectStoreID = ?;"));
     2126    if (!sql
     2127        || sql->bindInt64(1, objectStoreID) != SQLITE_OK) {
    21322128        LOG_ERROR("Could not retrieve currentKey from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    21332129        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error getting current key generator value from database") };
    21342130    }
    2135     int result = sql.step();
     2131    int result = sql->step();
    21362132    if (result != SQLITE_ROW) {
    21372133        LOG_ERROR("Could not retreive key generator value for object store, but it should be there.");
     
    21392135    }
    21402136
    2141     int64_t value = sql.getColumnInt64(0);
     2137    int64_t value = sql->getColumnInt64(0);
    21422138    if (value < 0)
    21432139        return { IDBDatabaseException::ConstraintError, "Current key generator value from database is invalid" };
     
    21492145IDBError SQLiteIDBBackingStore::uncheckedSetKeyGeneratorValue(int64_t objectStoreID, uint64_t value)
    21502146{
    2151     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, ?);"));
    2152     if (sql.prepare() != SQLITE_OK
    2153         || sql.bindInt64(1, objectStoreID) != SQLITE_OK
    2154         || sql.bindInt64(2, value) != SQLITE_OK
    2155         || sql.step() != SQLITE_DONE) {
     2147    auto* sql = cachedStatement(SQL::SetKeyGeneratorValue, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, ?);"));
     2148    if (!sql
     2149        || sql->bindInt64(1, objectStoreID) != SQLITE_OK
     2150        || sql->bindInt64(2, value) != SQLITE_OK
     2151        || sql->step() != SQLITE_DONE) {
    21562152        LOG_ERROR("Could not update key generator value (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    21572153        return { IDBDatabaseException::ConstraintError, "Error storing new key generator value in database" };
     
    23572353    if (m_sqliteDB) {
    23582354        m_sqliteDB->close();
    2359         m_sqliteDB = nullptr;
     2355        closeSQLiteDB();
    23602356    }
    23612357
     
    23712367}
    23722368
     2369SQLiteStatement* SQLiteIDBBackingStore::cachedStatement(SQLiteIDBBackingStore::SQL sql, const char* statement)
     2370{
     2371    if (sql >= SQL::Count) {
     2372        LOG_ERROR("Invalid SQL statement ID passed to cachedStatement()");
     2373        return nullptr;
     2374    }
     2375
     2376    if (m_cachedStatements[static_cast<size_t>(sql)]) {
     2377        if (m_cachedStatements[static_cast<size_t>(sql)]->reset() == SQLITE_OK)
     2378            return m_cachedStatements[static_cast<size_t>(sql)].get();
     2379        m_cachedStatements[static_cast<size_t>(sql)] = nullptr;
     2380    }
     2381
     2382    if (m_sqliteDB) {
     2383        m_cachedStatements[static_cast<size_t>(sql)] = std::make_unique<SQLiteStatement>(*m_sqliteDB, statement);
     2384        if (m_cachedStatements[static_cast<size_t>(sql)]->prepare() != SQLITE_OK)
     2385            m_cachedStatements[static_cast<size_t>(sql)] = nullptr;
     2386    }
     2387
     2388    return m_cachedStatements[static_cast<size_t>(sql)].get();
     2389}
     2390
     2391void SQLiteIDBBackingStore::closeSQLiteDB()
     2392{
     2393    for (size_t i = 0; i < static_cast<int>(SQL::Count); ++i)
     2394        m_cachedStatements[i] = nullptr;
     2395
     2396    m_sqliteDB = nullptr;
     2397}
     2398
    23732399} // namespace IDBServer
    23742400} // namespace WebCore
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h

    r208646 r209096  
    4040class IndexKey;
    4141class SQLiteDatabase;
     42class SQLiteStatement;
    4243
    4344namespace IDBServer {
     
    117118    IDBError getAllIndexRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&, IDBGetAllResult& outValue);
    118119
     120    void closeSQLiteDB();
     121
     122    enum class SQL : size_t {
     123        CreateObjectStoreInfo,
     124        CreateObjectStoreKeyGenerator,
     125        DeleteObjectStoreInfo,
     126        DeleteObjectStoreKeyGenerator,
     127        DeleteObjectStoreRecords,
     128        DeleteObjectStoreIndexInfo,
     129        DeleteObjectStoreIndexRecords,
     130        DeleteObjectStoreBlobRecords,
     131        RenameObjectStore,
     132        ClearObjectStoreRecords,
     133        ClearObjectStoreIndexRecords,
     134        CreateIndexInfo,
     135        DeleteIndexInfo,
     136        HasIndexRecord,
     137        PutIndexRecord,
     138        DeleteIndexRecords,
     139        RenameIndex,
     140        KeyExistsInObjectStore,
     141        GetUnusedBlobFilenames,
     142        DeleteUnusedBlobs,
     143        GetObjectStoreRecordID,
     144        DeleteBlobRecord,
     145        DeleteObjectStoreRecord,
     146        DeleteObjectStoreIndexRecord,
     147        AddObjectStoreRecord,
     148        AddBlobRecord,
     149        BlobFilenameForBlobURL,
     150        AddBlobFilename,
     151        GetBlobURL,
     152        GetKeyGeneratorValue,
     153        SetKeyGeneratorValue,
     154        GetAllKeyRecordsLowerOpenUpperOpen,
     155        GetAllKeyRecordsLowerOpenUpperClosed,
     156        GetAllKeyRecordsLowerClosedUpperOpen,
     157        GetAllKeyRecordsLowerClosedUpperClosed,
     158        GetValueRecordsLowerOpenUpperOpen,
     159        GetValueRecordsLowerOpenUpperClosed,
     160        GetValueRecordsLowerClosedUpperOpen,
     161        GetValueRecordsLowerClosedUpperClosed,
     162        Count
     163    };
     164
     165    SQLiteStatement* cachedStatement(SQL, const char*);
     166    SQLiteStatement* cachedStatementForGetAllObjectStoreRecords(const IDBGetAllRecordsData&);
     167
     168    std::unique_ptr<SQLiteStatement> m_cachedStatements[static_cast<int>(SQL::Count)];
     169
    119170    JSC::VM& vm();
    120171    JSC::JSGlobalObject& globalObject();
Note: See TracChangeset for help on using the changeset viewer.