Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement...
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryIndex.cpp
1 /*
2  * Copyright (C) 2015 Apple 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MemoryIndex.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBError.h"
32 #include "IDBGetAllResult.h"
33 #include "IDBGetResult.h"
34 #include "IDBKeyRangeData.h"
35 #include "IndexKey.h"
36 #include "Logging.h"
37 #include "MemoryBackingStoreTransaction.h"
38 #include "MemoryIndexCursor.h"
39 #include "MemoryObjectStore.h"
40 #include "ThreadSafeDataBuffer.h"
41
42 namespace WebCore {
43 namespace IDBServer {
44
45 Ref<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
46 {
47     return adoptRef(*new MemoryIndex(info, objectStore));
48 }
49
50 MemoryIndex::MemoryIndex(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
51     : m_info(info)
52     , m_objectStore(objectStore)
53 {
54 }
55
56 MemoryIndex::~MemoryIndex() = default;
57
58 void MemoryIndex::cursorDidBecomeClean(MemoryIndexCursor& cursor)
59 {
60     m_cleanCursors.add(&cursor);
61 }
62
63 void MemoryIndex::cursorDidBecomeDirty(MemoryIndexCursor& cursor)
64 {
65     m_cleanCursors.remove(&cursor);
66 }
67
68 void MemoryIndex::objectStoreCleared()
69 {
70     auto transaction = m_objectStore.writeTransaction();
71     ASSERT(transaction);
72
73     transaction->indexCleared(*this, WTFMove(m_records));
74
75     notifyCursorsOfAllRecordsChanged();
76 }
77
78 void MemoryIndex::notifyCursorsOfValueChange(const IDBKeyData& indexKey, const IDBKeyData& primaryKey)
79 {
80     for (auto* cursor : copyToVector(m_cleanCursors))
81         cursor->indexValueChanged(indexKey, primaryKey);
82 }
83
84 void MemoryIndex::notifyCursorsOfAllRecordsChanged()
85 {
86     for (auto* cursor : copyToVector(m_cleanCursors))
87         cursor->indexRecordsAllChanged();
88
89     ASSERT(m_cleanCursors.isEmpty());
90 }
91
92 void MemoryIndex::clearIndexValueStore()
93 {
94     ASSERT(m_objectStore.writeTransaction());
95     ASSERT(m_objectStore.writeTransaction()->isAborting());
96
97     m_records = nullptr;
98 }
99
100 void MemoryIndex::replaceIndexValueStore(std::unique_ptr<IndexValueStore>&& valueStore)
101 {
102     ASSERT(m_objectStore.writeTransaction());
103     ASSERT(m_objectStore.writeTransaction()->isAborting());
104
105     m_records = WTFMove(valueStore);
106 }
107
108 IDBGetResult MemoryIndex::getResultForKeyRange(IndexedDB::IndexRecordType type, const IDBKeyRangeData& range) const
109 {
110     LOG(IndexedDB, "MemoryIndex::getResultForKeyRange - %s", range.loggingString().utf8().data());
111
112     if (!m_records)
113         return { };
114
115     IDBKeyData keyToLookFor;
116     if (range.isExactlyOneKey())
117         keyToLookFor = range.lowerKey;
118     else
119         keyToLookFor = m_records->lowestKeyWithRecordInRange(range);
120
121     if (keyToLookFor.isNull())
122         return { };
123
124     const IDBKeyData* keyValue = m_records->lowestValueForKey(keyToLookFor);
125
126     if (!keyValue)
127         return { };
128
129     return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(*keyValue, m_objectStore.valueForKeyRange(*keyValue), m_objectStore.info().keyPath());
130 }
131
132 uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData& inRange)
133 {
134     LOG(IndexedDB, "MemoryIndex::countForKeyRange");
135
136     if (!m_records)
137         return 0;
138
139     uint64_t count = 0;
140     IDBKeyRangeData range = inRange;
141     while (true) {
142         auto key = m_records->lowestKeyWithRecordInRange(range);
143         if (key.isNull())
144             break;
145
146         count += m_records->countForKey(key);
147
148         range.lowerKey = key;
149         range.lowerOpen = true;
150     }
151
152     return count;
153 }
154
155 void MemoryIndex::getAllRecords(const IDBKeyRangeData& keyRangeData, Optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
156 {
157     LOG(IndexedDB, "MemoryIndex::getAllRecords");
158
159     result = { type, m_objectStore.info().keyPath() };
160
161     if (!m_records)
162         return;
163
164     uint32_t targetCount;
165     if (count && count.value())
166         targetCount = count.value();
167     else
168         targetCount = std::numeric_limits<uint32_t>::max();
169
170     IDBKeyRangeData range = keyRangeData;
171     uint32_t currentCount = 0;
172     while (currentCount < targetCount) {
173         auto key = m_records->lowestKeyWithRecordInRange(range);
174         if (key.isNull())
175             return;
176
177         range.lowerKey = key;
178         range.lowerOpen = true;
179
180         auto allValues = m_records->allValuesForKey(key, targetCount - currentCount);
181         for (auto& keyValue : allValues) {
182             result.addKey(IDBKeyData(keyValue));
183             if (type == IndexedDB::GetAllType::Values)
184                 result.addValue(m_objectStore.valueForKeyRange(keyValue));
185         }
186
187         currentCount += allValues.size();
188     }
189 }
190
191
192 IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey)
193 {
194     LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey");
195
196     if (!m_records) {
197         m_records = std::make_unique<IndexValueStore>(m_info.unique());
198         notifyCursorsOfAllRecordsChanged();
199     }
200
201     if (!m_info.multiEntry()) {
202         IDBKeyData key = indexKey.asOneKey();
203         IDBError result = m_records->addRecord(key, valueKey);
204         notifyCursorsOfValueChange(key, valueKey);
205         return result;
206     }
207
208     Vector<IDBKeyData> keys = indexKey.multiEntry();
209
210     if (m_info.unique()) {
211         for (auto& key : keys) {
212             if (m_records->contains(key))
213                 return IDBError(ConstraintError);
214         }
215     }
216
217     for (auto& key : keys) {
218         auto error = m_records->addRecord(key, valueKey);
219         ASSERT_UNUSED(error, error.isNull());
220         notifyCursorsOfValueChange(key, valueKey);
221     }
222
223     return IDBError { };
224 }
225
226 void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey)
227 {
228     LOG(IndexedDB, "MemoryIndex::removeRecord");
229
230     ASSERT(m_records);
231
232     if (!m_info.multiEntry()) {
233         IDBKeyData key = indexKey.asOneKey();
234         m_records->removeRecord(key, valueKey);
235         notifyCursorsOfValueChange(key, valueKey);
236         return;
237     }
238
239     Vector<IDBKeyData> keys = indexKey.multiEntry();
240     for (auto& key : keys) {
241         m_records->removeRecord(key, valueKey);
242         notifyCursorsOfValueChange(key, valueKey);
243     }
244 }
245
246 void MemoryIndex::removeEntriesWithValueKey(const IDBKeyData& valueKey)
247 {
248     LOG(IndexedDB, "MemoryIndex::removeEntriesWithValueKey");
249
250     if (!m_records)
251         return;
252
253     m_records->removeEntriesWithValueKey(*this, valueKey);
254 }
255
256 MemoryIndexCursor* MemoryIndex::maybeOpenCursor(const IDBCursorInfo& info)
257 {
258     auto result = m_cursors.add(info.identifier(), nullptr);
259     if (!result.isNewEntry)
260         return nullptr;
261
262     result.iterator->value = std::make_unique<MemoryIndexCursor>(*this, info);
263     return result.iterator->value.get();
264 }
265
266 } // namespace IDBServer
267 } // namespace WebCore
268
269 #endif // ENABLE(INDEXED_DATABASE)