b5d5256e2420f7b815ef5aa9e8fd7d7388526cd1
[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 "IDBGetResult.h"
35 #include "IDBKeyData.h"
36 #include "IDBObjectStoreInfo.h"
37 #include "IDBSerialization.h"
38 #include "IDBTransactionInfo.h"
39 #include "IndexKey.h"
40 #include "Logging.h"
41 #include "SQLiteDatabase.h"
42 #include "SQLiteFileSystem.h"
43 #include "SQLiteIDBCursor.h"
44 #include "SQLiteStatement.h"
45 #include "SQLiteTransaction.h"
46 #include "ThreadSafeDataBuffer.h"
47 #include <wtf/NeverDestroyed.h>
48
49 using namespace JSC;
50
51 namespace WebCore {
52 namespace IDBServer {
53
54 // Current version of the metadata schema being used in the metadata database.
55 static const int currentMetadataVersion = 1;
56
57 static int idbKeyCollate(int aLength, const void* aBuffer, int bLength, const void* bBuffer)
58 {
59     IDBKeyData a, b;
60     if (!deserializeIDBKeyData(static_cast<const uint8_t*>(aBuffer), aLength, a)) {
61         LOG_ERROR("Unable to deserialize key A in collation function.");
62
63         // There's no way to indicate an error to SQLite - we have to return a sorting decision.
64         // We arbitrarily choose "A > B"
65         return 1;
66     }
67     if (!deserializeIDBKeyData(static_cast<const uint8_t*>(bBuffer), bLength, b)) {
68         LOG_ERROR("Unable to deserialize key B in collation function.");
69
70         // There's no way to indicate an error to SQLite - we have to return a sorting decision.
71         // We arbitrarily choose "A > B"
72         return 1;
73     }
74
75     return a.compare(b);
76 }
77
78 static const String v1RecordsTableSchema(const String& tableName)
79 {
80     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)");
81 }
82
83 static const String& v1RecordsTableSchema()
84 {
85     static NeverDestroyed<WTF::String> v1RecordsTableSchemaString(v1RecordsTableSchema("Records"));
86     return v1RecordsTableSchemaString;
87 }
88
89 static const String& v1RecordsTableSchemaAlternate()
90 {
91     static NeverDestroyed<WTF::String> v1RecordsTableSchemaString(v1RecordsTableSchema("\"Records\""));
92     return v1RecordsTableSchemaString;
93 }
94
95 static const String v2RecordsTableSchema(const String& tableName)
96 {
97     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)");
98 }
99
100 static const String& v2RecordsTableSchema()
101 {
102     static NeverDestroyed<WTF::String> v2RecordsTableSchemaString(v2RecordsTableSchema("Records"));
103     return v2RecordsTableSchemaString;
104 }
105
106 static const String& v2RecordsTableSchemaAlternate()
107 {
108     static NeverDestroyed<WTF::String> v2RecordsTableSchemaString(v2RecordsTableSchema("\"Records\""));
109     return v2RecordsTableSchemaString;
110 }
111
112 static const String v1IndexRecordsTableSchema(const String& tableName)
113 {
114     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)");
115 }
116
117 static const String& v1IndexRecordsTableSchema()
118 {
119     static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("IndexRecords"));
120     return v1IndexRecordsTableSchemaString;
121 }
122
123 static const String& v1IndexRecordsTableSchemaAlternate()
124 {
125     static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("\"IndexRecords\""));
126     return v1IndexRecordsTableSchemaString;
127 }
128
129 static const String v2IndexRecordsTableSchema(const String& tableName)
130 {
131     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)");
132 }
133
134 static const String& v2IndexRecordsTableSchema()
135 {
136     static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("IndexRecords"));
137     return v2IndexRecordsTableSchemaString;
138 }
139
140 static const String& v2IndexRecordsTableSchemaAlternate()
141 {
142     static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("\"IndexRecords\""));
143     return v2IndexRecordsTableSchemaString;
144 }
145
146
147 SQLiteIDBBackingStore::SQLiteIDBBackingStore(const IDBDatabaseIdentifier& identifier, const String& databaseRootDirectory)
148     : m_identifier(identifier)
149 {
150     m_absoluteDatabaseDirectory = identifier.databaseDirectoryRelativeToRoot(databaseRootDirectory);
151 }
152
153 SQLiteIDBBackingStore::~SQLiteIDBBackingStore()
154 {
155     if (m_sqliteDB)
156         m_sqliteDB->close();
157
158     if (m_vm) {
159         JSLockHolder locker(m_vm.get());
160         m_globalObject.clear();
161         m_vm = nullptr;
162     }
163 }
164
165
166 void SQLiteIDBBackingStore::initializeVM()
167 {
168     if (!m_vm) {
169         ASSERT(!m_globalObject);
170         m_vm = VM::create();
171
172         JSLockHolder locker(m_vm.get());
173         m_globalObject.set(*m_vm, JSGlobalObject::create(*m_vm, JSGlobalObject::createStructure(*m_vm, jsNull())));
174     }
175 }
176
177 VM& SQLiteIDBBackingStore::vm()
178 {
179     initializeVM();
180     return *m_vm;
181 }
182
183 JSGlobalObject& SQLiteIDBBackingStore::globalObject()
184 {
185     initializeVM();
186     return **m_globalObject;
187 }
188
189 static bool createOrMigrateRecordsTableIfNecessary(SQLiteDatabase& database)
190 {
191     String currentSchema;
192     {
193         // Fetch the schema for an existing records table.
194         SQLiteStatement statement(database, "SELECT type, sql FROM sqlite_master WHERE tbl_name='Records'");
195         if (statement.prepare() != SQLITE_OK) {
196             LOG_ERROR("Unable to prepare statement to fetch schema for the Records table.");
197             return false;
198         }
199
200         int sqliteResult = statement.step();
201
202         // If there is no Records table at all, create it and then bail.
203         if (sqliteResult == SQLITE_DONE) {
204             if (!database.executeCommand(v2RecordsTableSchema())) {
205                 LOG_ERROR("Could not create Records table in database (%i) - %s", database.lastError(), database.lastErrorMsg());
206                 return false;
207             }
208
209             return true;
210         }
211
212         if (sqliteResult != SQLITE_ROW) {
213             LOG_ERROR("Error executing statement to fetch schema for the Records table.");
214             return false;
215         }
216
217         currentSchema = statement.getColumnText(1);
218     }
219
220     ASSERT(!currentSchema.isEmpty());
221
222     // If the schema in the backing store is the current schema, we're done.
223     if (currentSchema == v2RecordsTableSchema() || currentSchema == v2RecordsTableSchemaAlternate())
224         return true;
225
226     // If the record table is not the current schema then it must be one of the previous schemas.
227     // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
228     if (currentSchema != v1RecordsTableSchema() && currentSchema != v1RecordsTableSchemaAlternate())
229         RELEASE_ASSERT_NOT_REACHED();
230
231     SQLiteTransaction transaction(database);
232     transaction.begin();
233
234     // Create a temporary table with the correct schema and migrate all existing content over.
235     if (!database.executeCommand(v2RecordsTableSchema("_Temp_Records"))) {
236         LOG_ERROR("Could not create temporary records table in database (%i) - %s", database.lastError(), database.lastErrorMsg());
237         return false;
238     }
239
240     if (!database.executeCommand("INSERT INTO _Temp_Records SELECT * FROM Records")) {
241         LOG_ERROR("Could not migrate existing Records content (%i) - %s", database.lastError(), database.lastErrorMsg());
242         return false;
243     }
244
245     if (!database.executeCommand("DROP TABLE Records")) {
246         LOG_ERROR("Could not drop existing Records table (%i) - %s", database.lastError(), database.lastErrorMsg());
247         return false;
248     }
249
250     if (!database.executeCommand("ALTER TABLE _Temp_Records RENAME TO Records")) {
251         LOG_ERROR("Could not rename temporary Records table (%i) - %s", database.lastError(), database.lastErrorMsg());
252         return false;
253     }
254
255     transaction.commit();
256
257     return true;
258 }
259
260 bool SQLiteIDBBackingStore::ensureValidRecordsTable()
261 {
262     ASSERT(m_sqliteDB);
263     ASSERT(m_sqliteDB->isOpen());
264
265     if (!createOrMigrateRecordsTableIfNecessary(*m_sqliteDB))
266         return false;
267
268     // Whether the updated records table already existed or if it was just created and the data migrated over,
269     // make sure the uniqueness index exists.
270     if (!m_sqliteDB->executeCommand("CREATE UNIQUE INDEX IF NOT EXISTS RecordsIndex ON Records (objectStoreID, key);")) {
271         LOG_ERROR("Could not create RecordsIndex on Records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
272         return false;
273     }
274
275     return true;
276 }
277
278 bool SQLiteIDBBackingStore::ensureValidIndexRecordsTable()
279 {
280     ASSERT(m_sqliteDB);
281     ASSERT(m_sqliteDB->isOpen());
282
283     String currentSchema;
284     {
285         // Fetch the schema for an existing index record table.
286         SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='IndexRecords'");
287         if (statement.prepare() != SQLITE_OK) {
288             LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecords table.");
289             return false;
290         }
291
292         int sqliteResult = statement.step();
293
294         // If there is no IndexRecords table at all, create it and then bail.
295         if (sqliteResult == SQLITE_DONE) {
296             if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema())) {
297                 LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
298                 return false;
299             }
300
301             return true;
302         }
303
304         if (sqliteResult != SQLITE_ROW) {
305             LOG_ERROR("Error executing statement to fetch schema for the IndexRecords table.");
306             return false;
307         }
308
309         currentSchema = statement.getColumnText(1);
310     }
311
312     ASSERT(!currentSchema.isEmpty());
313
314     // If the schema in the backing store is the current schema, we're done.
315     if (currentSchema == v2IndexRecordsTableSchema() || currentSchema == v2IndexRecordsTableSchemaAlternate())
316         return true;
317
318     // If the record table is not the current schema then it must be one of the previous schemas.
319     // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
320     if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate())
321         RELEASE_ASSERT_NOT_REACHED();
322
323     SQLiteTransaction transaction(*m_sqliteDB);
324     transaction.begin();
325
326     // Create a temporary table with the correct schema and migrate all existing content over.
327     if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema("_Temp_IndexRecords"))) {
328         LOG_ERROR("Could not create temporary index records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
329         return false;
330     }
331
332     if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT * FROM IndexRecords")) {
333         LOG_ERROR("Could not migrate existing IndexRecords content (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
334         return false;
335     }
336
337     if (!m_sqliteDB->executeCommand("DROP TABLE IndexRecords")) {
338         LOG_ERROR("Could not drop existing IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
339         return false;
340     }
341
342     if (!m_sqliteDB->executeCommand("ALTER TABLE _Temp_IndexRecords RENAME TO IndexRecords")) {
343         LOG_ERROR("Could not rename temporary IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
344         return false;
345     }
346
347     transaction.commit();
348
349     return true;
350 }
351
352 std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo()
353 {
354     ASSERT(m_sqliteDB);
355     ASSERT(m_sqliteDB->isOpen());
356
357     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);")) {
358         LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
359         m_sqliteDB = nullptr;
360         return nullptr;
361     }
362
363     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);")) {
364         LOG_ERROR("Could not create ObjectStoreInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
365         m_sqliteDB = nullptr;
366         return nullptr;
367     }
368
369     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);")) {
370         LOG_ERROR("Could not create IndexInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
371         m_sqliteDB = nullptr;
372         return nullptr;
373     }
374
375     if (!ensureValidIndexRecordsTable()) {
376         LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
377         m_sqliteDB = nullptr;
378         return nullptr;
379     }
380
381     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);")) {
382         LOG_ERROR("Could not create KeyGenerators table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
383         m_sqliteDB = nullptr;
384         return nullptr;
385     }
386
387     {
388         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);"));
389         if (sql.prepare() != SQLITE_OK
390             || sql.bindInt(1, currentMetadataVersion) != SQLITE_OK
391             || sql.step() != SQLITE_DONE) {
392             LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
393             m_sqliteDB = nullptr;
394             return nullptr;
395         }
396     }
397     {
398         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseName', ?);"));
399         if (sql.prepare() != SQLITE_OK
400             || sql.bindText(1, m_identifier.databaseName()) != SQLITE_OK
401             || sql.step() != SQLITE_DONE) {
402             LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
403             m_sqliteDB = nullptr;
404             return nullptr;
405         }
406     }
407     {
408         // Database versions are defined to be a uin64_t in the spec but sqlite3 doesn't support native binding of unsigned integers.
409         // Therefore we'll store the version as a String.
410         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseVersion', ?);"));
411         if (sql.prepare() != SQLITE_OK
412             || sql.bindText(1, String::number(0)) != SQLITE_OK
413             || sql.step() != SQLITE_DONE) {
414             LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
415             m_sqliteDB = nullptr;
416             return nullptr;
417         }
418     }
419
420     if (!m_sqliteDB->executeCommand(ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MaxObjectStoreID', 1);"))) {
421         LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
422         m_sqliteDB = nullptr;
423         return nullptr;
424     }
425
426     // This initial database info matches the default values we just put into the metadata database.
427     return std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
428 }
429
430 std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseInfo()
431 {
432     ASSERT(m_sqliteDB);
433
434     if (!m_sqliteDB->tableExists(ASCIILiteral("IDBDatabaseInfo")))
435         return nullptr;
436
437     String databaseName;
438     {
439         SQLiteStatement sql(*m_sqliteDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseName';");
440         if (sql.isColumnNull(0))
441             return nullptr;
442         databaseName = sql.getColumnText(0);
443         if (databaseName != m_identifier.databaseName()) {
444             LOG_ERROR("Database name in the info database ('%s') does not match the expected name ('%s')", databaseName.utf8().data(), m_identifier.databaseName().utf8().data());
445             return nullptr;
446         }
447     }
448     uint64_t databaseVersion;
449     {
450         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseVersion';"));
451         if (sql.isColumnNull(0))
452             return nullptr;
453         String stringVersion = sql.getColumnText(0);
454         bool ok;
455         databaseVersion = stringVersion.toUInt64Strict(&ok);
456         if (!ok) {
457             LOG_ERROR("Database version on disk ('%s') does not cleanly convert to an unsigned 64-bit integer version", stringVersion.utf8().data());
458             return nullptr;
459         }
460     }
461
462     auto databaseInfo = std::make_unique<IDBDatabaseInfo>(databaseName, databaseVersion);
463
464     {
465         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT id, name, keyPath, autoInc, maxIndexID FROM ObjectStoreInfo;"));
466         if (sql.prepare() != SQLITE_OK)
467             return nullptr;
468
469         int result = sql.step();
470         while (result == SQLITE_ROW) {
471             uint64_t objectStoreID = sql.getColumnInt64(0);
472             String objectStoreName = sql.getColumnText(1);
473
474             Vector<char> keyPathBuffer;
475             sql.getColumnBlobAsVector(2, keyPathBuffer);
476
477             IDBKeyPath objectStoreKeyPath;
478             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), objectStoreKeyPath)) {
479                 LOG_ERROR("Unable to extract key path from database");
480                 return nullptr;
481             }
482
483             bool autoIncrement = sql.getColumnInt(3);
484
485             databaseInfo->addExistingObjectStore({ objectStoreID, objectStoreName, objectStoreKeyPath, autoIncrement });
486
487             result = sql.step();
488         }
489
490         if (result != SQLITE_DONE) {
491             LOG_ERROR("Error fetching object store info from database on disk");
492             return nullptr;
493         }
494     }
495
496     {
497         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT id, name, objectStoreID, keyPath, isUnique, multiEntry FROM IndexInfo;"));
498         if (sql.prepare() != SQLITE_OK)
499             return nullptr;
500
501         int result = sql.step();
502         while (result == SQLITE_ROW) {
503             uint64_t indexID = sql.getColumnInt64(0);
504             String indexName = sql.getColumnText(1);
505             uint64_t objectStoreID = sql.getColumnInt64(2);
506
507             Vector<char> keyPathBuffer;
508             sql.getColumnBlobAsVector(3, keyPathBuffer);
509
510             IDBKeyPath indexKeyPath;
511             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), indexKeyPath)) {
512                 LOG_ERROR("Unable to extract key path from database");
513                 return nullptr;
514             }
515
516             bool unique = sql.getColumnInt(4);
517             bool multiEntry = sql.getColumnInt(5);
518
519             auto objectStore = databaseInfo->infoForExistingObjectStore(objectStoreID);
520             if (!objectStore) {
521                 LOG_ERROR("Found index referring to a non-existant object store");
522                 return nullptr;
523             }
524
525             objectStore->addExistingIndex({ indexID, objectStoreID, indexName, indexKeyPath, unique, multiEntry });
526
527             result = sql.step();
528         }
529
530         if (result != SQLITE_DONE) {
531             LOG_ERROR("Error fetching index info from database on disk");
532             return nullptr;
533         }
534     }
535
536     return databaseInfo;
537 }
538
539 String SQLiteIDBBackingStore::filenameForDatabaseName() const
540 {
541     ASSERT(!m_identifier.databaseName().isNull());
542
543     if (m_identifier.databaseName().isEmpty())
544         return "%00";
545
546     String filename = encodeForFileName(m_identifier.databaseName());
547     filename.replace('.', "%2E");
548
549     return filename;
550 }
551
552 String SQLiteIDBBackingStore::fullDatabaseDirectory() const
553 {
554     ASSERT(!m_identifier.databaseName().isNull());
555
556     return pathByAppendingComponent(m_absoluteDatabaseDirectory, filenameForDatabaseName());
557 }
558
559 String SQLiteIDBBackingStore::fullDatabasePath() const
560 {
561     ASSERT(!m_identifier.databaseName().isNull());
562
563     return pathByAppendingComponent(fullDatabaseDirectory(), "IndexedDB.sqlite3");
564 }
565
566 const IDBDatabaseInfo& SQLiteIDBBackingStore::getOrEstablishDatabaseInfo()
567 {
568     LOG(IndexedDB, "SQLiteIDBBackingStore::getOrEstablishDatabaseInfo - database %s", m_identifier.databaseName().utf8().data());
569
570     if (m_databaseInfo)
571         return *m_databaseInfo;
572
573     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
574
575     makeAllDirectories(fullDatabaseDirectory());
576     String dbFilename = fullDatabasePath();
577
578     m_sqliteDB = std::make_unique<SQLiteDatabase>();
579     if (!m_sqliteDB->open(dbFilename)) {
580         LOG_ERROR("Failed to open SQLite database at path '%s'", dbFilename.utf8().data());
581         m_sqliteDB = nullptr;
582     }
583
584     if (!m_sqliteDB)
585         return *m_databaseInfo;
586
587     m_sqliteDB->setCollationFunction("IDBKEY", [this](int aLength, const void* a, int bLength, const void* b) {
588         return idbKeyCollate(aLength, a, bLength, b);
589     });
590
591     if (!ensureValidRecordsTable()) {
592         LOG_ERROR("Error creating or migrating Records table in database");
593         m_sqliteDB = nullptr;
594         return *m_databaseInfo;
595     }
596
597     auto databaseInfo = extractExistingDatabaseInfo();
598     if (!databaseInfo)
599         databaseInfo = createAndPopulateInitialDatabaseInfo();
600
601     if (!databaseInfo)
602         LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());
603     else
604         m_databaseInfo = WTFMove(databaseInfo);
605
606     return *m_databaseInfo;
607 }
608
609 IDBError SQLiteIDBBackingStore::beginTransaction(const IDBTransactionInfo& info)
610 {
611     LOG(IndexedDB, "SQLiteIDBBackingStore::beginTransaction - %s", info.identifier().loggingString().utf8().data());
612
613     ASSERT(m_sqliteDB);
614     ASSERT(m_sqliteDB->isOpen());
615     ASSERT(m_databaseInfo);
616
617     auto addResult = m_transactions.add(info.identifier(), nullptr);
618     if (!addResult.isNewEntry) {
619         LOG_ERROR("Attempt to establish transaction identifier that already exists");
620         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to establish transaction identifier that already exists") };
621     }
622
623     addResult.iterator->value = std::make_unique<SQLiteIDBTransaction>(*this, info);
624
625     auto error = addResult.iterator->value->begin(*m_sqliteDB);
626     if (error.isNull() && info.mode() == IndexedDB::TransactionMode::VersionChange)
627         m_originalDatabaseInfoBeforeVersionChange = std::make_unique<IDBDatabaseInfo>(*m_databaseInfo);
628
629     return error;
630 }
631
632 IDBError SQLiteIDBBackingStore::abortTransaction(const IDBResourceIdentifier& identifier)
633 {
634     LOG(IndexedDB, "SQLiteIDBBackingStore::abortTransaction - %s", identifier.loggingString().utf8().data());
635
636     ASSERT(m_sqliteDB);
637     ASSERT(m_sqliteDB->isOpen());
638
639     auto transaction = m_transactions.take(identifier);
640     if (!transaction) {
641         LOG_ERROR("Attempt to commit a transaction that hasn't been established");
642         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to abort a transaction that hasn't been established") };
643     }
644
645
646     if (transaction->mode() == IndexedDB::TransactionMode::VersionChange) {
647         ASSERT(m_originalDatabaseInfoBeforeVersionChange);
648         m_databaseInfo = WTFMove(m_originalDatabaseInfoBeforeVersionChange);
649     }
650
651     return transaction->abort();
652 }
653
654 IDBError SQLiteIDBBackingStore::commitTransaction(const IDBResourceIdentifier& identifier)
655 {
656     LOG(IndexedDB, "SQLiteIDBBackingStore::commitTransaction - %s", identifier.loggingString().utf8().data());
657
658     ASSERT(m_sqliteDB);
659     ASSERT(m_sqliteDB->isOpen());
660
661     auto transaction = m_transactions.take(identifier);
662     if (!transaction) {
663         LOG_ERROR("Attempt to commit a transaction that hasn't been established");
664         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to commit a transaction that hasn't been established") };
665     }
666
667     auto error = transaction->commit();
668     if (!error.isNull()) {
669         if (transaction->mode() == IndexedDB::TransactionMode::VersionChange) {
670             ASSERT(m_originalDatabaseInfoBeforeVersionChange);
671             m_databaseInfo = WTFMove(m_originalDatabaseInfoBeforeVersionChange);
672         }
673     } else
674         m_originalDatabaseInfoBeforeVersionChange = nullptr;
675
676     return error;
677 }
678
679 IDBError SQLiteIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
680 {
681     LOG(IndexedDB, "SQLiteIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
682
683     ASSERT(m_sqliteDB);
684     ASSERT(m_sqliteDB->isOpen());
685
686     auto* transaction = m_transactions.get(transactionIdentifier);
687     if (!transaction || !transaction->inProgress()) {
688         LOG_ERROR("Attempt to create an object store without an in-progress transaction");
689         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to create an object store without an in-progress transaction") };
690     }
691     if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
692         LOG_ERROR("Attempt to create an object store in a non-version-change transaction");
693         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to create an object store in a non-version-change transaction") };
694     }
695
696     RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(info.keyPath());
697     if (!keyPathBlob) {
698         LOG_ERROR("Unable to serialize IDBKeyPath to save in database for new object store");
699         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKeyPath to save in database for new object store") };
700     }
701
702     {
703         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO ObjectStoreInfo VALUES (?, ?, ?, ?, ?);"));
704         if (sql.prepare() != SQLITE_OK
705             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
706             || sql.bindText(2, info.name()) != SQLITE_OK
707             || sql.bindBlob(3, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
708             || sql.bindInt(4, info.autoIncrement()) != SQLITE_OK
709             || sql.bindInt64(5, info.maxIndexID()) != SQLITE_OK
710             || sql.step() != SQLITE_DONE) {
711             LOG_ERROR("Could not add object store '%s' to ObjectStoreInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
712             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not create object store") };
713         }
714     }
715
716     {
717         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, 0);"));
718         if (sql.prepare() != SQLITE_OK
719             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
720             || sql.step() != SQLITE_DONE) {
721             LOG_ERROR("Could not seed initial key generator value for ObjectStoreInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
722             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not seed initial key generator value for object store") };
723         }
724     }
725
726     m_databaseInfo->addExistingObjectStore(info);
727
728     return { };
729 }
730
731 IDBError SQLiteIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
732 {
733     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteObjectStore - object store %" PRIu64, objectStoreIdentifier);
734
735     ASSERT(m_sqliteDB);
736     ASSERT(m_sqliteDB->isOpen());
737
738     auto* transaction = m_transactions.get(transactionIdentifier);
739     if (!transaction || !transaction->inProgress()) {
740         LOG_ERROR("Attempt to delete an object store without an in-progress transaction");
741         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete an object store without an in-progress transaction") };
742     }
743     if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
744         LOG_ERROR("Attempt to delete an object store in a non-version-change transaction");
745         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete an object store in a non-version-change transaction") };
746     }
747
748     // Delete the ObjectStore record
749     {
750         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM ObjectStoreInfo WHERE id = ?;"));
751         if (sql.prepare() != SQLITE_OK
752             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
753             || sql.step() != SQLITE_DONE) {
754             LOG_ERROR("Could not delete object store id %" PRIi64 " from ObjectStoreInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
755             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete object store") };
756         }
757     }
758
759     // Delete the ObjectStore's key generator record if there is one.
760     {
761         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM KeyGenerators WHERE objectStoreID = ?;"));
762         if (sql.prepare() != SQLITE_OK
763             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
764             || sql.step() != SQLITE_DONE) {
765             LOG_ERROR("Could not delete object store from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
766             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete key generator for deleted object store") };
767         }
768     }
769
770     // Delete all associated records
771     {
772         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
773         if (sql.prepare() != SQLITE_OK
774             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
775             || sql.step() != SQLITE_DONE) {
776             LOG_ERROR("Could not delete records for object store %" PRIi64 " (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
777             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete records for deleted object store") };
778         }
779     }
780
781     // Delete all associated Indexes
782     {
783         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE objectStoreID = ?;"));
784         if (sql.prepare() != SQLITE_OK
785             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
786             || sql.step() != SQLITE_DONE) {
787             LOG_ERROR("Could not delete index from IndexInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
788             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete IDBIndex for deleted object store") };
789         }
790     }
791
792     // Delete all associated Index records
793     {
794         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
795         if (sql.prepare() != SQLITE_OK
796             || sql.bindInt64(1, objectStoreIdentifier) != SQLITE_OK
797             || sql.step() != SQLITE_DONE) {
798             LOG_ERROR("Could not delete index records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
799             return { IDBDatabaseException::UnknownError, ASCIILiteral("Could not delete IDBIndex records for deleted object store") };
800         }
801     }
802
803     m_databaseInfo->deleteObjectStore(objectStoreIdentifier);
804
805     return true;
806 }
807
808 IDBError SQLiteIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID)
809 {
810     LOG(IndexedDB, "SQLiteIDBBackingStore::clearObjectStore - object store %" PRIu64, objectStoreID);
811
812     ASSERT(m_sqliteDB);
813     ASSERT(m_sqliteDB->isOpen());
814
815     auto* transaction = m_transactions.get(transactionIdentifier);
816     if (!transaction || !transaction->inProgress()) {
817         LOG_ERROR("Attempt to clear an object store without an in-progress transaction");
818         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to clear an object store without an in-progress transaction") };
819     }
820     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
821         LOG_ERROR("Attempt to clear an object store in a read-only transaction");
822         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to clear an object store in a read-only transaction") };
823     }
824
825     {
826         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
827         if (sql.prepare() != SQLITE_OK
828             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
829             || sql.step() != SQLITE_DONE) {
830             LOG_ERROR("Could not clear records from object store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
831             return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to clear object store") };
832         }
833     }
834
835     {
836         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
837         if (sql.prepare() != SQLITE_OK
838             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
839             || sql.step() != SQLITE_DONE) {
840             LOG_ERROR("Could not delete records from index record store id %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
841             return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to delete index records while clearing object store") };
842         }
843     }
844
845     transaction->notifyCursorsOfChanges(objectStoreID);
846
847     return { };
848 }
849
850 IDBError SQLiteIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
851 {
852     LOG(IndexedDB, "SQLiteIDBBackingStore::createIndex - ObjectStore %" PRIu64 ", Index %" PRIu64, info.objectStoreIdentifier(), info.identifier());
853     ASSERT(m_sqliteDB);
854     ASSERT(m_sqliteDB->isOpen());
855
856     auto* transaction = m_transactions.get(transactionIdentifier);
857     if (!transaction || !transaction->inProgress()) {
858         LOG_ERROR("Attempt to create an index without an in-progress transaction");
859         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to create an index without an in-progress transaction") };
860     }
861     if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
862         LOG_ERROR("Attempt to create an index in a non-version-change transaction");
863         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to create an index in a non-version-change transaction") };
864     }
865
866     RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(info.keyPath());
867     if (!keyPathBlob) {
868         LOG_ERROR("Unable to serialize IDBKeyPath to save in database");
869         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKeyPath to create index in database") };
870     }
871
872     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);"));
873     if (sql.prepare() != SQLITE_OK
874         || sql.bindInt64(1, info.identifier()) != SQLITE_OK
875         || sql.bindText(2, info.name()) != SQLITE_OK
876         || sql.bindInt64(3, info.objectStoreIdentifier()) != SQLITE_OK
877         || sql.bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLITE_OK
878         || sql.bindInt(5, info.unique()) != SQLITE_OK
879         || sql.bindInt(6, info.multiEntry()) != SQLITE_OK
880         || sql.step() != SQLITE_DONE) {
881         LOG_ERROR("Could not add index '%s' to IndexInfo table (%i) - %s", info.name().utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
882         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to create index in database") };
883     }
884
885     // Write index records for any records that already exist in this object store.
886
887     auto cursor = transaction->maybeOpenBackingStoreCursor(info.objectStoreIdentifier(), 0, IDBKeyRangeData::allKeys());
888
889     if (!cursor) {
890         LOG_ERROR("Cannot open cursor to populate indexes in database");
891         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to populate indexes in database") };
892     }
893
894     while (!cursor->currentKey().isNull()) {
895         auto& key = cursor->currentKey();
896         auto valueBuffer = ThreadSafeDataBuffer::copyVector(cursor->currentValueBuffer());
897
898         IDBError error = updateOneIndexForAddRecord(info, key, valueBuffer);
899         if (!error.isNull()) {
900             SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
901             if (sql.prepare() != SQLITE_OK
902                 || sql.bindInt64(1, info.identifier()) != SQLITE_OK
903                 || sql.bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
904                 || sql.step() != SQLITE_DONE) {
905                 LOG_ERROR("Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database");
906                 return { IDBDatabaseException::UnknownError, ASCIILiteral("Index creation failed due to uniqueness constraint failure, but there was an error deleting the Index record from the database") };
907             }
908
909             return error;
910         }
911
912         if (!cursor->advance(1)) {
913             LOG_ERROR("Error advancing cursor while indexing existing records for new index.");
914             return { IDBDatabaseException::UnknownError, ASCIILiteral("Error advancing cursor while indexing existing records for new index") };
915         }
916     }
917
918     auto* objectStore = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
919     ASSERT(objectStore);
920     objectStore->addExistingIndex(info);
921
922     return { };
923 }
924
925 IDBError SQLiteIDBBackingStore::uncheckedHasIndexRecord(const IDBIndexInfo& info, const IDBKeyData& indexKey, bool& hasRecord)
926 {
927     hasRecord = false;
928
929     RefPtr<SharedBuffer> indexKeyBuffer = serializeIDBKeyData(indexKey);
930     if (!indexKeyBuffer) {
931         LOG_ERROR("Unable to serialize index key to be stored in the database");
932         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKey to check for index record in database") };
933     }
934
935     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT rowid FROM IndexRecords WHERE indexID = ? AND objectStoreID = ? AND key = CAST(? AS TEXT);"));
936     if (sql.prepare() != SQLITE_OK
937         || sql.bindInt64(1, info.identifier()) != SQLITE_OK
938         || sql.bindInt64(2, info.objectStoreIdentifier()) != SQLITE_OK
939         || sql.bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK) {
940         LOG_ERROR("Error checking for index record in database");
941         return { IDBDatabaseException::UnknownError, ASCIILiteral("Error checking for index record in database") };
942     }
943
944     int sqlResult = sql.step();
945     if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
946         return { };
947
948     if (sqlResult != SQLITE_ROW) {
949         // There was an error fetching the record from the database.
950         LOG_ERROR("Could not check if key exists in index (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
951         return { IDBDatabaseException::UnknownError, ASCIILiteral("Error checking for existence of IDBKey in index") };
952     }
953
954     hasRecord = true;
955     return { };
956 }
957
958 IDBError SQLiteIDBBackingStore::uncheckedPutIndexKey(const IDBIndexInfo& info, const IDBKeyData& key, const IndexKey& indexKey)
959 {
960     LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexKey - (%" PRIu64 ") %s, %s", info.identifier(), key.loggingString().utf8().data(), indexKey.asOneKey().loggingString().utf8().data());
961
962     Vector<IDBKeyData> indexKeys;
963     if (info.multiEntry())
964         indexKeys = indexKey.multiEntry();
965     else
966         indexKeys.append(indexKey.asOneKey());
967
968     if (info.unique()) {
969         bool hasRecord;
970         IDBError error;
971         for (auto& indexKey : indexKeys) {
972             error = uncheckedHasIndexRecord(info, indexKey, hasRecord);
973             if (!error.isNull())
974                 return error;
975             if (hasRecord)
976                 return IDBError(IDBDatabaseException::ConstraintError);
977         }
978     }
979
980     for (auto& indexKey : indexKeys) {
981         auto error = uncheckedPutIndexRecord(info.objectStoreIdentifier(), info.identifier(), key, indexKey);
982         if (!error.isNull()) {
983             LOG_ERROR("Unable to put index record for newly created index");
984             return error;
985         }
986     }
987
988     return { };
989 }
990
991 IDBError SQLiteIDBBackingStore::uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData& keyValue, const WebCore::IDBKeyData& indexKey)
992 {
993     LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexRecord - %s, %s", keyValue.loggingString().utf8().data(), indexKey.loggingString().utf8().data());
994
995     RefPtr<SharedBuffer> indexKeyBuffer = serializeIDBKeyData(indexKey);
996     if (!indexKeyBuffer) {
997         LOG_ERROR("Unable to serialize index key to be stored in the database");
998         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize index key to be stored in the database") };
999     }
1000
1001     RefPtr<SharedBuffer> valueBuffer = serializeIDBKeyData(keyValue);
1002     if (!valueBuffer) {
1003         LOG_ERROR("Unable to serialize the value to be stored in the database");
1004         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize value to be stored in the database") };
1005     }
1006
1007     {
1008         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT));"));
1009         if (sql.prepare() != SQLITE_OK
1010             || sql.bindInt64(1, indexID) != SQLITE_OK
1011             || sql.bindInt64(2, objectStoreID) != SQLITE_OK
1012             || sql.bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK
1013             || sql.bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLITE_OK
1014             || sql.step() != SQLITE_DONE) {
1015             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());
1016             return { IDBDatabaseException::UnknownError, ASCIILiteral("Error putting index record into database") };
1017         }
1018     }
1019
1020     return { };
1021 }
1022
1023
1024 IDBError SQLiteIDBBackingStore::deleteIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
1025 {
1026     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteIndex - object store %" PRIu64, objectStoreIdentifier);
1027
1028     ASSERT(m_sqliteDB);
1029     ASSERT(m_sqliteDB->isOpen());
1030
1031     auto* transaction = m_transactions.get(transactionIdentifier);
1032     if (!transaction || !transaction->inProgress()) {
1033         LOG_ERROR("Attempt to delete index without an in-progress transaction");
1034         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete index without an in-progress transaction") };
1035     }
1036
1037     if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
1038         LOG_ERROR("Attempt to delete index during a non-version-change transaction");
1039         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete index during a non-version-change transaction") };
1040     }
1041
1042     {
1043         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
1044         if (sql.prepare() != SQLITE_OK
1045             || sql.bindInt64(1, indexIdentifier) != SQLITE_OK
1046             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1047             || sql.step() != SQLITE_DONE) {
1048             LOG_ERROR("Could not delete index id %" PRIi64 " from IndexInfo table (%i) - %s", objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1049             return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting index from database") };
1050         }
1051     }
1052
1053     {
1054         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE indexID = ? AND objectStoreID = ?;"));
1055         if (sql.prepare() != SQLITE_OK
1056             || sql.bindInt64(1, indexIdentifier) != SQLITE_OK
1057             || sql.bindInt64(2, objectStoreIdentifier) != SQLITE_OK
1058             || sql.step() != SQLITE_DONE) {
1059             LOG_ERROR("Could not delete index records for index id %" PRIi64 " from IndexRecords table (%i) - %s", indexIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1060             return { IDBDatabaseException::UnknownError, ASCIILiteral("Error deleting index records from database") };
1061         }
1062     }
1063
1064     auto* objectStore = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
1065     ASSERT(objectStore);
1066     objectStore->deleteIndex(indexIdentifier);
1067
1068     return { };
1069 }
1070
1071 IDBError SQLiteIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyData& keyData, bool& keyExists)
1072 {
1073     LOG(IndexedDB, "SQLiteIDBBackingStore::keyExistsInObjectStore - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreID);
1074
1075     ASSERT(m_sqliteDB);
1076     ASSERT(m_sqliteDB->isOpen());
1077
1078     keyExists = false;
1079
1080     auto* transaction = m_transactions.get(transactionIdentifier);
1081     if (!transaction || !transaction->inProgress()) {
1082         LOG_ERROR("Attempt to see if key exists in objectstore without an in-progress transaction");
1083         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to see if key exists in objectstore without an in-progress transaction") };
1084     }
1085
1086     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1087     if (!keyBuffer) {
1088         LOG_ERROR("Unable to serialize IDBKey to check for existence in object store");
1089         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKey to check for existence in object store") };
1090     }
1091     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT key FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT) LIMIT 1;"));
1092     if (sql.prepare() != SQLITE_OK
1093         || sql.bindInt64(1, objectStoreID) != SQLITE_OK
1094         || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK) {
1095         LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1096         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to check for existence of IDBKey in object store") };
1097     }
1098
1099     int sqlResult = sql.step();
1100     if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE)
1101         return { };
1102
1103     if (sqlResult != SQLITE_ROW) {
1104         // There was an error fetching the record from the database.
1105         LOG_ERROR("Could not check if key exists in object store (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1106         return { IDBDatabaseException::UnknownError, ASCIILiteral("Error checking for existence of IDBKey in object store") };
1107     }
1108
1109     keyExists = true;
1110     return { };
1111 }
1112
1113 IDBError SQLiteIDBBackingStore::deleteRecord(SQLiteIDBTransaction& transaction, int64_t objectStoreID, const IDBKeyData& keyData)
1114 {
1115     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteRecord - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreID);
1116
1117     ASSERT(m_sqliteDB);
1118     ASSERT(m_sqliteDB->isOpen());
1119     ASSERT(transaction.inProgress());
1120     ASSERT(transaction.mode() != IndexedDB::TransactionMode::ReadOnly);
1121     UNUSED_PARAM(transaction);
1122
1123     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1124     if (!keyBuffer) {
1125         LOG_ERROR("Unable to serialize IDBKeyData to be removed from the database");
1126         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKeyData to be removed from the database") };
1127     }
1128
1129     // Delete record from object store
1130     {
1131         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
1132
1133         if (sql.prepare() != SQLITE_OK
1134             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
1135             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1136             || sql.step() != SQLITE_DONE) {
1137             LOG_ERROR("Could not delete record from object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1138             return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete record from object store") };
1139         }
1140     }
1141
1142     // Delete record from indexes store
1143     {
1144         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
1145
1146         if (sql.prepare() != SQLITE_OK
1147             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
1148             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1149             || sql.step() != SQLITE_DONE) {
1150             LOG_ERROR("Could not delete record from indexes for object store %" PRIi64 " (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1151             return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to delete index entries for object store record") };
1152         }
1153     }
1154
1155     return { };
1156 }
1157
1158 IDBError SQLiteIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyRangeData& keyRange)
1159 {
1160     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteRange - range %s, object store %" PRIu64, keyRange.loggingString().utf8().data(), objectStoreID);
1161
1162     ASSERT(m_sqliteDB);
1163     ASSERT(m_sqliteDB->isOpen());
1164
1165     auto* transaction = m_transactions.get(transactionIdentifier);
1166     if (!transaction || !transaction->inProgress()) {
1167         LOG_ERROR("Attempt to delete range from database without an in-progress transaction");
1168         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete range from database without an in-progress transaction") };
1169     }
1170     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
1171         LOG_ERROR("Attempt to delete records from an object store in a read-only transaction");
1172         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to delete records from an object store in a read-only transaction") };
1173     }
1174
1175     // If the range to delete is exactly one key we can delete it right now.
1176     if (keyRange.isExactlyOneKey()) {
1177         auto error = deleteRecord(*transaction, objectStoreID, keyRange.lowerKey);
1178         if (!error.isNull()) {
1179             LOG_ERROR("Failed to delete record for key '%s'", keyRange.lowerKey.loggingString().utf8().data());
1180             return error;
1181         }
1182
1183         return { };
1184     }
1185
1186     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreID, 0, keyRange);
1187     if (!cursor) {
1188         LOG_ERROR("Cannot open cursor to delete range of records from the database");
1189         return { IDBDatabaseException::UnknownError, ASCIILiteral("Cannot open cursor to delete range of records from the database") };
1190     }
1191
1192     Vector<IDBKeyData> keys;
1193     while (!cursor->didComplete() && !cursor->didError()) {
1194         keys.append(cursor->currentKey());
1195         cursor->advance(1);
1196     }
1197
1198     if (cursor->didError()) {
1199         LOG_ERROR("Cursor failed while accumulating range of records from the database");
1200         return { IDBDatabaseException::UnknownError, ASCIILiteral("Cursor failed while accumulating range of records from the database") };
1201     }
1202
1203     IDBError error;
1204     for (auto& key : keys) {
1205         error = deleteRecord(*transaction, objectStoreID, key);
1206         if (!error.isNull()) {
1207             LOG_ERROR("deleteRange: Error deleting keys in range");
1208             break;
1209         }
1210     }
1211
1212     transaction->notifyCursorsOfChanges(objectStoreID);
1213
1214     return error;
1215 }
1216
1217 IDBError SQLiteIDBBackingStore::updateOneIndexForAddRecord(const IDBIndexInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value)
1218 {
1219     JSLockHolder locker(vm());
1220
1221     auto jsValue = deserializeIDBValueDataToJSValue(*globalObject().globalExec(), value);
1222     if (jsValue.isUndefinedOrNull())
1223         return { };
1224
1225     IndexKey indexKey;
1226     generateIndexKeyForValue(*m_globalObject->globalExec(), info, jsValue, indexKey);
1227
1228     if (indexKey.isNull())
1229         return { };
1230
1231     return uncheckedPutIndexKey(info, key, indexKey);
1232 }
1233
1234 IDBError SQLiteIDBBackingStore::updateAllIndexesForAddRecord(const IDBObjectStoreInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value)
1235 {
1236     JSLockHolder locker(vm());
1237
1238     auto jsValue = deserializeIDBValueDataToJSValue(*globalObject().globalExec(), value);
1239     if (jsValue.isUndefinedOrNull())
1240         return { };
1241
1242     IDBError error;
1243     bool anyRecordsSucceeded = false;
1244     for (auto& index : info.indexMap().values()) {
1245         IndexKey indexKey;
1246         generateIndexKeyForValue(*m_globalObject->globalExec(), index, jsValue, indexKey);
1247
1248         if (indexKey.isNull())
1249             continue;
1250
1251         error = uncheckedPutIndexKey(index, key, indexKey);
1252         if (!error.isNull())
1253             break;
1254
1255         anyRecordsSucceeded = true;
1256     }
1257
1258     if (!error.isNull() && anyRecordsSucceeded) {
1259         RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(key);
1260
1261         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
1262
1263         if (sql.prepare() != SQLITE_OK
1264             || sql.bindInt64(1, info.identifier()) != SQLITE_OK
1265             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1266             || sql.step() != SQLITE_DONE) {
1267             LOG_ERROR("Adding one Index record failed, but failed to remove all others that previously succeeded");
1268             return { IDBDatabaseException::UnknownError, ASCIILiteral("Adding one Index record failed, but failed to remove all others that previously succeeded") };
1269         }
1270     }
1271
1272     return error;
1273 }
1274
1275 IDBError SQLiteIDBBackingStore::addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& objectStoreInfo, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
1276 {
1277     LOG(IndexedDB, "SQLiteIDBBackingStore::addRecord - key %s, object store %" PRIu64, keyData.loggingString().utf8().data(), objectStoreInfo.identifier());
1278
1279     ASSERT(m_sqliteDB);
1280     ASSERT(m_sqliteDB->isOpen());
1281     ASSERT(value.data());
1282
1283     auto* transaction = m_transactions.get(transactionIdentifier);
1284     if (!transaction || !transaction->inProgress()) {
1285         LOG_ERROR("Attempt to store a record in an object store without an in-progress transaction");
1286         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to store a record in an object store without an in-progress transaction") };
1287     }
1288     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
1289         LOG_ERROR("Attempt to store a record in an object store in a read-only transaction");
1290         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to store a record in an object store in a read-only transaction") };
1291     }
1292
1293     RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
1294     if (!keyBuffer) {
1295         LOG_ERROR("Unable to serialize IDBKey to be stored in an object store");
1296         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKey to be stored in an object store") };
1297     }
1298     {
1299         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO Records VALUES (?, CAST(? AS TEXT), ?);"));
1300         if (sql.prepare() != SQLITE_OK
1301             || sql.bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
1302             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1303             || sql.bindBlob(3, value.data()->data(), value.data()->size()) != SQLITE_OK
1304             || sql.step() != SQLITE_DONE) {
1305             LOG_ERROR("Could not put record for object store %" PRIi64 " in Records table (%i) - %s", objectStoreInfo.identifier(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1306             return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to store record in object store") };
1307         }
1308     }
1309
1310     auto error = updateAllIndexesForAddRecord(objectStoreInfo, keyData, value);
1311
1312     if (!error.isNull()) {
1313         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
1314         if (sql.prepare() != SQLITE_OK
1315             || sql.bindInt64(1, objectStoreInfo.identifier()) != SQLITE_OK
1316             || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLITE_OK
1317             || sql.step() != SQLITE_DONE) {
1318             LOG_ERROR("Indexing new object store record failed, but unable to remove the object store record itself");
1319             return { IDBDatabaseException::UnknownError, ASCIILiteral("Indexing new object store record failed, but unable to remove the object store record itself") };
1320         }
1321     }
1322
1323     transaction->notifyCursorsOfChanges(objectStoreInfo.identifier());
1324
1325     return error;
1326 }
1327
1328 IDBError SQLiteIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, const IDBKeyRangeData& keyRange, ThreadSafeDataBuffer& resultValue)
1329 {
1330     LOG(IndexedDB, "SQLiteIDBBackingStore::getRecord - key range %s, object store %" PRIu64, keyRange.loggingString().utf8().data(), objectStoreID);
1331
1332     ASSERT(m_sqliteDB);
1333     ASSERT(m_sqliteDB->isOpen());
1334
1335     auto* transaction = m_transactions.get(transactionIdentifier);
1336     if (!transaction || !transaction->inProgress()) {
1337         LOG_ERROR("Attempt to get a record from database without an in-progress transaction");
1338         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to get a record from database without an in-progress transaction") };
1339     }
1340
1341     auto key = keyRange.lowerKey;
1342     if (key.isNull())
1343         key = IDBKeyData::minimum();
1344     RefPtr<SharedBuffer> lowerBuffer = serializeIDBKeyData(key);
1345     if (!lowerBuffer) {
1346         LOG_ERROR("Unable to serialize lower IDBKey in lookup range");
1347         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize lower IDBKey in lookup range") };
1348     }
1349
1350     key = keyRange.upperKey;
1351     if (key.isNull())
1352         key = IDBKeyData::maximum();
1353     RefPtr<SharedBuffer> upperBuffer = serializeIDBKeyData(key);
1354     if (!upperBuffer) {
1355         LOG_ERROR("Unable to serialize upper IDBKey in lookup range");
1356         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize upper IDBKey in lookup range") };
1357     }
1358
1359     {
1360         static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpen("SELECT value FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
1361         static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosed("SELECT value FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
1362         static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpen("SELECT value FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
1363         static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosed("SELECT value FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
1364
1365         const ASCIILiteral* query = nullptr;
1366
1367         if (keyRange.lowerOpen) {
1368             if (keyRange.upperOpen)
1369                 query = &lowerOpenUpperOpen.get();
1370             else
1371                 query = &lowerOpenUpperClosed.get();
1372         } else {
1373             if (keyRange.upperOpen)
1374                 query = &lowerClosedUpperOpen.get();
1375             else
1376                 query = &lowerClosedUpperClosed.get();
1377         }
1378
1379         ASSERT(query);
1380
1381         SQLiteStatement sql(*m_sqliteDB, *query);
1382         if (sql.prepare() != SQLITE_OK
1383             || sql.bindInt64(1, objectStoreID) != SQLITE_OK
1384             || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
1385             || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
1386             LOG_ERROR("Could not get key range record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1387             return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up record in object store by key range") };
1388         }
1389
1390         int sqlResult = sql.step();
1391
1392         if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE) {
1393             // There was no record for the key in the database.
1394             return { };
1395         }
1396         if (sqlResult != SQLITE_ROW) {
1397             // There was an error fetching the record from the database.
1398             LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1399             return { IDBDatabaseException::UnknownError, ASCIILiteral("Error looking up record in object store by key range") };
1400         }
1401
1402         Vector<uint8_t> buffer;
1403         sql.getColumnBlobAsVector(0, buffer);
1404         resultValue = ThreadSafeDataBuffer::adoptVector(buffer);
1405     }
1406
1407     return { };
1408 }
1409
1410 IDBError SQLiteIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t indexID, IndexedDB::IndexRecordType type, const IDBKeyRangeData& range, IDBGetResult& getResult)
1411 {
1412     LOG(IndexedDB, "SQLiteIDBBackingStore::getIndexRecord - %s", range.loggingString().utf8().data());
1413
1414     ASSERT(m_sqliteDB);
1415     ASSERT(m_sqliteDB->isOpen());
1416
1417     auto* transaction = m_transactions.get(transactionIdentifier);
1418     if (!transaction || !transaction->inProgress()) {
1419         LOG_ERROR("Attempt to get an index record from database without an in-progress transaction");
1420         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to get an index record from database without an in-progress transaction") };
1421     }
1422
1423     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreID, indexID, range);
1424     if (!cursor) {
1425         LOG_ERROR("Cannot open cursor to perform index get in database");
1426         return { IDBDatabaseException::UnknownError, ASCIILiteral("Cannot open cursor to perform index get in database") };
1427     }
1428
1429     if (cursor->didError()) {
1430         LOG_ERROR("Cursor failed while looking up index record in database");
1431         return { IDBDatabaseException::UnknownError, ASCIILiteral("Cursor failed while looking up index record in database") };
1432     }
1433
1434     if (cursor->didComplete())
1435         getResult = { };
1436     else {
1437         if (type == IndexedDB::IndexRecordType::Key)
1438             getResult = { cursor->currentPrimaryKey() };
1439         else {
1440             getResult = { SharedBuffer::create(cursor->currentValueBuffer().data(), cursor->currentValueBuffer().size()) };
1441             getResult.setKeyData(cursor->currentPrimaryKey());
1442         }
1443     }
1444
1445     return { };
1446 }
1447
1448 IDBError SQLiteIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
1449 {
1450     LOG(IndexedDB, "SQLiteIDBBackingStore::getCount - object store %" PRIu64, objectStoreIdentifier);
1451     ASSERT(m_sqliteDB);
1452     ASSERT(m_sqliteDB->isOpen());
1453
1454     outCount = 0;
1455
1456     auto* transaction = m_transactions.get(transactionIdentifier);
1457     if (!transaction || !transaction->inProgress()) {
1458         LOG_ERROR("Attempt to get count from database without an in-progress transaction");
1459         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to get count from database without an in-progress transaction") };
1460     }
1461
1462     auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreIdentifier, indexIdentifier, range);
1463     if (!cursor) {
1464         LOG_ERROR("Cannot open cursor to populate indexes in database");
1465         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to populate indexes in database") };
1466     }
1467
1468     while (cursor->advance(1))
1469         ++outCount;
1470
1471     return { };
1472 }
1473
1474 IDBError SQLiteIDBBackingStore::uncheckedGetKeyGeneratorValue(int64_t objectStoreID, uint64_t& outValue)
1475 {
1476     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT currentKey FROM KeyGenerators WHERE objectStoreID = ?;"));
1477     if (sql.prepare() != SQLITE_OK
1478         || sql.bindInt64(1, objectStoreID) != SQLITE_OK) {
1479         LOG_ERROR("Could not retrieve currentKey from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1480         return { IDBDatabaseException::UnknownError, ASCIILiteral("Error getting current key generator value from database") };
1481     }
1482     int result = sql.step();
1483     if (result != SQLITE_ROW) {
1484         LOG_ERROR("Could not retreive key generator value for object store, but it should be there.");
1485         return { IDBDatabaseException::UnknownError, ASCIILiteral("Error finding current key generator value in database") };
1486     }
1487
1488     int64_t value = sql.getColumnInt64(0);
1489     if (value < 0)
1490         return { IDBDatabaseException::ConstraintError, "Current key generator value from database is invalid" };
1491
1492     outValue = value;
1493     return { };
1494 }
1495
1496 IDBError SQLiteIDBBackingStore::uncheckedSetKeyGeneratorValue(int64_t objectStoreID, uint64_t value)
1497 {
1498     SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, ?);"));
1499     if (sql.prepare() != SQLITE_OK
1500         || sql.bindInt64(1, objectStoreID) != SQLITE_OK
1501         || sql.bindInt64(2, value) != SQLITE_OK
1502         || sql.step() != SQLITE_DONE) {
1503         LOG_ERROR("Could not update key generator value (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1504         return { IDBDatabaseException::ConstraintError, "Error storing new key generator value in database" };
1505     }
1506
1507     return { };
1508 }
1509
1510 IDBError SQLiteIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t& generatedKey)
1511 {
1512     LOG(IndexedDB, "SQLiteIDBBackingStore::generateKeyNumber");
1513
1514     ASSERT(m_sqliteDB);
1515     ASSERT(m_sqliteDB->isOpen());
1516
1517     // The IndexedDatabase spec defines the max key generator value as 2^53;
1518     static uint64_t maxGeneratorValue = 0x20000000000000;
1519
1520     auto* transaction = m_transactions.get(transactionIdentifier);
1521     if (!transaction || !transaction->inProgress()) {
1522         LOG_ERROR("Attempt to generate key in database without an in-progress transaction");
1523         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to generate key in database without an in-progress transaction") };
1524     }
1525     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
1526         LOG_ERROR("Attempt to generate key in a read-only transaction");
1527         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to generate key in a read-only transaction") };
1528     }
1529
1530     uint64_t currentValue;
1531     auto error = uncheckedGetKeyGeneratorValue(objectStoreID, currentValue);
1532     if (!error.isNull())
1533         return error;
1534
1535     if (currentValue + 1 > maxGeneratorValue)
1536         return { IDBDatabaseException::ConstraintError, "Cannot generate new key value over 2^53 for object store operation" };
1537
1538     generatedKey = currentValue + 1;
1539     return uncheckedSetKeyGeneratorValue(objectStoreID, generatedKey);
1540 }
1541
1542 IDBError SQLiteIDBBackingStore::revertGeneratedKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t newKeyNumber)
1543 {
1544     LOG(IndexedDB, "SQLiteIDBBackingStore::revertGeneratedKeyNumber - object store %" PRIu64 ", reverted number %" PRIu64, objectStoreID, newKeyNumber);
1545
1546     ASSERT(m_sqliteDB);
1547     ASSERT(m_sqliteDB->isOpen());
1548
1549     auto* transaction = m_transactions.get(transactionIdentifier);
1550     if (!transaction || !transaction->inProgress()) {
1551         LOG_ERROR("Attempt to revert key generator value in database without an in-progress transaction");
1552         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to revert key generator value in database without an in-progress transaction") };
1553     }
1554     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
1555         LOG_ERROR("Attempt to revert key generator value in a read-only transaction");
1556         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to revert key generator value in a read-only transaction") };
1557     }
1558
1559     ASSERT(newKeyNumber);
1560     return uncheckedSetKeyGeneratorValue(objectStoreID, newKeyNumber - 1);
1561 }
1562
1563 IDBError SQLiteIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, double newKeyNumber)
1564 {
1565     LOG(IndexedDB, "SQLiteIDBBackingStore::maybeUpdateKeyGeneratorNumber");
1566
1567     ASSERT(m_sqliteDB);
1568     ASSERT(m_sqliteDB->isOpen());
1569
1570     auto* transaction = m_transactions.get(transactionIdentifier);
1571     if (!transaction || !transaction->inProgress()) {
1572         LOG_ERROR("Attempt to update key generator value in database without an in-progress transaction");
1573         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to update key generator value in database without an in-progress transaction") };
1574     }
1575     if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
1576         LOG_ERROR("Attempt to update key generator value in a read-only transaction");
1577         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to update key generator value in a read-only transaction") };
1578     }
1579
1580     uint64_t currentValue;
1581     auto error = uncheckedGetKeyGeneratorValue(objectStoreID, currentValue);
1582     if (!error.isNull())
1583         return error;
1584
1585     if (newKeyNumber <= currentValue)
1586         return { };
1587
1588     uint64_t newKeyInteger(newKeyNumber);
1589     if (newKeyInteger <= uint64_t(newKeyNumber))
1590         ++newKeyInteger;
1591
1592     ASSERT(newKeyInteger > uint64_t(newKeyNumber));
1593
1594     return uncheckedSetKeyGeneratorValue(objectStoreID, newKeyInteger - 1);
1595 }
1596
1597 IDBError SQLiteIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& result)
1598 {
1599     ASSERT(m_sqliteDB);
1600     ASSERT(m_sqliteDB->isOpen());
1601
1602     auto* transaction = m_transactions.get(transactionIdentifier);
1603     if (!transaction || !transaction->inProgress()) {
1604         LOG_ERROR("Attempt to open a cursor in database without an in-progress transaction");
1605         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to open a cursor in database without an in-progress transaction") };
1606     }
1607
1608     auto* cursor = transaction->maybeOpenCursor(info);
1609     if (!cursor) {
1610         LOG_ERROR("Unable to open cursor");
1611         return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to open cursor") };
1612     }
1613
1614     m_cursors.set(cursor->identifier(), cursor);
1615
1616     cursor->currentData(result);
1617     return { };
1618 }
1619
1620 IDBError SQLiteIDBBackingStore::iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData& key, uint32_t count, IDBGetResult& result)
1621 {
1622     LOG(IndexedDB, "SQLiteIDBBackingStore::iterateCursor");
1623
1624     ASSERT(m_sqliteDB);
1625     ASSERT(m_sqliteDB->isOpen());
1626
1627     auto* cursor = m_cursors.get(cursorIdentifier);
1628     if (!cursor) {
1629         LOG_ERROR("Attempt to iterate a cursor that doesn't exist");
1630         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to iterate a cursor that doesn't exist") };
1631     }
1632
1633     ASSERT_UNUSED(transactionIdentifier, cursor->transaction()->transactionIdentifier() == transactionIdentifier);
1634
1635     if (!cursor->transaction() || !cursor->transaction()->inProgress()) {
1636         LOG_ERROR("Attempt to iterate a cursor without an in-progress transaction");
1637         return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to iterate a cursor without an in-progress transaction") };
1638     }
1639
1640     if (key.isValid()) {
1641         if (!cursor->iterate(key)) {
1642             LOG_ERROR("Attempt to iterate cursor failed");
1643             return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to iterate cursor failed") };
1644         }
1645     } else {
1646         if (!count)
1647             count = 1;
1648         if (!cursor->advance(count)) {
1649             LOG_ERROR("Attempt to advance cursor failed");
1650             return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to advance cursor failed") };
1651         }
1652     }
1653
1654     cursor->currentData(result);
1655     return { };
1656 }
1657
1658 IDBObjectStoreInfo* SQLiteIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
1659 {
1660     ASSERT(m_databaseInfo);
1661     return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
1662 }
1663
1664 void SQLiteIDBBackingStore::deleteBackingStore()
1665 {
1666     String dbFilename = fullDatabasePath();
1667
1668     LOG(IndexedDB, "SQLiteIDBBackingStore::deleteBackingStore deleting file '%s' on disk", dbFilename.utf8().data());
1669
1670     if (m_sqliteDB) {
1671         m_sqliteDB->close();
1672         m_sqliteDB = nullptr;
1673     }
1674
1675     SQLiteFileSystem::deleteDatabaseFile(dbFilename);
1676     SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_absoluteDatabaseDirectory);
1677 }
1678
1679 void SQLiteIDBBackingStore::unregisterCursor(SQLiteIDBCursor& cursor)
1680 {
1681     ASSERT(m_cursors.contains(cursor.identifier()));
1682     m_cursors.remove(cursor.identifier());
1683 }
1684
1685 } // namespace IDBServer
1686 } // namespace WebCore
1687
1688 #endif // ENABLE(INDEXED_DATABASE)