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