15af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke/*
22daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2011 Google Inc. All rights reserved.
35af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *
45af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * Redistribution and use in source and binary forms, with or without
55af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * modification, are permitted provided that the following conditions
65af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * are met:
75af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *
85af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * 1.  Redistributions of source code must retain the above copyright
95af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *     notice, this list of conditions and the following disclaimer.
105af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * 2.  Redistributions in binary form must reproduce the above copyright
115af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *     notice, this list of conditions and the following disclaimer in the
125af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *     documentation and/or other materials provided with the distribution.
135af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke *
145af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
155af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
165af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
175af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
185af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
195af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
205af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
215af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
235af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke */
255af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
265af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include "config.h"
27dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "IDBObjectStoreBackendImpl.h"
285af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(INDEXED_DATABASE)
30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "CrossThreadTask.h"
325af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include "DOMStringList.h"
3381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "IDBBackingStore.h"
34e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "IDBBindingUtilities.h"
355af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include "IDBCallbacks.h"
36dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "IDBCursorBackendImpl.h"
37e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "IDBDatabaseBackendImpl.h"
385af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke#include "IDBDatabaseException.h"
39db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "IDBIndexBackendImpl.h"
40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "IDBKey.h"
41e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "IDBKeyPath.h"
42e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "IDBKeyPathBackendImpl.h"
43dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "IDBKeyRange.h"
44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "IDBTransactionBackendInterface.h"
45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "ScriptExecutionContext.h"
465af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
475af96e2c7b73ebc627c6894727826a7576d31758Leon Clarkenamespace WebCore {
485af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
49dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochIDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
505af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
515af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
525af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochIDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, int64_t id, const String& name, const String& keyPath, bool autoIncrement)
5481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_backingStore(backingStore)
552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_databaseId(databaseId)
56e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_id(id)
57e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_name(name)
58545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    , m_keyPath(keyPath)
59545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    , m_autoIncrement(autoIncrement)
60ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    , m_autoIncrementNumber(-1)
615af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
62e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    loadIndexes();
635af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
645af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochIDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement)
6681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_backingStore(backingStore)
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_databaseId(databaseId)
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_id(InvalidId)
69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_name(name)
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_keyPath(keyPath)
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_autoIncrement(autoIncrement)
72ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    , m_autoIncrementNumber(-1)
73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
76dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochPassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
775af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
785af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    RefPtr<DOMStringList> indexNames = DOMStringList::create();
795af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    for (IndexMap::const_iterator it = m_indexes.begin(); it != m_indexes.end(); ++it)
805af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        indexNames->append(it->first);
815af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return indexNames.release();
825af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
835af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
85bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBKey> key = prpKey;
88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::getInternal, objectStore, key, callbacks)))
90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
91bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
92bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
94e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String wireData = objectStore->m_backingStore->getObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key);
9681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (wireData.isNull()) {
97ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        callbacks->onSuccess(SerializedScriptValue::undefinedValue());
98e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return;
99e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
100e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
10181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    callbacks->onSuccess(SerializedScriptValue::createFromWire(wireData));
102e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
103e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
1045abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickstatic PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, const String& keyPath)
1055abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
1065abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    Vector<RefPtr<SerializedScriptValue> > values;
1075abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    values.append(value);
1085abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    Vector<RefPtr<IDBKey> > keys;
1095abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, keyPath, keys);
1105abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (keys.isEmpty())
1115abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return 0;
1125abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    ASSERT(keys.size() == 1);
1135abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return keys[0].release();
1145abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
1155abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
11681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic PassRefPtr<SerializedScriptValue> injectKeyIntoKeyPath(PassRefPtr<IDBKey> key, PassRefPtr<SerializedScriptValue> value, const String& keyPath)
1175abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
11881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return IDBKeyPathBackendImpl::injectIDBKeyIntoSerializedValue(key, value, keyPath);
119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (transactionPtr->mode() == IDBTransaction::READ_ONLY) {
12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ec = IDBDatabaseException::READ_ONLY_ERR;
12565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
12665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<SerializedScriptValue> value = prpValue;
130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBKey> key = prpKey;
131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: This should throw a SERIAL_ERR on structured clone problems.
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: This should throw a DATA_ERR when the wrong key/keyPath data is supplied.
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction)))
136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
1375abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
1385abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochPassRefPtr<IDBKey> IDBObjectStoreBackendImpl::selectKeyForPut(IDBObjectStoreBackendImpl* objectStore, IDBKey* key, PutMode putMode, IDBCallbacks* callbacks, RefPtr<SerializedScriptValue>& value)
140e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (putMode == CursorUpdate)
1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ASSERT(key);
143e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const bool autoIncrement = objectStore->autoIncrement();
1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const bool hasKeyPath = !objectStore->m_keyPath.isNull();
1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (hasKeyPath && key && putMode != CursorUpdate) {
148ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that has a keyPath."));
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return 0;
150ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
151ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (autoIncrement && key) {
1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        objectStore->resetAutoIncrementKeyCache();
1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return key;
155ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
156ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (autoIncrement) {
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ASSERT(!key);
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!hasKeyPath)
1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return objectStore->genAutoIncrementKey();
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
16281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
1632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (keyPathKey) {
1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            objectStore->resetAutoIncrementKeyCache();
1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return keyPathKey;
166e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        }
167ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
16881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<IDBKey> autoIncKey = objectStore->genAutoIncrementKey();
16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<SerializedScriptValue> valueAfterInjection = injectKeyIntoKeyPath(autoIncKey, value, objectStore->m_keyPath);
17081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!valueAfterInjection) {
17181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The generated key could not be inserted into the object using the keyPath."));
17281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return 0;
17381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
17481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        value = valueAfterInjection;
17581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return autoIncKey.release();
1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (hasKeyPath) {
17981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
1802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!keyPathKey) {
182ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key could not be fetched from the keyPath."));
1832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return 0;
184e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        }
1852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (putMode == CursorUpdate && !keyPathKey->isEqual(key)) {
1872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key fetched from the keyPath does not match the key of the cursor."));
1882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return 0;
1892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
1902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return keyPathKey.release();
1922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!key) {
1952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied"));
1962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return 0;
197e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
198ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
1992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return key;
2002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2022fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
2032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<SerializedScriptValue> value = prpValue;
20581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<IDBKey> key = selectKeyForPut(objectStore.get(), prpKey.get(), putMode, callbacks.get(), value);
2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!key)
2072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2094576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (key->type() == IDBKey::NullType) {
2104576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed."));
2114576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return;
2124576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
213e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
2145abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    Vector<RefPtr<IDBKey> > indexKeys;
215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
2165abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
2175abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        if (!key) {
2185abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
2195abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            return;
2205abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        }
2214576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (key->type() == IDBKey::NullType) {
2224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL."));
2234576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            return;
2244576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        }
2255abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        if (!it->second->addingKeyAllowed(key.get())) {
2265abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
2275abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            return;
2285abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        }
2295abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        indexKeys.append(key.release());
2305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    }
2315abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
2322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
2332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool isExistingValue = objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get());
234e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
2352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (putMode == AddOnly && isExistingValue) {
236e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
237e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return;
238e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
239e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
240a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Before this point, don't do any mutation.  After this point, rollback the transaction in case of error.
241e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
2422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!objectStore->m_backingStore->putObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key, value->toWireString(), recordIdentifier.get())) {
243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
244a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        transaction->abort();
246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2485abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
2495abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    int i = 0;
250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) {
25181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!it->second->hasValidId())
25281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue; // The index object has been created, but does not exist in the database yet.
2532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get())) {
2552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
2562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
2572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            transaction->abort();
2582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
2602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!objectStore->m_backingStore->putIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), *indexKeys[i], recordIdentifier.get())) {
262a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
263a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
264a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            transaction->abort();
265a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return;
266a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
267a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
268e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
269e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    callbacks->onSuccess(key.get());
270e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
271e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
2724576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid IDBObjectStoreBackendImpl::deleteFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
273a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
27465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (transaction->mode() == IDBTransaction::READ_ONLY) {
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ec = IDBDatabaseException::READ_ONLY_ERR;
27665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
279a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
280a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBKey> key = prpKey;
281a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
28265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
2834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteInternal, objectStore, key, callbacks)))
284a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
285a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
286a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2874576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
288e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
2902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get())) {
291e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
292e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
293e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
294e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
2952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
2962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->second->hasValidId())
2972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue; // The index object has been created, but does not exist in the database yet.
2982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get()))
3002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT_NOT_REACHED();
3012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
3022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    objectStore->m_backingStore->deleteObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), recordIdentifier.get());
3042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    callbacks->onSuccess(SerializedScriptValue::nullValue());
3052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3072fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid IDBObjectStoreBackendImpl::clear(PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
3082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (transaction->mode() == IDBTransaction::READ_ONLY) {
3102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ec = IDBDatabaseException::READ_ONLY_ERR;
3112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
3122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
3152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
3162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::clearInternal, objectStore, callbacks)))
3182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
3192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
32181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid IDBObjectStoreBackendImpl::clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBCallbacks> callbacks)
3222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    objectStore->m_backingStore->clearObjectStore(objectStore->m_databaseId, objectStore->id());
32481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    callbacks->onSuccess(SerializedScriptValue::undefinedValue());
3252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
32781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochnamespace {
32881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass PopulateIndexCallback : public IDBBackingStore::ObjectStoreRecordCallback {
32981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic:
3302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    PopulateIndexCallback(IDBBackingStore& backingStore, const String& indexKeyPath, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
33181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        : m_backingStore(backingStore)
33281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        , m_indexKeyPath(indexKeyPath)
3332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_databaseId(databaseId)
3342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_objectStoreId(objectStoreId)
33581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        , m_indexId(indexId)
33681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
33781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool callback(const IDBBackingStore::ObjectStoreRecordIdentifier* recordIdentifier, const String& value)
34081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
34181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<SerializedScriptValue> objectValue = SerializedScriptValue::createFromWire(value);
34281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(objectValue.get(), m_indexKeyPath);
34381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
34454cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block        if (!indexKey)
34554cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block            return true;
3462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_backingStore.putIndexDataForRecord(m_databaseId, m_objectStoreId, m_indexId, *indexKey, recordIdentifier))
34781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return false;
34881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
34981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return true;
35081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
35181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
35281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprivate:
35381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    IDBBackingStore& m_backingStore;
35481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const String& m_indexKeyPath;
3552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_databaseId;
3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
35781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    int64_t m_indexId;
35881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
35981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
36081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
3612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
36281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
3632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
3642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))
36581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
36681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return true;
367e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
368e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
369a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochPassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
3705af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
3715af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (m_indexes.contains(name)) {
372a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::CONSTRAINT_ERR;
373a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return 0;
374a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
375a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
376a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
377a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return 0;
3785af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    }
3795af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
3802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, name, m_name, keyPath, unique);
3815af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    ASSERT(index->name() == name);
382a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
383a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
384a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
385a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal, objectStore, index, transaction),
386a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                   createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexFromMap, objectStore, index))) {
387a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
388a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return 0;
389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3915af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_indexes.set(name, index);
392a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return index.release();
3935af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
3945af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
395a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
3965af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke{
39781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    int64_t id;
3982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!objectStore->m_backingStore->createIndex(objectStore->m_databaseId, objectStore->id(), index->name(), index->keyPath(), index->unique(), id)) {
399a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        transaction->abort();
400a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
401a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
40281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
40381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    index->setId(id);
40481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
4052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!populateIndex(*objectStore->m_backingStore, objectStore->m_databaseId, objectStore->m_id, id, index->keyPath())) {
406a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        transaction->abort();
407a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
408a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
40981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
410a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    transaction->didCompleteTaskEvents();
411a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
412a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
413a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochPassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name, ExceptionCode& ec)
414a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
415a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBIndexBackendInterface> index = m_indexes.get(name);
416a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!index) {
417a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_FOUND_ERR;
418a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return 0;
419a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
420a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return index.release();
4215af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
4225af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
4234576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
4245abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
42565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
42665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
42765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
42865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
42965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
4315abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (!index) {
432a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_FOUND_ERR;
4335abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return;
4345abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    }
435e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
436a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
437a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
4384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal, objectStore, index, transactionPtr),
439a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                   createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap, objectStore, index))) {
440a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
441a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
442a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
4435af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    m_indexes.remove(name);
4445af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke}
4455af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
4464576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
447a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
4482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    objectStore->m_backingStore->deleteIndex(objectStore->m_databaseId, objectStore->id(), index->id());
449a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    transaction->didCompleteTaskEvents();
450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
451a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
452a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
453a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
454a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
455a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBKeyRange> range = prpRange;
456a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
457a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
458a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, transaction)))
459a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ec = IDBDatabaseException::NOT_ALLOWED_ERR;
460a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
461a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
462a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
4635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
4645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);
46581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
4662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->m_backingStore->openObjectStoreCursor(objectStore->m_databaseId, objectStore->id(), range.get(), direction);
46781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!backingStoreCursor) {
4682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        callbacks->onSuccess(SerializedScriptValue::nullValue());
469e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
470e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
471e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
47281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
473e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    callbacks->onSuccess(cursor.release());
474e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
475e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
476e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid IDBObjectStoreBackendImpl::loadIndexes()
477e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
47881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Vector<int64_t> ids;
47981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Vector<String> names;
48081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Vector<String> keyPaths;
48181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Vector<bool> uniqueFlags;
4822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_backingStore->getIndexes(m_databaseId, m_id, ids, names, keyPaths, uniqueFlags);
483e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
48481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(names.size() == ids.size());
48581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(keyPaths.size() == ids.size());
48681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(uniqueFlags.size() == ids.size());
487e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
48881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (size_t i = 0; i < ids.size(); i++)
4892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_indexes.set(names[i], IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, ids[i], names[i], m_name, keyPaths[i], uniqueFlags[i]));
490dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch}
4915af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
492a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
493a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
494a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(objectStore->m_indexes.contains(index->name()));
495a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    objectStore->m_indexes.remove(index->name());
496a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
497a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
498a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid IDBObjectStoreBackendImpl::addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
499a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
500a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<IDBIndexBackendImpl> indexPtr = index;
501a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!objectStore->m_indexes.contains(indexPtr->name()));
502a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    objectStore->m_indexes.set(indexPtr->name(), indexPtr);
503a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
504a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
505ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen MurdochPassRefPtr<IDBKey> IDBObjectStoreBackendImpl::genAutoIncrementKey()
506ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
507ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (m_autoIncrementNumber > 0)
508ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return IDBKey::createNumber(m_autoIncrementNumber++);
509ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
5102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_autoIncrementNumber = static_cast<int>(m_backingStore->nextAutoIncrementNumber(m_databaseId, id()));
511ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return IDBKey::createNumber(m_autoIncrementNumber++);
512ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
513ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
514a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
515545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch} // namespace WebCore
5165af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
517545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#endif
518