16
16
17
17
import static com .google .common .truth .Truth .assertThat ;
18
18
import static com .google .firebase .firestore .testutil .TestUtil .addedRemoteEvent ;
19
+ import static com .google .firebase .firestore .testutil .TestUtil .deleteMutation ;
19
20
import static com .google .firebase .firestore .testutil .TestUtil .deletedDoc ;
20
21
import static com .google .firebase .firestore .testutil .TestUtil .doc ;
21
22
import static com .google .firebase .firestore .testutil .TestUtil .fieldIndex ;
35
36
import com .google .firebase .firestore .model .FieldIndex ;
36
37
import java .util .Arrays ;
37
38
import java .util .Collection ;
39
+ import java .util .Collections ;
38
40
import org .junit .Test ;
39
41
import org .junit .runner .RunWith ;
40
42
import org .robolectric .RobolectricTestRunner ;
@@ -141,15 +143,15 @@ public void testDeletedDocumentRemovesIndex() {
141
143
backfillIndexes ();
142
144
143
145
executeQuery (query );
144
- assertRemoteDocumentsRead (/* byKey= */ 1 , /* byQuery = */ 0 );
146
+ assertRemoteDocumentsRead (/* byKey= */ 1 , /* byCollection = */ 0 );
145
147
assertQueryReturned ("coll/a" );
146
148
147
149
applyRemoteEvent (
148
150
updateRemoteEvent (deletedDoc ("coll/a" , 0 ), singletonList (targetId ), emptyList ()));
149
151
150
152
// No backfill needed for deleted document.
151
153
executeQuery (query );
152
- assertRemoteDocumentsRead (/* byKey= */ 0 , /* byQuery = */ 0 );
154
+ assertRemoteDocumentsRead (/* byKey= */ 0 , /* byCollection = */ 0 );
153
155
assertQueryReturned ();
154
156
}
155
157
@@ -168,7 +170,7 @@ public void testUsesIndexes() {
168
170
backfillIndexes ();
169
171
170
172
executeQuery (query );
171
- assertRemoteDocumentsRead (/* byKey= */ 1 , /* byQuery = */ 0 );
173
+ assertRemoteDocumentsRead (/* byKey= */ 1 , /* byCollection = */ 0 );
172
174
assertQueryReturned ("coll/a" );
173
175
}
174
176
@@ -188,7 +190,7 @@ public void testUsesPartiallyIndexedRemoteDocumentsWhenAvailable() {
188
190
applyRemoteEvent (addedRemoteEvent (doc ("coll/b" , 20 , map ("matches" , true )), targetId ));
189
191
190
192
executeQuery (query );
191
- assertRemoteDocumentsRead (/* byKey= */ 1 , /* byQuery = */ 1 );
193
+ assertRemoteDocumentsRead (/* byKey= */ 1 , /* byCollection = */ 1 );
192
194
assertQueryReturned ("coll/a" , "coll/b" );
193
195
}
194
196
@@ -210,6 +212,61 @@ public void testUsesPartiallyIndexedOverlaysWhenAvailable() {
210
212
assertQueryReturned ("coll/a" , "coll/b" );
211
213
}
212
214
215
+ @ Test
216
+ public void testDoesNotUseIndexForLimitQueryWhenIndexIsOutdated () {
217
+ FieldIndex index =
218
+ fieldIndex ("coll" , 0 , FieldIndex .INITIAL_STATE , "count" , FieldIndex .Segment .Kind .ASCENDING );
219
+ configureFieldIndexes (singletonList (index ));
220
+
221
+ Query query = query ("coll" ).orderBy (orderBy ("count" )).limitToFirst (2 );
222
+ int targetId = allocateQuery (query );
223
+
224
+ applyRemoteEvent (
225
+ addedRemoteEvent (
226
+ Arrays .asList (
227
+ doc ("coll/a" , 10 , map ("count" , 1 )),
228
+ doc ("coll/b" , 10 , map ("count" , 2 )),
229
+ doc ("coll/c" , 10 , map ("count" , 3 ))),
230
+ Collections .singletonList (targetId ),
231
+ Collections .emptyList ()));
232
+ backfillIndexes ();
233
+
234
+ writeMutation (deleteMutation ("coll/b" ));
235
+
236
+ executeQuery (query );
237
+ // The query engine first reads the documents by key and then discards the results, which means
238
+ // that we read both by key and by collection.
239
+ assertRemoteDocumentsRead (/* byKey= */ 2 , /* byCollection= */ 3 );
240
+ assertOverlaysRead (/* byKey= */ 2 , /* byCollection= */ 1 );
241
+ assertQueryReturned ("coll/a" , "coll/c" );
242
+ }
243
+
244
+ @ Test
245
+ public void testUsesIndexForLimitQueryWhenIndexIsUpdated () {
246
+ FieldIndex index =
247
+ fieldIndex ("coll" , 0 , FieldIndex .INITIAL_STATE , "count" , FieldIndex .Segment .Kind .ASCENDING );
248
+ configureFieldIndexes (singletonList (index ));
249
+
250
+ Query query = query ("coll" ).orderBy (orderBy ("count" )).limitToFirst (2 );
251
+ int targetId = allocateQuery (query );
252
+
253
+ applyRemoteEvent (
254
+ addedRemoteEvent (
255
+ Arrays .asList (
256
+ doc ("coll/a" , 10 , map ("count" , 1 )),
257
+ doc ("coll/b" , 10 , map ("count" , 2 )),
258
+ doc ("coll/c" , 10 , map ("count" , 3 ))),
259
+ Collections .singletonList (targetId ),
260
+ Collections .emptyList ()));
261
+ writeMutation (deleteMutation ("coll/b" ));
262
+ backfillIndexes ();
263
+
264
+ executeQuery (query );
265
+ assertRemoteDocumentsRead (/* byKey= */ 2 , /* byCollection= */ 0 );
266
+ assertOverlaysRead (/* byKey= */ 2 , /* byCollection= */ 0 );
267
+ assertQueryReturned ("coll/a" , "coll/c" );
268
+ }
269
+
213
270
@ Test
214
271
public void testIndexesServerTimestamps () {
215
272
FieldIndex index =
0 commit comments