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