bool UniqueIDBDatabaseBackingStoreSQLite::putRecord(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, const IDBKey& key, const uint8_t* valueBuffer, size_t valueSize) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction"); return false; } if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) { LOG_ERROR("Attempt to put a record into database during read-only transaction"); return false; } RefPtr<SharedBuffer> keyBuffer = serializeIDBKey(key); if (!keyBuffer) { LOG_ERROR("Unable to serialize IDBKey to be stored in the database"); return false; } { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO Records VALUES (?, ?, ?);")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, objectStoreID) != SQLResultOk || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk || sql.bindBlob(3, valueBuffer, valueSize) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not put record for object store %lli in Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } } return true; }
bool UniqueIDBDatabaseBackingStoreSQLite::changeDatabaseVersion(const IDBTransactionIdentifier& identifier, uint64_t newVersion) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to change database version with an establish, in-progress transaction"); return false; } if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) { LOG_ERROR("Attempt to change database version during a non version-change transaction"); return false; } { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("UPDATE IDBDatabaseInfo SET value = ? where key = 'DatabaseVersion';")); if (sql.prepare() != SQLResultOk || sql.bindText(1, String::number(newVersion)) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not update database version in IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } } return true; }
bool UniqueIDBDatabaseBackingStoreSQLite::deleteIndex(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, int64_t indexID) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to delete index without an established, in-progress transaction"); return false; } if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) { LOG_ERROR("Attempt to delete index during a non-version-change transaction"); return false; } { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, indexID) != SQLResultOk || sql.bindInt64(2, objectStoreID) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not delete index id %lli from IndexInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } } // FIXME (<rdar://problem/15905293>) - Once we store records against indexes, delete them here. return true; }
bool UniqueIDBDatabaseBackingStoreSQLite::clearObjectStore(const IDBTransactionIdentifier& identifier, int64_t objectStoreID) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to change database version with an establish, in-progress transaction"); return false; } if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) { LOG_ERROR("Attempt to change database version during a read-only transaction"); return false; } { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM Records WHERE objectStoreID = ?;")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, objectStoreID) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not delete records from object store id %lli (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } } // FIXME <rdar://problem/15779642>: Once indexes are implemented, drop index records. return true; }
bool UniqueIDBDatabaseBackingStoreSQLite::deleteObjectStore(const IDBTransactionIdentifier& identifier, int64_t objectStoreID) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to change database version with an established, in-progress transaction"); return false; } if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) { LOG_ERROR("Attempt to change database version during a non version-change transaction"); return false; } // Delete the ObjectStore record { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("DELETE FROM ObjectStoreInfo WHERE id = ?;")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, objectStoreID) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not delete object store id %lli from ObjectStoreInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } } // Delete all associated Index records { Vector<int64_t> indexIDs; SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT id FROM IndexInfo WHERE objectStoreID = ?;")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, objectStoreID) != SQLResultOk) { LOG_ERROR("Error fetching index ID records for object store id %lli from IndexInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } int resultCode; while ((resultCode = sql.step()) == SQLResultRow) indexIDs.append(sql.getColumnInt64(0)); if (resultCode != SQLResultDone) { LOG_ERROR("Error fetching index ID records for object store id %lli from IndexInfo table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } for (auto indexID : indexIDs) { if (!deleteIndex(identifier, objectStoreID, indexID)) return false; } } { // FIXME: Execute SQL here to drop all records related to this object store. } return true; }
bool UniqueIDBDatabaseBackingStoreSQLite::rollbackTransaction(const IDBTransactionIdentifier& identifier) { ASSERT(!isMainThread()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction) { LOG_ERROR("Attempt to rollback a transaction that hasn't been established"); return false; } return transaction->rollback(); }
bool UniqueIDBDatabaseBackingStoreSQLite::getKeyRangeRecordFromObjectStore(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, const WebCore::IDBKeyRange& keyRange, RefPtr<WebCore::SharedBuffer>& result, RefPtr<WebCore::IDBKey>& resultKey) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction"); return false; } RefPtr<SharedBuffer> lowerBuffer = serializeIDBKey(*keyRange.lower()); if (!lowerBuffer) { LOG_ERROR("Unable to serialize IDBKey to be stored in the database"); return false; } RefPtr<SharedBuffer> upperBuffer = serializeIDBKey(*keyRange.upper()); if (!upperBuffer) { LOG_ERROR("Unable to serialize IDBKey to be stored in the database"); return false; } { SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM Records WHERE objectStoreID = ? AND key >= ? AND key <= ? ORDER BY key;")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, objectStoreID) != SQLResultOk || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLResultOk || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLResultOk) { LOG_ERROR("Could not get key range record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } int sqlResult = sql.step(); if (sqlResult == SQLResultOk || sqlResult == SQLResultDone) { // There was no record for the key in the database. return true; } if (sqlResult != SQLResultRow) { // There was an error fetching the record from the database. LOG_ERROR("Could not get record from object store %lli from Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } Vector<char> buffer; sql.getColumnBlobAsVector(0, buffer); result = SharedBuffer::create(static_cast<const char*>(buffer.data()), buffer.size()); } return true; }
SQLiteIDBCursor::SQLiteIDBCursor(SQLiteIDBTransaction& transaction, const uint64_t objectStoreID, const uint64_t indexID, const IDBKeyRangeData& range) : m_transaction(&transaction) , m_cursorIdentifier(transaction.transactionIdentifier()) , m_objectStoreID(objectStoreID) , m_indexID(indexID ? indexID : IDBIndexMetadata::InvalidId) , m_cursorDirection(IndexedDB::CursorDirection::Next) , m_keyRange(range) , m_backingStoreCursor(true) { ASSERT(m_objectStoreID); }
bool UniqueIDBDatabaseBackingStoreSQLite::createIndex(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, const WebCore::IDBIndexMetadata& metadata) { ASSERT(!isMainThread()); ASSERT(m_sqliteDB); ASSERT(m_sqliteDB->isOpen()); SQLiteIDBTransaction* transaction = m_transactions.get(identifier); if (!transaction || !transaction->inProgress()) { LOG_ERROR("Attempt to create index without an established, in-progress transaction"); return false; } if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) { LOG_ERROR("Attempt to create index during a non-version-change transaction"); return false; } RefPtr<SharedBuffer> keyPathBlob = serializeIDBKeyPath(metadata.keyPath); if (!keyPathBlob) { LOG_ERROR("Unable to serialize IDBKeyPath to save in database"); return false; } SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IndexInfo VALUES (?, ?, ?, ?, ?, ?);")); if (sql.prepare() != SQLResultOk || sql.bindInt64(1, metadata.id) != SQLResultOk || sql.bindText(2, metadata.name) != SQLResultOk || sql.bindInt64(3, objectStoreID) != SQLResultOk || sql.bindBlob(4, keyPathBlob->data(), keyPathBlob->size()) != SQLResultOk || sql.bindInt(5, metadata.unique) != SQLResultOk || sql.bindInt(6, metadata.multiEntry) != SQLResultOk || sql.step() != SQLResultDone) { LOG_ERROR("Could not add index '%s' to IndexInfo table (%i) - %s", metadata.name.utf8().data(), m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg()); return false; } return true; }