void IDBConnectionProxy::putOrAdd(TransactionOperation& operation, IDBKey* key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode mode) { const IDBRequestData requestData(operation); saveOperation(operation); callConnectionOnMainThread(&IDBConnectionToServer::putOrAdd, requestData, IDBKeyData(key), value, mode); }
void IDBCursor::advance(unsigned long count, ExceptionCode& ec) { LOG(IndexedDB, "IDBCursor::advance"); if (!m_request) { ec = IDBDatabaseException::InvalidStateError; return; } if (!count) { ec = TypeError; return; } if (sourcesDeleted()) { ec = IDBDatabaseException::InvalidStateError; return; } if (!transaction().isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return; } if (!m_gotValue) { ec = IDBDatabaseException::InvalidStateError; return; } m_gotValue = false; uncheckedIteratorCursor(IDBKeyData(), count); }
IDBKeyData::IDBKeyData(const IDBKey* key) : m_type(KeyType::Invalid) { if (!key) { m_isNull = true; return; } m_type = key->type(); switch (m_type) { case KeyType::Invalid: break; case KeyType::Array: for (auto& key2 : key->array()) m_arrayValue.append(IDBKeyData(key2.get())); break; case KeyType::String: m_stringValue = key->string(); break; case KeyType::Date: m_numberValue = key->date(); break; case KeyType::Number: m_numberValue = key->number(); break; case KeyType::Max: case KeyType::Min: break; } }
void IDBKeyData::setNumberValue(double value) { *this = IDBKeyData(); m_numberValue = value; m_type = KeyType::Number; m_isNull = false; }
void IDBKeyData::setStringValue(const String& value) { *this = IDBKeyData(); m_stringValue = value; m_type = KeyType::String; m_isNull = false; }
void IDBKeyData::setArrayValue(const Vector<IDBKeyData>& value) { *this = IDBKeyData(); m_arrayValue = value; m_type = KeyType::Array; m_isNull = false; }
void IDBCursor::continueFunction(ScriptExecutionContext* context, ExceptionCode& ec) { if (!context) { ec = IDBDatabaseException::InvalidStateError; return; } continueFunction(IDBKeyData(), ec); }
IDBKeyData IndexValueStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& range) const { LOG(IndexedDB, "IndexValueStore::lowestKeyWithRecordInRange - %s", range.loggingString().utf8().data()); if (range.isExactlyOneKey()) return m_records.contains(range.lowerKey) ? range.lowerKey : IDBKeyData(); auto iterator = lowestIteratorInRange(range); if (iterator == m_orderedKeys.end()) return { }; return *iterator; }
void generateIndexKeysForValue(ExecState* exec, const IDBIndexMetadata& indexMetadata, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys) { RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(exec, objectValue, indexMetadata.keyPath); if (!indexKey) return; if (!indexMetadata.multiEntry || indexKey->type() != KeyType::Array) { if (!indexKey->isValid()) return; indexKeys.append(IDBKeyData(indexKey.get())); } else { ASSERT(indexMetadata.multiEntry); ASSERT(indexKey->type() == KeyType::Array); indexKey = IDBKey::createMultiEntryArray(indexKey->array()); if (!indexKey->isValid()) return; for (auto& i : indexKey->array()) indexKeys.append(IDBKeyData(i.get())); } }
void IDBCursor::advance(unsigned long count, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBCursor::advance"); if (!m_request) { ec.code = IDBDatabaseException::InvalidStateError; return; } if (!count) { ec.code = TypeError; ec.message = ASCIILiteral("Failed to execute 'advance' on 'IDBCursor': A count argument with value 0 (zero) was supplied, must be greater than 0."); return; } if (sourcesDeleted()) { ec.code = IDBDatabaseException::InvalidStateError; return; } if (!transaction().isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; ec.message = ASCIILiteral("Failed to execute 'advance' on 'IDBCursor': The transaction is inactive or finished."); return; } if (!m_gotValue) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to execute 'advance' on 'IDBCursor': The cursor is being iterated or has iterated past its end."); return; } m_gotValue = false; uncheckedIteratorCursor(IDBKeyData(), count); }
SQLiteIDBCursor::AdvanceResult SQLiteIDBCursor::internalAdvanceOnce() { ASSERT(m_transaction->sqliteTransaction()); ASSERT(m_statement); if (m_completed) { LOG_ERROR("Attempt to advance a completed cursor"); return AdvanceResult::Failure; } int result = m_statement->step(); if (result == SQLITE_DONE) { m_completed = true; // When a cursor reaches its end, that is indicated by having undefined keys/values m_currentKey = IDBKeyData(); m_currentPrimaryKey = IDBKeyData(); m_currentValueBuffer.clear(); return AdvanceResult::Success; } if (result != SQLITE_ROW) { LOG_ERROR("Error advancing cursor - (%i) %s", result, m_transaction->sqliteTransaction()->database().lastErrorMsg()); m_completed = true; m_errored = true; return AdvanceResult::Failure; } int64_t recordID = m_statement->getColumnInt64(0); // If the recordID of the record just fetched is the same as the current record ID // then this statement must have been re-prepared in response to an object store change. // We don't want to re-use the current record so we'll move on to the next one. if (recordID == m_currentRecordID) return AdvanceResult::ShouldAdvanceAgain; m_currentRecordID = recordID; Vector<uint8_t> keyData; m_statement->getColumnBlobAsVector(1, keyData); if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentKey)) { LOG_ERROR("Unable to deserialize key data from database while advancing cursor"); m_completed = true; m_errored = true; return AdvanceResult::Failure; } m_statement->getColumnBlobAsVector(2, keyData); m_currentValueBuffer = keyData; // The primaryKey of an ObjectStore cursor is the same as its key. if (m_indexID == IDBIndexMetadata::InvalidId) m_currentPrimaryKey = m_currentKey; else { if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentPrimaryKey)) { LOG_ERROR("Unable to deserialize value data from database while advancing index cursor"); m_completed = true; m_errored = true; return AdvanceResult::Failure; } SQLiteStatement objectStoreStatement(m_statement->database(), "SELECT value FROM Records WHERE key = CAST(? AS TEXT) and objectStoreID = ?;"); if (objectStoreStatement.prepare() != SQLITE_OK || objectStoreStatement.bindBlob(1, m_currentValueBuffer.data(), m_currentValueBuffer.size()) != SQLITE_OK || objectStoreStatement.bindInt64(2, m_objectStoreID) != SQLITE_OK) { LOG_ERROR("Could not create index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg()); m_completed = true; m_errored = true; return AdvanceResult::Failure; } int result = objectStoreStatement.step(); if (result == SQLITE_ROW) objectStoreStatement.getColumnBlobAsVector(0, m_currentValueBuffer); else if (result == SQLITE_DONE) { // This indicates that the record we're trying to retrieve has been removed from the object store. // Skip over it. return AdvanceResult::ShouldAdvanceAgain; } else { LOG_ERROR("Could not step index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg()); m_completed = true; m_errored = true; return AdvanceResult::Failure; } } return AdvanceResult::Success; }
String IDBKey::loggingString() const { return IDBKeyData(this).loggingString(); }