jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 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 | */ |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 25 | |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 26 | #include "config.h" |
andreip@google.com | 63e3331 | 2010-08-03 19:20:09 +0000 | [diff] [blame] | 27 | #include "IDBObjectStore.h" |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 28 | |
jorlow@chromium.org | 9c02b65 | 2010-11-26 16:33:28 +0000 | [diff] [blame] | 29 | #if ENABLE(INDEXED_DATABASE) |
| 30 | |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 31 | #include "DOMStringList.h" |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 32 | #include "IDBAny.h" |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 33 | #include "IDBBindingUtilities.h" |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 34 | #include "IDBCursorWithValue.h" |
jsbell@chromium.org | ddfcb6f | 2012-06-22 22:09:22 +0000 | [diff] [blame] | 35 | #include "IDBDatabase.h" |
jorlow@chromium.org | 9c02b65 | 2010-11-26 16:33:28 +0000 | [diff] [blame] | 36 | #include "IDBDatabaseException.h" |
jorlow@chromium.org | eb5eb5b | 2010-07-30 15:29:58 +0000 | [diff] [blame] | 37 | #include "IDBIndex.h" |
jorlow@chromium.org | a815bc8 | 2010-07-12 10:00:45 +0000 | [diff] [blame] | 38 | #include "IDBKey.h" |
commit-queue@webkit.org | 6781638 | 2011-08-25 05:31:51 +0000 | [diff] [blame] | 39 | #include "IDBKeyPath.h" |
bulach@chromium.org | 51cb8ff | 2010-08-06 10:37:41 +0000 | [diff] [blame] | 40 | #include "IDBKeyRange.h" |
jorlow@chromium.org | 383e154 | 2011-02-04 23:45:27 +0000 | [diff] [blame] | 41 | #include "IDBTransaction.h" |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 42 | #include "Logging.h" |
alecflett@chromium.org | 4759eef | 2012-10-17 22:57:30 +0000 | [diff] [blame] | 43 | #include "ScriptExecutionContext.h" |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 44 | #include "SerializedScriptValue.h" |
alecflett@chromium.org | 9d1da95 | 2013-02-15 21:01:49 +0000 | [diff] [blame] | 45 | #include "SharedBuffer.h" |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 46 | |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 47 | namespace WebCore { |
| 48 | |
alecflett@chromium.org | 6d7e148 | 2013-01-10 07:33:14 +0000 | [diff] [blame] | 49 | IDBObjectStore::IDBObjectStore(const IDBObjectStoreMetadata& metadata, IDBTransaction* transaction) |
jsbell@chromium.org | ddfcb6f | 2012-06-22 22:09:22 +0000 | [diff] [blame] | 50 | : m_metadata(metadata) |
andreip@google.com | bccb32d | 2010-09-23 14:34:22 +0000 | [diff] [blame] | 51 | , m_transaction(transaction) |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 52 | , m_deleted(false) |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 53 | { |
jorlow@chromium.org | 4e087e0 | 2010-09-30 16:55:46 +0000 | [diff] [blame] | 54 | ASSERT(m_transaction); |
vitalyr@chromium.org | b613303 | 2010-07-08 17:01:51 +0000 | [diff] [blame] | 55 | // We pass a reference to this object before it can be adopted. |
| 56 | relaxAdoptionRequirement(); |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 57 | } |
| 58 | |
andreip@google.com | 63e3331 | 2010-08-03 19:20:09 +0000 | [diff] [blame] | 59 | PassRefPtr<DOMStringList> IDBObjectStore::indexNames() const |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 60 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 61 | LOG(StorageAPI, "IDBObjectStore::indexNames"); |
jsbell@chromium.org | ddfcb6f | 2012-06-22 22:09:22 +0000 | [diff] [blame] | 62 | RefPtr<DOMStringList> indexNames = DOMStringList::create(); |
| 63 | for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) |
alecflett@chromium.org | e33cc6b | 2012-11-01 18:07:22 +0000 | [diff] [blame] | 64 | indexNames->append(it->value.name); |
jsbell@chromium.org | ddfcb6f | 2012-06-22 22:09:22 +0000 | [diff] [blame] | 65 | indexNames->sort(); |
| 66 | return indexNames.release(); |
jsbell@chromium.org | b6581b6 | 2012-05-17 23:03:05 +0000 | [diff] [blame] | 67 | } |
| 68 | |
commit-queue@webkit.org | 205a632 | 2012-04-21 00:16:48 +0000 | [diff] [blame] | 69 | PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 70 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 71 | LOG(StorageAPI, "IDBObjectStore::get"); |
jsbell@chromium.org | 99332ea | 2012-06-21 00:31:41 +0000 | [diff] [blame] | 72 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 73 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 99332ea | 2012-06-21 00:31:41 +0000 | [diff] [blame] | 74 | return 0; |
| 75 | } |
commit-queue@webkit.org | 205a632 | 2012-04-21 00:16:48 +0000 | [diff] [blame] | 76 | if (!keyRange) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 77 | ec = IDBDatabaseException::DataError; |
commit-queue@webkit.org | a7e8f75 | 2011-10-24 20:51:02 +0000 | [diff] [blame] | 78 | return 0; |
| 79 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 80 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 81 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 82 | return 0; |
| 83 | } |
andreip@google.com | bccb32d | 2010-09-23 14:34:22 +0000 | [diff] [blame] | 84 | RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 85 | backendDB()->get(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange, false, request); |
andreip@google.com | bccb32d | 2010-09-23 14:34:22 +0000 | [diff] [blame] | 86 | return request.release(); |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 87 | } |
| 88 | |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 89 | PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, const ScriptValue& key, ExceptionCode& ec) |
commit-queue@webkit.org | 205a632 | 2012-04-21 00:16:48 +0000 | [diff] [blame] | 90 | { |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 91 | RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec); |
commit-queue@webkit.org | 205a632 | 2012-04-21 00:16:48 +0000 | [diff] [blame] | 92 | if (ec) |
| 93 | return 0; |
| 94 | return get(context, keyRange.release(), ec); |
| 95 | } |
| 96 | |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 97 | static void generateIndexKeysForValue(DOMRequestState* requestState, const IDBIndexMetadata& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* indexKeys) |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 98 | { |
| 99 | ASSERT(indexKeys); |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 100 | RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(requestState, objectValue, indexMetadata.keyPath); |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 101 | |
| 102 | if (!indexKey) |
| 103 | return; |
| 104 | |
| 105 | if (!indexMetadata.multiEntry || indexKey->type() != IDBKey::ArrayType) { |
| 106 | if (!indexKey->isValid()) |
| 107 | return; |
| 108 | |
| 109 | indexKeys->append(indexKey); |
| 110 | } else { |
| 111 | ASSERT(indexMetadata.multiEntry); |
| 112 | ASSERT(indexKey->type() == IDBKey::ArrayType); |
| 113 | indexKey = IDBKey::createMultiEntryArray(indexKey->array()); |
| 114 | |
| 115 | for (size_t i = 0; i < indexKey->array().size(); ++i) |
| 116 | indexKeys->append(indexKey->array()[i]); |
| 117 | } |
| 118 | } |
| 119 | |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 120 | PassRefPtr<IDBRequest> IDBObjectStore::add(JSC::ExecState* state, ScriptValue& value, const ScriptValue& key, ExceptionCode& ec) |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 121 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 122 | LOG(StorageAPI, "IDBObjectStore::add"); |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 123 | return put(IDBDatabaseBackend::AddOnly, IDBAny::create(this), state, value, key, ec); |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 124 | } |
| 125 | |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 126 | PassRefPtr<IDBRequest> IDBObjectStore::add(JSC::ExecState* state, ScriptValue& value, ExceptionCode& ec) |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 127 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 128 | LOG(StorageAPI, "IDBObjectStore::add"); |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 129 | return put(IDBDatabaseBackend::AddOnly, IDBAny::create(this), state, value, static_cast<IDBKey*>(0), ec); |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 130 | } |
| 131 | |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 132 | PassRefPtr<IDBRequest> IDBObjectStore::put(JSC::ExecState* state, ScriptValue& value, const ScriptValue& key, ExceptionCode& ec) |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 133 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 134 | LOG(StorageAPI, "IDBObjectStore::put"); |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 135 | return put(IDBDatabaseBackend::AddOrUpdate, IDBAny::create(this), state, value, key, ec); |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 136 | } |
| 137 | |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 138 | PassRefPtr<IDBRequest> IDBObjectStore::put(JSC::ExecState* state, ScriptValue& value, ExceptionCode& ec) |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 139 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 140 | LOG(StorageAPI, "IDBObjectStore::put"); |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 141 | return put(IDBDatabaseBackend::AddOrUpdate, IDBAny::create(this), state, value, static_cast<IDBKey*>(0), ec); |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 142 | } |
| 143 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 144 | PassRefPtr<IDBRequest> IDBObjectStore::put(IDBDatabaseBackend::PutMode putMode, PassRefPtr<IDBAny> source, JSC::ExecState* state, ScriptValue& value, const ScriptValue& keyValue, ExceptionCode& ec) |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 145 | { |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 146 | ScriptExecutionContext* context = scriptExecutionContextFromExecState(state); |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 147 | DOMRequestState requestState(context); |
| 148 | RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, keyValue); |
| 149 | return put(putMode, source, state, value, key.release(), ec); |
| 150 | } |
| 151 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 152 | PassRefPtr<IDBRequest> IDBObjectStore::put(IDBDatabaseBackend::PutMode putMode, PassRefPtr<IDBAny> source, JSC::ExecState* state, ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec) |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 153 | { |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 154 | RefPtr<IDBKey> key = prpKey; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 155 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 156 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 157 | return 0; |
| 158 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 159 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 160 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 161 | return 0; |
| 162 | } |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 163 | if (m_transaction->isReadOnly()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 164 | ec = IDBDatabaseException::ReadOnlyError; |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 165 | return 0; |
| 166 | } |
commit-queue@webkit.org | a4062fe | 2012-09-12 23:20:22 +0000 | [diff] [blame] | 167 | |
jsbell@chromium.org | 181492f | 2013-03-29 19:36:38 +0000 | [diff] [blame] | 168 | // FIXME: Expose the JS engine exception state through ScriptState. |
| 169 | bool didThrow = false; |
| 170 | RefPtr<SerializedScriptValue> serializedValue = value.serialize(state, 0, 0, didThrow); |
| 171 | if (didThrow) { |
| 172 | // Setting an explicit ExceptionCode here would defer handling the already thrown exception. |
commit-queue@webkit.org | a4062fe | 2012-09-12 23:20:22 +0000 | [diff] [blame] | 173 | return 0; |
| 174 | } |
| 175 | |
| 176 | if (serializedValue->blobURLs().size() > 0) { |
jsbell@chromium.org | dfafc06 | 2012-03-16 19:26:00 +0000 | [diff] [blame] | 177 | // FIXME: Add Blob/File/FileList support |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 178 | ec = IDBDatabaseException::DataCloneError; |
jsbell@chromium.org | dfafc06 | 2012-03-16 19:26:00 +0000 | [diff] [blame] | 179 | return 0; |
| 180 | } |
| 181 | |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 182 | const IDBKeyPath& keyPath = m_metadata.keyPath; |
| 183 | const bool usesInLineKeys = !keyPath.isNull(); |
| 184 | const bool hasKeyGenerator = autoIncrement(); |
commit-queue@webkit.org | dfdea21 | 2012-11-22 04:34:40 +0000 | [diff] [blame] | 185 | |
weinig@apple.com | 95472c9 | 2013-09-14 02:01:26 +0000 | [diff] [blame] | 186 | ScriptExecutionContext* context = scriptExecutionContextFromExecState(state); |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 187 | DOMRequestState requestState(context); |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 188 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 189 | if (putMode != IDBDatabaseBackend::CursorUpdate && usesInLineKeys && key) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 190 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 191 | return 0; |
| 192 | } |
| 193 | if (!usesInLineKeys && !hasKeyGenerator && !key) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 194 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 195 | return 0; |
| 196 | } |
| 197 | if (usesInLineKeys) { |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 198 | RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(&requestState, value, keyPath); |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 199 | if (keyPathKey && !keyPathKey->isValid()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 200 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 201 | return 0; |
| 202 | } |
| 203 | if (!hasKeyGenerator && !keyPathKey) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 204 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 205 | return 0; |
| 206 | } |
| 207 | if (hasKeyGenerator && !keyPathKey) { |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 208 | if (!canInjectIDBKeyIntoScriptValue(&requestState, value, keyPath)) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 209 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 210 | return 0; |
| 211 | } |
| 212 | } |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 213 | if (keyPathKey) |
| 214 | key = keyPathKey; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 215 | } |
| 216 | if (key && !key->isValid()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 217 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 218 | return 0; |
| 219 | } |
| 220 | |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 221 | Vector<int64_t> indexIds; |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 222 | Vector<IndexKeys> indexKeys; |
| 223 | for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { |
| 224 | IndexKeys keys; |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 225 | generateIndexKeysForValue(&requestState, it->value, value, &keys); |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 226 | indexIds.append(it->key); |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 227 | indexKeys.append(keys); |
| 228 | } |
commit-queue@webkit.org | 4b923fc | 2012-07-27 07:30:27 +0000 | [diff] [blame] | 229 | |
| 230 | RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 231 | Vector<uint8_t> valueBytes = serializedValue->toWireBytes(); |
alecflett@chromium.org | 9d1da95 | 2013-02-15 21:01:49 +0000 | [diff] [blame] | 232 | // This is a hack to account for disagreements about whether SerializedScriptValue should deal in Vector<uint8_t> or Vector<char>. |
| 233 | // See https://lists.webkit.org/pipermail/webkit-dev/2013-February/023682.html |
| 234 | Vector<char>* valueBytesSigned = reinterpret_cast<Vector<char>*>(&valueBytes); |
| 235 | RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(*valueBytesSigned); |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 236 | backendDB()->put(m_transaction->id(), id(), valueBuffer, key.release(), static_cast<IDBDatabaseBackend::PutMode>(putMode), request, indexIds, indexKeys); |
jorlow@chromium.org | 7425244 | 2011-03-01 23:55:36 +0000 | [diff] [blame] | 237 | return request.release(); |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 238 | } |
| 239 | |
jsbell@chromium.org | a8a4340 | 2012-02-18 02:46:13 +0000 | [diff] [blame] | 240 | PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) |
| 241 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 242 | LOG(StorageAPI, "IDBObjectStore::delete"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 243 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 244 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 245 | return 0; |
| 246 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 247 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 248 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 249 | return 0; |
| 250 | } |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 251 | if (m_transaction->isReadOnly()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 252 | ec = IDBDatabaseException::ReadOnlyError; |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 253 | return 0; |
| 254 | } |
jsbell@chromium.org | a8a4340 | 2012-02-18 02:46:13 +0000 | [diff] [blame] | 255 | if (!keyRange) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 256 | ec = IDBDatabaseException::DataError; |
jsbell@chromium.org | a8a4340 | 2012-02-18 02:46:13 +0000 | [diff] [blame] | 257 | return 0; |
| 258 | } |
| 259 | |
| 260 | RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 261 | backendDB()->deleteRange(m_transaction->id(), id(), keyRange, request); |
jsbell@chromium.org | a8a4340 | 2012-02-18 02:46:13 +0000 | [diff] [blame] | 262 | return request.release(); |
| 263 | } |
| 264 | |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 265 | PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, const ScriptValue& key, ExceptionCode& ec) |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 266 | { |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 267 | RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec); |
jsbell@chromium.org | 99332ea | 2012-06-21 00:31:41 +0000 | [diff] [blame] | 268 | if (ec) |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 269 | return 0; |
jsbell@chromium.org | 99332ea | 2012-06-21 00:31:41 +0000 | [diff] [blame] | 270 | return deleteFunction(context, keyRange.release(), ec); |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 271 | } |
| 272 | |
jochen@chromium.org | b1d4562 | 2011-02-12 11:56:03 +0000 | [diff] [blame] | 273 | PassRefPtr<IDBRequest> IDBObjectStore::clear(ScriptExecutionContext* context, ExceptionCode& ec) |
| 274 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 275 | LOG(StorageAPI, "IDBObjectStore::clear"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 276 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 277 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 278 | return 0; |
| 279 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 280 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 281 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 282 | return 0; |
| 283 | } |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 284 | if (m_transaction->isReadOnly()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 285 | ec = IDBDatabaseException::ReadOnlyError; |
commit-queue@webkit.org | d6cf20d | 2012-06-12 20:45:58 +0000 | [diff] [blame] | 286 | return 0; |
| 287 | } |
| 288 | |
jochen@chromium.org | b1d4562 | 2011-02-12 11:56:03 +0000 | [diff] [blame] | 289 | RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); |
beidson@apple.com | 05a35ca | 2013-11-15 20:57:35 +0000 | [diff] [blame] | 290 | backendDB()->clearObjectStore(m_transaction->id(), id(), request); |
jorlow@chromium.org | 7425244 | 2011-03-01 23:55:36 +0000 | [diff] [blame] | 291 | return request.release(); |
jochen@chromium.org | b1d4562 | 2011-02-12 11:56:03 +0000 | [diff] [blame] | 292 | } |
| 293 | |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 294 | namespace { |
| 295 | // This class creates the index keys for a given index by extracting |
| 296 | // them from the SerializedScriptValue, for all the existing values in |
| 297 | // the objectStore. It only needs to be kept alive by virtue of being |
| 298 | // a listener on an IDBRequest object, in the same way that JavaScript |
| 299 | // cursor success handlers are kept alive. |
| 300 | class IndexPopulator : public EventListener { |
| 301 | public: |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 302 | static PassRefPtr<IndexPopulator> create(PassRefPtr<IDBDatabaseBackend> backend, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 303 | { |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 304 | return adoptRef(new IndexPopulator(backend, transactionId, objectStoreId, indexMetadata)); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 305 | } |
| 306 | |
| 307 | virtual bool operator==(const EventListener& other) |
| 308 | { |
| 309 | return this == &other; |
| 310 | } |
| 311 | |
| 312 | private: |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 313 | IndexPopulator(PassRefPtr<IDBDatabaseBackend> backend, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 314 | : EventListener(CPPEventListenerType) |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 315 | , m_databaseBackend(backend) |
| 316 | , m_transactionId(transactionId) |
| 317 | , m_objectStoreId(objectStoreId) |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 318 | , m_indexMetadata(indexMetadata) |
| 319 | { |
| 320 | } |
| 321 | |
charles.wei@torchmobile.com.cn | 7a8f312 | 2013-03-28 00:13:12 +0000 | [diff] [blame] | 322 | virtual void handleEvent(ScriptExecutionContext*, Event* event) |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 323 | { |
| 324 | ASSERT(event->type() == eventNames().successEvent); |
| 325 | EventTarget* target = event->target(); |
| 326 | IDBRequest* request = static_cast<IDBRequest*>(target); |
| 327 | |
mkwst@chromium.org | d08810f | 2013-02-08 13:04:31 +0000 | [diff] [blame] | 328 | RefPtr<IDBAny> cursorAny = request->result(ASSERT_NO_EXCEPTION); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 329 | RefPtr<IDBCursorWithValue> cursor; |
| 330 | if (cursorAny->type() == IDBAny::IDBCursorWithValueType) |
| 331 | cursor = cursorAny->idbCursorWithValue(); |
| 332 | |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 333 | Vector<int64_t, 1> indexIds; |
| 334 | indexIds.append(m_indexMetadata.id); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 335 | if (cursor) { |
mkwst@chromium.org | d08810f | 2013-02-08 13:04:31 +0000 | [diff] [blame] | 336 | cursor->continueFunction(static_cast<IDBKey*>(0), ASSERT_NO_EXCEPTION); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 337 | |
jsbell@chromium.org | 17d698c | 2012-10-24 21:36:57 +0000 | [diff] [blame] | 338 | RefPtr<IDBKey> primaryKey = cursor->idbPrimaryKey(); |
jsbell@chromium.org | 569a150 | 2012-10-23 05:21:22 +0000 | [diff] [blame] | 339 | ScriptValue value = cursor->value(); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 340 | |
| 341 | IDBObjectStore::IndexKeys indexKeys; |
commit-queue@webkit.org | d159e4b | 2012-11-16 20:56:30 +0000 | [diff] [blame] | 342 | generateIndexKeysForValue(request->requestState(), m_indexMetadata, value, &indexKeys); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 343 | |
| 344 | Vector<IDBObjectStore::IndexKeys, 1> indexKeysList; |
| 345 | indexKeysList.append(indexKeys); |
| 346 | |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 347 | m_databaseBackend->setIndexKeys(m_transactionId, m_objectStoreId, primaryKey, indexIds, indexKeysList); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 348 | } else { |
| 349 | // Now that we are done indexing, tell the backend to go |
| 350 | // back to processing tasks of type NormalTask. |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 351 | m_databaseBackend->setIndexesReady(m_transactionId, m_objectStoreId, indexIds); |
| 352 | m_databaseBackend.clear(); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 353 | } |
| 354 | |
| 355 | } |
| 356 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 357 | RefPtr<IDBDatabaseBackend> m_databaseBackend; |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 358 | const int64_t m_transactionId; |
| 359 | const int64_t m_objectStoreId; |
| 360 | const IDBIndexMetadata m_indexMetadata; |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 361 | }; |
jsbell@chromium.org | af00b26 | 2012-05-21 21:34:39 +0000 | [diff] [blame] | 362 | } |
| 363 | |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 364 | PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionCode& ec) |
jsbell@chromium.org | af00b26 | 2012-05-21 21:34:39 +0000 | [diff] [blame] | 365 | { |
commit-queue@webkit.org | 41e22ba | 2012-12-19 00:10:20 +0000 | [diff] [blame] | 366 | bool unique = false; |
| 367 | options.get("unique", unique); |
| 368 | |
| 369 | bool multiEntry = false; |
| 370 | options.get("multiEntry", multiEntry); |
| 371 | |
| 372 | return createIndex(context, name, keyPath, unique, multiEntry, ec); |
| 373 | } |
| 374 | |
| 375 | PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCode& ec) |
| 376 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 377 | LOG(StorageAPI, "IDBObjectStore::createIndex"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 378 | if (!m_transaction->isVersionChange() || m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 379 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 380 | return 0; |
| 381 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 382 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 383 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 384 | return 0; |
| 385 | } |
jsbell@chromium.org | af00b26 | 2012-05-21 21:34:39 +0000 | [diff] [blame] | 386 | if (!keyPath.isValid()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 387 | ec = IDBDatabaseException::SyntaxError; |
commit-queue@webkit.org | 6781638 | 2011-08-25 05:31:51 +0000 | [diff] [blame] | 388 | return 0; |
| 389 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 390 | if (name.isNull()) { |
jsbell@chromium.org | 00c51d8 | 2012-11-14 20:22:41 +0000 | [diff] [blame] | 391 | ec = TypeError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 392 | return 0; |
| 393 | } |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 394 | if (containsIndex(name)) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 395 | ec = IDBDatabaseException::ConstraintError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 396 | return 0; |
| 397 | } |
commit-queue@webkit.org | 6781638 | 2011-08-25 05:31:51 +0000 | [diff] [blame] | 398 | |
jsbell@chromium.org | 9967a5e | 2012-05-22 18:46:07 +0000 | [diff] [blame] | 399 | if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 400 | ec = IDBDatabaseException::InvalidAccessError; |
jsbell@chromium.org | 9967a5e | 2012-05-22 18:46:07 +0000 | [diff] [blame] | 401 | return 0; |
| 402 | } |
commit-queue@webkit.org | e761715 | 2011-12-01 05:22:26 +0000 | [diff] [blame] | 403 | |
alecflett@chromium.org | cb23bff | 2012-10-09 01:17:59 +0000 | [diff] [blame] | 404 | int64_t indexId = m_metadata.maxIndexId + 1; |
alecflett@chromium.org | 6d7e148 | 2013-01-10 07:33:14 +0000 | [diff] [blame] | 405 | backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, unique, multiEntry); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 406 | |
alecflett@chromium.org | e49d929 | 2012-10-04 22:38:18 +0000 | [diff] [blame] | 407 | ++m_metadata.maxIndexId; |
| 408 | |
| 409 | IDBIndexMetadata metadata(name, indexId, keyPath, unique, multiEntry); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 410 | RefPtr<IDBIndex> index = IDBIndex::create(metadata, this, m_transaction.get()); |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 411 | m_indexMap.set(name, index); |
alecflett@chromium.org | e33cc6b | 2012-11-01 18:07:22 +0000 | [diff] [blame] | 412 | m_metadata.indexes.set(indexId, metadata); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 413 | |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 414 | ASSERT(!ec); |
| 415 | if (ec) |
| 416 | return 0; |
| 417 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 418 | RefPtr<IDBRequest> indexRequest = openCursor(context, static_cast<IDBKeyRange*>(0), IDBCursor::directionNext(), IDBDatabaseBackend::PreemptiveTask, ec); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 419 | ASSERT(!ec); |
| 420 | if (ec) |
| 421 | return 0; |
jsbell@chromium.org | dbe61e5 | 2012-10-20 00:55:33 +0000 | [diff] [blame] | 422 | indexRequest->preventPropagation(); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 423 | |
| 424 | // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction. |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 425 | RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(backendDB(), m_transaction->id(), id(), metadata); |
commit-queue@webkit.org | 6b2e796 | 2012-08-16 00:50:52 +0000 | [diff] [blame] | 426 | indexRequest->setOnsuccess(indexPopulator); |
| 427 | |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 428 | return index.release(); |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 429 | } |
| 430 | |
jorlow@chromium.org | b49ea0e | 2010-10-14 00:39:06 +0000 | [diff] [blame] | 431 | PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionCode& ec) |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 432 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 433 | LOG(StorageAPI, "IDBObjectStore::index"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 434 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 435 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 436 | return 0; |
| 437 | } |
jsbell@chromium.org | 1981096 | 2012-05-16 21:02:21 +0000 | [diff] [blame] | 438 | if (m_transaction->isFinished()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 439 | ec = IDBDatabaseException::InvalidStateError; |
jorlow@chromium.org | 0fb2ee7 | 2010-09-23 17:32:52 +0000 | [diff] [blame] | 440 | return 0; |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 441 | } |
| 442 | |
| 443 | IDBIndexMap::iterator it = m_indexMap.find(name); |
| 444 | if (it != m_indexMap.end()) |
benjamin@webkit.org | ee55405 | 2012-10-07 23:12:07 +0000 | [diff] [blame] | 445 | return it->value; |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 446 | |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 447 | int64_t indexId = findIndexId(name); |
| 448 | if (indexId == IDBIndexMetadata::InvalidId) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 449 | ec = IDBDatabaseException::NotFoundError; |
senorblanco@chromium.org | cde5849 | 2012-11-01 02:08:31 +0000 | [diff] [blame] | 450 | return 0; |
alecflett@chromium.org | e33cc6b | 2012-11-01 18:07:22 +0000 | [diff] [blame] | 451 | } |
jsbell@chromium.org | ddfcb6f | 2012-06-22 22:09:22 +0000 | [diff] [blame] | 452 | |
alecflett@chromium.org | e33cc6b | 2012-11-01 18:07:22 +0000 | [diff] [blame] | 453 | const IDBIndexMetadata* indexMetadata(0); |
| 454 | for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { |
| 455 | if (it->value.name == name) { |
| 456 | indexMetadata = &it->value; |
| 457 | break; |
| 458 | } |
| 459 | } |
| 460 | ASSERT(indexMetadata); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 461 | ASSERT(indexMetadata->id != IDBIndexMetadata::InvalidId); |
alecflett@chromium.org | e33cc6b | 2012-11-01 18:07:22 +0000 | [diff] [blame] | 462 | |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 463 | RefPtr<IDBIndex> index = IDBIndex::create(*indexMetadata, this, m_transaction.get()); |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 464 | m_indexMap.set(name, index); |
| 465 | return index.release(); |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 466 | } |
| 467 | |
andreip@google.com | 7e71883 | 2010-11-26 16:58:57 +0000 | [diff] [blame] | 468 | void IDBObjectStore::deleteIndex(const String& name, ExceptionCode& ec) |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 469 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 470 | LOG(StorageAPI, "IDBObjectStore::deleteIndex"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 471 | if (!m_transaction->isVersionChange() || m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 472 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 473 | return; |
| 474 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 475 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 476 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 477 | return; |
| 478 | } |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 479 | int64_t indexId = findIndexId(name); |
| 480 | if (indexId == IDBIndexMetadata::InvalidId) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 481 | ec = IDBDatabaseException::NotFoundError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 482 | return; |
| 483 | } |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 484 | |
alecflett@chromium.org | 6d7e148 | 2013-01-10 07:33:14 +0000 | [diff] [blame] | 485 | backendDB()->deleteIndex(m_transaction->id(), id(), indexId); |
| 486 | |
jsbell@chromium.org | 1d6014e | 2013-02-26 18:44:04 +0000 | [diff] [blame] | 487 | m_metadata.indexes.remove(indexId); |
alecflett@chromium.org | 6d7e148 | 2013-01-10 07:33:14 +0000 | [diff] [blame] | 488 | IDBIndexMap::iterator it = m_indexMap.find(name); |
| 489 | if (it != m_indexMap.end()) { |
alecflett@chromium.org | 6d7e148 | 2013-01-10 07:33:14 +0000 | [diff] [blame] | 490 | it->value->markDeleted(); |
| 491 | m_indexMap.remove(name); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 492 | } |
jorlow@chromium.org | 6d85cb8 | 2010-05-28 14:30:41 +0000 | [diff] [blame] | 493 | } |
| 494 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 495 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, ExceptionCode& ec) |
| 496 | { |
| 497 | return openCursor(context, static_cast<IDBKeyRange*>(0), ec); |
| 498 | } |
| 499 | |
| 500 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) |
| 501 | { |
| 502 | return openCursor(context, keyRange, IDBCursor::directionNext(), ec); |
| 503 | } |
| 504 | |
| 505 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, const ScriptValue& key, ExceptionCode& ec) |
| 506 | { |
| 507 | return openCursor(context, key, IDBCursor::directionNext(), ec); |
| 508 | } |
| 509 | |
| 510 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, const String& direction, ExceptionCode& ec) |
| 511 | { |
| 512 | return openCursor(context, range, direction, IDBDatabaseBackend::NormalTask, ec); |
| 513 | } |
| 514 | |
| 515 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, const String& directionString, IDBDatabaseBackend::TaskType taskType, ExceptionCode& ec) |
bulach@chromium.org | 51cb8ff | 2010-08-06 10:37:41 +0000 | [diff] [blame] | 516 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 517 | LOG(StorageAPI, "IDBObjectStore::openCursor"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 518 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 519 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 520 | return 0; |
| 521 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 522 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 523 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 524 | return 0; |
| 525 | } |
charles.wei@torchmobile.com.cn | 7a8f312 | 2013-03-28 00:13:12 +0000 | [diff] [blame] | 526 | IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec); |
commit-queue@webkit.org | 98b75ae | 2012-05-07 19:12:00 +0000 | [diff] [blame] | 527 | if (ec) |
jorlow@chromium.org | 9c02b65 | 2010-11-26 16:33:28 +0000 | [diff] [blame] | 528 | return 0; |
jorlow@chromium.org | 9c02b65 | 2010-11-26 16:33:28 +0000 | [diff] [blame] | 529 | |
jorlow@chromium.org | 4e087e0 | 2010-09-30 16:55:46 +0000 | [diff] [blame] | 530 | RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); |
alecflett@chromium.org | db5a6f7 | 2013-03-05 22:35:00 +0000 | [diff] [blame] | 531 | request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 532 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 533 | backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, direction, false, static_cast<IDBDatabaseBackend::TaskType>(taskType), request); |
bulach@chromium.org | 51cb8ff | 2010-08-06 10:37:41 +0000 | [diff] [blame] | 534 | return request.release(); |
| 535 | } |
| 536 | |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 537 | PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, const ScriptValue& key, const String& direction, ExceptionCode& ec) |
commit-queue@webkit.org | 634c672 | 2012-05-03 23:39:23 +0000 | [diff] [blame] | 538 | { |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 539 | RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec); |
commit-queue@webkit.org | 634c672 | 2012-05-03 23:39:23 +0000 | [diff] [blame] | 540 | if (ec) |
| 541 | return 0; |
jsbell@chromium.org | e85f95a | 2012-07-18 23:57:04 +0000 | [diff] [blame] | 542 | return openCursor(context, keyRange.release(), direction, ec); |
commit-queue@webkit.org | 634c672 | 2012-05-03 23:39:23 +0000 | [diff] [blame] | 543 | } |
| 544 | |
commit-queue@webkit.org | 1957618 | 2011-12-16 21:27:06 +0000 | [diff] [blame] | 545 | PassRefPtr<IDBRequest> IDBObjectStore::count(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, ExceptionCode& ec) |
| 546 | { |
beidson@apple.com | 1367e45 | 2013-09-30 20:32:21 +0000 | [diff] [blame] | 547 | LOG(StorageAPI, "IDBObjectStore::count"); |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 548 | if (m_deleted) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 549 | ec = IDBDatabaseException::InvalidStateError; |
jsbell@chromium.org | 4699008 | 2012-06-15 22:49:04 +0000 | [diff] [blame] | 550 | return 0; |
| 551 | } |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 552 | if (!m_transaction->isActive()) { |
jsbell@chromium.org | e9e6020 | 2012-12-03 18:54:02 +0000 | [diff] [blame] | 553 | ec = IDBDatabaseException::TransactionInactiveError; |
jsbell@chromium.org | 74a6fec | 2012-06-26 22:04:09 +0000 | [diff] [blame] | 554 | return 0; |
| 555 | } |
commit-queue@webkit.org | 1957618 | 2011-12-16 21:27:06 +0000 | [diff] [blame] | 556 | RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 557 | backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, request); |
commit-queue@webkit.org | 1957618 | 2011-12-16 21:27:06 +0000 | [diff] [blame] | 558 | return request.release(); |
| 559 | } |
| 560 | |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 561 | PassRefPtr<IDBRequest> IDBObjectStore::count(ScriptExecutionContext* context, const ScriptValue& key, ExceptionCode& ec) |
jsbell@chromium.org | 93ee742 | 2012-02-24 22:56:00 +0000 | [diff] [blame] | 562 | { |
jsbell@chromium.org | 174edbc | 2013-01-22 21:21:34 +0000 | [diff] [blame] | 563 | RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec); |
jsbell@chromium.org | 93ee742 | 2012-02-24 22:56:00 +0000 | [diff] [blame] | 564 | if (ec) |
| 565 | return 0; |
| 566 | return count(context, keyRange.release(), ec); |
| 567 | } |
| 568 | |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 569 | void IDBObjectStore::transactionFinished() |
| 570 | { |
jsbell@chromium.org | 1981096 | 2012-05-16 21:02:21 +0000 | [diff] [blame] | 571 | ASSERT(m_transaction->isFinished()); |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 572 | |
| 573 | // Break reference cycles. |
| 574 | m_indexMap.clear(); |
| 575 | } |
| 576 | |
alecflett@chromium.org | 0e11d58 | 2012-11-09 19:55:06 +0000 | [diff] [blame] | 577 | int64_t IDBObjectStore::findIndexId(const String& name) const |
| 578 | { |
| 579 | for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { |
| 580 | if (it->value.name == name) { |
| 581 | ASSERT(it->key != IDBIndexMetadata::InvalidId); |
| 582 | return it->key; |
| 583 | } |
| 584 | } |
| 585 | return IDBIndexMetadata::InvalidId; |
| 586 | } |
commit-queue@webkit.org | 8328724 | 2011-12-20 00:57:07 +0000 | [diff] [blame] | 587 | |
beidson@apple.com | 7b14f47 | 2013-11-09 06:27:23 +0000 | [diff] [blame] | 588 | IDBDatabaseBackend* IDBObjectStore::backendDB() const |
alecflett@chromium.org | 51757b6 | 2013-01-05 20:42:38 +0000 | [diff] [blame] | 589 | { |
| 590 | return m_transaction->backendDB(); |
| 591 | } |
| 592 | |
jorlow@chromium.org | e386591 | 2010-05-26 15:39:35 +0000 | [diff] [blame] | 593 | } // namespace WebCore |
| 594 | |
| 595 | #endif // ENABLE(INDEXED_DATABASE) |