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 "IDBIndexBackendImpl.h"
29 #if ENABLE(INDEXED_DATABASE)
31 #include "CrossThreadTask.h"
32 #include "IDBBackingStore.h"
33 #include "IDBCallbacks.h"
34 #include "IDBCursorBackendImpl.h"
35 #include "IDBDatabaseBackendImpl.h"
36 #include "IDBDatabaseException.h"
38 #include "IDBKeyRange.h"
39 #include "IDBMetadata.h"
40 #include "IDBObjectStoreBackendImpl.h"
41 #include "IDBTracing.h"
42 #include "IDBTransactionBackendImpl.h"
46 IDBIndexBackendImpl::IDBIndexBackendImpl(const IDBDatabaseBackendImpl* database, IDBObjectStoreBackendImpl* objectStoreBackend, int64_t id, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
47 : m_database(database)
48 , m_objectStoreBackend(objectStoreBackend)
53 , m_multiEntry(multiEntry)
57 IDBIndexBackendImpl::~IDBIndexBackendImpl()
61 IDBIndexMetadata IDBIndexBackendImpl::metadata() const
63 return IDBIndexMetadata(m_name, m_id, m_keyPath, m_unique, m_multiEntry);
66 void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> range, unsigned short untypedDirection, IDBCursorBackendInterface::CursorType cursorType, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
68 IDB_TRACE("IDBIndexBackendImpl::openCursorInternal");
69 IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(untypedDirection);
71 RefPtr<IDBBackingStore::Cursor> backingStoreCursor;
74 case IDBCursorBackendInterface::IndexKeyCursor:
75 backingStoreCursor = index->backingStore()->openIndexKeyCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), range.get(), direction);
77 case IDBCursorBackendInterface::IndexCursor:
78 backingStoreCursor = index->backingStore()->openIndexCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), range.get(), direction);
80 case IDBCursorBackendInterface::ObjectStoreCursor:
81 case IDBCursorBackendInterface::InvalidCursorType:
86 if (!backingStoreCursor) {
87 callbacks->onSuccess(static_cast<SerializedScriptValue*>(0));
91 RefPtr<IDBCursorBackendImpl> cursor = IDBCursorBackendImpl::create(backingStoreCursor.get(), cursorType, transaction.get(), index->m_objectStoreBackend);
92 callbacks->onSuccess(cursor, cursor->key(), cursor->primaryKey(), cursor->value());
95 void IDBIndexBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpKeyRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode&)
97 IDB_TRACE("IDBIndexBackendImpl::openCursor");
98 RefPtr<IDBIndexBackendImpl> index = this;
99 RefPtr<IDBKeyRange> keyRange = prpKeyRange;
100 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
101 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
102 if (!transaction->scheduleTask(
103 createCallbackTask(&openCursorInternal, index, keyRange, direction, IDBCursorBackendInterface::IndexCursor, callbacks, transaction)))
104 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR));
107 void IDBIndexBackendImpl::openKeyCursor(PassRefPtr<IDBKeyRange> prpKeyRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode&)
109 IDB_TRACE("IDBIndexBackendImpl::openKeyCursor");
110 RefPtr<IDBIndexBackendImpl> index = this;
111 RefPtr<IDBKeyRange> keyRange = prpKeyRange;
112 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
113 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
114 if (!transaction->scheduleTask(
115 createCallbackTask(&openCursorInternal, index, keyRange, direction, IDBCursorBackendInterface::IndexKeyCursor, callbacks, transaction)))
116 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR));
119 void IDBIndexBackendImpl::countInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> range, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
121 IDB_TRACE("IDBIndexBackendImpl::countInternal");
124 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = index->backingStore()->openIndexKeyCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), range.get(), IDBCursor::NEXT);
125 if (!backingStoreCursor) {
126 callbacks->onSuccess(count);
132 } while (backingStoreCursor->continueFunction(0));
133 backingStoreCursor->close();
134 callbacks->onSuccess(count);
137 void IDBIndexBackendImpl::count(PassRefPtr<IDBKeyRange> range, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode&)
139 IDB_TRACE("IDBIndexBackendImpl::count");
140 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
141 if (!transaction->scheduleTask(
142 createCallbackTask(&countInternal, this, range, callbacks, transaction)))
143 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR));
146 void IDBIndexBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
148 IDB_TRACE("IDBIndexBackendImpl::getInternal");
152 if (keyRange->isOnlyKey())
153 key = keyRange->lower();
155 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = index->backingStore()->openIndexCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), keyRange.get(), IDBCursor::NEXT);
157 if (!backingStoreCursor) {
158 callbacks->onSuccess();
161 key = backingStoreCursor->key();
162 backingStoreCursor->close();
165 RefPtr<IDBKey> primaryKey = index->backingStore()->getPrimaryKeyViaIndex(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), *key);
167 String value = index->backingStore()->getObjectStoreRecord(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), *primaryKey);
169 if (value.isNull()) {
170 callbacks->onSuccess();
173 if (index->m_objectStoreBackend->autoIncrement() && !index->m_objectStoreBackend->keyPath().isNull()) {
174 callbacks->onSuccess(SerializedScriptValue::createFromWire(value),
175 primaryKey, index->m_objectStoreBackend->keyPath());
178 callbacks->onSuccess(SerializedScriptValue::createFromWire(value));
181 void IDBIndexBackendImpl::getKeyInternal(ScriptExecutionContext* context, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
183 IDB_TRACE("IDBIndexBackendImpl::getInternal");
185 RefPtr<IDBBackingStore::Cursor> backingStoreCursor =
186 index->backingStore()->openIndexKeyCursor(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), keyRange.get(), IDBCursor::NEXT);
188 if (!backingStoreCursor) {
189 callbacks->onSuccess(static_cast<IDBKey*>(0));
193 RefPtr<IDBKey> keyResult = index->backingStore()->getPrimaryKeyViaIndex(transaction->backingStoreTransaction(), index->databaseId(), index->m_objectStoreBackend->id(), index->id(), *backingStoreCursor->key());
195 callbacks->onSuccess(static_cast<IDBKey*>(0));
196 backingStoreCursor->close();
199 callbacks->onSuccess(keyResult.get());
200 backingStoreCursor->close();
204 void IDBIndexBackendImpl::get(PassRefPtr<IDBKeyRange> prpKeyRange, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode&)
206 IDB_TRACE("IDBIndexBackendImpl::get");
207 RefPtr<IDBIndexBackendImpl> index = this;
208 RefPtr<IDBKeyRange> keyRange = prpKeyRange;
209 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
210 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
211 if (!transaction->scheduleTask(createCallbackTask(&getInternal, index, keyRange, callbacks, transaction)))
212 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR));
215 void IDBIndexBackendImpl::getKey(PassRefPtr<IDBKeyRange> prpKeyRange, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode&)
217 IDB_TRACE("IDBIndexBackendImpl::getKey");
218 RefPtr<IDBIndexBackendImpl> index = this;
219 RefPtr<IDBKeyRange> keyRange = prpKeyRange;
220 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
221 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
222 if (!transaction->scheduleTask(
223 createCallbackTask(&getKeyInternal, index, keyRange, callbacks, transaction)))
224 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR));
227 } // namespace WebCore
229 #endif // ENABLE(INDEXED_DATABASE)