2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "IDBObjectStoreBackendImpl.h"
29 #if ENABLE(INDEXED_DATABASE)
31 #include "CrossThreadTask.h"
32 #include "DOMStringList.h"
33 #include "IDBBackingStore.h"
34 #include "IDBBindingUtilities.h"
35 #include "IDBCallbacks.h"
36 #include "IDBCursorBackendImpl.h"
37 #include "IDBDatabaseBackendImpl.h"
38 #include "IDBDatabaseException.h"
39 #include "IDBIndexBackendImpl.h"
41 #include "IDBKeyPath.h"
42 #include "IDBKeyPathBackendImpl.h"
43 #include "IDBKeyRange.h"
44 #include "IDBTransactionBackendInterface.h"
45 #include "ScriptExecutionContext.h"
49 IDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
53 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, int64_t id, const String& name, const String& keyPath, bool autoIncrement)
54 : m_backingStore(backingStore)
55 , m_databaseId(databaseId)
59 , m_autoIncrement(autoIncrement)
60 , m_autoIncrementNumber(-1)
65 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement)
66 : m_backingStore(backingStore)
67 , m_databaseId(databaseId)
71 , m_autoIncrement(autoIncrement)
72 , m_autoIncrementNumber(-1)
76 PassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
78 RefPtr<DOMStringList> indexNames = DOMStringList::create();
79 for (IndexMap::const_iterator it = m_indexes.begin(); it != m_indexes.end(); ++it)
80 indexNames->append(it->first);
81 return indexNames.release();
84 void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
86 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
87 RefPtr<IDBKey> key = prpKey;
88 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
89 if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::getInternal, objectStore, key, callbacks)))
90 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
93 void IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
95 String wireData = objectStore->m_backingStore->getObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key);
96 if (wireData.isNull()) {
97 callbacks->onSuccess(SerializedScriptValue::undefinedValue());
101 callbacks->onSuccess(SerializedScriptValue::createFromWire(wireData));
104 static PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, const String& keyPath)
106 Vector<RefPtr<SerializedScriptValue> > values;
107 values.append(value);
108 Vector<RefPtr<IDBKey> > keys;
109 IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, keyPath, keys);
112 ASSERT(keys.size() == 1);
113 return keys[0].release();
116 static PassRefPtr<SerializedScriptValue> injectKeyIntoKeyPath(PassRefPtr<IDBKey> key, PassRefPtr<SerializedScriptValue> value, const String& keyPath)
118 return IDBKeyPathBackendImpl::injectIDBKeyIntoSerializedValue(key, value, keyPath);
121 void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
123 if (transactionPtr->mode() == IDBTransaction::READ_ONLY) {
124 ec = IDBDatabaseException::READ_ONLY_ERR;
128 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
129 RefPtr<SerializedScriptValue> value = prpValue;
130 RefPtr<IDBKey> key = prpKey;
131 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
132 RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
134 if (key && (key->type() == IDBKey::NullType)) {
135 ec = IDBDatabaseException::DATA_ERR;
139 const bool autoIncrement = objectStore->autoIncrement();
140 const bool hasKeyPath = !objectStore->m_keyPath.isNull();
141 if (!key && !autoIncrement && !hasKeyPath) {
142 ec = IDBDatabaseException::DATA_ERR;
146 // FIXME: This should throw a SERIAL_ERR on structured clone problems.
147 // FIXME: This should throw a DATA_ERR when the wrong key/keyPath data is supplied.
148 if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction)))
149 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
152 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::selectKeyForPut(IDBObjectStoreBackendImpl* objectStore, IDBKey* key, PutMode putMode, IDBCallbacks* callbacks, RefPtr<SerializedScriptValue>& value)
154 if (putMode == CursorUpdate)
157 const bool autoIncrement = objectStore->autoIncrement();
158 const bool hasKeyPath = !objectStore->m_keyPath.isNull();
160 if (hasKeyPath && key && putMode != CursorUpdate) {
161 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that has a keyPath."));
165 if (autoIncrement && key) {
166 objectStore->resetAutoIncrementKeyCache();
173 return objectStore->genAutoIncrementKey();
175 RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
177 objectStore->resetAutoIncrementKeyCache();
181 RefPtr<IDBKey> autoIncKey = objectStore->genAutoIncrementKey();
182 RefPtr<SerializedScriptValue> valueAfterInjection = injectKeyIntoKeyPath(autoIncKey, value, objectStore->m_keyPath);
183 if (!valueAfterInjection) {
184 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The generated key could not be inserted into the object using the keyPath."));
187 value = valueAfterInjection;
188 return autoIncKey.release();
192 RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
195 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key could not be fetched from the keyPath."));
199 if (putMode == CursorUpdate && !keyPathKey->isEqual(key)) {
200 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key fetched from the keyPath does not match the key of the cursor."));
204 return keyPathKey.release();
208 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied"));
215 void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
217 RefPtr<SerializedScriptValue> value = prpValue;
218 RefPtr<IDBKey> key = selectKeyForPut(objectStore.get(), prpKey.get(), putMode, callbacks.get(), value);
222 if (key->type() == IDBKey::NullType) {
223 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed."));
227 Vector<RefPtr<IDBKey> > indexKeys;
228 for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
229 const RefPtr<IDBIndexBackendImpl>& index = it->second;
231 RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(value.get(), index->keyPath());
233 indexKeys.append(indexKey.release());
236 if (indexKey->type() == IDBKey::NullType) {
237 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL."));
240 if (!index->addingKeyAllowed(indexKey.get(), key.get())) { // So problem is that if key() is the same as the old key for this record in this index, then we're not really *adding it*, just updating it...
241 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
244 indexKeys.append(indexKey.release());
247 RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
248 bool isExistingValue = objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get());
250 if (putMode == AddOnly && isExistingValue) {
251 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
255 // Before this point, don't do any mutation. After this point, rollback the transaction in case of error.
257 if (!objectStore->m_backingStore->putObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key, value->toWireString(), recordIdentifier.get())) {
258 // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
259 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
260 transaction->abort();
265 for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) {
266 if (!it->second->hasValidId())
267 continue; // The index object has been created, but does not exist in the database yet.
269 if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get())) {
270 // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
271 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
272 transaction->abort();
278 if (!objectStore->m_backingStore->putIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), *indexKeys[i], recordIdentifier.get())) {
279 // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
280 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
281 transaction->abort();
286 callbacks->onSuccess(key.get());
289 void IDBObjectStoreBackendImpl::deleteFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
291 if (transaction->mode() == IDBTransaction::READ_ONLY) {
292 ec = IDBDatabaseException::READ_ONLY_ERR;
296 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
297 RefPtr<IDBKey> key = prpKey;
298 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
299 if (key->type() == IDBKey::NullType) {
300 ec = IDBDatabaseException::DATA_ERR;
304 if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteInternal, objectStore, key, callbacks)))
305 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
308 void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
310 RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
311 if (!objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get())) {
312 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
316 for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
317 if (!it->second->hasValidId())
318 continue; // The index object has been created, but does not exist in the database yet.
320 if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get()))
321 ASSERT_NOT_REACHED();
324 objectStore->m_backingStore->deleteObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), recordIdentifier.get());
325 callbacks->onSuccess(SerializedScriptValue::nullValue());
328 void IDBObjectStoreBackendImpl::clear(PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
330 if (transaction->mode() == IDBTransaction::READ_ONLY) {
331 ec = IDBDatabaseException::READ_ONLY_ERR;
335 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
336 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
338 if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::clearInternal, objectStore, callbacks)))
339 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
342 void IDBObjectStoreBackendImpl::clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBCallbacks> callbacks)
344 objectStore->m_backingStore->clearObjectStore(objectStore->m_databaseId, objectStore->id());
345 callbacks->onSuccess(SerializedScriptValue::undefinedValue());
349 class PopulateIndexCallback : public IDBBackingStore::ObjectStoreRecordCallback {
351 PopulateIndexCallback(IDBBackingStore& backingStore, const String& indexKeyPath, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
352 : m_backingStore(backingStore)
353 , m_indexKeyPath(indexKeyPath)
354 , m_databaseId(databaseId)
355 , m_objectStoreId(objectStoreId)
360 virtual bool callback(const IDBBackingStore::ObjectStoreRecordIdentifier* recordIdentifier, const String& value)
362 RefPtr<SerializedScriptValue> objectValue = SerializedScriptValue::createFromWire(value);
363 RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(objectValue.get(), m_indexKeyPath);
367 if (!m_backingStore.putIndexDataForRecord(m_databaseId, m_objectStoreId, m_indexId, *indexKey, recordIdentifier))
374 IDBBackingStore& m_backingStore;
375 const String& m_indexKeyPath;
376 int64_t m_databaseId;
377 int64_t m_objectStoreId;
382 bool IDBObjectStoreBackendImpl::populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
384 PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
385 if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))
390 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
393 ec = IDBDatabaseException::NON_TRANSIENT_ERR;
396 if (m_indexes.contains(name)) {
397 ec = IDBDatabaseException::CONSTRAINT_ERR;
400 if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
401 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
405 RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, name, m_name, keyPath, unique);
406 ASSERT(index->name() == name);
408 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
409 RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
410 if (!transaction->scheduleTask(
411 createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal,
412 objectStore, index, transactionPtr),
413 createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexFromMap,
414 objectStore, index))) {
415 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
419 m_indexes.set(name, index);
420 return index.release();
423 void IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
426 if (!objectStore->m_backingStore->createIndex(objectStore->m_databaseId, objectStore->id(), index->name(), index->keyPath(), index->unique(), id)) {
427 transaction->abort();
433 if (!populateIndex(*objectStore->m_backingStore, objectStore->m_databaseId, objectStore->m_id, id, index->keyPath())) {
434 transaction->abort();
438 transaction->didCompleteTaskEvents();
441 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name, ExceptionCode& ec)
443 RefPtr<IDBIndexBackendInterface> index = m_indexes.get(name);
445 ec = IDBDatabaseException::NOT_FOUND_ERR;
448 return index.release();
451 void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
453 if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
454 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
458 RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
460 ec = IDBDatabaseException::NOT_FOUND_ERR;
464 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
465 RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
466 if (!transaction->scheduleTask(
467 createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal,
468 objectStore, index, transactionPtr),
469 createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap,
470 objectStore, index))) {
471 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
474 m_indexes.remove(name);
477 void IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
479 objectStore->m_backingStore->deleteIndex(objectStore->m_databaseId, objectStore->id(), index->id());
480 transaction->didCompleteTaskEvents();
483 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
485 RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
486 RefPtr<IDBKeyRange> range = prpRange;
487 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
488 RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
489 if (!transaction->scheduleTask(
490 createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal,
491 objectStore, range, direction, callbacks, transactionPtr))) {
492 ec = IDBDatabaseException::NOT_ALLOWED_ERR;
496 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
498 IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);
500 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->m_backingStore->openObjectStoreCursor(objectStore->m_databaseId, objectStore->id(), range.get(), direction);
501 if (!backingStoreCursor) {
502 callbacks->onSuccess(SerializedScriptValue::nullValue());
506 RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
507 callbacks->onSuccess(cursor.release());
510 void IDBObjectStoreBackendImpl::loadIndexes()
513 Vector<String> names;
514 Vector<String> keyPaths;
515 Vector<bool> uniqueFlags;
516 m_backingStore->getIndexes(m_databaseId, m_id, ids, names, keyPaths, uniqueFlags);
518 ASSERT(names.size() == ids.size());
519 ASSERT(keyPaths.size() == ids.size());
520 ASSERT(uniqueFlags.size() == ids.size());
522 for (size_t i = 0; i < ids.size(); i++)
523 m_indexes.set(names[i], IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, ids[i], names[i], m_name, keyPaths[i], uniqueFlags[i]));
526 void IDBObjectStoreBackendImpl::removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
528 ASSERT(objectStore->m_indexes.contains(index->name()));
529 objectStore->m_indexes.remove(index->name());
532 void IDBObjectStoreBackendImpl::addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
534 RefPtr<IDBIndexBackendImpl> indexPtr = index;
535 ASSERT(!objectStore->m_indexes.contains(indexPtr->name()));
536 objectStore->m_indexes.set(indexPtr->name(), indexPtr);
539 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::genAutoIncrementKey()
541 if (m_autoIncrementNumber > 0)
542 return IDBKey::createNumber(m_autoIncrementNumber++);
544 m_autoIncrementNumber = static_cast<int>(m_backingStore->nextAutoIncrementNumber(m_databaseId, id()));
545 return IDBKey::createNumber(m_autoIncrementNumber++);
549 } // namespace WebCore