Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement...
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryObjectStore.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 "MemoryObjectStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBBindingUtilities.h"
32 #include "IDBError.h"
33 #include "IDBGetAllResult.h"
34 #include "IDBKeyRangeData.h"
35 #include "IDBValue.h"
36 #include "IndexKey.h"
37 #include "Logging.h"
38 #include "MemoryBackingStoreTransaction.h"
39 #include "UniqueIDBDatabase.h"
40 #include <JavaScriptCore/JSCJSValue.h>
41 #include <JavaScriptCore/JSCJSValueInlines.h>
42 #include <JavaScriptCore/JSLock.h>
43
44 namespace WebCore {
45 using namespace JSC;
46 namespace IDBServer {
47
48 Ref<MemoryObjectStore> MemoryObjectStore::create(const IDBObjectStoreInfo& info)
49 {
50     return adoptRef(*new MemoryObjectStore(info));
51 }
52
53 MemoryObjectStore::MemoryObjectStore(const IDBObjectStoreInfo& info)
54     : m_info(info)
55 {
56 }
57
58 MemoryObjectStore::~MemoryObjectStore()
59 {
60     m_writeTransaction = nullptr;
61 }
62
63 MemoryIndex* MemoryObjectStore::indexForIdentifier(uint64_t identifier)
64 {
65     ASSERT(identifier);
66     return m_indexesByIdentifier.get(identifier);
67 }
68
69 void MemoryObjectStore::writeTransactionStarted(MemoryBackingStoreTransaction& transaction)
70 {
71     LOG(IndexedDB, "MemoryObjectStore::writeTransactionStarted");
72
73     ASSERT(!m_writeTransaction);
74     m_writeTransaction = &transaction;
75 }
76
77 void MemoryObjectStore::writeTransactionFinished(MemoryBackingStoreTransaction& transaction)
78 {
79     LOG(IndexedDB, "MemoryObjectStore::writeTransactionFinished");
80
81     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
82     m_writeTransaction = nullptr;
83 }
84
85 IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transaction, const IDBIndexInfo& info)
86 {
87     LOG(IndexedDB, "MemoryObjectStore::createIndex");
88
89     if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
90         return IDBError(ConstraintError);
91
92     ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
93     auto index = MemoryIndex::create(info, *this);
94
95     // If there was an error populating the new index, then the current records in the object store violate its contraints
96     auto error = populateIndexWithExistingRecords(index.get());
97     if (!error.isNull())
98         return error;
99
100     m_info.addExistingIndex(info);
101     transaction.addNewIndex(index.get());
102     registerIndex(WTFMove(index));
103
104     return IDBError { };
105 }
106
107 void MemoryObjectStore::maybeRestoreDeletedIndex(Ref<MemoryIndex>&& index)
108 {
109     LOG(IndexedDB, "MemoryObjectStore::maybeRestoreDeletedIndex");
110
111     if (m_info.hasIndex(index->info().name()))
112         return;
113
114     m_info.addExistingIndex(index->info());
115
116     ASSERT(!m_indexesByIdentifier.contains(index->info().identifier()));
117     index->clearIndexValueStore();
118     auto error = populateIndexWithExistingRecords(index.get());
119
120     // Since this index was installed in the object store before this transaction started,
121     // assuming things were in a valid state then, we should definitely be able to successfully
122     // repopulate the index with the object store's pre-transaction records.
123     ASSERT_UNUSED(error, error.isNull());
124
125     registerIndex(WTFMove(index));
126 }
127
128 RefPtr<MemoryIndex> MemoryObjectStore::takeIndexByIdentifier(uint64_t indexIdentifier)
129 {
130     auto indexByIdentifier = m_indexesByIdentifier.take(indexIdentifier);
131     if (!indexByIdentifier)
132         return nullptr;
133
134     auto index = m_indexesByName.take(indexByIdentifier->info().name());
135     ASSERT(index);
136
137     return index;
138 }
139
140 IDBError MemoryObjectStore::deleteIndex(MemoryBackingStoreTransaction& transaction, uint64_t indexIdentifier)
141 {
142     LOG(IndexedDB, "MemoryObjectStore::deleteIndex");
143
144     if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
145         return IDBError(ConstraintError);
146     
147     auto index = takeIndexByIdentifier(indexIdentifier);
148     ASSERT(index);
149     if (!index)
150         return IDBError(ConstraintError);
151
152     m_info.deleteIndex(indexIdentifier);
153     transaction.indexDeleted(*index);
154
155     return IDBError { };
156 }
157
158 void MemoryObjectStore::deleteAllIndexes(MemoryBackingStoreTransaction& transaction)
159 {
160     Vector<uint64_t> indexIdentifiers;
161     indexIdentifiers.reserveInitialCapacity(m_indexesByName.size());
162
163     for (auto& index : m_indexesByName.values())
164         indexIdentifiers.uncheckedAppend(index->info().identifier());
165
166     for (auto identifier : indexIdentifiers)
167         deleteIndex(transaction, identifier);
168 }
169
170 bool MemoryObjectStore::containsRecord(const IDBKeyData& key)
171 {
172     if (!m_keyValueStore)
173         return false;
174
175     return m_keyValueStore->contains(key);
176 }
177
178 void MemoryObjectStore::clear()
179 {
180     LOG(IndexedDB, "MemoryObjectStore::clear");
181     ASSERT(m_writeTransaction);
182
183     m_writeTransaction->objectStoreCleared(*this, WTFMove(m_keyValueStore), WTFMove(m_orderedKeys));
184     for (auto& index : m_indexesByIdentifier.values())
185         index->objectStoreCleared();
186
187     for (auto& cursor : m_cursors.values())
188         cursor->objectStoreCleared();
189 }
190
191 void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr<KeyValueMap>&& store, std::unique_ptr<IDBKeyDataSet>&& orderedKeys)
192 {
193     ASSERT(m_writeTransaction);
194     ASSERT(m_writeTransaction->isAborting());
195
196     m_keyValueStore = WTFMove(store);
197     m_orderedKeys = WTFMove(orderedKeys);
198 }
199
200 void MemoryObjectStore::deleteRecord(const IDBKeyData& key)
201 {
202     LOG(IndexedDB, "MemoryObjectStore::deleteRecord");
203
204     ASSERT(m_writeTransaction);
205
206     if (!m_keyValueStore) {
207         m_writeTransaction->recordValueChanged(*this, key, nullptr);
208         return;
209     }
210
211     ASSERT(m_orderedKeys);
212
213     auto iterator = m_keyValueStore->find(key);
214     if (iterator == m_keyValueStore->end()) {
215         m_writeTransaction->recordValueChanged(*this, key, nullptr);
216         return;
217     }
218
219     m_writeTransaction->recordValueChanged(*this, key, &iterator->value);
220     m_keyValueStore->remove(iterator);
221     m_orderedKeys->erase(key);
222
223     updateIndexesForDeleteRecord(key);
224     updateCursorsForDeleteRecord(key);
225 }
226
227 void MemoryObjectStore::deleteRange(const IDBKeyRangeData& inputRange)
228 {
229     LOG(IndexedDB, "MemoryObjectStore::deleteRange");
230
231     ASSERT(m_writeTransaction);
232
233     if (inputRange.isExactlyOneKey()) {
234         deleteRecord(inputRange.lowerKey);
235         return;
236     }
237
238     IDBKeyRangeData range = inputRange;
239     while (true) {
240         auto key = lowestKeyWithRecordInRange(range);
241         if (key.isNull())
242             break;
243
244         deleteRecord(key);
245
246         range.lowerKey = key;
247         range.lowerOpen = true;
248     }
249 }
250
251 IDBError MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const IDBValue& value)
252 {
253     LOG(IndexedDB, "MemoryObjectStore::addRecord");
254
255     ASSERT(m_writeTransaction);
256     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
257     ASSERT(!m_keyValueStore || !m_keyValueStore->contains(keyData));
258     ASSERT(!m_orderedKeys || m_orderedKeys->find(keyData) == m_orderedKeys->end());
259
260     if (!m_keyValueStore) {
261         ASSERT(!m_orderedKeys);
262         m_keyValueStore = std::make_unique<KeyValueMap>();
263         m_orderedKeys = std::make_unique<IDBKeyDataSet>();
264     }
265
266     auto mapResult = m_keyValueStore->set(keyData, value.data());
267     ASSERT(mapResult.isNewEntry);
268     auto listResult = m_orderedKeys->insert(keyData);
269     ASSERT(listResult.second);
270
271     // If there was an error indexing this addition, then revert it.
272     auto error = updateIndexesForPutRecord(keyData, value.data());
273     if (!error.isNull()) {
274         m_keyValueStore->remove(mapResult.iterator);
275         m_orderedKeys->erase(listResult.first);
276     } else
277         updateCursorsForPutRecord(listResult.first);
278
279     return error;
280 }
281
282 void MemoryObjectStore::updateCursorsForPutRecord(IDBKeyDataSet::iterator iterator)
283 {
284     for (auto& cursor : m_cursors.values())
285         cursor->keyAdded(iterator);
286 }
287
288 void MemoryObjectStore::updateCursorsForDeleteRecord(const IDBKeyData& key)
289 {
290     for (auto& cursor : m_cursors.values())
291         cursor->keyDeleted(key);
292 }
293
294 void MemoryObjectStore::updateIndexesForDeleteRecord(const IDBKeyData& value)
295 {
296     for (auto& index : m_indexesByName.values())
297         index->removeEntriesWithValueKey(value);
298 }
299
300 IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value)
301 {
302     JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
303
304     auto jsValue = deserializeIDBValueToJSValue(UniqueIDBDatabase::databaseThreadExecState(), value);
305     if (jsValue.isUndefinedOrNull())
306         return IDBError { };
307
308     IDBError error;
309     Vector<std::pair<MemoryIndex*, IndexKey>> changedIndexRecords;
310
311     for (auto& index : m_indexesByName.values()) {
312         IndexKey indexKey;
313         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey, m_info.keyPath(), key);
314
315         if (indexKey.isNull())
316             continue;
317
318         error = index->putIndexKey(key, indexKey);
319         if (!error.isNull())
320             break;
321
322         changedIndexRecords.append(std::make_pair(index.get(), indexKey));
323     }
324
325     // If any of the index puts failed, revert all of the ones that went through.
326     if (!error.isNull()) {
327         for (auto& record : changedIndexRecords)
328             record.first->removeRecord(key, record.second);
329     }
330
331     return error;
332 }
333
334 IDBError MemoryObjectStore::populateIndexWithExistingRecords(MemoryIndex& index)
335 {
336     if (!m_keyValueStore)
337         return IDBError { };
338
339     JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
340
341     for (const auto& iterator : *m_keyValueStore) {
342         auto jsValue = deserializeIDBValueToJSValue(UniqueIDBDatabase::databaseThreadExecState(), iterator.value);
343         if (jsValue.isUndefinedOrNull())
344             return IDBError { };
345
346         IndexKey indexKey;
347         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey, m_info.keyPath(), iterator.key);
348
349         if (indexKey.isNull())
350             continue;
351
352         IDBError error = index.putIndexKey(iterator.key, indexKey);
353         if (!error.isNull())
354             return error;
355     }
356
357     return IDBError { };
358 }
359
360 uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
361 {
362     LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
363
364     if (indexIdentifier) {
365         auto* index = m_indexesByIdentifier.get(indexIdentifier);
366         ASSERT(index);
367         return index->countForKeyRange(inRange);
368     }
369
370     if (!m_keyValueStore)
371         return 0;
372
373     uint64_t count = 0;
374     IDBKeyRangeData range = inRange;
375     while (true) {
376         auto key = lowestKeyWithRecordInRange(range);
377         if (key.isNull())
378             break;
379
380         ++count;
381         range.lowerKey = key;
382         range.lowerOpen = true;
383     }
384
385     return count;
386 }
387
388 ThreadSafeDataBuffer MemoryObjectStore::valueForKey(const IDBKeyData& key) const
389 {
390     if (!m_keyValueStore)
391         return { };
392
393     return m_keyValueStore->get(key);
394 }
395
396 ThreadSafeDataBuffer MemoryObjectStore::valueForKeyRange(const IDBKeyRangeData& keyRangeData) const
397 {
398     LOG(IndexedDB, "MemoryObjectStore::valueForKey");
399
400     IDBKeyData key = lowestKeyWithRecordInRange(keyRangeData);
401     if (key.isNull())
402         return ThreadSafeDataBuffer();
403
404     ASSERT(m_keyValueStore);
405     return m_keyValueStore->get(key);
406 }
407
408 void MemoryObjectStore::getAllRecords(const IDBKeyRangeData& keyRangeData, Optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
409 {
410     result = { type, m_info.keyPath() };
411
412     uint32_t targetCount;
413     if (count && count.value())
414         targetCount = count.value();
415     else
416         targetCount = std::numeric_limits<uint32_t>::max();
417
418     IDBKeyRangeData range = keyRangeData;
419     uint32_t currentCount = 0;
420     while (currentCount < targetCount) {
421         IDBKeyData key = lowestKeyWithRecordInRange(range);
422         if (key.isNull())
423             return;
424
425         range.lowerKey = key;
426         range.lowerOpen = true;
427         if (type == IndexedDB::GetAllType::Values)
428             result.addValue(valueForKey(key));
429         result.addKey(WTFMove(key));
430
431         ++currentCount;
432     }
433 }
434
435 IDBGetResult MemoryObjectStore::indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range) const
436 {
437     LOG(IndexedDB, "MemoryObjectStore::indexValueForKeyRange");
438
439     auto* index = m_indexesByIdentifier.get(indexIdentifier);
440     ASSERT(index);
441     return index->getResultForKeyRange(recordType, range);
442 }
443
444 IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
445 {
446     if (!m_keyValueStore)
447         return { };
448
449     if (keyRangeData.isExactlyOneKey() && m_keyValueStore->contains(keyRangeData.lowerKey))
450         return keyRangeData.lowerKey;
451
452     ASSERT(m_orderedKeys);
453
454     auto lowestInRange = m_orderedKeys->lower_bound(keyRangeData.lowerKey);
455
456     if (lowestInRange == m_orderedKeys->end())
457         return { };
458
459     if (keyRangeData.lowerOpen && *lowestInRange == keyRangeData.lowerKey)
460         ++lowestInRange;
461
462     if (lowestInRange == m_orderedKeys->end())
463         return { };
464
465     if (!keyRangeData.upperKey.isNull()) {
466         if (lowestInRange->compare(keyRangeData.upperKey) > 0)
467             return { };
468         if (keyRangeData.upperOpen && *lowestInRange == keyRangeData.upperKey)
469             return { };
470     }
471
472     return *lowestInRange;
473 }
474
475 void MemoryObjectStore::registerIndex(Ref<MemoryIndex>&& index)
476 {
477     ASSERT(!m_indexesByIdentifier.contains(index->info().identifier()));
478     ASSERT(!m_indexesByName.contains(index->info().name()));
479
480     auto identifier = index->info().identifier();
481     m_indexesByName.set(index->info().name(), &index.get());
482     m_indexesByIdentifier.set(identifier, WTFMove(index));
483 }
484
485 void MemoryObjectStore::unregisterIndex(MemoryIndex& index)
486 {
487     ASSERT(m_indexesByIdentifier.contains(index.info().identifier()));
488     ASSERT(m_indexesByName.contains(index.info().name()));
489
490     m_indexesByName.remove(index.info().name());
491     m_indexesByIdentifier.remove(index.info().identifier());
492 }
493
494 MemoryObjectStoreCursor* MemoryObjectStore::maybeOpenCursor(const IDBCursorInfo& info)
495 {
496     auto result = m_cursors.add(info.identifier(), nullptr);
497     if (!result.isNewEntry)
498         return nullptr;
499
500     result.iterator->value = std::make_unique<MemoryObjectStoreCursor>(*this, info);
501     return result.iterator->value.get();
502 }
503
504 void MemoryObjectStore::renameIndex(MemoryIndex& index, const String& newName)
505 {
506     ASSERT(m_indexesByName.get(index.info().name()) == &index);
507     ASSERT(!m_indexesByName.contains(newName));
508     ASSERT(m_info.infoForExistingIndex(index.info().name()));
509
510     m_info.infoForExistingIndex(index.info().name())->rename(newName);
511     m_indexesByName.set(newName, m_indexesByName.take(index.info().name()));
512     index.rename(newName);
513 }
514
515 } // namespace IDBServer
516 } // namespace WebCore
517
518 #endif // ENABLE(INDEXED_DATABASE)