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