47b0e955d5d54a754bd6d3848751b9a80458c39a
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryIndexCursor.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 "MemoryIndexCursor.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorInfo.h"
32 #include "IDBGetResult.h"
33 #include "IndexValueStore.h"
34 #include "Logging.h"
35 #include "MemoryCursor.h"
36 #include "MemoryIndex.h"
37 #include "MemoryObjectStore.h"
38
39 namespace WebCore {
40 namespace IDBServer {
41
42 MemoryIndexCursor::MemoryIndexCursor(MemoryIndex& index, const IDBCursorInfo& info)
43     : MemoryCursor(info)
44     , m_index(index)
45 {
46     LOG(IndexedDB, "MemoryIndexCursor::MemoryIndexCursor %s", info.range().loggingString().utf8().data());
47
48     auto* valueStore = m_index.valueStore();
49     if (!valueStore)
50         return;
51
52     if (m_info.isDirectionForward())
53         m_currentIterator = valueStore->find(m_info.range().lowerKey, m_info.range().lowerOpen);
54     else
55         m_currentIterator = valueStore->reverseFind(m_info.range().upperKey, m_info.duplicity(), m_info.range().upperOpen);
56
57     if (m_currentIterator.isValid() && m_info.range().containsKey(m_currentIterator.key())) {
58         m_currentKey = m_currentIterator.key();
59         m_currentPrimaryKey = m_currentIterator.primaryKey();
60         m_index.cursorDidBecomeClean(*this);
61     } else
62         m_currentIterator.invalidate();
63 }
64
65 MemoryIndexCursor::~MemoryIndexCursor() = default;
66
67 void MemoryIndexCursor::currentData(IDBGetResult& getResult)
68 {
69     if (!m_currentIterator.isValid()) {
70         getResult = { };
71         return;
72     }
73
74     if (m_info.cursorType() == IndexedDB::CursorType::KeyOnly)
75         getResult = { m_currentKey, m_currentPrimaryKey };
76     else {
77         IDBValue value = { m_index.objectStore().valueForKey(m_currentPrimaryKey), { }, { }, { } };
78         getResult = { m_currentKey, m_currentPrimaryKey, WTFMove(value) };
79     }
80 }
81
82 void MemoryIndexCursor::iterate(const IDBKeyData& key, const IDBKeyData& primaryKey, uint32_t count, IDBGetResult& getResult)
83 {
84     LOG(IndexedDB, "MemoryIndexCursor::iterate to key %s, %u count", key.loggingString().utf8().data(), count);
85
86 #ifndef NDEBUG
87     if (primaryKey.isValid())
88         ASSERT(key.isValid());
89 #endif
90
91     if (key.isValid()) {
92         // Cannot iterate by both a count and to a key
93         ASSERT(!count);
94
95         auto* valueStore = m_index.valueStore();
96         if (!valueStore) {
97             m_currentKey = { };
98             m_currentPrimaryKey = { };
99             getResult = { };
100             return;
101         }
102
103         if (primaryKey.isValid()) {
104             if (m_info.isDirectionForward())
105                 m_currentIterator = valueStore->find(key, primaryKey);
106             else
107                 m_currentIterator = valueStore->reverseFind(key, primaryKey, m_info.duplicity());
108         } else {
109             if (m_info.isDirectionForward())
110                 m_currentIterator = valueStore->find(key);
111             else
112                 m_currentIterator = valueStore->reverseFind(key, m_info.duplicity());
113         }
114
115         if (m_currentIterator.isValid() && !m_info.range().containsKey(m_currentIterator.key()))
116             m_currentIterator.invalidate();
117
118         if (!m_currentIterator.isValid()) {
119             m_currentKey = { };
120             m_currentPrimaryKey = { };
121             getResult = { };
122             return;
123         }
124
125         m_index.cursorDidBecomeClean(*this);
126
127         m_currentKey = m_currentIterator.key();
128         m_currentPrimaryKey = m_currentIterator.primaryKey();
129         currentData(getResult);
130
131         return;
132     }
133
134     // If there was not a valid key argument and no positive count argument
135     // that means the default iteration count of "1"
136     if (!count)
137         count = 1;
138
139     if (!m_currentIterator.isValid()) {
140         auto* valueStore = m_index.valueStore();
141         if (!valueStore) {
142             m_currentKey = { };
143             m_currentPrimaryKey = { };
144             getResult = { };
145             return;
146         }
147
148         switch (m_info.cursorDirection()) {
149         case IndexedDB::CursorDirection::Next:
150             m_currentIterator = valueStore->find(m_currentKey, m_currentPrimaryKey);
151             break;
152         case IndexedDB::CursorDirection::Nextunique:
153             m_currentIterator = valueStore->find(m_currentKey, true);
154             break;
155         case IndexedDB::CursorDirection::Prev:
156             m_currentIterator = valueStore->reverseFind(m_currentKey, m_currentPrimaryKey, m_info.duplicity());
157             break;
158         case IndexedDB::CursorDirection::Prevunique:
159             m_currentIterator = valueStore->reverseFind(m_currentKey, m_info.duplicity(), true);
160             break;
161         }
162
163         if (!m_currentIterator.isValid()) {
164             m_currentKey = { };
165             m_currentPrimaryKey = { };
166             getResult = { };
167             return;
168         }
169
170         m_index.cursorDidBecomeClean(*this);
171
172         // If we restored the current iterator and it does *not* match the current key/primaryKey,
173         // then it is the next record in line and we should consider that an iteration.
174         if (m_currentKey != m_currentIterator.key() || m_currentPrimaryKey != m_currentIterator.primaryKey())
175             --count;
176     }
177
178     ASSERT(m_currentIterator.isValid());
179
180     while (count) {
181         if (m_info.duplicity() == CursorDuplicity::NoDuplicates)
182             m_currentIterator.nextIndexEntry();
183         else
184             ++m_currentIterator;
185
186         if (!m_currentIterator.isValid())
187             break;
188
189         --count;
190     }
191
192     if (m_currentIterator.isValid() && !m_info.range().containsKey(m_currentIterator.key()))
193         m_currentIterator.invalidate();
194
195     // Not having a valid iterator after finishing any iteration means we've reached the end of the cursor.
196     if (!m_currentIterator.isValid()) {
197         m_currentKey = { };
198         m_currentPrimaryKey = { };
199         getResult = { };
200         return;
201     }
202
203     m_currentKey = m_currentIterator.key();
204     m_currentPrimaryKey = m_currentIterator.primaryKey();
205     currentData(getResult);
206 }
207
208 void MemoryIndexCursor::indexRecordsAllChanged()
209 {
210     m_currentIterator.invalidate();
211     m_index.cursorDidBecomeDirty(*this);
212 }
213
214 void MemoryIndexCursor::indexValueChanged(const IDBKeyData& key, const IDBKeyData& primaryKey)
215 {
216     if (m_currentKey != key || m_currentPrimaryKey != primaryKey)
217         return;
218
219     m_currentIterator.invalidate();
220     m_index.cursorDidBecomeDirty(*this);
221 }
222
223 } // namespace IDBServer
224 } // namespace WebCore
225
226 #endif // ENABLE(INDEXED_DATABASE)