@@ -28,32 +28,25 @@ import { assert } from '../util/assert';
28
28
import { debug , getLogLevel , LogLevel } from '../util/log' ;
29
29
import { SortedSet } from '../util/sorted_set' ;
30
30
31
+ // TOOD(b/140938512): Drop SimpleQueryEngine and rename IndexFreeQueryEngine.
32
+
31
33
/**
32
34
* A query engine that takes advantage of the target document mapping in the
33
35
* QueryCache. The IndexFreeQueryEngine optimizes query execution by only
34
- * reading the documents previously matched a query plus any documents that were
36
+ * reading the documents that previously matched a query plus any documents that were
35
37
* edited after the query was last listened to.
36
38
*
37
39
* There are some cases where Index-Free queries are not guaranteed to produce
38
- * to the same results as full collection scans. In these case , the
39
- * IndexFreeQueryEngine falls back to a full query processing. These cases are:
40
+ * the same results as full collection scans. In these cases , the
41
+ * IndexFreeQueryEngine falls back to full query processing. These cases are:
40
42
*
41
43
* - Limit queries where a document that matched the query previously no longer
42
- * matches the query. In this case, we have to scan all local documents since a
43
- * document that was sent to us as part of a different query result may now fall
44
- * into the limit.
44
+ * matches the query.
45
45
*
46
- * - Limit queries that include edits that occurred after the last remote
47
- * snapshot (both latency-compensated or committed). Even if an edited document
48
- * continues to match the query, an edit may cause a document to sort below
49
- * another document that is in the local cache.
46
+ * - Limit queries where a document edit may cause the document to sort below
47
+ * another document that is in the local cache.
50
48
*
51
- * - Queries where the last snapshot contained Limbo documents. Even though a
52
- * Limbo document is not part of the backend result set, we need to include
53
- * Limbo documents in local views to ensure consistency between different Query
54
- * views. If there exists a previous query snapshot that contained no limbo
55
- * documents, we can instead use the older snapshot version for Index-Free
56
- * processing.
49
+ * - Queries that have never been CURRENT or free of Limbo documents.
57
50
*/
58
51
export class IndexFreeQueryEngine implements QueryEngine {
59
52
private localDocumentsView : LocalDocumentsView | undefined ;
@@ -89,7 +82,7 @@ export class IndexFreeQueryEngine implements QueryEngine {
89
82
return this . executeFullCollectionScan ( transaction , query ) ;
90
83
}
91
84
92
- return this . getSortedPreviousResults ( transaction , query , remoteKeys ) . next (
85
+ return this . getSortedDocuments ( transaction , query , remoteKeys ) . next (
93
86
previousResults => {
94
87
if (
95
88
query . hasLimit ( ) &&
@@ -131,21 +124,20 @@ export class IndexFreeQueryEngine implements QueryEngine {
131
124
* Returns the documents for the specified remote keys if they still match the
132
125
* query, sorted by the query's comparator.
133
126
*/
134
- getSortedPreviousResults (
127
+ private getSortedDocuments (
135
128
transaction : PersistenceTransaction ,
136
- query : Query ,
129
+ sortByQuery : Query ,
137
130
remoteKeys : DocumentKeySet
138
131
) : PersistencePromise < SortedSet < Document > > {
139
- // Fetch the documents that matched the query at the last snapshot.
140
132
return this . localDocumentsView ! . getDocuments ( transaction , remoteKeys ) . next (
141
133
previousResults => {
142
134
// Sort the documents and re-apply the query filter since previously
143
135
// matching documents do not necessarily still match the query.
144
136
let results = new SortedSet < Document > ( ( d1 , d2 ) =>
145
- query . docComparator ( d1 , d2 )
137
+ sortByQuery . docComparator ( d1 , d2 )
146
138
) ;
147
139
previousResults . forEach ( ( _ , maybeDoc ) => {
148
- if ( maybeDoc instanceof Document && query . matches ( maybeDoc ) ) {
140
+ if ( maybeDoc instanceof Document && sortByQuery . matches ( maybeDoc ) ) {
149
141
results = results . add ( maybeDoc ) ;
150
142
}
151
143
} ) ;
@@ -166,7 +158,7 @@ export class IndexFreeQueryEngine implements QueryEngine {
166
158
* @param limboFreeSnapshotVersion The version of the snapshot when the query
167
159
* was last synchronized.
168
160
*/
169
- needsRefill (
161
+ private needsRefill (
170
162
sortedPreviousResults : SortedSet < Document > ,
171
163
remoteKeys : DocumentKeySet ,
172
164
limboFreeSnapshotVersion : SnapshotVersion
@@ -177,12 +169,6 @@ export class IndexFreeQueryEngine implements QueryEngine {
177
169
return true ;
178
170
}
179
171
180
- // We don't need to find a better match from cache if no documents matched
181
- // the query.
182
- if ( sortedPreviousResults . isEmpty ( ) ) {
183
- return false ;
184
- }
185
-
186
172
// Limit queries are not eligible for index-free query execution if there is
187
173
// a potential that an older document from cache now sorts before a document
188
174
// that was previously part of the limit. This, however, can only happen if
@@ -192,14 +178,18 @@ export class IndexFreeQueryEngine implements QueryEngine {
192
178
// documents from cache will continue to be "rejected" by this boundary.
193
179
// Therefore, we can ignore any modifications that don't affect the last
194
180
// document.
195
- const lastDocumentInLimit = sortedPreviousResults . last ( ) ! ;
181
+ const lastDocumentInLimit = sortedPreviousResults . last ( ) ;
182
+ if ( ! lastDocumentInLimit ) {
183
+ // We don't need to refill the query if there were already no documents.
184
+ return false ;
185
+ }
196
186
return (
197
187
lastDocumentInLimit . hasPendingWrites ||
198
188
lastDocumentInLimit . version . compareTo ( limboFreeSnapshotVersion ) > 0
199
189
) ;
200
190
}
201
191
202
- executeFullCollectionScan (
192
+ private executeFullCollectionScan (
203
193
transaction : PersistenceTransaction ,
204
194
query : Query
205
195
) : PersistencePromise < DocumentMap > {
0 commit comments