IDBError MemoryObjectStore::populateIndexWithExistingRecords(MemoryIndex& index) { if (!m_keyValueStore) return { }; JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM()); for (auto iterator : *m_keyValueStore) { auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), iterator.value); if (jsValue.isUndefinedOrNull()) return { }; IndexKey indexKey; generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey); if (indexKey.isNull()) continue; IDBError error = index.putIndexKey(iterator.key, indexKey); if (!error.isNull()) return error; } return { }; }
IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value) { JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM()); auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), value); if (jsValue.isUndefinedOrNull()) return { }; IDBError error; Vector<std::pair<MemoryIndex*, IndexKey>> changedIndexRecords; for (auto* index : m_indexesByName.values()) { IndexKey indexKey; generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey); if (indexKey.isNull()) continue; error = index->putIndexKey(key, indexKey); if (!error.isNull()) break; changedIndexRecords.append(std::make_pair(index, indexKey)); } // If any of the index puts failed, revert all of the ones that went through. if (!error.isNull()) { for (auto& record : changedIndexRecords) record.first->removeRecord(key, record.second); } return error; }
IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey) { LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey"); if (!m_records) m_records = std::make_unique<IndexValueStore>(m_info.unique()); if (!m_info.multiEntry()) { IDBKeyData key = indexKey.asOneKey(); return m_records->addRecord(key, valueKey); } Vector<IDBKeyData> keys = indexKey.multiEntry(); if (m_info.unique()) { for (auto& key : keys) { if (m_records->contains(key)) return IDBError(IDBExceptionCode::ConstraintError); } } for (auto& key : keys) { auto error = m_records->addRecord(key, valueKey); ASSERT_UNUSED(error, error.isNull()); } return { }; }
IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey) { LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey"); if (!m_records) { m_records = std::make_unique<IndexValueStore>(m_info.unique()); notifyCursorsOfAllRecordsChanged(); } if (!m_info.multiEntry()) { IDBKeyData key = indexKey.asOneKey(); IDBError result = m_records->addRecord(key, valueKey); notifyCursorsOfValueChange(key, valueKey); return result; } Vector<IDBKeyData> keys = indexKey.multiEntry(); if (m_info.unique()) { for (auto& key : keys) { if (m_records->contains(key)) return IDBError(ConstraintError); } } for (auto& key : keys) { auto error = m_records->addRecord(key, valueKey); ASSERT_UNUSED(error, error.isNull()); notifyCursorsOfValueChange(key, valueKey); } return IDBError { }; }
void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey) { LOG(IndexedDB, "MemoryIndex::removeRecord"); ASSERT(m_records); if (!m_info.multiEntry()) { IDBKeyData key = indexKey.asOneKey(); m_records->removeRecord(key, valueKey); return; } Vector<IDBKeyData> keys = indexKey.multiEntry(); for (auto& key : keys) m_records->removeRecord(key, valueKey); }