Skip to content

Commit 5c325fc

Browse files
Comments
1 parent 23b99d0 commit 5c325fc

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/core/Target.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public boolean hasLimit() {
114114
return endAt;
115115
}
116116

117-
/** Returns the list of values that are used in ARRAY_CONTAINS and ARRAY_CONTAINS_ANY filter. */
117+
/** Returns the list of values that are used in ARRAY_CONTAINS or ARRAY_CONTAINS_ANY filters. */
118118
public List<Value> getArrayValues(FieldIndex fieldIndex) {
119119
for (FieldIndex.Segment segment : fieldIndex.getArraySegments()) {
120120
for (Filter filter : filters) {

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,31 +240,38 @@ private SQLitePersistence.Query generateQuery(
240240
String lowerBoundOp,
241241
@Nullable Object[] upperBounds,
242242
String upperBoundOp) {
243+
// The number of total statements we union together. This is similar to a distributed normal
244+
// form, but adapted for array values. We create a single statement per value in an
245+
// ARRAY_CONTAINS or ARRAY_CONTAINS_ANY filter combined with the values from the query bounds.
243246
int statementCount =
244247
max(arrayValues.size(), 1)
245248
* lowerBounds.length
246249
* (upperBounds == null ? 1 : upperBounds.length);
250+
// The number of "question marks" per single statement
247251
int bindsPerStatement = 2 + (arrayValues.isEmpty() ? 0 : 1) + (upperBounds != null ? 1 : 0);
248252
Object[] bindArgs = new Object[statementCount * bindsPerStatement];
249253

254+
// Build the statement. We always include the lower bound, and optionally include an array value
255+
// and an upper bound.
250256
StringBuilder statement = new StringBuilder();
251257
statement.append(
252258
"SELECT document_name, directional_value FROM index_entries WHERE index_id = ? ");
253-
if (!arrayValues.isEmpty()) {
254-
statement.append("AND array_value = ? ");
255-
}
259+
statement.append(arrayValues.isEmpty() ? "AND array_value IS NULL ": "AND array_value = ? ");
256260
statement.append("AND directional_value ").append(lowerBoundOp).append(" ? ");
257261
if (upperBounds != null) {
258262
statement.append("AND directional_value ").append(upperBoundOp).append(" ? ");
259263
}
260264

265+
// Create the UNION statement by repeating the above generated statement. We can then add
266+
// ordering and a limit clause.
261267
String sql = repeatSequence(statement, statementCount, " UNION ");
262268
if (target.getLimit() != -1) {
263269
String direction = target.getFirstOrderBy().getDirection().canonicalString();
264270
sql += "ORDER BY directional_value " + direction + ", document_name " + direction + " ";
265271
sql += "LIMIT " + target.getLimit() + " ";
266272
}
267273

274+
// Fill in the bind ("question marks") variables.
268275
Iterator<Value> arrayValueIterator = arrayValues.iterator();
269276
for (int offset = 0; offset < bindArgs.length; ) {
270277
Object arrayValue = encode(arrayValueIterator.hasNext() ? arrayValueIterator.next() : null);
@@ -282,6 +289,7 @@ private int fillBounds(
282289
@Nullable Object arrayValue,
283290
Object[] lowerBounds,
284291
@Nullable Object[] upperBounds) {
292+
// Add bind variables for each combination of arrayValue, lowerBound and upperBound.
285293
for (Object lower : lowerBounds) {
286294
for (int i = 0; i < (upperBounds != null ? upperBounds.length : 1); ++i) {
287295
bindArgs[offset++] = indexId;

0 commit comments

Comments
 (0)