Skip to content

Commit d65a6e0

Browse files
committed
Address comments.
1 parent c829fe1 commit d65a6e0

File tree

6 files changed

+51
-50
lines changed

6 files changed

+51
-50
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/local/IndexBackfiller.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@
2020
import androidx.annotation.VisibleForTesting;
2121
import com.google.firebase.firestore.model.Document;
2222
import com.google.firebase.firestore.model.DocumentKey;
23-
import com.google.firebase.firestore.model.FieldIndex;
2423
import com.google.firebase.firestore.model.FieldIndex.IndexOffset;
2524
import com.google.firebase.firestore.util.AsyncQueue;
2625
import com.google.firebase.firestore.util.Logger;
27-
import java.util.Collection;
2826
import java.util.HashSet;
2927
import java.util.Map;
3028
import java.util.Set;
@@ -131,9 +129,7 @@ private int writeIndexEntries() {
131129
private int writeEntriesForCollectionGroup(
132130
String collectionGroup, int documentsRemainingUnderCap) {
133131
// Use the earliest offset of all field indexes to query the local cache.
134-
Collection<FieldIndex> fieldIndexes = indexManager.getFieldIndexes(collectionGroup);
135-
hardAssert(!fieldIndexes.isEmpty(), "Updating collection without indexes");
136-
IndexOffset existingOffset = indexManager.getLeastRecentIndexOffset(fieldIndexes);
132+
IndexOffset existingOffset = indexManager.minOffset(collectionGroup);
137133

138134
LocalDocumentsResult nextBatch =
139135
localDocumentsView.getNextDocuments(

firebase-firestore/src/main/java/com/google/firebase/firestore/local/IndexManager.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.firebase.firestore.model.Document;
2121
import com.google.firebase.firestore.model.DocumentKey;
2222
import com.google.firebase.firestore.model.FieldIndex;
23+
import com.google.firebase.firestore.model.FieldIndex.IndexOffset;
2324
import com.google.firebase.firestore.model.ResourcePath;
2425
import java.util.Collection;
2526
import java.util.List;
@@ -74,17 +75,17 @@ public interface IndexManager {
7475
/** Returns all configured field indexes. */
7576
Collection<FieldIndex> getFieldIndexes();
7677

77-
/** Returns whether we can serve the given target from the index. */
78+
/** Returns whether we can serve the given target from an index. */
7879
boolean canServeFromIndex(Target target);
7980

8081
/**
8182
* Iterates over all field indexes that are used to serve the given target, and returns the least
8283
* recent offset of them all. Asserts that the target can be served from index.
8384
*/
84-
FieldIndex.IndexOffset getLeastRecentIndexOffset(Target target);
85+
IndexOffset minOffset(Target target);
8586

86-
/** Returns the lowest offset for the provided index group. */
87-
FieldIndex.IndexOffset getLeastRecentIndexOffset(Collection<FieldIndex> fieldIndexes);
87+
/** Returns the lowest offset for the given collection group. */
88+
IndexOffset minOffset(String collectionGroup);
8889

8990
/**
9091
* Returns an index that can be used to serve the provided target. Returns {@code null} if no

firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryIndexManager.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.firebase.firestore.model.Document;
2222
import com.google.firebase.firestore.model.DocumentKey;
2323
import com.google.firebase.firestore.model.FieldIndex;
24+
import com.google.firebase.firestore.model.FieldIndex.IndexOffset;
2425
import com.google.firebase.firestore.model.ResourcePath;
2526
import java.util.ArrayList;
2627
import java.util.Collection;
@@ -82,7 +83,7 @@ public String getNextCollectionGroupToUpdate() {
8283
}
8384

8485
@Override
85-
public void updateCollectionGroup(String collectionGroup, FieldIndex.IndexOffset offset) {
86+
public void updateCollectionGroup(String collectionGroup, IndexOffset offset) {
8687
// Field indices are not supported with memory persistence.
8788
}
8889

@@ -104,13 +105,13 @@ public boolean canServeFromIndex(Target target) {
104105
}
105106

106107
@Override
107-
public FieldIndex.IndexOffset getLeastRecentIndexOffset(Target target) {
108-
return FieldIndex.IndexOffset.NONE;
108+
public IndexOffset minOffset(Target target) {
109+
return IndexOffset.NONE;
109110
}
110111

111112
@Override
112-
public FieldIndex.IndexOffset getLeastRecentIndexOffset(Collection<FieldIndex> fieldIndexes) {
113-
return FieldIndex.IndexOffset.NONE;
113+
public IndexOffset minOffset(String collectionGroup) {
114+
return IndexOffset.NONE;
114115
}
115116

116117
@Override

firebase-firestore/src/main/java/com/google/firebase/firestore/local/QueryEngine.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
118118
ImmutableSortedMap<DocumentKey, Document> indexedDocuments =
119119
localDocumentsView.getDocuments(keys);
120120

121-
return appendRemainingResults(
122-
values(indexedDocuments), query, indexManager.getLeastRecentIndexOffset(target));
121+
return appendRemainingResults(values(indexedDocuments), query, indexManager.minOffset(target));
123122
}
124123

125124
/**
@@ -238,11 +237,7 @@ private ImmutableSortedMap<DocumentKey, Document> appendRemainingResults(
238237
ImmutableSortedMap<DocumentKey, Document> remainingResults =
239238
localDocumentsView.getDocumentsMatchingQuery(query, offset);
240239
for (Document entry : indexedResults) {
241-
// For OR queries, it is possible that a document that's been indexed also shows up in
242-
// "remaining results" since we use the least recent IndexOffset of all DNF terms.
243-
if (!remainingResults.containsKey(entry.getKey())) {
244-
remainingResults = remainingResults.insert(entry.getKey(), entry);
245-
}
240+
remainingResults = remainingResults.insert(entry.getKey(), entry);
246241
}
247242
return remainingResults;
248243
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteIndexManager.java

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import android.text.TextUtils;
2525
import androidx.annotation.Nullable;
26-
import com.google.common.collect.ObjectArrays;
2726
import com.google.firebase.Timestamp;
2827
import com.google.firebase.database.collection.ImmutableSortedMap;
2928
import com.google.firebase.firestore.auth.User;
@@ -39,6 +38,7 @@
3938
import com.google.firebase.firestore.model.Document;
4039
import com.google.firebase.firestore.model.DocumentKey;
4140
import com.google.firebase.firestore.model.FieldIndex;
41+
import com.google.firebase.firestore.model.FieldIndex.IndexOffset;
4242
import com.google.firebase.firestore.model.FieldPath;
4343
import com.google.firebase.firestore.model.ResourcePath;
4444
import com.google.firebase.firestore.model.SnapshotVersion;
@@ -76,6 +76,7 @@ final class SQLiteIndexManager implements IndexManager {
7676
* Maps from a target to its equivalent list of sub-targets. Each sub-target contains only one
7777
* term from the target's disjunctive normal form (DNF).
7878
*/
79+
// TODO(orquery): Find a way for the GC algorithm to remove the mapping once we remove a target.
7980
private final Map<Target, List<Target>> targetToDnfSubTargets = new HashMap<>();
8081

8182
/**
@@ -296,29 +297,34 @@ public boolean canServeFromIndex(Target target) {
296297
return true;
297298
}
298299

299-
@Override
300-
public FieldIndex.IndexOffset getLeastRecentIndexOffset(Collection<FieldIndex> fieldIndexes) {
300+
private IndexOffset getLeastRecentIndexOffset(Collection<FieldIndex> fieldIndexes) {
301301
hardAssert(
302302
!fieldIndexes.isEmpty(),
303303
"Found empty index group when looking for least recent index offset.");
304304

305305
Iterator<FieldIndex> it = fieldIndexes.iterator();
306-
FieldIndex.IndexOffset minOffset = it.next().getIndexState().getOffset();
306+
IndexOffset minOffset = it.next().getIndexState().getOffset();
307307
int minBatchId = minOffset.getLargestBatchId();
308308
while (it.hasNext()) {
309-
FieldIndex.IndexOffset newOffset = it.next().getIndexState().getOffset();
309+
IndexOffset newOffset = it.next().getIndexState().getOffset();
310310
if (newOffset.compareTo(minOffset) < 0) {
311311
minOffset = newOffset;
312312
}
313313
minBatchId = Math.max(newOffset.getLargestBatchId(), minBatchId);
314314
}
315315

316-
return FieldIndex.IndexOffset.create(
317-
minOffset.getReadTime(), minOffset.getDocumentKey(), minBatchId);
316+
return IndexOffset.create(minOffset.getReadTime(), minOffset.getDocumentKey(), minBatchId);
317+
}
318+
319+
@Override
320+
public IndexOffset minOffset(String collectionGroup) {
321+
Collection<FieldIndex> fieldIndexes = getFieldIndexes(collectionGroup);
322+
hardAssert(!fieldIndexes.isEmpty(), "minOffset was called for collection without indexes");
323+
return getLeastRecentIndexOffset(fieldIndexes);
318324
}
319325

320326
@Override
321-
public FieldIndex.IndexOffset getLeastRecentIndexOffset(Target target) {
327+
public IndexOffset minOffset(Target target) {
322328
hardAssert(
323329
canServeFromIndex(target),
324330
"Cannot find least recent index offset if target cannot be served from index.");
@@ -494,14 +500,19 @@ public Set<DocumentKey> getDocumentsMatchingTarget(Target target) {
494500
bindings.addAll(Arrays.asList(subQueryAndBindings).subList(1, subQueryAndBindings.length));
495501
}
496502

497-
String queryString =
498-
subQueries.size() == 1
499-
?
500-
// If there's only one subQuery, just execute the one subQuery.
501-
subQueries.get(0)
502-
:
503-
// Construct "subQuery1 UNION subQuery2 UNION ... LIMIT N"
504-
TextUtils.join(" UNION ", subQueries) + " LIMIT " + target.getLimit();
503+
String queryString;
504+
if (subQueries.size() == 1) {
505+
// If there's only one subQuery, just execute the one subQuery.
506+
queryString = subQueries.get(0);
507+
} else {
508+
// Construct "SELECT * FROM (subQuery1 UNION subQuery2 UNION ...) LIMIT N"
509+
queryString = "SELECT * FROM (" + TextUtils.join(" UNION ", subQueries) + ")";
510+
if (target.getLimit() != -1) {
511+
queryString = queryString + " LIMIT " + target.getLimit();
512+
}
513+
}
514+
515+
hardAssert(bindings.size() < 1000, "Cannot perform query with more than 999 bind elements");
505516

506517
SQLitePersistence.Query query = db.query(queryString).binding(bindings.toArray());
507518

@@ -569,7 +580,11 @@ private Object[] generateQueryAndBindings(
569580
// Fill in the bind ("question marks") variables.
570581
Object[] bindArgs =
571582
fillBounds(statementCount, indexId, arrayValues, lowerBounds, upperBounds, notIn);
572-
return ObjectArrays.concat(sql.toString(), bindArgs);
583+
584+
List<Object> result = new ArrayList<Object>();
585+
result.add(sql.toString());
586+
result.addAll(Arrays.asList(bindArgs));
587+
return result.toArray();
573588
}
574589

575590
/** Returns the bind arguments for all {@code statementCount} statements. */
@@ -758,7 +773,7 @@ private byte[] encodeSegments(FieldIndex fieldIndex) {
758773
}
759774

760775
@Override
761-
public void updateCollectionGroup(String collectionGroup, FieldIndex.IndexOffset offset) {
776+
public void updateCollectionGroup(String collectionGroup, IndexOffset offset) {
762777
hardAssert(started, "IndexManager not started");
763778

764779
++memoizedMaxSequenceNumber;

firebase-firestore/src/main/java/com/google/firebase/firestore/util/LogicUtils.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,10 @@ public class LogicUtils {
2727
/**
2828
* Given a composite filter, returns the list of terms in its disjunctive normal form.
2929
*
30-
* <p>Each element in the return value is one term of the resulting DNF.
31-
*
32-
* <p>For instance, for the input: (A || B) && C
33-
*
34-
* <p>The DNF form is: (A && C) || (B && C)
35-
*
36-
* <p>The return value is a list with two elements:
37-
*
38-
* <p>The first element is a composite filter that performs (A && C).
39-
*
40-
* <p>The second element is a composite filter that performs (B && C).
30+
* <p>Each element in the return value is one term of the resulting DNF. For instance: For the
31+
* input: (A || B) && C, the DNF form is: (A && C) || (B && C), and the return value is a list
32+
* with two elements: a composite filter that performs (A && C), and a composite filter that
33+
* performs (B && C).
4134
*
4235
* @param filter the composite filter to calculate DNF transform for.
4336
* @return the terms in the DNF transform.

0 commit comments

Comments
 (0)