void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks) { SQLiteStatement idQuery(objectStore->sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get())); bool ok = idQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(idQuery, objectStore->id(), key.get()); if (idQuery.step() != SQLResultRow) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store.")); return; } int64_t id = idQuery.getColumnInt64(0); SQLiteStatement osQuery(objectStore->sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE id = ?"); ok = osQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? osQuery.bindInt64(1, id); ok = osQuery.step() == SQLResultDone; ASSERT_UNUSED(ok, ok); SQLiteStatement indexQuery(objectStore->sqliteDatabase(), "DELETE FROM IndexData WHERE objectStoreDataId = ?"); ok = indexQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? indexQuery.bindInt64(1, id); ok = indexQuery.step() == SQLResultDone; ASSERT_UNUSED(ok, ok); callbacks->onSuccess(); }
bool IDBIndexBackendImpl::addingKeyAllowed(IDBKey* key) { if (!m_unique) return true; SQLiteStatement query(sqliteDatabase(), "SELECT id FROM IndexData " + whereClause(key)); bool ok = query.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(query, m_id, key); bool existingValue = query.step() == SQLResultRow; return !existingValue; }
void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks) { SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key->type())); bool ok = query.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(query, m_id, key.get()); if (query.step() != SQLResultDone) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store.")); return; } callbacks->onSuccess(); }
void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks) { // FIXME: Fully implement. RefPtr<IDBKey> key = range->left(); SQLiteStatement query(sqliteDatabase(), "SELECT id, value FROM ObjectStoreData " + whereClause(key->type())); bool ok = query.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(query, m_id, key.get()); if (query.step() != SQLResultRow) { callbacks->onSuccess(); return; } RefPtr<SerializedScriptValue> value = SerializedScriptValue::createFromWire(query.getColumnText(1)); RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(this, range, static_cast<IDBCursor::Direction>(direction), key.release(), value.release()); callbacks->onSuccess(cursor.release()); }
void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks) { SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key->type())); bool ok = query.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(query, m_id, key.get()); if (query.step() != SQLResultRow) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store.")); return; } ASSERT((key->type() == IDBKey::StringType) != query.isColumnNull(0)); // FIXME: Implement date. ASSERT((key->type() == IDBKey::NumberType) != query.isColumnNull(2)); callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnText(3))); ASSERT(query.step() != SQLResultRow); }
void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks) { RefPtr<SerializedScriptValue> value = prpValue; RefPtr<IDBKey> key = prpKey; if (!m_keyPath.isNull()) { if (key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath.")); return; } Vector<RefPtr<SerializedScriptValue> > values; values.append(value); Vector<RefPtr<IDBKey> > idbKeys; IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, m_keyPath, idbKeys); if (idbKeys.isEmpty()) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "An invalid keyPath was supplied for an objectStore.")); return; } key = idbKeys[0]; } if (!key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied.")); return; } SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key->type())); bool ok = getQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(getQuery, m_id, key.get()); bool existingValue = getQuery.step() == SQLResultRow; if (addOnly && existingValue) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store.")); return; } String sql = existingValue ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?" : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)"; SQLiteStatement putQuery(sqliteDatabase(), sql); ok = putQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? switch (key->type()) { case IDBKey::StringType: putQuery.bindText(1, key->string()); putQuery.bindNull(2); putQuery.bindNull(3); break; // FIXME: Implement date. case IDBKey::NumberType: putQuery.bindNull(1); putQuery.bindNull(2); putQuery.bindInt(3, key->number()); break; case IDBKey::NullType: putQuery.bindNull(1); putQuery.bindNull(2); putQuery.bindNull(3); break; default: ASSERT_NOT_REACHED(); } putQuery.bindText(4, value->toWireString()); if (existingValue) putQuery.bindInt(5, getQuery.getColumnInt(0)); else putQuery.bindInt64(5, m_id); ok = putQuery.step() == SQLResultDone; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? callbacks->onSuccess(key.get()); }
void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction) { RefPtr<SerializedScriptValue> value = prpValue; RefPtr<IDBKey> key = prpKey; // FIXME: Support auto-increment. if (!objectStore->m_keyPath.isNull()) { if (key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath.")); return; } key = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath); if (!key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from the keyPath.")); return; } } else if (!key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied.")); return; } if (key->type() == IDBKey::NullType) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed.")); return; } Vector<RefPtr<IDBKey> > indexKeys; for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) { RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath()); if (!key) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath.")); return; } if (key->type() == IDBKey::NullType) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL.")); return; } if (!it->second->addingKeyAllowed(key.get())) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements.")); return; } indexKeys.append(key.release()); } SQLiteStatement getQuery(objectStore->sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get())); bool ok = getQuery.prepare() == SQLResultOk; ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? bindWhereClause(getQuery, objectStore->id(), key.get()); bool isExistingValue = getQuery.step() == SQLResultRow; if (addOnly && isExistingValue) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store.")); return; } // Before this point, don't do any mutation. After this point, rollback the transaction in case of error. int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : InvalidId; if (!putObjectStoreData(objectStore->sqliteDatabase(), key.get(), value.get(), objectStore->id(), dataRowId)) { // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors. callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage.")); transaction->abort(); return; } if (!deleteIndexData(objectStore->sqliteDatabase(), dataRowId)) { // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors. callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage.")); transaction->abort(); return; } int i = 0; for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) { if (!putIndexData(objectStore->sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId)) { // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors. callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage.")); transaction->abort(); return; } } callbacks->onSuccess(key.get()); }