1/*
2 * Copyright (C) 2013 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 "UniqueIDBDatabaseBackingStoreSQLite.h"
28
29#if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
30
31#include "ArgumentDecoder.h"
32#include "IDBSerialization.h"
33#include "Logging.h"
34#include "SQLiteIDBCursor.h"
35#include "SQLiteIDBTransaction.h"
36#include <WebCore/FileSystem.h>
37#include <WebCore/IDBBindingUtilities.h>
38#include <WebCore/IDBDatabaseMetadata.h>
39#include <WebCore/IDBGetResult.h>
40#include <WebCore/IDBKeyData.h>
41#include <WebCore/IDBKeyRange.h>
42#include <WebCore/SQLiteDatabase.h>
43#include <WebCore/SQLiteStatement.h>
44#include <WebCore/SharedBuffer.h>
45#include <wtf/RunLoop.h>
46
47using namespace JSC;
48using namespace WebCore;
49
50namespace WebKit {
51
52// Current version of the metadata schema being used in the metadata database.
53static const int currentMetadataVersion = 1;
54
55static int64_t generateDatabaseId()
56{
57    static int64_t databaseID = 0;
58
59    ASSERT(!RunLoop::isMain());
60    return ++databaseID;
61}
62
63UniqueIDBDatabaseBackingStoreSQLite::UniqueIDBDatabaseBackingStoreSQLite(const UniqueIDBDatabaseIdentifier& identifier, const String& databaseDirectory)
64    : m_identifier(identifier)
65    , m_absoluteDatabaseDirectory(databaseDirectory)
66{
67    // The backing store is meant to be created and used entirely on a background thread.
68    ASSERT(!RunLoop::isMain());
69}
70
71UniqueIDBDatabaseBackingStoreSQLite::~UniqueIDBDatabaseBackingStoreSQLite()
72{
73    ASSERT(!RunLoop::isMain());
74
75    m_transactions.clear();
76    m_sqliteDB = nullptr;
77
78    if (m_vm) {
79        JSLockHolder locker(m_vm.get());
80        m_globalObject.clear();
81        m_vm = nullptr;
82    }
83}
84
85std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata()
86{
87    ASSERT(!RunLoop::isMain());
88    ASSERT(m_sqliteDB);
89    ASSERT(m_sqliteDB->isOpen());
90
91    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);")) {
92        LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
93        m_sqliteDB = nullptr;
94        return nullptr;
95    }
96
97    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);")) {
98        LOG_ERROR("Could not create ObjectStoreInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
99        m_sqliteDB = nullptr;
100        return nullptr;
101    }
102
103    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);")) {
104        LOG_ERROR("Could not create IndexInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
105        m_sqliteDB = nullptr;
106        return nullptr;
107    }
108
109    if (!m_sqliteDB->executeCommand("CREATE TABLE Records (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);")) {
110        LOG_ERROR("Could not create Records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
111        m_sqliteDB = nullptr;
112        return nullptr;
113    }
114
115    if (!m_sqliteDB->executeCommand("CREATE TABLE IndexRecords (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);")) {
116        LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
117        m_sqliteDB = nullptr;
118        return nullptr;
119    }
120
121    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);")) {
122        LOG_ERROR("Could not create KeyGenerators table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
123        m_sqliteDB = nullptr;
124        return nullptr;
125    }
126
127    {
128        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);"));
129        if (sql.prepare() != SQLResultOk
130            || sql.bindInt(1, currentMetadataVersion) != SQLResultOk
131            || sql.step() != SQLResultDone) {
132            LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
133            m_sqliteDB = nullptr;
134            return nullptr;
135        }
136    }
137    {
138        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseName', ?);"));
139        if (sql.prepare() != SQLResultOk
140            || sql.bindText(1, m_identifier.databaseName()) != SQLResultOk
141            || sql.step() != SQLResultDone) {
142            LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
143            m_sqliteDB = nullptr;
144            return nullptr;
145        }
146    }
147    {
148        // Database versions are defined to be a uin64_t in the spec but sqlite3 doesn't support native binding of unsigned integers.
149        // Therefore we'll store the version as a String.
150        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseVersion', ?);"));
151        if (sql.prepare() != SQLResultOk
152            || sql.bindText(1, String::number(IDBDatabaseMetadata::NoIntVersion)) != SQLResultOk
153            || sql.step() != SQLResultDone) {
154            LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
155            m_sqliteDB = nullptr;
156            return nullptr;
157        }
158    }
159
160    if (!m_sqliteDB->executeCommand(ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MaxObjectStoreID', 1);"))) {
161        LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
162        m_sqliteDB = nullptr;
163        return nullptr;
164    }
165
166    // This initial metadata matches the default values we just put into the metadata database.
167    auto metadata = std::make_unique<IDBDatabaseMetadata>();
168    metadata->name = m_identifier.databaseName();
169    metadata->version = IDBDatabaseMetadata::NoIntVersion;
170    metadata->maxObjectStoreId = 1;
171
172    return metadata;
173}
174
175std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::extractExistingMetadata()
176{
177    ASSERT(!RunLoop::isMain());
178    ASSERT(m_sqliteDB);
179
180    if (!m_sqliteDB->tableExists(ASCIILiteral("IDBDatabaseInfo")))
181        return nullptr;
182
183    auto metadata = std::make_unique<IDBDatabaseMetadata>();
184    {
185        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM IDBDatabaseInfo WHERE key = 'MetadataVersion';"));
186        if (sql.isColumnNull(0))
187            return nullptr;
188        metadata->version = sql.getColumnInt(0);
189    }
190    {
191        SQLiteStatement sql(*m_sqliteDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseName';");
192        if (sql.isColumnNull(0))
193            return nullptr;
194        metadata->name = sql.getColumnText(0);
195        if (metadata->name != m_identifier.databaseName()) {
196            LOG_ERROR("Database name in the metadata database ('%s') does not match the expected name ('%s')", metadata->name.utf8().data(), m_identifier.databaseName().utf8().data());
197            return nullptr;
198        }
199    }
200    {
201        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseVersion';"));
202        if (sql.isColumnNull(0))
203            return nullptr;
204        String stringVersion = sql.getColumnText(0);
205        bool ok;
206        metadata->version = stringVersion.toUInt64Strict(&ok);
207        if (!ok) {
208            LOG_ERROR("Database version on disk ('%s') does not cleanly convert to an unsigned 64-bit integer version", stringVersion.utf8().data());
209            return nullptr;
210        }
211    }
212
213    {
214        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT id, name, keyPath, autoInc, maxIndexID FROM ObjectStoreInfo;"));
215        if (sql.prepare() != SQLResultOk)
216            return nullptr;
217
218        int result = sql.step();
219        while (result == SQLResultRow) {
220            IDBObjectStoreMetadata osMetadata;
221            osMetadata.id = sql.getColumnInt64(0);
222            osMetadata.name = sql.getColumnText(1);
223
224            Vector<char> keyPathBuffer;
225            sql.getColumnBlobAsVector(2, keyPathBuffer);
226
227            if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), osMetadata.keyPath)) {
228                LOG_ERROR("Unable to extract key path metadata from database");
229                return nullptr;
230            }
231
232            osMetadata.autoIncrement = sql.getColumnInt(3);
233            osMetadata.maxIndexId = sql.getColumnInt64(4);
234
235            metadata->objectStores.set(osMetadata.id, osMetadata);
236            result = sql.step();
237        }
238
239        if (result != SQLResultDone) {
240            LOG_ERROR("Error fetching object store metadata from database on disk");
241            return nullptr;
242        }
243    }
244
245    {
246        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT id, name, objectStoreID, keyPath, isUnique, multiEntry FROM IndexInfo;"));
247        if (sql.prepare() != SQLResultOk)
248            return nullptr;
249
250        int result = sql.step();
251        while (result == SQLResultRow) {
252            IDBIndexMetadata indexMetadata;
253
254            indexMetadata.id = sql.getColumnInt64(0);
255            indexMetadata.name = sql.getColumnText(1);
256            int64_t objectStoreID = sql.getColumnInt64(2);
257
258            Vector<char> keyPathBuffer;
259            sql.getColumnBlobAsVector(3, keyPathBuffer);
260
261            if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), indexMetadata.keyPath)) {
262                LOG_ERROR("Unable to extract key path metadata from database");
263                return nullptr;
264            }
265
266            indexMetadata.unique = sql.getColumnInt(4);
267            indexMetadata.multiEntry = sql.getColumnInt(5);
268
269            auto objectStoreMetadataIt = metadata->objectStores.find(objectStoreID);
270            if (objectStoreMetadataIt == metadata->objectStores.end()) {
271                LOG_ERROR("Found index referring to a non-existant object store");
272                return nullptr;
273            }
274
275            objectStoreMetadataIt->value.indexes.set(indexMetadata.id, indexMetadata);
276
277            result = sql.step();
278        }
279
280        if (result != SQLResultDone) {
281            LOG_ERROR("Error fetching index metadata from database on disk");
282            return nullptr;
283        }
284    }
285
286    return metadata;
287}
288
289std::unique_ptr<SQLiteDatabase> UniqueIDBDatabaseBackingStoreSQLite::openSQLiteDatabaseAtPath(const String& path)
290{
291    ASSERT(!RunLoop::isMain());
292
293    auto sqliteDatabase = std::make_unique<SQLiteDatabase>();
294    if (!sqliteDatabase->open(path)) {
295        LOG_ERROR("Failed to open SQLite database at path '%s'", path.utf8().data());
296        return nullptr;
297    }
298
299    // Since a WorkQueue isn't bound to a specific thread, we have to disable threading checks
300    // even though we never access the database from different threads simultaneously.
301    sqliteDatabase->disableThreadingChecks();
302
303    return sqliteDatabase;
304}
305
306std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata()
307{
308    ASSERT(!RunLoop::isMain());
309
310    String dbFilename = UniqueIDBDatabase::calculateAbsoluteDatabaseFilename(m_absoluteDatabaseDirectory);
311
312    m_sqliteDB = openSQLiteDatabaseAtPath(dbFilename);
313    if (!m_sqliteDB)
314        return nullptr;
315
316    m_sqliteDB->setCollationFunction("IDBKEY", [this](int aLength, const void* a, int bLength, const void* b) {
317        return idbKeyCollate(aLength, a, bLength, b);
318    });
319
320    std::unique_ptr<IDBDatabaseMetadata> metadata = extractExistingMetadata();
321    if (!metadata)
322        metadata = createAndPopulateInitialMetadata();
323
324    if (!metadata)
325        LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());
326
327    // The database id is a runtime concept and doesn't need to be stored in the metadata database.
328    metadata->id = generateDatabaseId();
329
330    return metadata;
331}
332
333bool UniqueIDBDatabaseBackingStoreSQLite::establishTransaction(const IDBIdentifier& transactionIdentifier, const Vector<int64_t>&, IndexedDB::TransactionMode mode)
334{
335    ASSERT(!RunLoop::isMain());
336
337    if (!m_transactions.add(transactionIdentifier, SQLiteIDBTransaction::create(*this, transactionIdentifier, mode)).isNewEntry) {
338        LOG_ERROR("Attempt to establish transaction identifier that already exists");
339        return false;
340    }
341
342    return true;
343}
344
345bool UniqueIDBDatabaseBackingStoreSQLite::beginTransaction(const IDBIdentifier& transactionIdentifier)
346{
347    ASSERT(!RunLoop::isMain());
348
349    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
350    if (!transaction) {
351        LOG_ERROR("Attempt to begin a transaction that hasn't been established");
352        return false;
353    }
354
355    return transaction->begin(*m_sqliteDB);
356}
357
358bool UniqueIDBDatabaseBackingStoreSQLite::commitTransaction(const IDBIdentifier& transactionIdentifier)
359{
360    ASSERT(!RunLoop::isMain());
361
362    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
363    if (!transaction) {
364        LOG_ERROR("Attempt to commit a transaction that hasn't been established");
365        return false;
366    }
367
368    return transaction->commit();
369}
370
371bool UniqueIDBDatabaseBackingStoreSQLite::resetTransaction(const IDBIdentifier& transactionIdentifier)
372{
373    ASSERT(!RunLoop::isMain());
374
375    std::unique_ptr<SQLiteIDBTransaction> transaction = m_transactions.take(transactionIdentifier);
376    if (!transaction) {
377        LOG_ERROR("Attempt to reset a transaction that hasn't been established");
378        return false;
379    }
380
381    return transaction->reset();
382}
383
384bool UniqueIDBDatabaseBackingStoreSQLite::rollbackTransaction(const IDBIdentifier& transactionIdentifier)
385{
386    ASSERT(!RunLoop::isMain());
387
388    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
389    if (!transaction) {
390        LOG_ERROR("Attempt to rollback a transaction that hasn't been established");
391        return false;
392    }
393
394    if (!transaction->inProgress()) {
395        LOG_ERROR("Attempt to rollback a transaction that hasn't begun");
396        return false;
397    }
398
399    return transaction->rollback();
400}
401
402bool UniqueIDBDatabaseBackingStoreSQLite::changeDatabaseVersion(const IDBIdentifier& transactionIdentifier, uint64_t newVersion)
403{
404    ASSERT(!RunLoop::isMain());
405    ASSERT(m_sqliteDB);
406    ASSERT(m_sqliteDB->isOpen());
407
408    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
409    if (!transaction || !transaction->inProgress()) {
410        LOG_ERROR("Attempt to change database version with an established, in-progress transaction");
411        return false;
412    }
413    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
414        LOG_ERROR("Attempt to change database version during a non version-change transaction");
415        return false;
416    }
417
418    {
419        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("UPDATE IDBDatabaseInfo SET value = ? where key = 'DatabaseVersion';"));
420        if (sql.prepare() != SQLResultOk
421            || sql.bindText(1, String::number(newVersion)) != SQLResultOk
422            || sql.step() != SQLResultDone) {
423            LOG_ERROR("Could not update database version in IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
424            return false;
425        }
426    }
427
428    return true;
429}
430
431bool UniqueIDBDatabaseBackingStoreSQLite::createObjectStore(const IDBIdentifier& transactionIdentifier, const IDBObjectStoreMetadata& metadata)
432{
433    ASSERT(!RunLoop::isMain());
434    ASSERT(m_sqliteDB);
435    ASSERT(m_sqliteDB->isOpen());
436
437    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
438    if (!transaction || !transaction->inProgress()) {
439        LOG_ERROR("Attempt to change database version with an established, in-progress transaction");
440        return false;
441    }
442    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
443        LOG_ERROR("Attempt to change database version during a non version-change transaction");
444        return false;
445    }
446
447    RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(metadata.keyPath);
448    if (!keyPathBlob) {
449        LOG_ERROR("Unable to serialize IDBKeyPath to save in database");
450        return false;
451    }
452
453    {
454        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO ObjectStoreInfo VALUES (?, ?, ?, ?, ?);"));
455        if (sql.prepare() != SQLResultOk
456            || sql.bindInt64(1, metadata.id) != SQLResultOk
457            || sql.bindText(2, metadata.name) != SQLResultOk
458            || sql.bindBlob(3, keyPathBlob->data(), keyPathBlob->size()) != SQLResultOk
459            || sql.bindInt(4, metadata.autoIncrement) != SQLResultOk
460            || sql.bindInt64(5, metadata.maxIndexId) != SQLResultOk
461            || sql.step() != SQLResultDone) {
462            LOG_ERROR("Could not add object store '%s' to ObjectStoreInfo table (%i) - %s", metadata.name.utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
463            return false;
464        }
465    }
466
467    {
468        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, 0);"));
469        if (sql.prepare() != SQLResultOk
470            || sql.bindInt64(1, metadata.id) != SQLResultOk
471            || sql.step() != SQLResultDone) {
472            LOG_ERROR("Could not seed initial key generator value for ObjectStoreInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
473            return false;
474        }
475    }
476
477    return true;
478}
479
480bool UniqueIDBDatabaseBackingStoreSQLite::deleteObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID)
481{
482    ASSERT(!RunLoop::isMain());
483    ASSERT(m_sqliteDB);
484    ASSERT(m_sqliteDB->isOpen());
485
486    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
487    if (!transaction || !transaction->inProgress()) {
488        LOG_ERROR("Attempt to change database version with an established, in-progress transaction");
489        return false;
490    }
491    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
492        LOG_ERROR("Attempt to change database version during a non version-change transaction");
493        return false;
494    }
495
496    // Delete the ObjectStore record
497    {
498        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM ObjectStoreInfo WHERE id = ?;"));
499        if (sql.prepare() != SQLResultOk
500            || sql.bindInt64(1, objectStoreID) != SQLResultOk
501            || sql.step() != SQLResultDone) {
502            LOG_ERROR("Could not delete object store id %lli from ObjectStoreInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
503            return false;
504        }
505    }
506
507    // Delete the ObjectStore's key generator record if there is one.
508    {
509        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM KeyGenerators WHERE objectStoreID = ?;"));
510        if (sql.prepare() != SQLResultOk
511            || sql.bindInt64(1, objectStoreID) != SQLResultOk
512            || sql.step() != SQLResultDone) {
513            LOG_ERROR("Could not delete object store from KeyGenerators table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
514            return false;
515        }
516    }
517
518    // Delete all associated records
519    {
520        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
521        if (sql.prepare() != SQLResultOk
522            || sql.bindInt64(1, objectStoreID) != SQLResultOk
523            || sql.step() != SQLResultDone) {
524            LOG_ERROR("Could not delete records for object store %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
525            return false;
526        }
527    }
528
529    // Delete all associated Indexes
530    {
531        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE objectStoreID = ?;"));
532        if (sql.prepare() != SQLResultOk
533            || sql.bindInt64(1, objectStoreID) != SQLResultOk
534            || sql.step() != SQLResultDone) {
535            LOG_ERROR("Could not delete index from IndexInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
536            return false;
537        }
538    }
539
540    // Delete all associated Index records
541    {
542        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
543        if (sql.prepare() != SQLResultOk
544            || sql.bindInt64(1, objectStoreID) != SQLResultOk
545            || sql.step() != SQLResultDone) {
546            LOG_ERROR("Could not delete index records(%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
547            return false;
548        }
549    }
550
551    return true;
552}
553
554bool UniqueIDBDatabaseBackingStoreSQLite::clearObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID)
555{
556    ASSERT(!RunLoop::isMain());
557    ASSERT(m_sqliteDB);
558    ASSERT(m_sqliteDB->isOpen());
559
560    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
561    if (!transaction || !transaction->inProgress()) {
562        LOG_ERROR("Attempt to change database version with an establish, in-progress transaction");
563        return false;
564    }
565    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
566        LOG_ERROR("Attempt to change database version during a read-only transaction");
567        return false;
568    }
569
570    {
571        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;"));
572        if (sql.prepare() != SQLResultOk
573            || sql.bindInt64(1, objectStoreID) != SQLResultOk
574            || sql.step() != SQLResultDone) {
575            LOG_ERROR("Could not delete records from object store id %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
576            return false;
577        }
578    }
579
580    {
581        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ?;"));
582        if (sql.prepare() != SQLResultOk
583            || sql.bindInt64(1, objectStoreID) != SQLResultOk
584            || sql.step() != SQLResultDone) {
585            LOG_ERROR("Could not delete records from index record store id %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
586            return false;
587        }
588    }
589
590    return true;
591}
592
593bool UniqueIDBDatabaseBackingStoreSQLite::createIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBIndexMetadata& metadata)
594{
595    ASSERT(!RunLoop::isMain());
596    ASSERT(m_sqliteDB);
597    ASSERT(m_sqliteDB->isOpen());
598
599    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
600    if (!transaction || !transaction->inProgress()) {
601        LOG_ERROR("Attempt to create index without an established, in-progress transaction");
602        return false;
603    }
604    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
605        LOG_ERROR("Attempt to create index during a non-version-change transaction");
606        return false;
607    }
608
609    RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(metadata.keyPath);
610    if (!keyPathBlob) {
611        LOG_ERROR("Unable to serialize IDBKeyPath to save in database");
612        return false;
613    }
614
615    SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);"));
616    if (sql.prepare() != SQLResultOk
617        || sql.bindInt64(1, metadata.id) != SQLResultOk
618        || sql.bindText(2, metadata.name) != SQLResultOk
619        || sql.bindInt64(3, objectStoreID) != SQLResultOk
620        || sql.bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLResultOk
621        || sql.bindInt(5, metadata.unique) != SQLResultOk
622        || sql.bindInt(6, metadata.multiEntry) != SQLResultOk
623        || sql.step() != SQLResultDone) {
624        LOG_ERROR("Could not add index '%s' to IndexInfo table (%i) - %s", metadata.name.utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
625        return false;
626    }
627
628    // Write index records for any records that already exist in this object store.
629    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, IDBIndexMetadata::InvalidId, IndexedDB::CursorDirection::Next, IndexedDB::CursorType::KeyAndValue, IDBDatabaseBackend::NormalTask, IDBKeyRangeData());
630
631    if (!cursor) {
632        LOG_ERROR("Cannot open cursor to populate indexes in database");
633        return false;
634    }
635
636    m_cursors.set(cursor->identifier(), cursor);
637
638    std::unique_ptr<JSLockHolder> locker;
639    while (!cursor->currentKey().isNull) {
640        const IDBKeyData& key = cursor->currentKey();
641        const Vector<uint8_t>& valueBuffer = cursor->currentValueBuffer();
642
643        if (!m_globalObject) {
644            ASSERT(!m_vm);
645            m_vm = VM::create();
646            locker = std::make_unique<JSLockHolder>(m_vm.get());
647            m_globalObject.set(*m_vm, JSGlobalObject::create(*m_vm, JSGlobalObject::createStructure(*m_vm, jsNull())));
648        }
649
650        if (!locker)
651            locker = std::make_unique<JSLockHolder>(m_vm.get());
652
653        Deprecated::ScriptValue value = deserializeIDBValueBuffer(m_globalObject->globalExec(), valueBuffer, true);
654        Vector<IDBKeyData> indexKeys;
655        generateIndexKeysForValue(m_globalObject->globalExec(), metadata, value, indexKeys);
656
657        for (auto& indexKey : indexKeys) {
658            if (!uncheckedPutIndexRecord(objectStoreID, metadata.id, key, indexKey)) {
659                LOG_ERROR("Unable to put index record for newly created index");
660                return false;
661            }
662        }
663
664        if (!cursor->advance(1)) {
665            LOG_ERROR("Error advancing cursor while indexing existing records for new index.");
666            return false;
667        }
668    }
669
670    transaction->closeCursor(*cursor);
671
672    return true;
673}
674
675bool UniqueIDBDatabaseBackingStoreSQLite::deleteIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID)
676{
677    ASSERT(!RunLoop::isMain());
678    ASSERT(m_sqliteDB);
679    ASSERT(m_sqliteDB->isOpen());
680
681    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
682    if (!transaction || !transaction->inProgress()) {
683        LOG_ERROR("Attempt to delete index without an established, in-progress transaction");
684        return false;
685    }
686    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
687        LOG_ERROR("Attempt to delete index during a non-version-change transaction");
688        return false;
689    }
690
691    {
692        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
693        if (sql.prepare() != SQLResultOk
694            || sql.bindInt64(1, indexID) != SQLResultOk
695            || sql.bindInt64(2, objectStoreID) != SQLResultOk
696            || sql.step() != SQLResultDone) {
697            LOG_ERROR("Could not delete index id %lli from IndexInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
698            return false;
699        }
700    }
701
702    {
703        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE indexID = ? AND objectStoreID = ?;"));
704        if (sql.prepare() != SQLResultOk
705            || sql.bindInt64(1, indexID) != SQLResultOk
706            || sql.bindInt64(2, objectStoreID) != SQLResultOk
707            || sql.step() != SQLResultDone) {
708            LOG_ERROR("Could not delete index records for index id %lli from IndexRecords table (%i) - %s", indexID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
709            return false;
710        }
711    }
712
713    return true;
714}
715
716bool UniqueIDBDatabaseBackingStoreSQLite::generateKeyNumber(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t& generatedKey)
717{
718    ASSERT(!RunLoop::isMain());
719    ASSERT(m_sqliteDB);
720    ASSERT(m_sqliteDB->isOpen());
721
722    // The IndexedDatabase spec defines the max key generator value as 2^53;
723    static const int64_t maxGeneratorValue = 9007199254740992LL;
724
725    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
726    if (!transaction || !transaction->inProgress()) {
727        LOG_ERROR("Attempt to generate key in database without an established, in-progress transaction");
728        return false;
729    }
730    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
731        LOG_ERROR("Attempt to generate key in database during read-only transaction");
732        return false;
733    }
734
735    int64_t currentValue;
736    {
737        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT currentKey FROM KeyGenerators WHERE objectStoreID = ?;"));
738        if (sql.prepare() != SQLResultOk
739            || sql.bindInt64(1, objectStoreID) != SQLResultOk) {
740            LOG_ERROR("Could not delete index id %lli from IndexInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
741            return false;
742        }
743        int result = sql.step();
744        if (result != SQLResultRow) {
745            LOG_ERROR("Could not retreive key generator value for object store, but it should be there.");
746            return false;
747        }
748
749        currentValue = sql.getColumnInt64(0);
750    }
751
752    if (currentValue < 0 || currentValue > maxGeneratorValue)
753        return false;
754
755    generatedKey = currentValue + 1;
756    return true;
757}
758
759bool UniqueIDBDatabaseBackingStoreSQLite::updateKeyGeneratorNumber(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t keyNumber, bool)
760{
761    ASSERT(!RunLoop::isMain());
762    ASSERT(m_sqliteDB);
763    ASSERT(m_sqliteDB->isOpen());
764
765    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
766    if (!transaction || !transaction->inProgress()) {
767        LOG_ERROR("Attempt to update key generator in database without an established, in-progress transaction");
768        return false;
769    }
770    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
771        LOG_ERROR("Attempt to update key generator in database during read-only transaction");
772        return false;
773    }
774
775    {
776        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO KeyGenerators VALUES (?, ?);"));
777        if (sql.prepare() != SQLResultOk
778            || sql.bindInt64(1, objectStoreID) != SQLResultOk
779            || sql.bindInt64(2, keyNumber) != SQLResultOk
780            || sql.step() != SQLResultDone) {
781            LOG_ERROR("Could not update key generator value (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
782            return false;
783        }
784    }
785
786    return true;
787}
788
789bool UniqueIDBDatabaseBackingStoreSQLite::keyExistsInObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyData& keyData, bool& keyExists)
790{
791    ASSERT(!RunLoop::isMain());
792    ASSERT(m_sqliteDB);
793    ASSERT(m_sqliteDB->isOpen());
794
795    keyExists = false;
796
797    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
798    if (!transaction || !transaction->inProgress()) {
799        LOG_ERROR("Attempt to see if key exists in objectstore without established, in-progress transaction");
800        return false;
801    }
802
803    RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
804    if (!keyBuffer) {
805        LOG_ERROR("Unable to serialize IDBKey to check for existence");
806        return false;
807    }
808
809    SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT key FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT) LIMIT 1;"));
810    if (sql.prepare() != SQLResultOk
811        || sql.bindInt64(1, objectStoreID) != SQLResultOk
812        || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk) {
813        LOG_ERROR("Could not get record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
814        return false;
815    }
816
817    int sqlResult = sql.step();
818    if (sqlResult == SQLResultOk || sqlResult == SQLResultDone) {
819        keyExists = false;
820        return true;
821    }
822
823    if (sqlResult != SQLResultRow) {
824        // There was an error fetching the record from the database.
825        LOG_ERROR("Could not check if key exists in object store (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
826        return false;
827    }
828
829    keyExists = true;
830    return true;
831}
832
833bool UniqueIDBDatabaseBackingStoreSQLite::putRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyData& keyData, const uint8_t* valueBuffer, size_t valueSize)
834{
835    ASSERT(!RunLoop::isMain());
836    ASSERT(m_sqliteDB);
837    ASSERT(m_sqliteDB->isOpen());
838
839    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
840    if (!transaction || !transaction->inProgress()) {
841        LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction");
842        return false;
843    }
844    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
845        LOG_ERROR("Attempt to put a record into database during read-only transaction");
846        return false;
847    }
848
849    RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData);
850    if (!keyBuffer) {
851        LOG_ERROR("Unable to serialize IDBKey to be stored in the database");
852        return false;
853    }
854    {
855        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO Records VALUES (?, CAST(? AS TEXT), ?);"));
856        if (sql.prepare() != SQLResultOk
857            || sql.bindInt64(1, objectStoreID) != SQLResultOk
858            || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk
859            || sql.bindBlob(3, valueBuffer, valueSize) != SQLResultOk
860            || sql.step() != SQLResultDone) {
861            LOG_ERROR("Could not put record for object store %lli in Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
862            return false;
863        }
864    }
865
866    return true;
867}
868
869bool UniqueIDBDatabaseBackingStoreSQLite::putIndexRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyData& keyValue, const IDBKeyData& indexKey)
870{
871    ASSERT(!RunLoop::isMain());
872    ASSERT(m_sqliteDB);
873    ASSERT(m_sqliteDB->isOpen());
874
875    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
876    if (!transaction || !transaction->inProgress()) {
877        LOG_ERROR("Attempt to put index record into database without an established, in-progress transaction");
878        return false;
879    }
880    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
881        LOG_ERROR("Attempt to put index record into database during read-only transaction");
882        return false;
883    }
884
885    return uncheckedPutIndexRecord(objectStoreID, indexID, keyValue, indexKey);
886}
887
888bool UniqueIDBDatabaseBackingStoreSQLite::uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData& keyValue, const WebCore::IDBKeyData& indexKey)
889{
890    RefPtr<SharedBuffer> indexKeyBuffer = serializeIDBKeyData(indexKey);
891    if (!indexKeyBuffer) {
892        LOG_ERROR("Unable to serialize index key to be stored in the database");
893        return false;
894    }
895
896    RefPtr<SharedBuffer> valueBuffer = serializeIDBKeyData(keyValue);
897    if (!valueBuffer) {
898        LOG_ERROR("Unable to serialize the value to be stored in the database");
899        return false;
900    }
901    {
902        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT));"));
903        if (sql.prepare() != SQLResultOk
904            || sql.bindInt64(1, indexID) != SQLResultOk
905            || sql.bindInt64(2, objectStoreID) != SQLResultOk
906            || sql.bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLResultOk
907            || sql.bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLResultOk
908            || sql.step() != SQLResultDone) {
909            LOG_ERROR("Could not put index record for index %lli in object store %lli in Records table (%i) - %s", indexID, objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
910            return false;
911        }
912    }
913
914    return true;
915}
916
917bool UniqueIDBDatabaseBackingStoreSQLite::getIndexRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData, IndexedDB::CursorType cursorType, IDBGetResult& result)
918{
919    ASSERT(!RunLoop::isMain());
920    ASSERT(m_sqliteDB);
921    ASSERT(m_sqliteDB->isOpen());
922
923    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
924    if (!transaction || !transaction->inProgress()) {
925        LOG_ERROR("Attempt to get count from database without an established, in-progress transaction");
926        return false;
927    }
928
929    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, indexID, IndexedDB::CursorDirection::Next, cursorType, IDBDatabaseBackend::NormalTask, keyRangeData);
930
931    if (!cursor) {
932        LOG_ERROR("Cannot open cursor to perform index get in database");
933        return false;
934    }
935
936    // Even though we're only using this cursor locally, add it to our cursor set.
937    m_cursors.set(cursor->identifier(), cursor);
938
939    if (cursorType == IndexedDB::CursorType::KeyOnly)
940        result = IDBGetResult(cursor->currentPrimaryKey());
941    else {
942        result = IDBGetResult(SharedBuffer::create(cursor->currentValueBuffer().data(), cursor->currentValueBuffer().size()));
943        result.keyData = cursor->currentPrimaryKey();
944    }
945
946    // Closing the cursor will destroy the cursor object and remove it from our cursor set.
947    transaction->closeCursor(*cursor);
948
949    return true;
950}
951
952bool UniqueIDBDatabaseBackingStoreSQLite::deleteRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyData& keyData)
953{
954    ASSERT(!RunLoop::isMain());
955    ASSERT(m_sqliteDB);
956    ASSERT(m_sqliteDB->isOpen());
957
958    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
959    if (!transaction || !transaction->inProgress()) {
960        LOG_ERROR("Attempt to get count from database without an established, in-progress transaction");
961        return false;
962    }
963
964    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
965        LOG_ERROR("Attempt to delete range from a read-only transaction");
966        return false;
967    }
968
969    return deleteRecord(*transaction, objectStoreID, keyData);
970}
971
972bool UniqueIDBDatabaseBackingStoreSQLite::deleteRange(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyRangeData& keyRangeData)
973{
974    ASSERT(!RunLoop::isMain());
975    ASSERT(m_sqliteDB);
976    ASSERT(m_sqliteDB->isOpen());
977
978    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
979    if (!transaction || !transaction->inProgress()) {
980        LOG_ERROR("Attempt to get count from database without an established, in-progress transaction");
981        return false;
982    }
983
984    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
985        LOG_ERROR("Attempt to delete range from a read-only transaction");
986        return false;
987    }
988
989    // If the range to delete is exactly one key we can delete it right now.
990    if (keyRangeData.isExactlyOneKey()) {
991        if (!deleteRecord(*transaction, objectStoreID, keyRangeData.lowerKey)) {
992            LOG_ERROR("Failed to delete record for key '%s'", keyRangeData.lowerKey.loggingString().utf8().data());
993            return false;
994        }
995        return true;
996    }
997
998    // Otherwise the range might span multiple keys so we collect them with a cursor.
999    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, IDBIndexMetadata::InvalidId, IndexedDB::CursorDirection::Next, IndexedDB::CursorType::KeyAndValue, IDBDatabaseBackend::NormalTask, keyRangeData);
1000
1001    if (!cursor) {
1002        LOG_ERROR("Cannot open cursor to perform index get in database");
1003        return false;
1004    }
1005
1006    m_cursors.set(cursor->identifier(), cursor);
1007
1008    Vector<IDBKeyData> keys;
1009    do
1010        keys.append(cursor->currentKey());
1011    while (cursor->advance(1));
1012
1013    bool cursorDidError = cursor->didError();
1014
1015    // closeCursor() will remove the cursor from m_cursors and delete the cursor object
1016    transaction->closeCursor(*cursor);
1017
1018    if (cursorDidError) {
1019        LOG_ERROR("Unable to iterate over object store to deleteRange in database");
1020        return false;
1021    }
1022
1023    for (auto& key : keys) {
1024        if (!deleteRecord(*transaction, objectStoreID, key)) {
1025            LOG_ERROR("Failed to delete record for key '%s'", key.loggingString().utf8().data());
1026            return false;
1027        }
1028    }
1029
1030    return true;
1031}
1032
1033bool UniqueIDBDatabaseBackingStoreSQLite::deleteRecord(SQLiteIDBTransaction& transaction, int64_t objectStoreID, const WebCore::IDBKeyData& key)
1034{
1035    ASSERT(!RunLoop::isMain());
1036    ASSERT(m_sqliteDB);
1037    ASSERT(m_sqliteDB->isOpen());
1038
1039    RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(key);
1040    if (!keyBuffer) {
1041        LOG_ERROR("Unable to serialize IDBKeyData to be removed from the database");
1042        return false;
1043    }
1044
1045    // Delete record from object store
1046    {
1047        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
1048
1049        if (sql.prepare() != SQLResultOk
1050            || sql.bindInt64(1, objectStoreID) != SQLResultOk
1051            || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk
1052            || sql.step() != SQLResultDone) {
1053            LOG_ERROR("Could not delete record from object store %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1054            return false;
1055        }
1056    }
1057
1058    // Delete record from indexes store
1059    {
1060        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexRecords WHERE objectStoreID = ? AND value = CAST(? AS TEXT);"));
1061
1062        if (sql.prepare() != SQLResultOk
1063            || sql.bindInt64(1, objectStoreID) != SQLResultOk
1064            || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk
1065            || sql.step() != SQLResultDone) {
1066            LOG_ERROR("Could not delete record from indexes for object store %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1067            return false;
1068        }
1069    }
1070
1071    return true;
1072}
1073
1074bool UniqueIDBDatabaseBackingStoreSQLite::getKeyRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKey& key, RefPtr<SharedBuffer>& result)
1075{
1076    ASSERT(!RunLoop::isMain());
1077    ASSERT(m_sqliteDB);
1078    ASSERT(m_sqliteDB->isOpen());
1079
1080    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
1081    if (!transaction || !transaction->inProgress()) {
1082        LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction");
1083        return false;
1084    }
1085
1086    RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(IDBKeyData(&key));
1087    if (!keyBuffer) {
1088        LOG_ERROR("Unable to serialize IDBKey to be stored in the database");
1089        return false;
1090    }
1091
1092    {
1093        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM Records WHERE objectStoreID = ? AND key = CAST(? AS TEXT);"));
1094        if (sql.prepare() != SQLResultOk
1095            || sql.bindInt64(1, objectStoreID) != SQLResultOk
1096            || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk) {
1097            LOG_ERROR("Could not get record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1098            return false;
1099        }
1100
1101        int sqlResult = sql.step();
1102        if (sqlResult == SQLResultOk || sqlResult == SQLResultDone) {
1103            // There was no record for the key in the database.
1104            return true;
1105        }
1106        if (sqlResult != SQLResultRow) {
1107            // There was an error fetching the record from the database.
1108            LOG_ERROR("Could not get record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1109            return false;
1110        }
1111
1112        Vector<char> buffer;
1113        sql.getColumnBlobAsVector(0, buffer);
1114        result = SharedBuffer::create(static_cast<const char*>(buffer.data()), buffer.size());
1115    }
1116
1117    return true;
1118}
1119
1120bool UniqueIDBDatabaseBackingStoreSQLite::getKeyRangeRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const IDBKeyRange& keyRange, RefPtr<SharedBuffer>& result, RefPtr<IDBKey>& resultKey)
1121{
1122    ASSERT(!RunLoop::isMain());
1123    ASSERT(m_sqliteDB);
1124    ASSERT(m_sqliteDB->isOpen());
1125
1126    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
1127    if (!transaction || !transaction->inProgress()) {
1128        LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction");
1129        return false;
1130    }
1131
1132    RefPtr<SharedBuffer> lowerBuffer = serializeIDBKeyData(IDBKeyData(keyRange.lower().get()));
1133    if (!lowerBuffer) {
1134        LOG_ERROR("Unable to serialize IDBKey to be stored in the database");
1135        return false;
1136    }
1137
1138    RefPtr<SharedBuffer> upperBuffer = serializeIDBKeyData(IDBKeyData(keyRange.upper().get()));
1139    if (!upperBuffer) {
1140        LOG_ERROR("Unable to serialize IDBKey to be stored in the database");
1141        return false;
1142    }
1143
1144    {
1145        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;"));
1146        if (sql.prepare() != SQLResultOk
1147            || sql.bindInt64(1, objectStoreID) != SQLResultOk
1148            || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLResultOk
1149            || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLResultOk) {
1150            LOG_ERROR("Could not get key range record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1151            return false;
1152        }
1153
1154        int sqlResult = sql.step();
1155
1156        if (sqlResult == SQLResultOk || sqlResult == SQLResultDone) {
1157            // There was no record for the key in the database.
1158            return true;
1159        }
1160        if (sqlResult != SQLResultRow) {
1161            // There was an error fetching the record from the database.
1162            LOG_ERROR("Could not get record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
1163            return false;
1164        }
1165
1166        Vector<char> buffer;
1167        sql.getColumnBlobAsVector(0, buffer);
1168        result = SharedBuffer::create(static_cast<const char*>(buffer.data()), buffer.size());
1169    }
1170
1171    return true;
1172}
1173
1174bool UniqueIDBDatabaseBackingStoreSQLite::count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData, int64_t& count)
1175{
1176    ASSERT(!RunLoop::isMain());
1177    ASSERT(m_sqliteDB);
1178    ASSERT(m_sqliteDB->isOpen());
1179
1180    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
1181    if (!transaction || !transaction->inProgress()) {
1182        LOG_ERROR("Attempt to get count from database without an established, in-progress transaction");
1183        return false;
1184    }
1185
1186    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, indexID, IndexedDB::CursorDirection::Next, IndexedDB::CursorType::KeyOnly, IDBDatabaseBackend::NormalTask, keyRangeData);
1187
1188    if (!cursor) {
1189        LOG_ERROR("Cannot open cursor to get count in database");
1190        return false;
1191    }
1192
1193    m_cursors.set(cursor->identifier(), cursor);
1194
1195    count = 0;
1196    while (cursor->advance(1))
1197        ++count;
1198
1199    transaction->closeCursor(*cursor);
1200
1201    return true;
1202}
1203
1204bool UniqueIDBDatabaseBackingStoreSQLite::openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, IndexedDB::CursorDirection cursorDirection, IndexedDB::CursorType cursorType, IDBDatabaseBackend::TaskType taskType, const IDBKeyRangeData& keyRange, int64_t& cursorID, IDBKeyData& key, IDBKeyData& primaryKey, Vector<uint8_t>& valueBuffer)
1205{
1206    ASSERT(!RunLoop::isMain());
1207    ASSERT(m_sqliteDB);
1208    ASSERT(m_sqliteDB->isOpen());
1209
1210    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
1211    if (!transaction || !transaction->inProgress()) {
1212        LOG_ERROR("Attempt to open a cursor in database without an established, in-progress transaction");
1213        return false;
1214    }
1215
1216    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, indexID, cursorDirection, cursorType, taskType, keyRange);
1217    if (!cursor)
1218        return false;
1219
1220    m_cursors.set(cursor->identifier(), cursor);
1221    cursorID = cursor->identifier().id();
1222    key = cursor->currentKey();
1223    primaryKey = cursor->currentPrimaryKey();
1224    valueBuffer = cursor->currentValueBuffer();
1225
1226    return true;
1227}
1228
1229bool UniqueIDBDatabaseBackingStoreSQLite::advanceCursor(const IDBIdentifier& cursorIdentifier, uint64_t count, IDBKeyData& key, IDBKeyData& primaryKey, Vector<uint8_t>& valueBuffer)
1230{
1231    ASSERT(!RunLoop::isMain());
1232    ASSERT(m_sqliteDB);
1233    ASSERT(m_sqliteDB->isOpen());
1234
1235    SQLiteIDBCursor* cursor = m_cursors.get(cursorIdentifier);
1236    if (!cursor) {
1237        LOG_ERROR("Attempt to advance a cursor that doesn't exist");
1238        return false;
1239    }
1240    if (!cursor->transaction() || !cursor->transaction()->inProgress()) {
1241        LOG_ERROR("Attempt to advance a cursor without an established, in-progress transaction");
1242        return false;
1243    }
1244
1245    if (!cursor->advance(count)) {
1246        LOG_ERROR("Attempt to advance cursor %lli steps failed", count);
1247        return false;
1248    }
1249
1250    key = cursor->currentKey();
1251    primaryKey = cursor->currentPrimaryKey();
1252    valueBuffer = cursor->currentValueBuffer();
1253
1254    return true;
1255}
1256
1257bool UniqueIDBDatabaseBackingStoreSQLite::iterateCursor(const IDBIdentifier& cursorIdentifier, const IDBKeyData& targetKey, IDBKeyData& key, IDBKeyData& primaryKey, Vector<uint8_t>& valueBuffer)
1258{
1259    ASSERT(!RunLoop::isMain());
1260    ASSERT(m_sqliteDB);
1261    ASSERT(m_sqliteDB->isOpen());
1262
1263    SQLiteIDBCursor* cursor = m_cursors.get(cursorIdentifier);
1264    if (!cursor) {
1265        LOG_ERROR("Attempt to iterate a cursor that doesn't exist");
1266        return false;
1267    }
1268    if (!cursor->transaction() || !cursor->transaction()->inProgress()) {
1269        LOG_ERROR("Attempt to iterate a cursor without an established, in-progress transaction");
1270        return false;
1271    }
1272
1273    if (!cursor->iterate(targetKey)) {
1274        LOG_ERROR("Attempt to iterate cursor failed");
1275        return false;
1276    }
1277
1278    key = cursor->currentKey();
1279    primaryKey = cursor->currentPrimaryKey();
1280    valueBuffer = cursor->currentValueBuffer();
1281
1282    return true;
1283}
1284
1285void UniqueIDBDatabaseBackingStoreSQLite::notifyCursorsOfChanges(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID)
1286{
1287    ASSERT(!RunLoop::isMain());
1288    ASSERT(m_sqliteDB);
1289    ASSERT(m_sqliteDB->isOpen());
1290
1291    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
1292    if (!transaction || !transaction->inProgress()) {
1293        LOG_ERROR("Attempt to notify cursors of changes in database without an established, in-progress transaction");
1294        return;
1295    }
1296
1297    transaction->notifyCursorsOfChanges(objectStoreID);
1298}
1299
1300int UniqueIDBDatabaseBackingStoreSQLite::idbKeyCollate(int aLength, const void* aBuffer, int bLength, const void* bBuffer)
1301{
1302    IDBKeyData a, b;
1303    if (!deserializeIDBKeyData(static_cast<const uint8_t*>(aBuffer), aLength, a)) {
1304        LOG_ERROR("Unable to deserialize key A in collation function.");
1305
1306        // There's no way to indicate an error to SQLite - we have to return a sorting decision.
1307        // We arbitrarily choose "A > B"
1308        return 1;
1309    }
1310    if (!deserializeIDBKeyData(static_cast<const uint8_t*>(bBuffer), bLength, b)) {
1311        LOG_ERROR("Unable to deserialize key B in collation function.");
1312
1313        // There's no way to indicate an error to SQLite - we have to return a sorting decision.
1314        // We arbitrarily choose "A > B"
1315        return 1;
1316    }
1317
1318    return a.compare(b);
1319}
1320
1321void UniqueIDBDatabaseBackingStoreSQLite::unregisterCursor(SQLiteIDBCursor* cursor)
1322{
1323    ASSERT(m_cursors.contains(cursor->identifier()));
1324    m_cursors.remove(cursor->identifier());
1325}
1326
1327} // namespace WebKit
1328
1329#endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
1330