Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / SQLiteIDBBackingStore.cpp
1 /*
2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SQLiteIDBBackingStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "FileSystem.h"
32 #include "IDBBindingUtilities.h"
33 #include "IDBGetAllRecordsData.h"
34 #include "IDBGetAllResult.h"
35 #include "IDBGetRecordData.h"
36 #include "IDBGetResult.h"
37 #include "IDBIterateCursorData.h"
38 #include "IDBKeyData.h"
39 #include "IDBObjectStoreInfo.h"
40 #include "IDBSerialization.h"
41 #include "IDBTransactionInfo.h"
42 #include "IDBValue.h"
43 #include "IndexKey.h"
44 #include "Logging.h"
45 #include "SQLiteDatabase.h"
46 #include "SQLiteFileSystem.h"
47 #include "SQLiteIDBCursor.h"
48 #include "SQLiteStatement.h"
49 #include "SQLiteTransaction.h"
50 #include "ThreadSafeDataBuffer.h"
51 #include <JavaScriptCore/AuxiliaryBarrierInlines.h>
52 #include <JavaScriptCore/HeapInlines.h>
53 #include <JavaScriptCore/JSCJSValueInlines.h>
54 #include <JavaScriptCore/JSGlobalObject.h>
55 #include <JavaScriptCore/StrongInlines.h>
56 #include <JavaScriptCore/StructureInlines.h>
57 #include <wtf/NeverDestroyed.h>
58
59 namespace WebCore {
60 using namespace JSC;
61 namespace IDBServer {
62
63 // Current version of the metadata schema being used in the metadata database.
64 static const int currentMetadataVersion = 1;
65
66 static int idbKeyCollate(int aLength, const void* aBuffer, int bLength, const void* bBuffer)
67 {
68     IDBKeyData a, b;
69     if (!deserializeIDBKeyData(static_cast<const uint8_t*>(aBuffer), aLength, a)) {
70         LOG_ERROR("Unable to deserialize key A in collation function.");
71
72         // There's no way to indicate an error to SQLite - we have to return a sorting decision.
73         // We arbitrarily choose "A > B"
74         return 1;
75     }
76     if (!deserializeIDBKeyData(static_cast<const uint8_t*>(bBuffer), bLength, b)) {
77         LOG_ERROR("Unable to deserialize key B in collation function.");
78
79         // There's no way to indicate an error to SQLite - we have to return a sorting decision.
80         // We arbitrarily choose "A > B"
81         return 1;
82     }
83
84     return a.compare(b);
85 }
86
87 static const String v1RecordsTableSchema(const String& tableName)
88 {
89     return makeString("CREATE TABLE ", tableName, " (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value NOT NULL ON CONFLICT FAIL)");
90 }
91
92 static const String& v1RecordsTableSchema()
93 {
94     static NeverDestroyed<WTF::String> v1RecordsTableSchemaString(v1RecordsTableSchema("Records"));
95     return v1RecordsTableSchemaString;
96 }
97
98 static const String& v1RecordsTableSchemaAlternate()
99 {
100     static NeverDestroyed<WTF::String> v1RecordsTableSchemaString(v1RecordsTableSchema("\"Records\""));
101     return v1RecordsTableSchemaString;
102 }
103
104 static const String v2RecordsTableSchema(const String& tableName)
105 {
106     return makeString("CREATE TABLE ", tableName, " (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value NOT NULL ON CONFLICT FAIL)");
107 }
108
109 static const String& v2RecordsTableSchema()
110 {
111     static NeverDestroyed<WTF::String> v2RecordsTableSchemaString(v2RecordsTableSchema("Records"));
112     return v2RecordsTableSchemaString;
113 }
114
115 static const String& v2RecordsTableSchemaAlternate()
116 {
117     static NeverDestroyed<WTF::String> v2RecordsTableSchemaString(v2RecordsTableSchema("\"Records\""));
118     return v2RecordsTableSchemaString;
119 }
120
121 static const String v3RecordsTableSchema(const String& tableName)
122 {
123     return makeString("CREATE TABLE ", tableName, " (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value NOT NULL ON CONFLICT FAIL, recordID INTEGER PRIMARY KEY)");
124 }
125
126 static const String& v3RecordsTableSchema()
127 {
128     static NeverDestroyed<WTF::String> v3RecordsTableSchemaString(v3RecordsTableSchema("Records"));
129     return v3RecordsTableSchemaString;
130 }
131
132 static const String& v3RecordsTableSchemaAlternate()
133 {
134     static NeverDestroyed<WTF::String> v3RecordsTableSchemaString(v3RecordsTableSchema("\"Records\""));
135     return v3RecordsTableSchemaString;
136 }
137
138 static const String v1IndexRecordsTableSchema(const String& tableName)
139 {
140     return makeString("CREATE TABLE ", tableName, " (indexID INTEGER NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value NOT NULL ON CONFLICT FAIL)");
141 }
142
143 static const String& v1IndexRecordsTableSchema()
144 {
145     static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("IndexRecords"));
146     return v1IndexRecordsTableSchemaString;
147 }
148
149 static const String& v1IndexRecordsTableSchemaAlternate()
150 {
151     static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("\"IndexRecords\""));
152     return v1IndexRecordsTableSchemaString;
153 }
154
155 static const String v2IndexRecordsTableSchema(const String& tableName)
156 {
157     return makeString("CREATE TABLE ", tableName, " (indexID INTEGER NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL)");
158 }
159
160 static const String& v2IndexRecordsTableSchema()
161 {
162     static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("IndexRecords"));
163     return v2IndexRecordsTableSchemaString;
164 }
165
166 static const String& v2IndexRecordsTableSchemaAlternate()
167 {
168     static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("\"IndexRecords\""));
169     return v2IndexRecordsTableSchemaString;
170 }
171
172 static const String v3IndexRecordsTableSchema(const String& tableName)
173 {
174     return makeString("CREATE TABLE ", tableName, " (indexID INTEGER NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, objectStoreRecordID INTEGER NOT NULL ON CONFLICT FAIL)");
175 }
176
177 static const String v3IndexRecordsTableSchema()
178 {
179     static NeverDestroyed<WTF::String> indexRecordsTableSchemaString = v3IndexRecordsTableSchema("IndexRecords");
180     return indexRecordsTableSchemaString;
181 }
182
183 static const String v3IndexRecordsTableSchemaAlternate()
184 {
185     static NeverDestroyed<WTF::String> indexRecordsTableSchemaString = v3IndexRecordsTableSchema("\"IndexRecords\"");
186     return indexRecordsTableSchemaString;
187 }
188
189 static const String& v1IndexRecordsIndexSchema()
190 {
191     static NeverDestroyed<WTF::String> indexRecordsIndexSchemaString("CREATE INDEX IndexRecordsIndex ON IndexRecords (key)");
192     return indexRecordsIndexSchemaString;
193 }
194
195 static const String blobRecordsTableSchema(const String& tableName)
196 {
197     return makeString("CREATE TABLE ", tableName, " (objectStoreRow INTEGER NOT NULL ON CONFLICT FAIL, blobURL TEXT NOT NULL ON CONFLICT FAIL)");
198 }
199
200 static const String& blobRecordsTableSchema()
201 {
202     static NeverDestroyed<String> blobRecordsTableSchemaString(blobRecordsTableSchema("BlobRecords"));
203     return blobRecordsTableSchemaString;
204 }
205
206 static const String& blobRecordsTableSchemaAlternate()
207 {
208     static NeverDestroyed<String> blobRecordsTableSchemaString(blobRecordsTableSchema("\"BlobRecords\""));
209     return blobRecordsTableSchemaString;
210 }
211
212 static const String blobFilesTableSchema(const String& tableName)
213 {
214     return makeString("CREATE TABLE ", tableName, " (blobURL TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL, fileName TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL)");
215 }
216
217 static const String& blobFilesTableSchema()
218 {
219     static NeverDestroyed<String> blobFilesTableSchemaString(blobFilesTableSchema("BlobFiles"));
220     return blobFilesTableSchemaString;
221 }
222
223 static const String& blobFilesTableSchemaAlternate()
224 {
225     static NeverDestroyed<String> blobFilesTableSchemaString(blobFilesTableSchema("\"BlobFiles\""));
226     return blobFilesTableSchemaString;
227 }
228
229 SQLiteIDBBackingStore::SQLiteIDBBackingStore(const IDBDatabaseIdentifier& identifier, const String& databaseRootDirectory, IDBBackingStoreTemporaryFileHandler& fileHandler)
230     : m_identifier(identifier)
231     , m_temporaryFileHandler(fileHandler)
232 {
233     m_absoluteDatabaseDirectory = identifier.databaseDirectoryRelativeToRoot(databaseRootDirectory);
234 }
235
236 SQLiteIDBBackingStore::~SQLiteIDBBackingStore()
237 {
238     if (m_sqliteDB)
239         closeSQLiteDB();
240
241     if (m_vm) {
242         JSLockHolder locker(m_vm.get());
243         m_globalObject.clear();
244         m_vm = nullptr;
245     }
246 }
247
248
249 void SQLiteIDBBackingStore::initializeVM()
250 {
251     if (!m_vm) {
252         ASSERT(!m_globalObject);
253         m_vm = VM::create();
254
255         JSLockHolder locker(m_vm.get());
256         m_globalObject.set(*m_vm, JSGlobalObject::create(*m_vm, JSGlobalObject::createStructure(*m_vm, jsNull())));
257     }
258 }
259
260 VM& SQLiteIDBBackingStore::vm()
261 {
262     initializeVM();
263     return *m_vm;
264 }
265
266 JSGlobalObject& SQLiteIDBBackingStore::globalObject()
267 {
268     initializeVM();
269     return **m_globalObject;
270 }
271
272 static bool createOrMigrateRecordsTableIfNecessary(SQLiteDatabase& database)
273 {
274     String currentSchema;
275     {
276         // Fetch the schema for an existing records table.
277         SQLiteStatement statement(database, "SELECT type, sql FROM sqlite_master WHERE tbl_name='Records'");
278         if (statement.prepare() != SQLITE_OK) {
279             LOG_ERROR("Unable to prepare statement to fetch schema for the Records table.");
280             return false;
281         }
282
283         int sqliteResult = statement.step();
284
285         // If there is no Records table at all, create it and then bail.
286         if (sqliteResult == SQLITE_DONE) {
287             if (!database.executeCommand(v3RecordsTableSchema())) {
288                 LOG_ERROR("Could not create Records table in database (%i) - %s", database.lastError(), database.lastErrorMsg());
289                 return false;
290             }
291
292             return true;
293         }
294
295         if (sqliteResult != SQLITE_ROW) {
296             LOG_ERROR("Error executing statement to fetch schema for the Records table.");
297             return false;
298         }
299
300         currentSchema = statement.getColumnText(1);
301     }
302
303     ASSERT(!currentSchema.isEmpty());
304
305     // If the schema in the backing store is the current schema, we're done.
306     if (currentSchema == v3RecordsTableSchema() || currentSchema == v3RecordsTableSchemaAlternate())
307         return true;
308
309     // If the record table is not the current schema then it must be one of the previous schemas.
310     // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
311     if (currentSchema != v1RecordsTableSchema() && currentSchema != v1RecordsTableSchemaAlternate()
312         && currentSchema != v2RecordsTableSchema() && currentSchema != v2RecordsTableSchemaAlternate())
313         RELEASE_ASSERT_NOT_REACHED();
314
315     SQLiteTransaction transaction(database);
316     transaction.begin();
317
318     // Create a temporary table with the correct schema and migrate all existing content over.
319     if (!database.executeCommand(v3RecordsTableSchema("_Temp_Records"))) {
320         LOG_ERROR("Could not create temporary records table in database (%i) - %s", database.lastError(), database.lastErrorMsg());
321         return false;
322     }
323
324     if (!database.executeCommand("INSERT INTO _Temp_Records (objectStoreID, key, value) SELECT objectStoreID, CAST(key AS TEXT), value FROM Records")) {
325         LOG_ERROR("Could not migrate existing Records content (%i) - %s", database.lastError(), database.lastErrorMsg());
326         return false;
327     }
328
329     if (!database.executeCommand("DROP TABLE Records")) {
330         LOG_ERROR("Could not drop existing Records table (%i) - %s", database.lastError(), database.lastErrorMsg());
331         return false;
332     }
333
334     if (!database.executeCommand("ALTER TABLE _Temp_Records RENAME TO Records")) {
335         LOG_ERROR("Could not rename temporary Records table (%i) - %s", database.lastError(), database.lastErrorMsg());
336         return false;
337     }
338
339     transaction.commit();
340
341     return true;
342 }
343
344 bool SQLiteIDBBackingStore::ensureValidBlobTables()
345 {
346     ASSERT(m_sqliteDB);
347     ASSERT(m_sqliteDB->isOpen());
348
349     String currentSchema;
350     {
351         // Fetch the schema for an existing blob record table.
352         SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='BlobRecords'");
353         if (statement.prepare() != SQLITE_OK) {
354             LOG_ERROR("Unable to prepare statement to fetch schema for the BlobRecords table.");
355             return false;
356         }
357
358         int sqliteResult = statement.step();
359
360         // If there is no BlobRecords table at all, create it..
361         if (sqliteResult == SQLITE_DONE) {
362             if (!m_sqliteDB->executeCommand(blobRecordsTableSchema())) {
363                 LOG_ERROR("Could not create BlobRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
364                 return false;
365             }
366
367             currentSchema = blobRecordsTableSchema();
368         } else if (sqliteResult != SQLITE_ROW) {
369             LOG_ERROR("Error executing statement to fetch schema for the BlobRecords table.");
370             return false;
371         } else
372             currentSchema = statement.getColumnText(1);
373     }
374
375     if (currentSchema != blobRecordsTableSchema() && currentSchema != blobRecordsTableSchemaAlternate()) {
376         LOG_ERROR("Invalid BlobRecords table schema found");
377         return false;
378     }
379
380     {
381         // Fetch the schema for an existing blob file table.
382         SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='BlobFiles'");
383         if (statement.prepare() != SQLITE_OK) {
384             LOG_ERROR("Unable to prepare statement to fetch schema for the BlobFiles table.");
385             return false;
386         }
387
388         int sqliteResult = statement.step();
389
390         // If there is no BlobFiles table at all, create it and then bail.
391         if (sqliteResult == SQLITE_DONE) {
392             if (!m_sqliteDB->executeCommand(blobFilesTableSchema())) {
393                 LOG_ERROR("Could not create BlobFiles table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
394                 return false;
395             }
396
397             return true;
398         }
399
400         if (sqliteResult != SQLITE_ROW) {
401             LOG_ERROR("Error executing statement to fetch schema for the BlobFiles table.");
402             return false;
403         }
404
405         currentSchema = statement.getColumnText(1);
406     }
407
408     if (currentSchema != blobFilesTableSchema() && currentSchema != blobFilesTableSchemaAlternate()) {
409         LOG_ERROR("Invalid BlobFiles table schema found");
410         return false;
411     }
412
413     return true;
414 }
415
416 bool SQLiteIDBBackingStore::ensureValidRecordsTable()
417 {
418     ASSERT(m_sqliteDB);
419     ASSERT(m_sqliteDB->isOpen());
420
421     if (!createOrMigrateRecordsTableIfNecessary(*m_sqliteDB))
422         return false;
423
424     // Whether the updated records table already existed or if it was just created and the data migrated over,
425     // make sure the uniqueness index exists.
426     if (!m_sqliteDB->executeCommand("CREATE UNIQUE INDEX IF NOT EXISTS RecordsIndex ON Records (objectStoreID, key);")) {
427         LOG_ERROR("Could not create RecordsIndex on Records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
428         return false;
429     }
430
431     return true;
432 }
433
434 bool SQLiteIDBBackingStore::ensureValidIndexRecordsTable()
435 {
436     ASSERT(m_sqliteDB);
437     ASSERT(m_sqliteDB->isOpen());
438
439     String currentSchema;
440     {
441         // Fetch the schema for an existing index record table.
442         SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='IndexRecords'");
443         if (statement.prepare() != SQLITE_OK) {
444             LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecords table.");
445             return false;
446         }
447
448         int sqliteResult = statement.step();
449
450         // If there is no IndexRecords table at all, create it and then bail.
451         if (sqliteResult == SQLITE_DONE) {
452             if (!m_sqliteDB->executeCommand(v3IndexRecordsTableSchema())) {
453                 LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
454                 return false;
455             }
456
457             return true;
458         }
459
460         if (sqliteResult != SQLITE_ROW) {
461             LOG_ERROR("Error executing statement to fetch schema for the IndexRecords table.");
462             return false;
463         }
464
465         currentSchema = statement.getColumnText(1);
466     }
467
468     ASSERT(!currentSchema.isEmpty());
469
470     // If the schema in the backing store is the current schema, we're done.
471     if (currentSchema == v3IndexRecordsTableSchema() || currentSchema == v3IndexRecordsTableSchemaAlternate())
472         return true;
473
474     // If the record table is not the current schema then it must be one of the previous schemas.
475     // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
476     if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate()
477         && currentSchema != v2IndexRecordsTableSchema() && currentSchema != v2IndexRecordsTableSchemaAlternate())
478         RELEASE_ASSERT_NOT_REACHED();
479
480     SQLiteTransaction transaction(*m_sqliteDB);
481     transaction.begin();
482
483     // Create a temporary table with the correct schema and migrate all existing content over.
484     if (!m_sqliteDB->executeCommand(v3IndexRecordsTableSchema("_Temp_IndexRecords"))) {
485         LOG_ERROR("Could not create temporary index records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
486         return false;
487     }
488
489     if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT IndexRecords.indexID, IndexRecords.objectStoreID, IndexRecords.key, IndexRecords.value, Records.rowid FROM IndexRecords INNER JOIN Records ON Records.key = IndexRecords.value AND Records.objectStoreID = IndexRecords.objectStoreID")) {
490         LOG_ERROR("Could not migrate existing IndexRecords content (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
491         return false;
492     }
493
494     if (!m_sqliteDB->executeCommand("DROP TABLE IndexRecords")) {
495         LOG_ERROR("Could not drop existing IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
496         return false;
497     }
498
499     if (!m_sqliteDB->executeCommand("ALTER TABLE _Temp_IndexRecords RENAME TO IndexRecords")) {
500         LOG_ERROR("Could not rename temporary IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
501         return false;
502     }
503
504     transaction.commit();
505
506     return true;
507 }
508
509 bool SQLiteIDBBackingStore::ensureValidIndexRecordsIndex()
510 {
511     ASSERT(m_sqliteDB);
512     ASSERT(m_sqliteDB->isOpen());
513
514     String currentSchema;
515     {
516         // Fetch the schema for an existing index record index.
517         SQLiteStatement statement(*m_sqliteDB, "SELECT sql FROM sqlite_master WHERE name='IndexRecordsIndex'");
518         if (statement.prepare() != SQLITE_OK) {
519             LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecordsIndex index.");
520             return false;
521         }
522
523         int sqliteResult = statement.step();
524
525         // If there is no IndexRecordsIndex index at all, create it and then bail.
526         if (sqliteResult == SQLITE_DONE) {
527             if (!m_sqliteDB->executeCommand(v1IndexRecordsIndexSchema())) {
528                 LOG_ERROR("Could not create IndexRecordsIndex index in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
529                 return false;
530             }
531
532             return true;
533         }
534
535         if (sqliteResult != SQLITE_ROW) {
536             LOG_ERROR("Error executing statement to fetch schema for the IndexRecordsIndex index.");
537             return false;
538         }
539
540         currentSchema = statement.getColumnText(0);
541     }
542
543     ASSERT(!currentSchema.isEmpty());
544
545     // If the schema in the backing store is the current schema, we're done.
546     if (currentSchema == v1IndexRecordsIndexSchema())
547         return true;
548
549     // There is currently no outdated schema for the IndexRecordsIndex, so any other existing schema means this database is invalid.
550     return false;
551 }
552
553 std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo()
554 {
555     ASSERT(m_sqliteDB);
556     ASSERT(m_sqliteDB->isOpen());
557
558     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);")) {
559         LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
560         closeSQLiteDB();
561         return nullptr;
562     }
563
564     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);")) {
565         LOG_ERROR("Could not create ObjectStoreInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
566         closeSQLiteDB();
567         return nullptr;
568     }
569
570     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);")) {
571         LOG_ERROR("Could not create IndexInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
572         closeSQLiteDB();
573         return nullptr;
574     }
575
576     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);")) {
577         LOG_ERROR("Could not create KeyGenerators table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
578         closeSQLiteDB();
579         return nullptr;
580     }
581
582     {
583         SQLiteStatement sql(*m_sqliteDB, "INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);"_s);
584         if (sql.prepare() != SQLITE_OK
585             || sql.bindInt(1, currentMetadataVersion) != SQLITE_OK
586             || sql.step() != SQLITE_DONE) {
587             LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
588             closeSQLiteDB();
589             return nullptr;
590         }
591     }
592     {
593         SQLiteStatement sql(*m_sqliteDB, "INSERT INTO IDBDatabaseInfo VALUES ('DatabaseName', ?);"_s);
594         if (sql.prepare() != SQLITE_OK
595             || sql.bindText(1, m_identifier.databaseName()) != SQLITE_OK
596             || sql.step() != SQLITE_DONE) {
597             LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
598             closeSQLiteDB();
599             return nullptr;
600         }
601     }
602     {
603         // Database versions are defined to be a uin64_t in the spec but sqlite3 doesn't support native binding of unsigned integers.
604         // Therefore we'll store the version as a String.
605         SQLiteStatement sql(*m_sqliteDB, "INSERT INTO IDBDatabaseInfo VALUES ('DatabaseVersion', ?);"_s);
606         if (sql.prepare() != SQLITE_OK
607             || sql.bindText(1, String::number(0)) != SQLITE_OK
608             || sql.step() != SQLITE_DONE) {
609             LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
610             closeSQLiteDB();
611             return nullptr;
612         }
613     }
614
615     if (!m_sqliteDB->executeCommand("INSERT INTO IDBDatabaseInfo VALUES ('MaxObjectStoreID', 1);"_s)) {
616         LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
617         closeSQLiteDB();
618         return nullptr;
619     }
620
621     // This initial database info matches the default values we just put into the metadata database.
622     return std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
623 }
624
625 std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseInfo()
626 {
627     ASSERT(m_sqliteDB);
628
629     if (!m_sqliteDB->tableExists("IDBDatabaseInfo"_s))
630         return nullptr;
631
632     String databaseName;
633     {
634         SQLiteStatement sql(*m_sqliteDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseName';");
635         if (sql.isColumnNull(0))
636             return nullptr;
637         databaseName = sql.getColumnText(0);
638         if (databaseName != m_identifier.databaseName()) {
639             LOG_ERROR("Database name in the info database ('%s') does not match the expected name ('%s')", databaseName.utf8().data(), m_identifier.databaseName().utf8().data());
640             return nullptr;
641         }
642     }
643     uint64_t databaseVersion;
644     {
645         SQLiteStatement sql(*m_sqliteDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseVersion';"_s);
646         if (sql.isColumnNull(0))
647             return nullptr;
648         String stringVersion = sql.getColumnText(0);
649         bool ok;
650         databaseVersion = stringVersion.toUInt64Strict(&ok);
651         if (!ok) {
652             LOG_ERROR("Database version on disk ('%s') does not cleanly convert to an unsigned 64-bit integer version", stringVersion.utf8().data());
653             return nullptr;
654         }
655     }
656
657     auto databaseInfo = std::make_unique<IDBDatabaseInfo>(databaseName, databaseVersion);
658
659     {
660         SQLiteStatement sql(*m_sqliteDB, "SELECT id, name, keyPath, autoInc, maxIndexID FROM ObjectStoreInfo;"_s);
661         if (sql.prepare() != SQLITE_OK)
662             return nullptr;
663
664         int result = sql.step();
665         while (result == SQLITE_ROW) {
666             uint64_t objectStoreID = sql.getColumnInt64(0);
667             String objectStoreName = sql.getColumnText(1);
668
669             Vector<char> keyPathBuffer;
670             sql.getColumnBlobAsVector(2, keyPathBuffer);
671
672             std::optional<IDBKeyPath> objectStoreKeyPath;
673             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), objectStoreKeyPath)) {
674                 LOG_ERROR("Unable to extract key path from database");
675                 return nullptr;
676             }
677
678             bool autoIncrement = sql.getColumnInt(3);
679
680             databaseInfo->addExistingObjectStore({ objectStoreID, objectStoreName, WTFMove(objectStoreKeyPath), autoIncrement });
681
682             result = sql.step();
683         }
684
685         if (result != SQLITE_DONE) {
686             LOG_ERROR("Error fetching object store info from database on disk");
687             return nullptr;
688         }
689     }
690
691     {
692         SQLiteStatement sql(*m_sqliteDB, "SELECT id, name, objectStoreID, keyPath, isUnique, multiEntry FROM IndexInfo;"_s);
693         if (sql.prepare() != SQLITE_OK)
694             return nullptr;
695
696         int result = sql.step();
697         while (result == SQLITE_ROW) {
698             uint64_t indexID = sql.getColumnInt64(0);
699             String indexName = sql.getColumnText(1);
700             uint64_t objectStoreID = sql.getColumnInt64(2);
701
702             Vector<char> keyPathBuffer;
703             sql.getColumnBlobAsVector(3, keyPathBuffer);
704
705             std::optional<IDBKeyPath> indexKeyPath;
706             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), indexKeyPath)) {
707                 LOG_ERROR("Unable to extract key path from database");
708                 return nullptr;
709             }
710             if (!indexKeyPath) {
711                 LOG_ERROR("Unable to extract key path from database");
712                 return nullptr;
713             }
714
715             bool unique = sql.getColumnInt(4);
716             bool multiEntry = sql.getColumnInt(5);
717
718             auto objectStore = databaseInfo->infoForExistingObjectStore(objectStoreID);
719             if (!objectStore) {
720                 LOG_ERROR("Found index referring to a non-existant object store");
721                 return nullptr;
722             }
723
724             objectStore->addExistingIndex({ indexID, objectStoreID, indexName, WTFMove(indexKeyPath.value()), unique, multiEntry });
725
726             result = sql.step();
727         }
728
729         if (result != SQLITE_DONE) {
730             LOG_ERROR("Error fetching index info from database on disk");
731             return nullptr;
732         }
733     }
734
735     return databaseInfo;
736 }
737
738 String SQLiteIDBBackingStore::databaseNameFromEncodedFilename(const String& encodedName)
739 {
740     if (encodedName == "%00"_s)
741         return { };
742
743     String partiallyDecoded = encodedName;
744     partiallyDecoded.replace("%2E"_s, "."_s);
745
746     return FileSystem::decodeFromFilename(partiallyDecoded);
747 }
748
749 String SQLiteIDBBackingStore::filenameForDatabaseName() const
750 {
751     ASSERT(!m_identifier.databaseName().isNull());
752
753     if (m_identifier.databaseName().isEmpty())
754         return "%00";
755
756     String filename = FileSystem::encodeForFileName(m_identifier.databaseName());
757     filename.replace('.', "%2E");
758
759     return filename;
760 }
761
762 String SQLiteIDBBackingStore::fullDatabaseDirectory() const
763 {
764     ASSERT(!m_identifier.databaseName().isNull());
765
766     return FileSystem::pathByAppendingComponent(m_absoluteDatabaseDirectory, filenameForDatabaseName());
767 }
768
769 String SQLiteIDBBackingStore::fullDatabasePath() const
770 {
771     ASSERT(!m_identifier.databaseName().isNull());
772
773     return FileSystem::pathByAppendingComponent(fullDatabaseDirectory(), "IndexedDB.sqlite3");
774 }
775
776 IDBError SQLiteIDBBackingStore::getOrEstablishDatabaseInfo(IDBDatabaseInfo& info)
777 {
778     LOG(IndexedDB, "SQLiteIDBBackingStore::getOrEstablishDatabaseInfo - database %s", m_identifier.databaseName().utf8().data());
779
780     if (m_databaseInfo) {
781         info = *m_databaseInfo;
782         return IDBError { };
783     }
784
785     FileSystem::makeAllDirectories(fullDatabaseDirectory());
786     String dbFilename = fullDatabasePath();
787
788     m_sqliteDB = std::make_unique<SQLiteDatabase>();
789     if (!m_sqliteDB->open(dbFilename)) {
790         LOG_ERROR("Failed to open SQLite database at path '%s'", dbFilename.utf8().data());
791         closeSQLiteDB();
792     }
793
794     if (!m_sqliteDB)
795         return IDBError { UnknownError, "Unable to open database file on disk"_s };
796
797     m_sqliteDB->setCollationFunction("IDBKEY", [](int aLength, const void* a, int bLength, const void* b) {
798         return idbKeyCollate(aLength, a, bLength, b);
799     });
800
801     if (!ensureValidRecordsTable()) {
802         LOG_ERROR("Error creating or migrating Records table in database");
803         closeSQLiteDB();
804         return IDBError { UnknownError, "Error creating or migrating Records table in database"_s };
805     }
806
807     if (!ensureValidIndexRecordsTable()) {
808         LOG_ERROR("Error creating or migrating Index Records table in database");
809         closeSQLiteDB();
810         return IDBError { UnknownError, "Error creating or migrating Index Records table in database"_s };
811     }
812
813     if (!ensureValidIndexRecordsIndex()) {
814         LOG_ERROR("Error creating or migrating Index Records index in database");
815         closeSQLiteDB();
816         return IDBError { UnknownError, "Error creating or migrating Index Records index in database"_s };
817     }
818
819     if (!ensureValidBlobTables()) {
820         LOG_ERROR("Error creating or confirming Blob Records tables in database");
821         closeSQLiteDB();
822         return IDBError { UnknownError, "Error creating or confirming Blob Records tables in database"_s };
823     }
824
825     auto databaseInfo = extractExistingDatabaseInfo();
826     if (!databaseInfo)
827         databaseInfo = createAndPopulateInitialDatabaseInfo();
828
829     if (!databaseInfo) {
830         LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());
831         closeSQLiteDB();
832         return IDBError { UnknownError, "Unable to establish IDB database file"_s };
833     }
834
835     m_databaseInfo = WTFMove(databaseInfo);
836     info = *m_databaseInfo;
837     return IDBError { };
838 }
839
840 IDBError SQLiteIDBBackingStore::beginTransaction(const IDBTransactionInfo& info)
841 {
842     LOG(IndexedDB, "SQLiteIDBBackingStore::beginTransaction - %s", info.identifier().loggingString().utf8().data());
843
844     ASSERT(m_sqliteDB);
845     ASSERT(m_sqliteDB->isOpen());
846     ASSERT(m_databaseInfo);
847
848     auto addResult = m_transactions.add(info.identifier(), nullptr);
849     if (!addResult.isNewEntry) {
850         LOG_ERROR("Attempt to establish transaction identifier that already exists");
851         return IDBError { UnknownError, "Attempt to establish transaction identifier that already exists"_s };
852     }
853
854     addResult.iterator->value = std::make_unique<SQLiteIDBTransaction>(*this, info);
855
856     auto error = addResult.iterator->value->begin(*m_sqliteDB);
857     if (error.isNull() && info.mode() == IDBTransactionMode::Versionchange) {
858         m_originalDatabaseInfoBeforeVersionChange = std::make_unique<IDBDatabaseInfo>(*m_databaseInfo);
859
860         SQLiteStatement sql(*m_sqliteDB, "UPDATE IDBDatabaseInfo SET value = ? where key = 'DatabaseVersion';"_s);
861         if (sql.prepare() != SQLITE_OK
862             || sql.bindText(1, String::number(info.newVersion())) != SQLITE_OK
863             || sql.step() != SQLITE_DONE)
864             error = IDBError { UnknownError, "Failed to store new database version in database"_s };
865     }
866
867     return error;
868 }
869
870 IDBError SQLiteIDBBackingStore::abortTransaction(const IDBResourceIdentifier& identifier)
871 {
872     LOG(IndexedDB, "SQLiteIDBBackingStore::abortTransaction - %s", identifier.loggingString().utf8().data());
873
874     ASSERT(m_sqliteDB);
875     ASSERT(m_sqliteDB->isOpen());
876
877     auto transaction = m_transactions.take(identifier);
878     if (!transaction) {
879         LOG_ERROR("Attempt to commit a transaction that hasn't been established");
880         return IDBError { UnknownError, "Attempt to abort a transaction that hasn't been established"_s };
881     }
882
883     if (transaction->mode() == IDBTransactionMode::Versionchange && m_originalDatabaseInfoBeforeVersionChange)
884         m_databaseInfo = WTFMove(m_originalDatabaseInfoBeforeVersionChange);
885
886     return transaction->abort();
887 }
888
889 IDBError SQLiteIDBBackingStore::commitTransaction(const IDBResourceIdentifier& identifier)
890 {
891     LOG(IndexedDB, "SQLiteIDBBackingStore::commitTransaction - %s", identifier.loggingString().utf8().data());
892
893     ASSERT(m_sqliteDB);
894     ASSERT(m_sqliteDB->isOpen());
895
896     auto transaction = m_transactions.take(identifier);
897     if (!transaction) {
898         LOG_ERROR("Attempt to commit a transaction that hasn't been established");
899         return IDBError { UnknownError, "Attempt to commit a transaction that hasn't been established"_s };
900     }
901
902     auto error = transaction->commit();
903     if (!error.isNull()) {
904         if (transaction->mode() == IDBTransactionMode::Versionchange) {
905             ASSERT(m_originalDatabaseInfoBeforeVersionChange);
906             m_databaseInfo = WTFMove(m_originalDatabaseInfoBeforeVersionChange);
907         }
908     } else
909         m_originalDatabaseInfoBeforeVersionChange = nullptr;
910
911     return error;
912 }
913
914 IDBError SQLiteIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
915 {
916     LOG(IndexedDB, "SQLiteIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
917
918     ASSERT(m_sqliteDB);
919     ASSERT(m_sqliteDB->isOpen());
920
921     auto* transaction = m_transactions.get(transactionIdentifier);
922     if (!transaction || !transaction->inProgress()) {
923         LOG_ERROR("Attempt to create an object store without an in-progress transaction");
924         return IDBError { UnknownError, "Attempt to create an object store without an in-progress transaction"_s };
925     }
926     if (transaction->mode() != IDBTransactionMode::Versionchange) {
927         LOG_ERROR("Attempt to create an object store in a non-version-change transaction");
928         return IDBError { UnknownError, "Attempt to create an object store in a non-version-change transaction"_s };
929     }
930
931     RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(info.keyPath());
932     if (!keyPathBlob) {
933         LOG_ERROR("Unable to serialize IDBKeyPath to save in database for new object store");
934         return IDBError { UnknownError, "Unable to serialize IDBKeyPath to save in database for new object store"_s };
935     }
936
937     {
938         auto* sql = cachedStatement(SQL::CreateObjectStoreInfo, "INSERT INTO ObjectStoreInfo VALUES (?, ?, ?, ?, ?);"_s);
939         if (!sql
940             || sql->bindInt64(1, info.identifier()) != SQLITE_OK
941             || sql->bindText(2, info.name()) != SQLITE_OK
942             || sql->bindBlob(3, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
943             || sql->bindInt(4, info.autoIncrement()) != SQLITE_OK
944             || sql->bindInt64(5, info.maxIndexID()) != SQLITE_OK
945             || sql->step() != SQLITE_DONE) {
946             LOG_ERROR("Could not add object store '%s' to ObjectStoreInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
947             return IDBError { UnknownError, "Could not create object store"_s };
948         }
949     }
950
951     {
952         auto* sql = cachedStatement(SQL::CreateObjectStoreKeyGenerator, "INSERT INTO KeyGenerators VALUES (?, 0);"_s);
953         if (!sql
954             || sql->bindInt64(1, info.identifier()) != SQLITE_OK
955             || sql->step() != SQLITE_DONE) {
956             LOG_ERROR("Could not seed initial key generator value for ObjectStoreInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
957             return IDBError { UnknownError, "Could not seed initial key generator value for object store"_s };
958         }
959     }
960
961     m_databaseInfo->addExistingObjectStore(info);
962
963     return IDBError { };
964 }
965
966 IDBError SQLiteIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
967 {
968     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteObjectStore - object store %" PRIu64, objectStoreIdentifier);
969
970     ASSERT(m_sqliteDB);
971     ASSERT(m_sqliteDB->isOpen());
972
973     auto* transaction = m_transactions.get(transactionIdentifier);
974     if (!transaction || !transaction->inProgress()) {
975         LOG_ERROR("Attempt to delete an object store without an in-progress transaction");
976         return IDBError { UnknownError, "Attempt to delete an object store without an in-progress transaction"_s };
977     }
978     if (transaction->mode() != IDBTransactionMode::Versionchange) {
979         LOG_ERROR("Attempt to delete an object store in a non-version-change transaction");
980         return IDBError { UnknownError, "Attempt to delete an object store in a non-version-change transaction"_s };
981     }
982
983     // Delete the ObjectStore record
984     {
985         auto* sql = cachedStatement(SQL::DeleteObjectStoreInfo, "DELETE FROM ObjectStoreInfo WHERE id = ?;"_s);
986         if (!sql
987             || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
988             || sql->step() != SQLITE_DONE) {
989             LOG_ERROR("Could not delete object store id %" PRIi64 " from ObjectStoreInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
990             return IDBError { UnknownError, "Could not delete object store"_s };
991         }
992     }
993
994     // Delete the ObjectStore's key generator record if there is one.
995     {
996         auto* sql = cachedStatement(SQL::DeleteObjectStoreKeyGenerator, "DELETE FROM KeyGenerators WHERE objectStoreID = ?;"_s);
997         if (!sql
998             || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
999             || sql->step() != SQLITE_DONE) {
1000             LOG_ERROR("Could not delete object store from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1001             return IDBError { UnknownError, "Could not delete key generator for deleted object store"_s };
1002         }
1003     }
1004
1005     // Delete all associated records
1006     {
1007         auto* sql = cachedStatement(SQL::DeleteObjectStoreRecords, "DELETE FROM Records WHERE objectStoreID = ?;"_s);
1008         if (!sql
1009             || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
1010             || sql->step() != SQLITE_DONE) {
1011             LOG_ERROR("Could not delete records for object store %" PRIi64 " (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1012             return IDBError { UnknownError, "Could not delete records for deleted object store"_s };
1013         }
1014     }
1015
1016     // Delete all associated Indexes
1017     {
1018         auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexInfo, "DELETE FROM IndexInfo WHERE objectStoreID = ?;"_s);
1019         if (!sql
1020             || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
1021             || sql->step() != SQLITE_DONE) {
1022             LOG_ERROR("Could not delete index from IndexInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1023             return IDBError { UnknownError, "Could not delete IDBIndex for deleted object store"_s };
1024         }
1025     }
1026
1027     // Delete all associated Index records
1028     {
1029         auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecords, "DELETE FROM IndexRecords WHERE objectStoreID = ?;"_s);
1030         if (!sql
1031             || sql->bindInt64(1, objectStoreIdentifier) != SQLITE_OK
1032             || sql->step() != SQLITE_DONE) {
1033             LOG_ERROR("Could not delete index records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1034             return IDBError { UnknownError, "Could not delete IDBIndex records for deleted object store"_s };
1035         }
1036     }
1037
1038     // Delete all unused Blob URL records.
1039     {
1040         auto* sql = cachedStatement(SQL::DeleteObjectStoreBlobRecords, "DELETE FROM BlobRecords WHERE objectStoreRow NOT IN (SELECT recordID FROM Records)"_s);
1041         if (!sql
1042             || sql->step() != SQLITE_DONE) {
1043             LOG_ERROR("Could not delete Blob URL records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1044             return IDBError { UnknownError, "Could not delete stored blob records for deleted object store"_s };
1045         }
1046     }
1047
1048     // Delete all unused Blob File records.
1049     auto error = deleteUnusedBlobFileRecords(*transaction);
1050     if (!error.isNull())
1051         return error;
1052
1053     m_databaseInfo->deleteObjectStore(objectStoreIdentifier);
1054
1055     return IDBError { };
1056 }
1057
1058 IDBError SQLiteIDBBackingStore::renameObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName)
1059 {
1060     LOG(IndexedDB, "SQLiteIDBBackingStore::renameObjectStore - object store %" PRIu64, objectStoreIdentifier);
1061
1062     ASSERT(m_sqliteDB);
1063     ASSERT(m_sqliteDB->isOpen());
1064
1065     auto* transaction = m_transactions.get(transactionIdentifier);
1066     if (!transaction || !transaction->inProgress()) {
1067         LOG_ERROR("Attempt to rename an object store without an in-progress transaction");
1068         return IDBError { UnknownError, "Attempt to rename an object store without an in-progress transaction"_s };
1069     }
1070     if (transaction->mode() != IDBTransactionMode::Versionchange) {
1071         LOG_ERROR("Attempt to rename an object store in a non-version-change transaction");
1072         return IDBError { UnknownError, "Attempt to rename an object store in a non-version-change transaction"_s };
1073     }
1074
1075     {
1076         auto* sql = cachedStatement(SQL::RenameObjectStore, "UPDATE ObjectStoreInfo SET name = ? WHERE id = ?;"_s);
1077         if (!sql
1078             || sql->bindText(1, newName) != SQLITE_OK
1079             || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1080             || sql->step() != SQLITE_DONE) {
1081             LOG_ERROR("Could not update name for object store id %" PRIi64 " in ObjectStoreInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1082             return IDBError { UnknownError, "Could not rename object store"_s };
1083         }
1084     }
1085
1086     m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
1087
1088     return IDBError { };
1089 }
1090
1091 IDBError SQLiteIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID)
1092 {
1093     LOG(IndexedDB, "SQLiteIDBBackingStore::clearObjectStore - object store %" PRIu64, objectStoreID);
1094
1095     ASSERT(m_sqliteDB);
1096     ASSERT(m_sqliteDB->isOpen());
1097
1098     auto* transaction = m_transactions.get(transactionIdentifier);
1099     if (!transaction || !transaction->inProgress()) {
1100         LOG_ERROR("Attempt to clear an object store without an in-progress transaction");
1101         return IDBError { UnknownError, "Attempt to clear an object store without an in-progress transaction"_s };
1102     }
1103     if (transaction->mode() == IDBTransactionMode::Readonly) {
1104         LOG_ERROR("Attempt to clear an object store in a read-only transaction");
1105         return IDBError { UnknownError, "Attempt to clear an object store in a read-only transaction"_s };
1106     }
1107
1108     {
1109         auto* sql = cachedStatement(SQL::ClearObjectStoreRecords, "DELETE FROM Records WHERE objectStoreID = ?;"_s);
1110         if (!sql
1111             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1112             || sql->step() != SQLITE_DONE) {
1113             LOG_ERROR("Could not clear records from object store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1114             return IDBError { UnknownError, "Unable to clear object store"_s };
1115         }
1116     }
1117
1118     {
1119         auto* sql = cachedStatement(SQL::ClearObjectStoreIndexRecords, "DELETE FROM IndexRecords WHERE objectStoreID = ?;"_s);
1120         if (!sql
1121             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1122             || sql->step() != SQLITE_DONE) {
1123             LOG_ERROR("Could not delete records from index record store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1124             return IDBError { UnknownError, "Unable to delete index records while clearing object store"_s };
1125         }
1126     }
1127
1128     transaction->notifyCursorsOfChanges(objectStoreID);
1129
1130     return IDBError { };
1131 }
1132
1133 IDBError SQLiteIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
1134 {
1135     LOG(IndexedDB, "SQLiteIDBBackingStore::createIndex - ObjectStore %" PRIu64 ", Index %" PRIu64, info.objectStoreIdentifier(), info.identifier());
1136     ASSERT(m_sqliteDB);
1137     ASSERT(m_sqliteDB->isOpen());
1138
1139     auto* transaction = m_transactions.get(transactionIdentifier);
1140     if (!transaction || !transaction->inProgress()) {
1141         LOG_ERROR("Attempt to create an index without an in-progress transaction");
1142         return IDBError { UnknownError, "Attempt to create an index without an in-progress transaction"_s };
1143     }
1144     if (transaction->mode() != IDBTransactionMode::Versionchange) {
1145         LOG_ERROR("Attempt to create an index in a non-version-change transaction");
1146         return IDBError { UnknownError, "Attempt to create an index in a non-version-change transaction"_s };
1147     }
1148
1149     RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(info.keyPath());
1150     if (!keyPathBlob) {
1151         LOG_ERROR("Unable to serialize IDBKeyPath to save in database");
1152         return IDBError { UnknownError, "Unable to serialize IDBKeyPath to create index in database"_s };
1153     }
1154
1155     auto* sql = cachedStatement(SQL::CreateIndexInfo, "INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);"_s);
1156     if (!sql
1157         || sql->bindInt64(1, info.identifier()) != SQLITE_OK
1158         || sql->bindText(2, info.name()) != SQLITE_OK
1159         || sql->bindInt64(3, info.objectStoreIdentifier()) != SQLITE_OK
1160         || sql->bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
1161         || sql->bindInt(5, info.unique()) != SQLITE_OK
1162         || sql->bindInt(6, info.multiEntry()) != SQLITE_OK
1163         || sql->step() != SQLITE_DONE) {
1164         LOG_ERROR("Could not add index '%s' to IndexInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1165         return IDBError { UnknownError, "Unable to create index in database"_s };
1166     }
1167
1168     // Write index records for any records that already exist in this object store.
1169
1170     auto cursor = transaction->maybeOpenBackingStoreCursor(info.objectStoreIdentifier(), 0, IDBKeyRangeData::allKeys());
1171
1172     if (!cursor) {
1173         LOG_ERROR("Cannot open cursor to populate indexes in database");
1174         return IDBError { UnknownError, "Unable to populate indexes in database"_s };
1175     }
1176
1177     while (!cursor->currentKey().isNull()) {
1178         auto& key = cursor->currentKey();
1179         auto* value = cursor->currentValue();
1180         ThreadSafeDataBuffer valueBuffer = value ? value->data() : ThreadSafeDataBuffer();
1181
1182         ASSERT(cursor->currentRecordRowID());
1183
1184         IDBError error = updateOneIndexForAddRecord(info, key, valueBuffer, cursor->currentRecordRowID());
1185         if (!error.isNull()) {
1186             auto* sql = cachedStatement(SQL::DeleteIndexInfo, "DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"_s);
1187             if (!sql
1188                 || sql->bindInt64(1, info.identifier()) != SQLITE_OK
1189                 || sql->bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
1190                 || sql->step() != SQLITE_DONE) {
1191                 LOG_ERROR("Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database");
1192                 return IDBError { UnknownError, "Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database"_s };
1193             }
1194
1195             return error;
1196         }
1197
1198         if (!cursor->advance(1)) {
1199             LOG_ERROR("Error advancing cursor while indexing existing records for new index.");
1200             return IDBError { UnknownError, "Error advancing cursor while indexing existing records for new index"_s };
1201         }
1202     }
1203
1204     auto* objectStore = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
1205     ASSERT(objectStore);
1206     objectStore->addExistingIndex(info);
1207
1208     return IDBError { };
1209 }
1210
1211 IDBError SQLiteIDBBackingStore::uncheckedHasIndexRecord(const IDBIndexInfo& info, const IDBKeyData& indexKey, bool& hasRecord)
1212 {
1213     hasRecord = false;
1214
1215     RefPtr<SharedBuffer> indexKeyBuffer = serializeIDBKeyData(indexKey);
1216     if (!indexKeyBuffer) {
1217         LOG_ERROR("Unable to serialize index key to be stored in the database");
1218         return IDBError { UnknownError, "Unable to serialize IDBKey to check for index record in database"_s };
1219     }
1220
1221     auto* sql = cachedStatement(SQL::HasIndexRecord, "SELECT rowid FROM IndexRecords WHERE indexID = ? AND objectStoreID = ? AND key = CAST(? AS TEXT);"_s);
1222     if (!sql
1223         || sql->bindInt64(1, info.identifier()) != SQLITE_OK
1224         || sql->bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
1225         || sql->bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK) {
1226         LOG_ERROR("Error checking for index record in database");
1227         return IDBError { UnknownError, "Error checking for index record in database"_s };
1228     }
1229
1230     int sqlResult = sql->step();
1231     if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
1232         return IDBError { };
1233
1234     if (sqlResult != SQLITE_ROW) {
1235         // There was an error fetching the record from the database.
1236         LOG_ERROR("Could not check if key exists in index (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1237         return IDBError { UnknownError, "Error checking for existence of IDBKey in index"_s };
1238     }
1239
1240     hasRecord = true;
1241     return IDBError { };
1242 }
1243
1244 IDBError SQLiteIDBBackingStore::uncheckedPutIndexKey(const IDBIndexInfo& info, const IDBKeyData& key, const IndexKey& indexKey, int64_t recordID)
1245 {
1246     LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexKey - (%" PRIu64 ") %s, %s", info.identifier(), key.loggingString().utf8().data(), indexKey.asOneKey().loggingString().utf8().data());
1247
1248     Vector<IDBKeyData> indexKeys;
1249     if (info.multiEntry())
1250         indexKeys = indexKey.multiEntry();
1251     else
1252         indexKeys.append(indexKey.asOneKey());
1253
1254     if (info.unique()) {
1255         bool hasRecord;
1256         IDBError error;
1257         for (auto& indexKey : indexKeys) {
1258             if (!indexKey.isValid())
1259                 continue;
1260             error = uncheckedHasIndexRecord(info, indexKey, hasRecord);
1261             if (!error.isNull())
1262                 return error;
1263             if (hasRecord)
1264                 return IDBError(ConstraintError);
1265         }
1266     }
1267
1268     for (auto& indexKey : indexKeys) {
1269         if (!indexKey.isValid())
1270             continue;
1271         auto error = uncheckedPutIndexRecord(info.objectStoreIdentifier(), info.identifier(), key, indexKey, recordID);
1272         if (!error.isNull()) {
1273             LOG_ERROR("Unable to put index record for newly created index");
1274             return error;
1275         }
1276     }
1277
1278     return IDBError { };
1279 }
1280
1281 IDBError SQLiteIDBBackingStore::uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData& keyValue, const WebCore::IDBKeyData& indexKey, int64_t recordID)
1282 {
1283     LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexRecord - %s, %s", keyValue.loggingString().utf8().data(), indexKey.loggingString().utf8().data());
1284
1285     RefPtr<SharedBuffer> indexKeyBuffer = serializeIDBKeyData(indexKey);
1286     if (!indexKeyBuffer) {
1287         LOG_ERROR("Unable to serialize index key to be stored in the database");
1288         return IDBError { UnknownError, "Unable to serialize index key to be stored in the database"_s };
1289     }
1290
1291     RefPtr<SharedBuffer> valueBuffer = serializeIDBKeyData(keyValue);
1292     if (!valueBuffer) {
1293         LOG_ERROR("Unable to serialize the value to be stored in the database");
1294         return IDBError { UnknownError, "Unable to serialize value to be stored in the database"_s };
1295     }
1296
1297     {
1298         auto* sql = cachedStatement(SQL::PutIndexRecord, "INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT), ?);"_s);
1299         if (!sql
1300             || sql->bindInt64(1, indexID) != SQLITE_OK
1301             || sql->bindInt64(2, objectStoreID) != SQLITE_OK
1302             || sql->bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK
1303             || sql->bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLITE_OK
1304             || sql->bindInt64(5, recordID) != SQLITE_OK
1305             || sql->step() != SQLITE_DONE) {
1306             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());
1307             return IDBError { UnknownError, "Error putting index record into database"_s };
1308         }
1309     }
1310
1311     return IDBError { };
1312 }
1313
1314
1315 IDBError SQLiteIDBBackingStore::deleteIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
1316 {
1317     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteIndex - object store %" PRIu64, objectStoreIdentifier);
1318
1319     ASSERT(m_sqliteDB);
1320     ASSERT(m_sqliteDB->isOpen());
1321
1322     auto* transaction = m_transactions.get(transactionIdentifier);
1323     if (!transaction || !transaction->inProgress()) {
1324         LOG_ERROR("Attempt to delete index without an in-progress transaction");
1325         return IDBError { UnknownError, "Attempt to delete index without an in-progress transaction"_s };
1326     }
1327
1328     if (transaction->mode() != IDBTransactionMode::Versionchange) {
1329         LOG_ERROR("Attempt to delete index during a non-version-change transaction");
1330         return IDBError { UnknownError, "Attempt to delete index during a non-version-change transaction"_s };
1331     }
1332
1333     {
1334         auto* sql = cachedStatement(SQL::DeleteIndexInfo, "DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"_s);
1335         if (!sql
1336             || sql->bindInt64(1, indexIdentifier) != SQLITE_OK
1337             || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1338             || sql->step() != SQLITE_DONE) {
1339             LOG_ERROR("Could not delete index id %" PRIi64 " from IndexInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1340             return IDBError { UnknownError, "Error deleting index from database"_s };
1341         }
1342     }
1343
1344     {
1345         auto* sql = cachedStatement(SQL::DeleteIndexRecords, "DELETE FROM IndexRecords WHERE indexID = ? AND objectStoreID = ?;"_s);
1346         if (!sql
1347             || sql->bindInt64(1, indexIdentifier) != SQLITE_OK
1348             || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1349             || sql->step() != SQLITE_DONE) {
1350             LOG_ERROR("Could not delete index records for index id %" PRIi64 " from IndexRecords table (%i) - %s", indexIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1351             return IDBError { UnknownError, "Error deleting index records from database"_s };
1352         }
1353     }
1354
1355     auto* objectStore = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
1356     ASSERT(objectStore);
1357     objectStore->deleteIndex(indexIdentifier);
1358
1359     return IDBError { };
1360 }
1361
1362 IDBError SQLiteIDBBackingStore::renameIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
1363 {
1364     LOG(IndexedDB, "SQLiteIDBBackingStore::renameIndex - object store %" PRIu64 ", index %" PRIu64, objectStoreIdentifier, indexIdentifier);
1365
1366     ASSERT(m_sqliteDB);
1367     ASSERT(m_sqliteDB->isOpen());
1368
1369     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
1370     if (!objectStoreInfo)
1371         return IDBError { UnknownError, "Could not rename index"_s };
1372
1373     auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
1374     if (!indexInfo)
1375         return IDBError { UnknownError, "Could not rename index"_s };
1376
1377     auto* transaction = m_transactions.get(transactionIdentifier);
1378     if (!transaction || !transaction->inProgress()) {
1379         LOG_ERROR("Attempt to rename an index without an in-progress transaction");
1380         return IDBError { UnknownError, "Attempt to rename an index without an in-progress transaction"_s };
1381     }
1382
1383     if (transaction->mode() != IDBTransactionMode::Versionchange) {
1384         LOG_ERROR("Attempt to rename an index in a non-version-change transaction");
1385         return IDBError { UnknownError, "Attempt to rename an index in a non-version-change transaction"_s };
1386     }
1387
1388     {
1389         auto* sql = cachedStatement(SQL::RenameIndex, "UPDATE IndexInfo SET name = ? WHERE objectStoreID = ? AND id = ?;"_s);
1390         if (!sql
1391             || sql->bindText(1, newName) != SQLITE_OK
1392             || sql->bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1393             || sql->bindInt64(3, indexIdentifier) != SQLITE_OK
1394             || sql->step() != SQLITE_DONE) {
1395             LOG_ERROR("Could not update name for index id (%" PRIi64 ", %" PRIi64 ") in IndexInfo table (%i) - %s", objectStoreIdentifier, indexIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1396             return IDBError { UnknownError, "Could not rename index"_s };
1397         }
1398     }
1399
1400     indexInfo->rename(newName);
1401
1402     return IDBError { };
1403 }
1404
1405 IDBError SQLiteIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyData& keyData, bool& keyExists)
1406 {
1407     LOG(IndexedDB, "SQLiteIDBBackingStore::keyExistsInObjectStore - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreID);
1408
1409     ASSERT(m_sqliteDB);
1410     ASSERT(m_sqliteDB->isOpen());
1411
1412     keyExists = false;
1413
1414     auto* transaction = m_transactions.get(transactionIdentifier);
1415     if (!transaction || !transaction->inProgress()) {
1416         LOG_ERROR("Attempt to see if key exists in objectstore without an in-progress transaction");
1417         return IDBError { UnknownError, "Attempt to see if key exists in objectstore without an in-progress transaction"_s };
1418     }
1419
1420     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1421     if (!keyBuffer) {
1422         LOG_ERROR("Unable to serialize IDBKey to check for existence in object store");
1423         return IDBError { UnknownError, "Unable to serialize IDBKey to check for existence in object store"_s };
1424     }
1425     auto* sql = cachedStatement(SQL::KeyExistsInObjectStore, "SELECT key FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT) LIMIT 1;"_s);
1426     if (!sql
1427         || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1428         || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
1429         LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1430         return IDBError { UnknownError, "Unable to check for existence of IDBKey in object store"_s };
1431     }
1432
1433     int sqlResult = sql->step();
1434     if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
1435         return IDBError { };
1436
1437     if (sqlResult != SQLITE_ROW) {
1438         // There was an error fetching the record from the database.
1439         LOG_ERROR("Could not check if key exists in object store (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1440         return IDBError { UnknownError, "Error checking for existence of IDBKey in object store"_s };
1441     }
1442
1443     keyExists = true;
1444     return IDBError { };
1445 }
1446
1447 IDBError SQLiteIDBBackingStore::deleteUnusedBlobFileRecords(SQLiteIDBTransaction& transaction)
1448 {
1449     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteUnusedBlobFileRecords");
1450
1451     // Gather the set of blob URLs and filenames that are no longer in use.
1452     HashSet<String> removedBlobFilenames;
1453     {
1454         auto* sql = cachedStatement(SQL::GetUnusedBlobFilenames, "SELECT fileName FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"_s);
1455
1456         if (!sql) {
1457             LOG_ERROR("Error deleting stored blobs (%i) (Could not gather unused blobURLs) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1458             return IDBError { UnknownError, "Error deleting stored blobs"_s };
1459         }
1460
1461         int result = sql->step();
1462         while (result == SQLITE_ROW) {
1463             removedBlobFilenames.add(sql->getColumnText(0));
1464             result = sql->step();
1465         }
1466
1467         if (result != SQLITE_DONE) {
1468             LOG_ERROR("Error deleting stored blobs (%i) (Could not gather unused blobURLs) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1469             return IDBError { UnknownError, "Error deleting stored blobs"_s };
1470         }
1471     }
1472
1473     // Remove the blob records that are no longer in use.
1474     if (!removedBlobFilenames.isEmpty()) {
1475         auto* sql = cachedStatement(SQL::DeleteUnusedBlobs, "DELETE FROM BlobFiles WHERE blobURL NOT IN (SELECT blobURL FROM BlobRecords)"_s);
1476
1477         if (!sql
1478             || sql->step() != SQLITE_DONE) {
1479             LOG_ERROR("Error deleting stored blobs (%i) (Could not delete blobFile records) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1480             return IDBError { UnknownError, "Error deleting stored blobs"_s };
1481         }
1482     }
1483
1484     for (auto& file : removedBlobFilenames)
1485         transaction.addRemovedBlobFile(file);
1486
1487     return IDBError { };
1488 }
1489
1490 IDBError SQLiteIDBBackingStore::deleteRecord(SQLiteIDBTransaction& transaction, int64_t objectStoreID, const IDBKeyData& keyData)
1491 {
1492     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteRecord - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreID);
1493
1494     ASSERT(m_sqliteDB);
1495     ASSERT(m_sqliteDB->isOpen());
1496     ASSERT(transaction.inProgress());
1497     ASSERT(transaction.mode() != IDBTransactionMode::Readonly);
1498     UNUSED_PARAM(transaction);
1499
1500     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1501     if (!keyBuffer) {
1502         LOG_ERROR("Unable to serialize IDBKeyData to be removed from the database");
1503         return IDBError { UnknownError, "Unable to serialize IDBKeyData to be removed from the database"_s };
1504     }
1505
1506     // Get the record ID
1507     int64_t recordID;
1508     {
1509         auto* sql = cachedStatement(SQL::GetObjectStoreRecordID, "SELECT recordID FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"_s);
1510
1511         if (!sql
1512             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1513             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
1514             LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1515             return IDBError { UnknownError, "Failed to delete record from object store"_s };
1516         }
1517
1518         int result = sql->step();
1519
1520         // If there's no record ID, there's no record to delete.
1521         if (result == SQLITE_DONE)
1522             return IDBError { };
1523
1524         if (result != SQLITE_ROW) {
1525             LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) (unable to fetch record ID) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1526             return IDBError { UnknownError, "Failed to delete record from object store"_s };
1527         }
1528
1529         recordID = sql->getColumnInt64(0);
1530     }
1531
1532     if (recordID < 1) {
1533         LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) (record ID is invalid) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1534         return IDBError { UnknownError, "Failed to delete record from object store"_s };
1535     }
1536
1537     // Delete the blob records for this object store record.
1538     {
1539         auto* sql = cachedStatement(SQL::DeleteBlobRecord, "DELETE FROM BlobRecords WHERE objectStoreRow = ?;"_s);
1540
1541         if (!sql
1542             || sql->bindInt64(1, recordID) != SQLITE_OK
1543             || sql->step() != SQLITE_DONE) {
1544             LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) (Could not delete BlobRecords records) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1545             return IDBError { UnknownError, "Failed to delete record from object store"_s };
1546         }
1547     }
1548
1549     auto error = deleteUnusedBlobFileRecords(transaction);
1550     if (!error.isNull())
1551         return error;
1552
1553     // Delete record from object store
1554     {
1555         auto* sql = cachedStatement(SQL::DeleteObjectStoreRecord, "DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"_s);
1556
1557         if (!sql
1558             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1559             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1560             || sql->step() != SQLITE_DONE) {
1561             LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1562             return IDBError { UnknownError, "Failed to delete record from object store"_s };
1563         }
1564     }
1565
1566     // Delete record from indexes store
1567     {
1568         auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecord, "DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"_s);
1569
1570         if (!sql
1571             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1572             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1573             || sql->step() != SQLITE_DONE) {
1574             LOG_ERROR("Could not delete record from indexes for object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1575             return IDBError { UnknownError, "Failed to delete index entries for object store record"_s };
1576         }
1577     }
1578
1579     return IDBError { };
1580 }
1581
1582 IDBError SQLiteIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyRangeData& keyRange)
1583 {
1584     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteRange - range %s, object store %" PRIu64, keyRange.loggingString().utf8().data(), objectStoreID);
1585
1586     ASSERT(m_sqliteDB);
1587     ASSERT(m_sqliteDB->isOpen());
1588
1589     auto* transaction = m_transactions.get(transactionIdentifier);
1590     if (!transaction || !transaction->inProgress()) {
1591         LOG_ERROR("Attempt to delete range from database without an in-progress transaction");
1592         return IDBError { UnknownError, "Attempt to delete range from database without an in-progress transaction"_s };
1593     }
1594     if (transaction->mode() == IDBTransactionMode::Readonly) {
1595         LOG_ERROR("Attempt to delete records from an object store in a read-only transaction");
1596         return IDBError { UnknownError, "Attempt to delete records from an object store in a read-only transaction"_s };
1597     }
1598
1599     // If the range to delete is exactly one key we can delete it right now.
1600     if (keyRange.isExactlyOneKey()) {
1601         auto error = deleteRecord(*transaction, objectStoreID, keyRange.lowerKey);
1602         if (!error.isNull()) {
1603             LOG_ERROR("Failed to delete record for key '%s'", keyRange.lowerKey.loggingString().utf8().data());
1604             return error;
1605         }
1606
1607         transaction->notifyCursorsOfChanges(objectStoreID);
1608
1609         return IDBError { };
1610     }
1611
1612     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreID, 0, keyRange);
1613     if (!cursor) {
1614         LOG_ERROR("Cannot open cursor to delete range of records from the database");
1615         return IDBError { UnknownError, "Cannot open cursor to delete range of records from the database"_s };
1616     }
1617
1618     Vector<IDBKeyData> keys;
1619     while (!cursor->didComplete() && !cursor->didError()) {
1620         keys.append(cursor->currentKey());
1621         cursor->advance(1);
1622     }
1623
1624     if (cursor->didError()) {
1625         LOG_ERROR("Cursor failed while accumulating range of records from the database");
1626         return IDBError { UnknownError, "Cursor failed while accumulating range of records from the database"_s };
1627     }
1628
1629     IDBError error;
1630     for (auto& key : keys) {
1631         error = deleteRecord(*transaction, objectStoreID, key);
1632         if (!error.isNull()) {
1633             LOG_ERROR("deleteRange: Error deleting keys in range");
1634             break;
1635         }
1636     }
1637
1638     transaction->notifyCursorsOfChanges(objectStoreID);
1639
1640     return error;
1641 }
1642
1643 IDBError SQLiteIDBBackingStore::updateOneIndexForAddRecord(const IDBIndexInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value, int64_t recordID)
1644 {
1645     JSLockHolder locker(vm());
1646
1647     auto jsValue = deserializeIDBValueToJSValue(*globalObject().globalExec(), value);
1648     if (jsValue.isUndefinedOrNull())
1649         return IDBError { };
1650
1651     IndexKey indexKey;
1652     generateIndexKeyForValue(*m_globalObject->globalExec(), info, jsValue, indexKey);
1653
1654     if (indexKey.isNull())
1655         return IDBError { };
1656
1657     return uncheckedPutIndexKey(info, key, indexKey, recordID);
1658 }
1659
1660 IDBError SQLiteIDBBackingStore::updateAllIndexesForAddRecord(const IDBObjectStoreInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value, int64_t recordID)
1661 {
1662     JSLockHolder locker(vm());
1663
1664     auto jsValue = deserializeIDBValueToJSValue(*globalObject().globalExec(), value);
1665     if (jsValue.isUndefinedOrNull())
1666         return IDBError { };
1667
1668     IDBError error;
1669     bool anyRecordsSucceeded = false;
1670     for (auto& index : info.indexMap().values()) {
1671         IndexKey indexKey;
1672         generateIndexKeyForValue(*m_globalObject->globalExec(), index, jsValue, indexKey);
1673
1674         if (indexKey.isNull())
1675             continue;
1676
1677         error = uncheckedPutIndexKey(index, key, indexKey, recordID);
1678         if (!error.isNull())
1679             break;
1680
1681         anyRecordsSucceeded = true;
1682     }
1683
1684     if (!error.isNull() && anyRecordsSucceeded) {
1685         RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(key);
1686
1687         auto* sql = cachedStatement(SQL::DeleteObjectStoreIndexRecord, "DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"_s);
1688
1689         if (!sql
1690             || sql->bindInt64(1, info.identifier()) != SQLITE_OK
1691             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1692             || sql->step() != SQLITE_DONE) {
1693             LOG_ERROR("Adding one Index record failed, but failed to remove all others that previously succeeded");
1694             return IDBError { UnknownError, "Adding one Index record failed, but failed to remove all others that previously succeeded"_s };
1695         }
1696     }
1697
1698     return error;
1699 }
1700
1701 IDBError SQLiteIDBBackingStore::addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& objectStoreInfo, const IDBKeyData& keyData, const IDBValue& value)
1702 {
1703     LOG(IndexedDB, "SQLiteIDBBackingStore::addRecord - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreInfo.identifier());
1704
1705     ASSERT(m_sqliteDB);
1706     ASSERT(m_sqliteDB->isOpen());
1707     ASSERT(value.data().data());
1708     ASSERT(value.blobURLs().size() == value.blobFilePaths().size());
1709
1710     auto* transaction = m_transactions.get(transactionIdentifier);
1711     if (!transaction || !transaction->inProgress()) {
1712         LOG_ERROR("Attempt to store a record in an object store without an in-progress transaction");
1713         return IDBError { UnknownError, "Attempt to store a record in an object store without an in-progress transaction"_s };
1714     }
1715     if (transaction->mode() == IDBTransactionMode::Readonly) {
1716         LOG_ERROR("Attempt to store a record in an object store in a read-only transaction");
1717         return IDBError { UnknownError, "Attempt to store a record in an object store in a read-only transaction"_s };
1718     }
1719
1720     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1721     if (!keyBuffer) {
1722         LOG_ERROR("Unable to serialize IDBKey to be stored in an object store");
1723         return IDBError { UnknownError, "Unable to serialize IDBKey to be stored in an object store"_s };
1724     }
1725
1726     int64_t recordID = 0;
1727     {
1728         auto* sql = cachedStatement(SQL::AddObjectStoreRecord, "INSERT INTO Records VALUES (?, CAST(? AS TEXT), ?, NULL);"_s);
1729         if (!sql
1730             || sql->bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
1731             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1732             || sql->bindBlob(3, value.data().data()->data(), value.data().data()->size()) != SQLITE_OK
1733             || sql->step() != SQLITE_DONE) {
1734             LOG_ERROR("Could not put record for object store %" PRIi64 " in Records table (%i) - %s", objectStoreInfo.identifier(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1735             return IDBError { UnknownError, "Unable to store record in object store"_s };
1736         }
1737
1738         recordID = m_sqliteDB->lastInsertRowID();
1739     }
1740
1741     auto error = updateAllIndexesForAddRecord(objectStoreInfo, keyData, value.data(), recordID);
1742
1743     if (!error.isNull()) {
1744         auto* sql = cachedStatement(SQL::DeleteObjectStoreRecord, "DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"_s);
1745         if (!sql
1746             || sql->bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
1747             || sql->bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1748             || sql->step() != SQLITE_DONE) {
1749             LOG_ERROR("Indexing new object store record failed, but unable to remove the object store record itself");
1750             return IDBError { UnknownError, "Indexing new object store record failed, but unable to remove the object store record itself"_s };
1751         }
1752
1753         return error;
1754     }
1755
1756     const Vector<String>& blobURLs = value.blobURLs();
1757     const Vector<String>& blobFiles = value.blobFilePaths();
1758     for (size_t i = 0; i < blobURLs.size(); ++i) {
1759         auto& url = blobURLs[i];
1760         {
1761             auto* sql = cachedStatement(SQL::AddBlobRecord, "INSERT INTO BlobRecords VALUES (?, ?);"_s);
1762             if (!sql
1763                 || sql->bindInt64(1, recordID) != SQLITE_OK
1764                 || sql->bindText(2, url) != SQLITE_OK
1765                 || sql->step() != SQLITE_DONE) {
1766                 LOG_ERROR("Unable to record Blob record in database");
1767                 return IDBError { UnknownError, "Unable to record Blob record in database"_s };
1768             }
1769         }
1770         int64_t potentialFileNameInteger = m_sqliteDB->lastInsertRowID();
1771
1772         // If we already have a file for this blobURL, nothing left to do.
1773         {
1774             auto* sql = cachedStatement(SQL::BlobFilenameForBlobURL, "SELECT fileName FROM BlobFiles WHERE blobURL = ?;"_s);
1775             if (!sql
1776                 || sql->bindText(1, url) != SQLITE_OK) {
1777                 LOG_ERROR("Unable to examine Blob filenames in database");
1778                 return IDBError { UnknownError, "Unable to examine Blob filenames in database"_s };
1779             }
1780
1781             int result = sql->step();
1782             if (result != SQLITE_ROW && result != SQLITE_DONE) {
1783                 LOG_ERROR("Unable to examine Blob filenames in database");
1784                 return IDBError { UnknownError, "Unable to examine Blob filenames in database"_s };
1785             }
1786
1787             if (result == SQLITE_ROW)
1788                 continue;
1789         }
1790
1791         // We don't already have a file for this blobURL, so commit our file as a unique filename
1792         String storedFilename = String::format("%" PRId64 ".blob", potentialFileNameInteger);
1793         {
1794             auto* sql = cachedStatement(SQL::AddBlobFilename, "INSERT INTO BlobFiles VALUES (?, ?);"_s);
1795             if (!sql
1796                 || sql->bindText(1, url) != SQLITE_OK
1797                 || sql->bindText(2, storedFilename) != SQLITE_OK
1798                 || sql->step() != SQLITE_DONE) {
1799                 LOG_ERROR("Unable to record Blob file record in database");
1800                 return IDBError { UnknownError, "Unable to record Blob file record in database"_s };
1801             }
1802         }
1803
1804         transaction->addBlobFile(blobFiles[i], storedFilename);
1805     }
1806
1807     transaction->notifyCursorsOfChanges(objectStoreInfo.identifier());
1808
1809     return error;
1810 }
1811
1812 IDBError SQLiteIDBBackingStore::getBlobRecordsForObjectStoreRecord(int64_t objectStoreRecord, Vector<String>& blobURLs, Vector<String>& blobFilePaths)
1813 {
1814     ASSERT(objectStoreRecord);
1815
1816     HashSet<String> blobURLSet;
1817     {
1818         auto* sql = cachedStatement(SQL::GetBlobURL, "SELECT blobURL FROM BlobRecords WHERE objectStoreRow = ?"_s);
1819         if (!sql
1820             || sql->bindInt64(1, objectStoreRecord) != SQLITE_OK) {
1821             LOG_ERROR("Could not prepare statement to fetch blob URLs for object store record (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1822             return IDBError { UnknownError, "Failed to look up blobURL records in object store by key range"_s };
1823         }
1824
1825         int sqlResult = sql->step();
1826         if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE) {
1827             // There are no blobURLs in the database for this object store record.
1828             return IDBError { };
1829         }
1830
1831         while (sqlResult == SQLITE_ROW) {
1832             blobURLSet.add(sql->getColumnText(0));
1833             sqlResult = sql->step();
1834         }
1835
1836         if (sqlResult != SQLITE_DONE) {
1837             LOG_ERROR("Could not fetch blob URLs for object store record (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1838             return IDBError { UnknownError, "Failed to look up blobURL records in object store by key range"_s };
1839         }
1840     }
1841
1842     ASSERT(!blobURLSet.isEmpty());
1843     String databaseDirectory = fullDatabaseDirectory();
1844     for (auto& blobURL : blobURLSet) {
1845         auto* sql = cachedStatement(SQL::BlobFilenameForBlobURL, "SELECT fileName FROM BlobFiles WHERE blobURL = ?;"_s);
1846         if (!sql
1847             || sql->bindText(1, blobURL) != SQLITE_OK) {
1848             LOG_ERROR("Could not prepare statement to fetch blob filename for object store record (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1849             return IDBError { UnknownError, "Failed to look up blobURL records in object store by key range"_s };
1850         }
1851
1852         if (sql->step() != SQLITE_ROW) {
1853             LOG_ERROR("Entry for blob filename for blob url %s does not exist (%i) - %s", blobURL.utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1854             return IDBError { UnknownError, "Failed to look up blobURL records in object store by key range"_s };
1855         }
1856
1857         blobURLs.append(blobURL);
1858
1859         String fileName = sql->getColumnText(0);
1860         blobFilePaths.append(FileSystem::pathByAppendingComponent(databaseDirectory, fileName));
1861     }
1862
1863     return IDBError { };
1864 }
1865
1866 IDBError SQLiteIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyRangeData& keyRange, IDBGetRecordDataType type, IDBGetResult& resultValue)
1867 {
1868     LOG(IndexedDB, "SQLiteIDBBackingStore::getRecord - key range %s, object store %" PRIu64, keyRange.loggingString().utf8().data(), objectStoreID);
1869
1870     ASSERT(m_sqliteDB);
1871     ASSERT(m_sqliteDB->isOpen());
1872
1873     auto* transaction = m_transactions.get(transactionIdentifier);
1874     if (!transaction || !transaction->inProgress()) {
1875         LOG_ERROR("Attempt to get a record from database without an in-progress transaction");
1876         return IDBError { UnknownError, "Attempt to get a record from database without an in-progress transaction"_s };
1877     }
1878
1879     auto key = keyRange.lowerKey;
1880     if (key.isNull())
1881         key = IDBKeyData::minimum();
1882     RefPtr<SharedBuffer> lowerBuffer = serializeIDBKeyData(key);
1883     if (!lowerBuffer) {
1884         LOG_ERROR("Unable to serialize lower IDBKey in lookup range");
1885         return IDBError { UnknownError, "Unable to serialize lower IDBKey in lookup range"_s };
1886     }
1887
1888     key = keyRange.upperKey;
1889     if (key.isNull())
1890         key = IDBKeyData::maximum();
1891     RefPtr<SharedBuffer> upperBuffer = serializeIDBKeyData(key);
1892     if (!upperBuffer) {
1893         LOG_ERROR("Unable to serialize upper IDBKey in lookup range");
1894         return IDBError { UnknownError, "Unable to serialize upper IDBKey in lookup range"_s };
1895     }
1896
1897     int64_t recordID = 0;
1898     ThreadSafeDataBuffer resultBuffer;
1899     {
1900         static const char* const lowerOpenUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
1901         static const char* const lowerOpenUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
1902         static const char* const lowerClosedUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
1903         static const char* const lowerClosedUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
1904
1905         static const char* const lowerOpenUpperOpenKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
1906         static const char* const lowerOpenUpperClosedKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
1907         static const char* const lowerClosedUpperOpenKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
1908         static const char* const lowerClosedUpperClosedKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
1909
1910         SQLiteStatement* sql = nullptr;
1911
1912         switch (type) {
1913         case IDBGetRecordDataType::KeyAndValue:
1914             if (keyRange.lowerOpen) {
1915                 if (keyRange.upperOpen)
1916                     sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpen);
1917                 else
1918                     sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosed);
1919             } else {
1920                 if (keyRange.upperOpen)
1921                     sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpen);
1922                 else
1923                     sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosed);
1924             }
1925             break;
1926         case IDBGetRecordDataType::KeyOnly:
1927             if (keyRange.lowerOpen) {
1928                 if (keyRange.upperOpen)
1929                     sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKeyOnly);
1930                 else
1931                     sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKeyOnly);
1932             } else {
1933                 if (keyRange.upperOpen)
1934                     sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKeyOnly);
1935                 else
1936                     sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKeyOnly);
1937             }
1938         }
1939
1940         if (!sql
1941             || sql->bindInt64(1, objectStoreID) != SQLITE_OK
1942             || sql->bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
1943             || sql->bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
1944             LOG_ERROR("Could not get key range record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1945             return IDBError { UnknownError, "Failed to look up record in object store by key range"_s };
1946         }
1947
1948         int sqlResult = sql->step();
1949
1950         if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE) {
1951             // There was no record for the key in the database.
1952             return IDBError { };
1953         }
1954         if (sqlResult != SQLITE_ROW) {
1955             // There was an error fetching the record from the database.
1956             LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1957             return IDBError { UnknownError, "Error looking up record in object store by key range"_s };
1958         }
1959
1960         Vector<uint8_t> buffer;
1961         sql->getColumnBlobAsVector(0, buffer);
1962         resultBuffer = ThreadSafeDataBuffer::create(WTFMove(buffer));
1963
1964         if (type == IDBGetRecordDataType::KeyAndValue)
1965             recordID = sql->getColumnInt64(1);
1966     }
1967
1968     if (type == IDBGetRecordDataType::KeyOnly) {
1969         auto* vector = resultBuffer.data();
1970         if (!vector) {
1971             LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore.getKey()");
1972             return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore.getKey()"_s };
1973         }
1974
1975         IDBKeyData keyData;
1976         if (!deserializeIDBKeyData(vector->data(), vector->size(), keyData)) {
1977             LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore.getKey()");
1978             return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore.getKey()"_s };
1979         }
1980
1981         resultValue = { keyData };
1982         return IDBError { };
1983     }
1984
1985     ASSERT(recordID);
1986     Vector<String> blobURLs, blobFilePaths;
1987     auto error = getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
1988     ASSERT(blobURLs.size() == blobFilePaths.size());
1989
1990     if (!error.isNull())
1991         return error;
1992
1993     resultValue = { { resultBuffer, WTFMove(blobURLs), WTFMove(blobFilePaths) } };
1994     return IDBError { };
1995 }
1996
1997 IDBError SQLiteIDBBackingStore::getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
1998 {
1999     return getAllRecordsData.indexIdentifier ? getAllIndexRecords(transactionIdentifier, getAllRecordsData, result) : getAllObjectStoreRecords(transactionIdentifier, getAllRecordsData, result);
2000 }
2001
2002 SQLiteStatement* SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords(const IDBGetAllRecordsData& getAllRecordsData)
2003 {
2004     static const char* const lowerOpenUpperOpenKey ="SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
2005     static const char* const lowerOpenUpperClosedKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
2006     static const char* const lowerClosedUpperOpenKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
2007     static const char* const lowerClosedUpperClosedKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
2008     static const char* const lowerOpenUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
2009     static const char* const lowerOpenUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
2010     static const char* const lowerClosedUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
2011     static const char* const lowerClosedUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
2012
2013     if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
2014         if (getAllRecordsData.keyRangeData.lowerOpen) {
2015             if (getAllRecordsData.keyRangeData.upperOpen)
2016                 return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKey);
2017             return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKey);
2018         }
2019
2020         if (getAllRecordsData.keyRangeData.upperOpen)
2021             return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKey);
2022         return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKey);
2023     }
2024
2025     if (getAllRecordsData.keyRangeData.lowerOpen) {
2026         if (getAllRecordsData.keyRangeData.upperOpen)
2027             return cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpenValue);
2028         return cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosedValue);
2029     }
2030
2031     if (getAllRecordsData.keyRangeData.upperOpen)
2032         return cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpenValue);
2033     return cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosedValue);
2034 }
2035
2036 IDBError SQLiteIDBBackingStore::getAllObjectStoreRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
2037 {
2038     LOG(IndexedDB, "SQLiteIDBBackingStore::getAllObjectStoreRecords");
2039
2040     ASSERT(m_sqliteDB);
2041     ASSERT(m_sqliteDB->isOpen());
2042
2043     auto* transaction = m_transactions.get(transactionIdentifier);
2044     if (!transaction || !transaction->inProgress()) {
2045         LOG_ERROR("Attempt to get records from database without an in-progress transaction");
2046         return IDBError { UnknownError, "Attempt to get records from database without an in-progress transaction"_s };
2047     }
2048
2049     auto key = getAllRecordsData.keyRangeData.lowerKey;
2050     if (key.isNull())
2051         key = IDBKeyData::minimum();
2052     auto lowerBuffer = serializeIDBKeyData(key);
2053     if (!lowerBuffer) {
2054         LOG_ERROR("Unable to serialize lower IDBKey in lookup range");
2055         return IDBError { UnknownError, "Unable to serialize lower IDBKey in lookup range"_s };
2056     }
2057
2058     key = getAllRecordsData.keyRangeData.upperKey;
2059     if (key.isNull())
2060         key = IDBKeyData::maximum();
2061     auto upperBuffer = serializeIDBKeyData(key);
2062     if (!upperBuffer) {
2063         LOG_ERROR("Unable to serialize upper IDBKey in lookup range");
2064         return IDBError { UnknownError, "Unable to serialize upper IDBKey in lookup range"_s };
2065     }
2066
2067     auto* sql = cachedStatementForGetAllObjectStoreRecords(getAllRecordsData);
2068     if (!sql
2069         || sql->bindInt64(1, getAllRecordsData.objectStoreIdentifier) != SQLITE_OK
2070         || sql->bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
2071         || sql->bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
2072         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());
2073         return IDBError { UnknownError, "Failed to look up record in object store by key range"_s };
2074     }
2075
2076     result = { getAllRecordsData.getAllType };
2077
2078     uint32_t targetResults;
2079     if (getAllRecordsData.count && getAllRecordsData.count.value())
2080         targetResults = getAllRecordsData.count.value();
2081     else
2082         targetResults = std::numeric_limits<uint32_t>::max();
2083
2084     int sqlResult = sql->step();
2085     uint32_t returnedResults = 0;
2086
2087     while (sqlResult == SQLITE_ROW && returnedResults < targetResults) {
2088         if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values) {
2089             Vector<uint8_t> buffer;
2090             sql->getColumnBlobAsVector(0, buffer);
2091             ThreadSafeDataBuffer resultBuffer = ThreadSafeDataBuffer::create(WTFMove(buffer));
2092
2093             auto recordID = sql->getColumnInt64(1);
2094
2095             ASSERT(recordID);
2096             Vector<String> blobURLs, blobFilePaths;
2097             auto error = getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
2098             ASSERT(blobURLs.size() == blobFilePaths.size());
2099
2100             if (!error.isNull())
2101                 return error;
2102
2103             result.addValue({ resultBuffer, WTFMove(blobURLs), WTFMove(blobFilePaths) });
2104         } else {
2105             Vector<uint8_t> keyData;
2106             IDBKeyData key;
2107             sql->getColumnBlobAsVector(0, keyData);
2108
2109             if (!deserializeIDBKeyData(keyData.data(), keyData.size(), key)) {
2110                 LOG_ERROR("Unable to deserialize key data from database while getting all key records");
2111                 return IDBError { UnknownError, "Unable to deserialize key data while getting all key records"_s };
2112             }
2113
2114             result.addKey(WTFMove(key));
2115         }
2116
2117         ++returnedResults;
2118         sqlResult = sql->step();
2119     }
2120
2121     if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE || sqlResult == SQLITE_ROW) {
2122         // Finished getting results
2123         return IDBError { };
2124     }
2125
2126     // There was an error fetching records from the database.
2127     LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", getAllRecordsData.objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
2128     return IDBError { UnknownError, "Error looking up record in object store by key range"_s };
2129 }
2130
2131 IDBError SQLiteIDBBackingStore::getAllIndexRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
2132 {
2133     LOG(IndexedDB, "SQLiteIDBBackingStore::getAllIndexRecords - %s", getAllRecordsData.keyRangeData.loggingString().utf8().data());
2134
2135     ASSERT(m_sqliteDB);
2136     ASSERT(m_sqliteDB->isOpen());
2137
2138     auto* transaction = m_transactions.get(transactionIdentifier);
2139     if (!transaction || !transaction->inProgress()) {
2140         LOG_ERROR("Attempt to get all index records from database without an in-progress transaction");
2141         return IDBError { UnknownError, "Attempt to get all index records from database without an in-progress transaction"_s };
2142     }
2143
2144     auto cursor = transaction->maybeOpenBackingStoreCursor(getAllRecordsData.objectStoreIdentifier, getAllRecordsData.indexIdentifier, getAllRecordsData.keyRangeData);
2145     if (!cursor) {
2146         LOG_ERROR("Cannot open cursor to perform index gets in database");
2147         return IDBError { UnknownError, "Cannot open cursor to perform index gets in database"_s };
2148     }
2149
2150     if (cursor->didError()) {
2151         LOG_ERROR("Cursor failed while looking up index records in database");
2152         return IDBError { UnknownError, "Cursor failed while looking up index records in database"_s };
2153     }
2154
2155     result = { getAllRecordsData.getAllType };
2156     uint32_t currentCount = 0;
2157     uint32_t targetCount = getAllRecordsData.count ? getAllRecordsData.count.value() : 0;
2158     if (!targetCount)
2159         targetCount = std::numeric_limits<uint32_t>::max();
2160     while (!cursor->didComplete() && !cursor->didError() && currentCount < targetCount) {
2161         if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
2162             IDBKeyData keyCopy = cursor->currentPrimaryKey();
2163             result.addKey(WTFMove(keyCopy));
2164         } else
2165             result.addValue(cursor->currentValue() ? *cursor->currentValue() : IDBValue());
2166
2167         ++currentCount;
2168         cursor->advance(1);
2169     }
2170
2171     if (cursor->didError()) {
2172         LOG_ERROR("Cursor failed while looking up index records in database");
2173         return IDBError { UnknownError, "Cursor failed while looking up index records in database"_s };
2174     }
2175
2176     return IDBError { };
2177 }
2178
2179 IDBError SQLiteIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t indexID, IndexedDB::IndexRecordType type, const IDBKeyRangeData& range, IDBGetResult& getResult)
2180 {
2181     LOG(IndexedDB, "SQLiteIDBBackingStore::getIndexRecord - %s", range.loggingString().utf8().data());
2182
2183     ASSERT(m_sqliteDB);
2184     ASSERT(m_sqliteDB->isOpen());
2185
2186     auto* transaction = m_transactions.get(transactionIdentifier);
2187     if (!transaction || !transaction->inProgress()) {
2188         LOG_ERROR("Attempt to get an index record from database without an in-progress transaction");
2189         return IDBError { UnknownError, "Attempt to get an index record from database without an in-progress transaction"_s };
2190     }
2191
2192     if (range.isExactlyOneKey())
2193         return uncheckedGetIndexRecordForOneKey(indexID, objectStoreID, type, range.lowerKey, getResult);
2194
2195     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreID, indexID, range);
2196     if (!cursor) {
2197         LOG_ERROR("Cannot open cursor to perform index get in database");
2198         return IDBError { UnknownError, "Cannot open cursor to perform index get in database"_s };
2199     }
2200
2201     if (cursor->didError()) {
2202         LOG_ERROR("Cursor failed while looking up index record in database");
2203         return IDBError { UnknownError, "Cursor failed while looking up index record in database"_s };
2204     }
2205
2206     if (cursor->didComplete())
2207         getResult = { };
2208     else {
2209         if (type == IndexedDB::IndexRecordType::Key)
2210             getResult = { cursor->currentPrimaryKey() };
2211         else
2212             getResult = { cursor->currentValue() ? *cursor->currentValue() : IDBValue(), cursor->currentPrimaryKey() };
2213     }
2214
2215     return IDBError { };
2216 }
2217
2218 IDBError SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey(int64_t indexID, int64_t objectStoreID, IndexedDB::IndexRecordType type, const IDBKeyData& key, IDBGetResult& getResult)
2219 {
2220     LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey");
2221
2222     ASSERT(key.isValid() && key.type() != KeyType::Max && key.type() != KeyType::Min);
2223
2224     RefPtr<SharedBuffer> buffer = serializeIDBKeyData(key);
2225     if (!buffer) {
2226         LOG_ERROR("Unable to serialize IDBKey to look up one index record");
2227         return IDBError { UnknownError, "Unable to serialize IDBKey to look up one index record"_s };
2228     }
2229
2230     auto* sql = cachedStatement(SQL::GetIndexRecordForOneKey, "SELECT IndexRecords.value, Records.value, Records.recordID FROM Records INNER JOIN IndexRecords ON Records.recordID = IndexRecords.objectStoreRecordID WHERE IndexRecords.indexID = ? AND IndexRecords.objectStoreID = ? AND IndexRecords.key = CAST(? AS TEXT) ORDER BY IndexRecords.key, IndexRecords.value"_s);
2231
2232     if (!sql
2233         || sql->bindInt64(1, indexID) != SQLITE_OK
2234         || sql->bindInt64(2, objectStoreID) != SQLITE_OK
2235         || sql->bindBlob(3, buffer->data(), buffer->size()) != SQLITE_OK) {
2236         LOG_ERROR("Unable to lookup index record in database");
2237         return IDBError { UnknownError, "Unable to lookup index record in database"_s };
2238     }
2239
2240     int result = sql->step();
2241     if (result != SQLITE_ROW && result != SQLITE_DONE) {
2242         LOG_ERROR("Unable to lookup index record in database");
2243         return IDBError { UnknownError, "Unable to lookup index record in database"_s };
2244     }
2245
2246     if (result == SQLITE_DONE)
2247         return IDBError { };
2248
2249     IDBKeyData objectStoreKey;
2250     Vector<uint8_t> keyVector;
2251     sql->getColumnBlobAsVector(0, keyVector);
2252
2253     if (!deserializeIDBKeyData(keyVector.data(), keyVector.size(), objectStoreKey)) {
2254         LOG_ERROR("Unable to deserialize key looking up index record in database");
2255         return IDBError { UnknownError, "Unable to deserialize key looking up index record in database"_s };
2256     }
2257
2258     if (type == IndexedDB::IndexRecordType::Key) {
2259         getResult = { objectStoreKey };
2260         return IDBError { };
2261     }
2262
2263     sql->getColumnBlobAsVector(1, keyVector);
2264
2265     int64_t recordID = sql->getColumnInt64(2);
2266     Vector<String> blobURLs, blobFilePaths;
2267     auto error = getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
2268     ASSERT(blobURLs.size() == blobFilePaths.size());
2269
2270     if (!error.isNull())
2271         return error;
2272
2273     getResult = { { ThreadSafeDataBuffer::create(WTFMove(keyVector)), WTFMove(blobURLs), WTFMove(blobFilePaths) }, objectStoreKey };
2274     return IDBError { };
2275 }
2276
2277 IDBError SQLiteIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
2278 {
2279     LOG(IndexedDB, "SQLiteIDBBackingStore::getCount - object store %" PRIu64, objectStoreIdentifier);
2280     ASSERT(m_sqliteDB);
2281     ASSERT(m_sqliteDB->isOpen());
2282
2283     outCount = 0;
2284
2285     auto* transaction = m_transactions.get(transactionIdentifier);
2286     if (!transaction || !transaction->inProgress()) {
2287         LOG_ERROR("Attempt to get count from database without an in-progress transaction");
2288         return IDBError { UnknownError, "Attempt to get count from database without an in-progress transaction"_s };
2289     }
2290
2291     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreIdentifier, indexIdentifier, range);
2292     if (!cursor) {
2293         LOG_ERROR("Cannot open cursor to populate indexes in database");
2294         return IDBError { UnknownError, "Unable to populate indexes in database"_s };
2295     }
2296
2297     while (cursor->advance(1))
2298         ++outCount;
2299
2300     return IDBError { };
2301 }
2302
2303 IDBError SQLiteIDBBackingStore::uncheckedGetKeyGeneratorValue(int64_t objectStoreID, uint64_t& outValue)
2304 {
2305     auto* sql = cachedStatement(SQL::GetKeyGeneratorValue, "SELECT currentKey FROM KeyGenerators WHERE objectStoreID = ?;"_s);
2306     if (!sql
2307         || sql->bindInt64(1, objectStoreID) != SQLITE_OK) {
2308         LOG_ERROR("Could not retrieve currentKey from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
2309         return IDBError { UnknownError, "Error getting current key generator value from database"_s };
2310     }
2311     int result = sql->step();
2312     if (result != SQLITE_ROW) {
2313         LOG_ERROR("Could not retreive key generator value for object store, but it should be there.");
2314         return IDBError { UnknownError, "Error finding current key generator value in database"_s };
2315     }
2316
2317     int64_t value = sql->getColumnInt64(0);
2318     if (value < 0)
2319         return IDBError { ConstraintError, "Current key generator value from database is invalid" };
2320
2321     outValue = value;
2322     return IDBError { };
2323 }
2324
2325 IDBError SQLiteIDBBackingStore::uncheckedSetKeyGeneratorValue(int64_t objectStoreID, uint64_t value)
2326 {
2327     auto* sql = cachedStatement(SQL::SetKeyGeneratorValue, "INSERT INTO KeyGenerators VALUES (?, ?);"_s);
2328     if (!sql
2329         || sql->bindInt64(1, objectStoreID) != SQLITE_OK
2330         || sql->bindInt64(2, value) != SQLITE_OK
2331         || sql->step() != SQLITE_DONE) {
2332         LOG_ERROR("Could not update key generator value (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
2333         return IDBError { ConstraintError, "Error storing new key generator value in database" };
2334     }
2335
2336     return IDBError { };
2337 }
2338
2339 IDBError SQLiteIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t& generatedKey)
2340 {
2341     LOG(IndexedDB, "SQLiteIDBBackingStore::generateKeyNumber");
2342
2343     ASSERT(m_sqliteDB);
2344     ASSERT(m_sqliteDB->isOpen());
2345
2346     // The IndexedDatabase spec defines the max key generator value as 2^53;
2347     static uint64_t maxGeneratorValue = 0x20000000000000;
2348
2349     auto* transaction = m_transactions.get(transactionIdentifier);
2350     if (!transaction || !transaction->inProgress()) {
2351         LOG_ERROR("Attempt to generate key in database without an in-progress transaction");
2352         return IDBError { UnknownError, "Attempt to generate key in database without an in-progress transaction"_s };
2353     }
2354     if (transaction->mode() == IDBTransactionMode::Readonly) {
2355         LOG_ERROR("Attempt to generate key in a read-only transaction");
2356         return IDBError { UnknownError, "Attempt to generate key in a read-only transaction"_s };
2357     }
2358
2359     uint64_t currentValue;
2360     auto error = uncheckedGetKeyGeneratorValue(objectStoreID, currentValue);
2361     if (!error.isNull())
2362         return error;
2363
2364     if (currentValue + 1 > maxGeneratorValue)
2365         return IDBError { ConstraintError, "Cannot generate new key value over 2^53 for object store operation" };
2366
2367     generatedKey = currentValue + 1;
2368     return uncheckedSetKeyGeneratorValue(objectStoreID, generatedKey);
2369 }
2370
2371 IDBError SQLiteIDBBackingStore::revertGeneratedKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t newKeyNumber)
2372 {
2373     LOG(IndexedDB, "SQLiteIDBBackingStore::revertGeneratedKeyNumber - object store %" PRIu64 ", reverted number %" PRIu64, objectStoreID, newKeyNumber);
2374
2375     ASSERT(m_sqliteDB);
2376     ASSERT(m_sqliteDB->isOpen());
2377
2378     auto* transaction = m_transactions.get(transactionIdentifier);
2379     if (!transaction || !transaction->inProgress()) {
2380         LOG_ERROR("Attempt to revert key generator value in database without an in-progress transaction");
2381         return IDBError { UnknownError, "Attempt to revert key generator value in database without an in-progress transaction"_s };
2382     }
2383     if (transaction->mode() == IDBTransactionMode::Readonly) {
2384         LOG_ERROR("Attempt to revert key generator value in a read-only transaction");
2385         return IDBError { UnknownError, "Attempt to revert key generator value in a read-only transaction"_s };
2386     }
2387
2388     ASSERT(newKeyNumber);
2389     return uncheckedSetKeyGeneratorValue(objectStoreID, newKeyNumber - 1);
2390 }
2391
2392 IDBError SQLiteIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, double newKeyNumber)
2393 {
2394     LOG(IndexedDB, "SQLiteIDBBackingStore::maybeUpdateKeyGeneratorNumber");
2395
2396     ASSERT(m_sqliteDB);
2397     ASSERT(m_sqliteDB->isOpen());
2398
2399     auto* transaction = m_transactions.get(transactionIdentifier);
2400     if (!transaction || !transaction->inProgress()) {
2401         LOG_ERROR("Attempt to update key generator value in database without an in-progress transaction");
2402         return IDBError { UnknownError, "Attempt to update key generator value in database without an in-progress transaction"_s };
2403     }
2404     if (transaction->mode() == IDBTransactionMode::Readonly) {
2405         LOG_ERROR("Attempt to update key generator value in a read-only transaction");
2406         return IDBError { UnknownError, "Attempt to update key generator value in a read-only transaction"_s };
2407     }
2408
2409     uint64_t currentValue;
2410     auto error = uncheckedGetKeyGeneratorValue(objectStoreID, currentValue);
2411     if (!error.isNull())
2412         return error;
2413
2414     if (newKeyNumber <= currentValue)
2415         return IDBError { };
2416
2417     uint64_t newKeyInteger(newKeyNumber);
2418     if (newKeyInteger <= uint64_t(newKeyNumber))
2419         ++newKeyInteger;
2420
2421     ASSERT(newKeyInteger > uint64_t(newKeyNumber));
2422
2423     return uncheckedSetKeyGeneratorValue(objectStoreID, newKeyInteger - 1);
2424 }
2425
2426 IDBError SQLiteIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& result)
2427 {
2428     ASSERT(m_sqliteDB);
2429     ASSERT(m_sqliteDB->isOpen());
2430
2431     auto* transaction = m_transactions.get(transactionIdentifier);
2432     if (!transaction || !transaction->inProgress()) {
2433         LOG_ERROR("Attempt to open a cursor in database without an in-progress transaction");
2434         return IDBError { UnknownError, "Attempt to open a cursor in database without an in-progress transaction"_s };
2435     }
2436
2437     auto* cursor = transaction->maybeOpenCursor(info);
2438     if (!cursor) {
2439         LOG_ERROR("Unable to open cursor");
2440         return IDBError { UnknownError, "Unable to open cursor"_s };
2441     }
2442
2443     m_cursors.set(cursor->identifier(), cursor);
2444
2445     cursor->currentData(result);
2446     return IDBError { };
2447 }
2448
2449 IDBError SQLiteIDBBackingStore::iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData& data, IDBGetResult& result)
2450 {
2451     LOG(IndexedDB, "SQLiteIDBBackingStore::iterateCursor");
2452
2453     ASSERT(m_sqliteDB);
2454     ASSERT(m_sqliteDB->isOpen());
2455
2456     auto* cursor = m_cursors.get(cursorIdentifier);
2457     if (!cursor) {
2458         LOG_ERROR("Attempt to iterate a cursor that doesn't exist");
2459         return IDBError { UnknownError, "Attempt to iterate a cursor that doesn't exist"_s };
2460     }
2461
2462     ASSERT_UNUSED(transactionIdentifier, cursor->transaction()->transactionIdentifier() == transactionIdentifier);
2463
2464     if (!cursor->transaction() || !cursor->transaction()->inProgress()) {
2465         LOG_ERROR("Attempt to iterate a cursor without an in-progress transaction");
2466         return IDBError { UnknownError, "Attempt to iterate a cursor without an in-progress transaction"_s };
2467     }
2468
2469     auto key = data.keyData;
2470     auto primaryKey = data.primaryKeyData;
2471     auto count = data.count;
2472
2473     if (key.isValid()) {
2474         if (!cursor->iterate(key, primaryKey)) {
2475             LOG_ERROR("Attempt to iterate cursor failed");
2476             return IDBError { UnknownError, "Attempt to iterate cursor failed"_s };
2477         }
2478     } else {
2479         ASSERT(!primaryKey.isValid());
2480         if (!count)
2481             count = 1;
2482         if (!cursor->advance(count)) {
2483             LOG_ERROR("Attempt to advance cursor failed");
2484             return IDBError { UnknownError, "Attempt to advance cursor failed"_s };
2485         }
2486     }
2487
2488     cursor->currentData(result);
2489     return IDBError { };
2490 }
2491
2492 bool SQLiteIDBBackingStore::prefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier)
2493 {
2494     LOG(IndexedDB, "SQLiteIDBBackingStore::prefetchCursor");
2495
2496     ASSERT(m_sqliteDB);
2497     ASSERT(m_sqliteDB->isOpen());
2498
2499     auto* cursor = m_cursors.get(cursorIdentifier);
2500     if (!cursor || !cursor->transaction() || !cursor->transaction()->inProgress())
2501         return false;
2502
2503     ASSERT_UNUSED(transactionIdentifier, cursor->transaction()->transactionIdentifier() == transactionIdentifier);
2504
2505     return cursor->prefetch();
2506 }
2507
2508 IDBObjectStoreInfo* SQLiteIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
2509 {
2510     ASSERT(m_databaseInfo);
2511     return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
2512 }
2513
2514 void SQLiteIDBBackingStore::deleteBackingStore()
2515 {
2516     String dbFilename = fullDatabasePath();
2517
2518     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteBackingStore deleting file '%s' on disk", dbFilename.utf8().data());
2519
2520     Vector<String> blobFiles;
2521     {
2522         bool errored = true;
2523
2524         if (m_sqliteDB) {
2525             SQLiteStatement sql(*m_sqliteDB, "SELECT fileName FROM BlobFiles;"_s);
2526             if (sql.prepare() == SQLITE_OK) {
2527                 int result = sql.step();
2528                 while (result == SQLITE_ROW) {
2529                     blobFiles.append(sql.getColumnText(0));
2530                     result = sql.step();
2531                 }
2532
2533                 if (result == SQLITE_DONE)
2534                     errored = false;
2535             }
2536         }
2537
2538         if (errored)
2539             LOG_ERROR("Error getting all blob filenames to be deleted");
2540     }
2541
2542     String databaseDirectory = fullDatabaseDirectory();
2543     for (auto& file : blobFiles) {
2544         String fullPath = FileSystem::pathByAppendingComponent(databaseDirectory, file);
2545         if (!FileSystem::deleteFile(fullPath))
2546             LOG_ERROR("Error deleting blob file %s", fullPath.utf8().data());
2547     }
2548
2549     if (m_sqliteDB)
2550         closeSQLiteDB();
2551
2552     SQLiteFileSystem::deleteDatabaseFile(dbFilename);
2553     SQLiteFileSystem::deleteEmptyDatabaseDirectory(fullDatabaseDirectory());
2554     SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_absoluteDatabaseDirectory);
2555 }
2556
2557 void SQLiteIDBBackingStore::unregisterCursor(SQLiteIDBCursor& cursor)
2558 {
2559     ASSERT(m_cursors.contains(cursor.identifier()));
2560     m_cursors.remove(cursor.identifier());
2561 }
2562
2563 SQLiteStatement* SQLiteIDBBackingStore::cachedStatement(SQLiteIDBBackingStore::SQL sql, const char* statement)
2564 {
2565     if (sql >= SQL::Count) {
2566         LOG_ERROR("Invalid SQL statement ID passed to cachedStatement()");
2567         return nullptr;
2568     }
2569
2570     if (m_cachedStatements[static_cast<size_t>(sql)]) {
2571         if (m_cachedStatements[static_cast<size_t>(sql)]->reset() == SQLITE_OK)
2572             return m_cachedStatements[static_cast<size_t>(sql)].get();
2573         m_cachedStatements[static_cast<size_t>(sql)] = nullptr;
2574     }
2575
2576     if (m_sqliteDB) {
2577         m_cachedStatements[static_cast<size_t>(sql)] = std::make_unique<SQLiteStatement>(*m_sqliteDB, statement);
2578         if (m_cachedStatements[static_cast<size_t>(sql)]->prepare() != SQLITE_OK)
2579             m_cachedStatements[static_cast<size_t>(sql)] = nullptr;
2580     }
2581
2582     return m_cachedStatements[static_cast<size_t>(sql)].get();
2583 }
2584
2585 void SQLiteIDBBackingStore::closeSQLiteDB()
2586 {
2587     for (size_t i = 0; i < static_cast<int>(SQL::Count); ++i)
2588         m_cachedStatements[i] = nullptr;
2589
2590     if (m_sqliteDB)
2591         m_sqliteDB->close();
2592
2593     m_sqliteDB = nullptr;
2594 }
2595
2596 } // namespace IDBServer
2597 } // namespace WebCore
2598
2599 #endif // ENABLE(INDEXED_DATABASE)