[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / SQLiteIDBCursor.cpp
1 /*
2  * Copyright (C) 2014, 2016 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SQLiteIDBCursor.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorInfo.h"
32 #include "IDBGetResult.h"
33 #include "IDBSerialization.h"
34 #include "Logging.h"
35 #include "SQLiteIDBBackingStore.h"
36 #include "SQLiteIDBTransaction.h"
37 #include "SQLiteStatement.h"
38 #include "SQLiteTransaction.h"
39 #include <sqlite3.h>
40 #include <wtf/text/StringBuilder.h>
41
42 namespace WebCore {
43 namespace IDBServer {
44
45 static const size_t prefetchLimit = 8;
46
47 std::unique_ptr<SQLiteIDBCursor> SQLiteIDBCursor::maybeCreate(SQLiteIDBTransaction& transaction, const IDBCursorInfo& info)
48 {
49     auto cursor = makeUnique<SQLiteIDBCursor>(transaction, info);
50
51     if (!cursor->establishStatement())
52         return nullptr;
53
54     if (!cursor->advance(1))
55         return nullptr;
56
57     return cursor;
58 }
59
60 std::unique_ptr<SQLiteIDBCursor> SQLiteIDBCursor::maybeCreateBackingStoreCursor(SQLiteIDBTransaction& transaction, const uint64_t objectStoreID, const uint64_t indexID, const IDBKeyRangeData& range)
61 {
62     auto cursor = makeUnique<SQLiteIDBCursor>(transaction, objectStoreID, indexID, range);
63
64     if (!cursor->establishStatement())
65         return nullptr;
66
67     if (!cursor->advance(1))
68         return nullptr;
69
70     return cursor;
71 }
72
73 SQLiteIDBCursor::SQLiteIDBCursor(SQLiteIDBTransaction& transaction, const IDBCursorInfo& info)
74     : m_transaction(&transaction)
75     , m_cursorIdentifier(info.identifier())
76     , m_objectStoreID(info.objectStoreIdentifier())
77     , m_indexID(info.cursorSource() == IndexedDB::CursorSource::Index ? info.sourceIdentifier() : IDBIndexInfo::InvalidId)
78     , m_cursorDirection(info.cursorDirection())
79     , m_cursorType(info.cursorType())
80     , m_keyRange(info.range())
81 {
82     ASSERT(m_objectStoreID);
83 }
84
85 SQLiteIDBCursor::SQLiteIDBCursor(SQLiteIDBTransaction& transaction, const uint64_t objectStoreID, const uint64_t indexID, const IDBKeyRangeData& range)
86     : m_transaction(&transaction)
87     , m_cursorIdentifier(transaction.transactionIdentifier())
88     , m_objectStoreID(objectStoreID)
89     , m_indexID(indexID ? indexID : IDBIndexInfo::InvalidId)
90     , m_cursorDirection(IndexedDB::CursorDirection::Next)
91     , m_cursorType(IndexedDB::CursorType::KeyAndValue)
92     , m_keyRange(range)
93     , m_backingStoreCursor(true)
94 {
95     ASSERT(m_objectStoreID);
96 }
97
98 SQLiteIDBCursor::~SQLiteIDBCursor()
99 {
100     if (m_backingStoreCursor)
101         m_transaction->closeCursor(*this);
102 }
103
104 void SQLiteIDBCursor::currentData(IDBGetResult& result, const Optional<IDBKeyPath>& keyPath)
105 {
106     ASSERT(!m_fetchedRecords.isEmpty());
107
108     auto& currentRecord = m_fetchedRecords.first();
109     if (currentRecord.completed) {
110         ASSERT(!currentRecord.errored);
111         result = { };
112         return;
113     }
114
115     result = { currentRecord.record.key, currentRecord.record.primaryKey, currentRecord.record.value ? *currentRecord.record.value : IDBValue(), keyPath};
116 }
117
118 static String buildIndexStatement(const IDBKeyRangeData& keyRange, IndexedDB::CursorDirection cursorDirection)
119 {
120     StringBuilder builder;
121
122     builder.appendLiteral("SELECT rowid, key, value FROM IndexRecords WHERE indexID = ? AND objectStoreID = ? AND key ");
123     if (!keyRange.lowerKey.isNull() && !keyRange.lowerOpen)
124         builder.appendLiteral(">=");
125     else
126         builder.append('>');
127
128     builder.appendLiteral(" CAST(? AS TEXT) AND key ");
129     if (!keyRange.upperKey.isNull() && !keyRange.upperOpen)
130         builder.appendLiteral("<=");
131     else
132         builder.append('<');
133
134     builder.appendLiteral(" CAST(? AS TEXT) ORDER BY key");
135     if (cursorDirection == IndexedDB::CursorDirection::Prev || cursorDirection == IndexedDB::CursorDirection::Prevunique)
136         builder.appendLiteral(" DESC");
137
138     builder.appendLiteral(", value");
139     if (cursorDirection == IndexedDB::CursorDirection::Prev)
140         builder.appendLiteral(" DESC");
141
142     builder.append(';');
143
144     return builder.toString();
145 }
146
147 static String buildObjectStoreStatement(const IDBKeyRangeData& keyRange, IndexedDB::CursorDirection cursorDirection)
148 {
149     StringBuilder builder;
150
151     builder.appendLiteral("SELECT rowid, key, value FROM Records WHERE objectStoreID = ? AND key ");
152
153     if (!keyRange.lowerKey.isNull() && !keyRange.lowerOpen)
154         builder.appendLiteral(">=");
155     else
156         builder.append('>');
157
158     builder.appendLiteral(" CAST(? AS TEXT) AND key ");
159
160     if (!keyRange.upperKey.isNull() && !keyRange.upperOpen)
161         builder.appendLiteral("<=");
162     else
163         builder.append('<');
164
165     builder.appendLiteral(" CAST(? AS TEXT) ORDER BY key");
166
167     if (cursorDirection == IndexedDB::CursorDirection::Prev || cursorDirection == IndexedDB::CursorDirection::Prevunique)
168         builder.appendLiteral(" DESC");
169
170     builder.append(';');
171
172     return builder.toString();
173 }
174
175 bool SQLiteIDBCursor::establishStatement()
176 {
177     ASSERT(!m_statement);
178     String sql;
179
180     if (m_indexID != IDBIndexInfo::InvalidId) {
181         sql = buildIndexStatement(m_keyRange, m_cursorDirection);
182         m_boundID = m_indexID;
183     } else {
184         sql = buildObjectStoreStatement(m_keyRange, m_cursorDirection);
185         m_boundID = m_objectStoreID;
186     }
187
188     m_currentLowerKey = m_keyRange.lowerKey.isNull() ? IDBKeyData::minimum() : m_keyRange.lowerKey;
189     m_currentUpperKey = m_keyRange.upperKey.isNull() ? IDBKeyData::maximum() : m_keyRange.upperKey;
190
191     return createSQLiteStatement(sql);
192 }
193
194 bool SQLiteIDBCursor::createSQLiteStatement(const String& sql)
195 {
196     LOG(IndexedDB, "Creating cursor with SQL query: \"%s\"", sql.utf8().data());
197
198     ASSERT(!m_currentLowerKey.isNull());
199     ASSERT(!m_currentUpperKey.isNull());
200     ASSERT(m_transaction->sqliteTransaction());
201
202     m_statement = makeUnique<SQLiteStatement>(m_transaction->sqliteTransaction()->database(), sql);
203
204     if (m_statement->prepare() != SQLITE_OK) {
205         LOG_ERROR("Could not create cursor statement (prepare/id) - '%s'", m_transaction->sqliteTransaction()->database().lastErrorMsg());
206         return false;
207     }
208
209     return bindArguments();
210 }
211
212 void SQLiteIDBCursor::objectStoreRecordsChanged()
213 {
214     if (m_statementNeedsReset)
215         return;
216
217     ASSERT(!m_fetchedRecords.isEmpty());
218
219     m_currentKeyForUniqueness = m_fetchedRecords.first().record.key;
220
221     if (m_cursorDirection != IndexedDB::CursorDirection::Nextunique && m_cursorDirection != IndexedDB::CursorDirection::Prevunique) {
222         if (!m_fetchedRecords.last().isTerminalRecord())
223             fetch(ShouldFetchForSameKey::Yes);
224
225         while (m_fetchedRecords.last().record.key != m_fetchedRecords.first().record.key)
226             m_fetchedRecords.removeLast();
227     } else
228         m_fetchedRecords.clear();
229
230     // If ObjectStore or Index contents changed, we need to reset the statement and bind new parameters to it.
231     // This is to pick up any changes that might exist.
232     // We also need to throw away any fetched records as they may no longer be valid.
233
234     m_statementNeedsReset = true;
235
236     if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::Nextunique) {
237         m_currentLowerKey = m_currentKeyForUniqueness;
238         if (!m_keyRange.lowerOpen) {
239             m_keyRange.lowerOpen = true;
240             m_keyRange.lowerKey = m_currentLowerKey;
241             m_statement = nullptr;
242         }
243     } else {
244         m_currentUpperKey = m_currentKeyForUniqueness;
245         if (!m_keyRange.upperOpen) {
246             m_keyRange.upperOpen = true;
247             m_keyRange.upperKey = m_currentUpperKey;
248             m_statement = nullptr;
249         }
250     }
251 }
252
253 void SQLiteIDBCursor::resetAndRebindStatement()
254 {
255     ASSERT(!m_currentLowerKey.isNull());
256     ASSERT(!m_currentUpperKey.isNull());
257     ASSERT(m_transaction->sqliteTransaction());
258     ASSERT(m_statementNeedsReset);
259
260     m_statementNeedsReset = false;
261
262     if (!m_statement && !establishStatement()) {
263         LOG_ERROR("Unable to establish new statement for cursor iteration");
264         return;
265     }
266
267     if (m_statement->reset() != SQLITE_OK) {
268         LOG_ERROR("Could not reset cursor statement to respond to object store changes");
269         return;
270     }
271
272     bindArguments();
273 }
274
275 bool SQLiteIDBCursor::bindArguments()
276 {
277     LOG(IndexedDB, "Cursor is binding lower key '%s' and upper key '%s'", m_currentLowerKey.loggingString().utf8().data(), m_currentUpperKey.loggingString().utf8().data());
278
279     int currentBindArgument = 1;
280
281     if (m_statement->bindInt64(currentBindArgument++, m_boundID) != SQLITE_OK) {
282         LOG_ERROR("Could not bind id argument (bound ID)");
283         return false;
284     }
285
286     if (m_indexID != IDBIndexInfo::InvalidId && m_statement->bindInt64(currentBindArgument++, m_objectStoreID) != SQLITE_OK) {
287         LOG_ERROR("Could not bind object store id argument for an index cursor");
288         return false;
289     }
290
291     RefPtr<SharedBuffer> buffer = serializeIDBKeyData(m_currentLowerKey);
292     if (m_statement->bindBlob(currentBindArgument++, buffer->data(), buffer->size()) != SQLITE_OK) {
293         LOG_ERROR("Could not create cursor statement (lower key)");
294         return false;
295     }
296
297     buffer = serializeIDBKeyData(m_currentUpperKey);
298     if (m_statement->bindBlob(currentBindArgument++, buffer->data(), buffer->size()) != SQLITE_OK) {
299         LOG_ERROR("Could not create cursor statement (upper key)");
300         return false;
301     }
302
303     return true;
304 }
305
306 bool SQLiteIDBCursor::prefetch()
307 {
308     LOG(IndexedDB, "SQLiteIDBCursor::prefetch() - Cursor already has %zu fetched records", m_fetchedRecords.size());
309
310     if (m_fetchedRecords.isEmpty() || m_fetchedRecords.size() >= prefetchLimit || m_fetchedRecords.last().isTerminalRecord())
311         return false;
312
313     m_currentKeyForUniqueness = m_fetchedRecords.last().record.key;
314     fetch();
315
316     return m_fetchedRecords.size() < prefetchLimit;
317 }
318
319 bool SQLiteIDBCursor::advance(uint64_t count)
320 {
321     LOG(IndexedDB, "SQLiteIDBCursor::advance() - Count %" PRIu64 ", %zu fetched records", count, m_fetchedRecords.size());
322     ASSERT(count);
323
324     if (!m_fetchedRecords.isEmpty() && m_fetchedRecords.first().isTerminalRecord()) {
325         LOG_ERROR("Attempt to advance a completed cursor");
326         return false;
327     }
328
329     if (!m_fetchedRecords.isEmpty())
330         m_currentKeyForUniqueness = m_fetchedRecords.last().record.key;
331
332     // Drop already-fetched records up to `count` to see if we've already fetched the record we're looking for.
333     bool hadCurrentRecord = !m_fetchedRecords.isEmpty();
334     for (; count && !m_fetchedRecords.isEmpty(); --count) {
335         if (m_fetchedRecords.first().isTerminalRecord())
336             break;
337
338         m_fetchedRecords.removeFirst();
339     }
340
341     // If we still have any records left, the first record is our new current record.
342     if (!m_fetchedRecords.isEmpty())
343         return true;
344
345     ASSERT(m_fetchedRecords.isEmpty());
346
347     // If we started out with a current record, we burnt a count on removing it.
348     // Replace that count now.
349     if (hadCurrentRecord)
350         ++count;
351
352     for (; count; --count) {
353         if (!m_fetchedRecords.isEmpty()) {
354             ASSERT(m_fetchedRecords.size() == 1);
355             m_currentKeyForUniqueness = m_fetchedRecords.first().record.key;
356             m_fetchedRecords.removeFirst();
357         }
358
359         if (!fetch())
360             return false;
361
362         ASSERT(!m_fetchedRecords.isEmpty());
363         ASSERT(!m_fetchedRecords.first().errored);
364         if (m_fetchedRecords.first().completed)
365             break;
366     }
367
368     return true;
369 }
370
371 bool SQLiteIDBCursor::fetch(ShouldFetchForSameKey shouldFetchForSameKey)
372 {
373     ASSERT(m_fetchedRecords.isEmpty() || !m_fetchedRecords.last().isTerminalRecord());
374
375     m_fetchedRecords.append({ });
376
377     bool isUnique = m_cursorDirection == IndexedDB::CursorDirection::Nextunique || m_cursorDirection == IndexedDB::CursorDirection::Prevunique || shouldFetchForSameKey == ShouldFetchForSameKey::Yes;
378     if (!isUnique)
379         return fetchNextRecord(m_fetchedRecords.last());
380
381     while (fetchNextRecord(m_fetchedRecords.last())) {
382         if (m_currentKeyForUniqueness.compare(m_fetchedRecords.last().record.key))
383             return true;
384
385         if (m_fetchedRecords.last().completed)
386             return false;
387
388         if (shouldFetchForSameKey == ShouldFetchForSameKey::Yes)
389             m_fetchedRecords.append({ });
390     }
391
392     return false;
393 }
394
395 bool SQLiteIDBCursor::fetchNextRecord(SQLiteCursorRecord& record)
396 {
397     if (m_statementNeedsReset)
398         resetAndRebindStatement();
399
400     FetchResult result;
401     do {
402         result = internalFetchNextRecord(record);
403     } while (result == FetchResult::ShouldFetchAgain);
404
405     return result == FetchResult::Success;
406 }
407
408 void SQLiteIDBCursor::markAsErrored(SQLiteCursorRecord& record)
409 {
410     record.record = { };
411     record.completed = true;
412     record.errored = true;
413     record.rowID = 0;
414 }
415
416 SQLiteIDBCursor::FetchResult SQLiteIDBCursor::internalFetchNextRecord(SQLiteCursorRecord& record)
417 {
418     ASSERT(m_transaction->sqliteTransaction());
419     ASSERT(m_statement);
420     ASSERT(!m_fetchedRecords.isEmpty());
421     ASSERT(!m_fetchedRecords.last().isTerminalRecord());
422
423     record.record.value = nullptr;
424
425     int result = m_statement->step();
426     if (result == SQLITE_DONE) {
427         // When a cursor reaches its end, that is indicated by having undefined keys/values
428         record = { };
429         record.completed = true;
430
431         return FetchResult::Success;
432     }
433
434     if (result != SQLITE_ROW) {
435         LOG_ERROR("Error advancing cursor - (%i) %s", result, m_transaction->sqliteTransaction()->database().lastErrorMsg());
436         markAsErrored(record);
437         return FetchResult::Failure;
438     }
439
440     record.rowID = m_statement->getColumnInt64(0);
441     ASSERT(record.rowID);
442
443     Vector<uint8_t> keyData;
444     m_statement->getColumnBlobAsVector(1, keyData);
445
446     if (!deserializeIDBKeyData(keyData.data(), keyData.size(), record.record.key)) {
447         LOG_ERROR("Unable to deserialize key data from database while advancing cursor");
448         markAsErrored(record);
449         return FetchResult::Failure;
450     }
451
452     m_statement->getColumnBlobAsVector(2, keyData);
453
454     // The primaryKey of an ObjectStore cursor is the same as its key.
455     if (m_indexID == IDBIndexInfo::InvalidId) {
456         record.record.primaryKey = record.record.key;
457
458         Vector<String> blobURLs, blobFilePaths;
459         auto error = m_transaction->backingStore().getBlobRecordsForObjectStoreRecord(record.rowID, blobURLs, blobFilePaths);
460         if (!error.isNull()) {
461             LOG_ERROR("Unable to fetch blob records from database while advancing cursor");
462             markAsErrored(record);
463             return FetchResult::Failure;
464         }
465
466         if (m_cursorType == IndexedDB::CursorType::KeyAndValue)
467             record.record.value = makeUnique<IDBValue>(ThreadSafeDataBuffer::create(WTFMove(keyData)), blobURLs, blobFilePaths);
468     } else {
469         if (!deserializeIDBKeyData(keyData.data(), keyData.size(), record.record.primaryKey)) {
470             LOG_ERROR("Unable to deserialize value data from database while advancing index cursor");
471             markAsErrored(record);
472             return FetchResult::Failure;
473         }
474
475         SQLiteStatement objectStoreStatement(m_statement->database(), "SELECT value FROM Records WHERE key = CAST(? AS TEXT) and objectStoreID = ?;");
476
477         if (objectStoreStatement.prepare() != SQLITE_OK
478             || objectStoreStatement.bindBlob(1, keyData.data(), keyData.size()) != SQLITE_OK
479             || objectStoreStatement.bindInt64(2, m_objectStoreID) != SQLITE_OK) {
480             LOG_ERROR("Could not create index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
481             markAsErrored(record);
482             return FetchResult::Failure;
483         }
484
485         int result = objectStoreStatement.step();
486
487         if (result == SQLITE_ROW) {
488             objectStoreStatement.getColumnBlobAsVector(0, keyData);
489             record.record.value = makeUnique<IDBValue>(ThreadSafeDataBuffer::create(WTFMove(keyData)));
490         } else if (result == SQLITE_DONE) {
491             // This indicates that the record we're trying to retrieve has been removed from the object store.
492             // Skip over it.
493             return FetchResult::ShouldFetchAgain;
494         } else {
495             LOG_ERROR("Could not step index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
496             markAsErrored(record);
497             return FetchResult::Failure;
498
499         }
500     }
501
502     return FetchResult::Success;
503 }
504
505 bool SQLiteIDBCursor::iterate(const IDBKeyData& targetKey, const IDBKeyData& targetPrimaryKey)
506 {
507     ASSERT(m_transaction->sqliteTransaction());
508     ASSERT(m_statement);
509
510     bool result = advance(1);
511     ASSERT(!m_fetchedRecords.isEmpty());
512
513     // Iterating with no key is equivalent to advancing 1 step.
514     if (targetKey.isNull() || !result)
515         return result;
516
517     while (!m_fetchedRecords.first().isTerminalRecord()) {
518         if (!result)
519             return false;
520
521         // Search for the next key >= the target if the cursor is a Next cursor, or the next key <= if the cursor is a Previous cursor.
522         if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::Nextunique) {
523             if (m_fetchedRecords.first().record.key.compare(targetKey) >= 0)
524                 break;
525         } else if (m_fetchedRecords.first().record.key.compare(targetKey) <= 0)
526             break;
527
528         result = advance(1);
529     }
530
531     if (targetPrimaryKey.isValid()) {
532         while (!m_fetchedRecords.first().isTerminalRecord() && !m_fetchedRecords.first().record.key.compare(targetKey)) {
533             if (!result)
534                 return false;
535
536             // Search for the next primary key >= the primary target if the cursor is a Next cursor, or the next key <= if the cursor is a Previous cursor.
537             if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::Nextunique) {
538                 if (m_fetchedRecords.first().record.primaryKey.compare(targetPrimaryKey) >= 0)
539                     break;
540             } else if (m_fetchedRecords.first().record.primaryKey.compare(targetPrimaryKey) <= 0)
541                 break;
542
543             result = advance(1);
544         }
545     }
546
547     return result;
548 }
549
550 const IDBKeyData& SQLiteIDBCursor::currentKey() const
551 {
552     ASSERT(!m_fetchedRecords.isEmpty());
553     return m_fetchedRecords.first().record.key;
554 }
555
556 const IDBKeyData& SQLiteIDBCursor::currentPrimaryKey() const
557 {
558     ASSERT(!m_fetchedRecords.isEmpty());
559     return m_fetchedRecords.first().record.primaryKey;
560 }
561
562 IDBValue* SQLiteIDBCursor::currentValue() const
563 {
564     ASSERT(!m_fetchedRecords.isEmpty());
565     return m_fetchedRecords.first().record.value.get();
566 }
567
568 bool SQLiteIDBCursor::didComplete() const
569 {
570     ASSERT(!m_fetchedRecords.isEmpty());
571     return m_fetchedRecords.first().completed;
572 }
573
574 bool SQLiteIDBCursor::didError() const
575 {
576     ASSERT(!m_fetchedRecords.isEmpty());
577     return m_fetchedRecords.first().errored;
578 }
579
580 int64_t SQLiteIDBCursor::currentRecordRowID() const
581 {
582     ASSERT(!m_fetchedRecords.isEmpty());
583     return m_fetchedRecords.first().rowID;
584 }
585
586
587 } // namespace IDBServer
588 } // namespace WebCore
589
590 #endif // ENABLE(INDEXED_DATABASE)