Skip to content

Commit f7bb571

Browse files
committed
WIP: in expansion.
1 parent 58c1677 commit f7bb571

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import com.google.firebase.firestore.core.CompositeFilter;
2020
import com.google.firebase.firestore.core.FieldFilter;
2121
import com.google.firebase.firestore.core.Filter;
22+
import com.google.firebase.firestore.core.InFilter;
23+
import com.google.firestore.v1.ArrayValue;
24+
import com.google.firestore.v1.Value;
25+
2226
import java.util.ArrayList;
2327
import java.util.Arrays;
2428
import java.util.Collections;
@@ -286,6 +290,37 @@ protected static Filter computeDistributedNormalForm(Filter filter) {
286290
return runningResult;
287291
}
288292

293+
/**
294+
* The `in` filter is only a syntactic sugar over a disjunction of equalities. For instance:
295+
* `a in [1,2,3]` is in fact `a==1 || a==2 || a==3`. This method expands any `in` filter in the
296+
* given input into a disjunction of equality filters and returns the expanded filter.
297+
*/
298+
protected static Filter computeInExpansion(Filter filter) {
299+
assertFieldFilterOrCompositeFilter(filter);
300+
301+
List<Filter> expandedFilters = new ArrayList<>();
302+
303+
if(filter instanceof FieldFilter) {
304+
if(filter instanceof InFilter) {
305+
// We have reached a field filter with `in` operator.
306+
for(Value value : ((InFilter) filter).getValue().getArrayValue().getValuesList()) {
307+
expandedFilters.add(FieldFilter.create(((InFilter) filter).getField(), FieldFilter.Operator.EQUAL, value));
308+
}
309+
return new CompositeFilter(expandedFilters, CompositeFilter.Operator.OR);
310+
} else {
311+
// We have reached other kinds of field filters.
312+
return filter;
313+
}
314+
}
315+
316+
// We have a composite filter.
317+
CompositeFilter compositeFilter = (CompositeFilter) filter;
318+
for(Filter subfilter : compositeFilter.getFilters()) {
319+
expandedFilters.add(computeInExpansion(subfilter));
320+
}
321+
return new CompositeFilter(expandedFilters, compositeFilter.getOperator());
322+
}
323+
289324
/**
290325
* Given a composite filter, returns the list of terms in its disjunctive normal form.
291326
*

firebase-firestore/src/test/java/com/google/firebase/firestore/util/LogicUtilsTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.firebase.firestore.util.LogicUtils.applyAssociation;
2222
import static com.google.firebase.firestore.util.LogicUtils.applyDistribution;
2323
import static com.google.firebase.firestore.util.LogicUtils.computeDistributedNormalForm;
24+
import static com.google.firebase.firestore.util.LogicUtils.computeInExpansion;
2425
import static com.google.firebase.firestore.util.LogicUtils.getDnfTerms;
2526
import static org.junit.Assert.assertEquals;
2627

@@ -275,4 +276,39 @@ public void testComputeDnf8() {
275276
assertThat(computeDistributedNormalForm(compositeFilter)).isEqualTo(expectedResult);
276277
assertThat(getDnfTerms(compositeFilter)).isEqualTo(Arrays.asList(expectedDnfTerms));
277278
}
279+
280+
@Test
281+
public void testInExpansionForFieldFilters() {
282+
FieldFilter input1 = filter("a", "in", Arrays.asList(1, 2, 3));
283+
FieldFilter input2 = filter("a", "<", 1);
284+
FieldFilter input3 = filter("a", "<=", 1);
285+
FieldFilter input4 = filter("a", "==", 1);
286+
FieldFilter input5 = filter("a", "!=", 1);
287+
FieldFilter input6 = filter("a", ">", 1);
288+
FieldFilter input7 = filter("a", ">=", 1);
289+
FieldFilter input8 = filter("a", "array-contains", 1);
290+
FieldFilter input9 = filter("a", "array-contains-any", Arrays.asList(1,2));
291+
FieldFilter input10 = filter("a", "not-in", Arrays.asList(1,2));
292+
293+
assertThat(computeInExpansion(input1)).isEqualTo(
294+
orFilters(
295+
filter("a", "==", 1),
296+
filter("a", "==", 2),
297+
filter("a", "==", 3)));
298+
299+
// Other operators should remain the same
300+
assertThat(computeInExpansion(input2)).isEqualTo(input2);
301+
assertThat(computeInExpansion(input3)).isEqualTo(input3);
302+
assertThat(computeInExpansion(input4)).isEqualTo(input4);
303+
assertThat(computeInExpansion(input5)).isEqualTo(input5);
304+
assertThat(computeInExpansion(input6)).isEqualTo(input6);
305+
assertThat(computeInExpansion(input7)).isEqualTo(input7);
306+
assertThat(computeInExpansion(input8)).isEqualTo(input8);
307+
assertThat(computeInExpansion(input9)).isEqualTo(input9);
308+
assertThat(computeInExpansion(input10)).isEqualTo(input10);
309+
}
310+
@Test
311+
public void testInExpansionForCompositeFilters() {
312+
// TODO
313+
}
278314
}

0 commit comments

Comments
 (0)