1/*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
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.
13 *
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.
24 */
25
26#include "config.h"
27#include "IDBIndex.h"
28
29#if ENABLE(INDEXED_DATABASE)
30
31#include "IDBDatabaseException.h"
32#include "IDBKey.h"
33#include "IDBKeyRange.h"
34#include "IDBObjectStore.h"
35#include "IDBRequest.h"
36#include "IDBTransaction.h"
37#include "Logging.h"
38#include "ScriptExecutionContext.h"
39
40namespace WebCore {
41
42IDBIndex::IDBIndex(const IDBIndexMetadata& metadata, IDBObjectStore* objectStore, IDBTransaction* transaction)
43    : m_metadata(metadata)
44    , m_objectStore(objectStore)
45    , m_transaction(transaction)
46    , m_deleted(false)
47{
48    ASSERT(m_objectStore);
49    ASSERT(m_transaction);
50    ASSERT(m_metadata.id != IDBIndexMetadata::InvalidId);
51}
52
53IDBIndex::~IDBIndex()
54{
55}
56
57PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, const String& directionString, ExceptionCode& ec)
58{
59    LOG(StorageAPI, "IDBIndex::openCursor");
60    if (m_deleted) {
61        ec = IDBDatabaseException::InvalidStateError;
62        return 0;
63    }
64    if (!m_transaction->isActive()) {
65        ec = IDBDatabaseException::TransactionInactiveError;
66        return 0;
67    }
68    IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec);
69    if (ec)
70        return 0;
71
72    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
73    request->setCursorDetails(IndexedDB::CursorType::KeyAndValue, direction);
74    backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, false, IDBDatabaseBackend::NormalTask, request);
75    return request;
76}
77
78PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, const String& direction, ExceptionCode& ec)
79{
80    LOG(StorageAPI, "IDBIndex::openCursor");
81    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
82    if (ec)
83        return 0;
84    return openCursor(context, keyRange.release(), direction, ec);
85}
86
87PassRefPtr<IDBRequest> IDBIndex::count(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
88{
89    LOG(StorageAPI, "IDBIndex::count");
90    if (m_deleted) {
91        ec = IDBDatabaseException::InvalidStateError;
92        return 0;
93    }
94    if (!m_transaction->isActive()) {
95        ec = IDBDatabaseException::TransactionInactiveError;
96        return 0;
97    }
98    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
99    backendDB()->count(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, request);
100    return request;
101}
102
103PassRefPtr<IDBRequest> IDBIndex::count(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
104{
105    LOG(StorageAPI, "IDBIndex::count");
106    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
107    if (ec)
108        return 0;
109    return count(context, keyRange.release(), ec);
110}
111
112PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, const String& directionString, ExceptionCode& ec)
113{
114    LOG(StorageAPI, "IDBIndex::openKeyCursor");
115    if (m_deleted) {
116        ec = IDBDatabaseException::InvalidStateError;
117        return 0;
118    }
119    if (!m_transaction->isActive()) {
120        ec = IDBDatabaseException::TransactionInactiveError;
121        return 0;
122    }
123    IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec);
124    if (ec)
125        return 0;
126
127    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
128    request->setCursorDetails(IndexedDB::CursorType::KeyOnly, direction);
129    backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, true, IDBDatabaseBackend::NormalTask, request);
130    return request;
131}
132
133PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, const String& direction, ExceptionCode& ec)
134{
135    LOG(StorageAPI, "IDBIndex::openKeyCursor");
136    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
137    if (ec)
138        return 0;
139    return openKeyCursor(context, keyRange.release(), direction, ec);
140}
141
142PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
143{
144    LOG(StorageAPI, "IDBIndex::get");
145    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
146    if (ec)
147        return 0;
148    return get(context, keyRange.release(), ec);
149}
150
151PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
152{
153    LOG(StorageAPI, "IDBIndex::get");
154    if (m_deleted) {
155        ec = IDBDatabaseException::InvalidStateError;
156        return 0;
157    }
158    if (!m_transaction->isActive()) {
159        ec = IDBDatabaseException::TransactionInactiveError;
160        return 0;
161    }
162    if (!keyRange) {
163        ec = IDBDatabaseException::DataError;
164        return 0;
165    }
166
167    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
168    backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, false, request);
169    return request;
170}
171
172PassRefPtr<IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
173{
174    LOG(StorageAPI, "IDBIndex::getKey");
175    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
176    if (ec)
177        return 0;
178
179    return getKey(context, keyRange.release(), ec);
180}
181
182PassRefPtr<IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
183{
184    LOG(StorageAPI, "IDBIndex::getKey");
185    if (m_deleted) {
186        ec = IDBDatabaseException::InvalidStateError;
187        return 0;
188    }
189    if (!m_transaction->isActive()) {
190        ec = IDBDatabaseException::TransactionInactiveError;
191        return 0;
192    }
193    if (!keyRange) {
194        ec = IDBDatabaseException::DataError;
195        return 0;
196    }
197
198    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
199    backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, true, request);
200    return request;
201}
202
203IDBDatabaseBackend* IDBIndex::backendDB() const
204{
205    return m_transaction->backendDB();
206}
207
208} // namespace WebCore
209
210#endif // ENABLE(INDEXED_DATABASE)
211