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