Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IN and ARRAY_CONTAINS_ANY (not publicly exposed) #519

Merged
merged 18 commits into from
Jun 20, 2019
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -509,26 +509,34 @@ public void testQueriesAreValidatedOnClient() {
// NOTE: Failure cases are validated in ValidationTest.
CollectionReference collection = testCollection();
final Query query = collection.whereGreaterThanOrEqualTo("x", 32);
// Same inequality field works;
// Same inequality field works.
query.whereLessThanOrEqualTo("x", "cat");
// Equality on different field works;
// Equality on different field works.
query.whereEqualTo("y", "cat");
// Array contains on different field works;
// Array contains on different field works.
query.whereArrayContains("y", "cat");
// Array contains any on different field works.
query.whereArrayContainsAny("y", Arrays.asList("cat"));
// In on different field works.
query.whereIn("y", Arrays.asList("cat"));

// Ordering by inequality field succeeds.
query.orderBy("x");
collection.orderBy("x").whereGreaterThanOrEqualTo("x", 32);

// inequality same as first order by works
// Inequality same as first order by works.
query.orderBy("x").orderBy("y");
collection.orderBy("x").orderBy("y").whereGreaterThanOrEqualTo("x", 32);
collection.orderBy("x", Direction.DESCENDING).whereEqualTo("y", "true");

// Equality different than orderBy works
// Equality different than orderBy works.
collection.orderBy("x").whereEqualTo("y", "cat");
// Array contains different than orderBy works
// Array contains different than orderBy works.
collection.orderBy("x").whereArrayContains("y", "cat");
// Array contains any different than orderBy works.
collection.orderBy("x").whereArrayContainsAny("y", Arrays.asList("cat"));
// In different than orderBy works.
collection.orderBy("x").whereIn("y", Arrays.asList("cat"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.Map;
import java.util.concurrent.Semaphore;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand Down Expand Up @@ -427,6 +428,55 @@ public void testQueriesCanUseArrayContainsFilters() {
// much of anything else interesting to test.
}

// TODO(in-queries): Re-enable once emulator support is added to travis.
@Test
@Ignore
public void testQueriesCanUseInFilters() {
thebrianchen marked this conversation as resolved.
Show resolved Hide resolved
Map<String, Object> docA = map("zip", 98101);
Map<String, Object> docB = map("zip", 91102);
Map<String, Object> docC = map("zip", 98103);
Map<String, Object> docD = map("zip", asList(98101));
Map<String, Object> docE = map("zip", asList("98101", map("zip", 98101)));
Map<String, Object> docF = map("zip", map("code", 500));
CollectionReference collection =
testCollectionWithDocs(
map("a", docA, "b", docB, "c", docC, "d", docD, "e", docE, "f", docF));

// Search for zips matching [98101, 98103].
QuerySnapshot snapshot = waitFor(collection.whereIn("zip", asList(98101, 98103)).get());
assertEquals(asList(docA, docC), querySnapshotToValues(snapshot));

// With objects.
snapshot = waitFor(collection.whereIn("zip", asList(map("code", 500))).get());
assertEquals(asList(docF), querySnapshotToValues(snapshot));
}

// TODO(in-queries): Re-enable once emulator support is added to travis.
@Test
@Ignore
public void testQueriesCanUseArrayContainsAnyFilters() {
Map<String, Object> docA = map("array", asList(42L));
Map<String, Object> docB = map("array", asList("a", 42L, "c"));
Map<String, Object> docC = map("array", asList(41.999, "42", map("a", asList(42))));
Map<String, Object> docD = map("array", asList(42L), "array2", asList("bingo"));
Map<String, Object> docE = map("array", asList(43L));
Map<String, Object> docF = map("array", asList(map("a", 42L)));
Map<String, Object> docG = map("array", 42L);

CollectionReference collection =
testCollectionWithDocs(
map("a", docA, "b", docB, "c", docC, "d", docD, "e", docE, "f", docF));

// Search for "array" to contain [42, 43].
QuerySnapshot snapshot =
waitFor(collection.whereArrayContainsAny("array", asList(42L, 43L)).get());
assertEquals(asList(docA, docB, docD, docE), querySnapshotToValues(snapshot));

// With objects.
snapshot = waitFor(collection.whereArrayContainsAny("array", asList(map("a", 42L))).get());
assertEquals(asList(docF), querySnapshotToValues(snapshot));
}

@Test
public void testCollectionGroupQueries() {
FirebaseFirestore db = testFirestore();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,12 @@ public void queriesWithNullOrNaNFiltersOtherThanEqualityFail() {
expectError(
() -> collection.whereArrayContains("a", null),
"Invalid Query. You can only perform equality comparisons on null (via whereEqualTo()).");
expectError(
() -> collection.whereArrayContainsAny("a", null),
"Invalid Query. A non-empty array is required for 'array_contains_any' filters.");
expectError(
() -> collection.whereIn("a", null),
"Invalid Query. A non-empty array is required for 'in' filters.");
thebrianchen marked this conversation as resolved.
Show resolved Hide resolved

expectError(
() -> collection.whereGreaterThan("a", Double.NaN),
Expand Down Expand Up @@ -535,10 +541,129 @@ public void queriesWithInequalityDifferentThanFirstOrderByFail() {
}

@Test
public void queriesWithMultipleArrayContainsFiltersFail() {
public void queriesWithMultipleArrayFiltersFail() {
expectError(
() -> testCollection().whereArrayContains("foo", 1).whereArrayContains("foo", 2),
"Invalid Query. Queries only support having a single array-contains filter.");
"Invalid Query. You cannot use more than one 'array_contains' filter.");

expectError(
() ->
testCollection()
.whereArrayContains("foo", 1)
.whereArrayContainsAny("foo", asList(1, 2)),
"Invalid Query. You cannot use 'array_contains_any' filters with 'array_contains' filters.");

expectError(
() ->
testCollection()
.whereArrayContainsAny("foo", asList(1, 2))
.whereArrayContains("foo", 1),
"Invalid Query. You cannot use 'array_contains' filters with 'array_contains_any' filters.");
}

@Test
public void queriesWithMultipleDisjunctiveFiltersFail() {
thebrianchen marked this conversation as resolved.
Show resolved Hide resolved
expectError(
() -> testCollection().whereIn("foo", asList(1, 2)).whereIn("bar", asList(1, 2)),
"Invalid Query. You cannot use more than one 'in' filter.");

expectError(
() ->
testCollection()
.whereArrayContainsAny("foo", asList(1, 2))
.whereArrayContainsAny("bar", asList(1, 2)),
"Invalid Query. You cannot use more than one 'array_contains_any' filter.");

expectError(
() ->
testCollection()
.whereArrayContainsAny("foo", asList(1, 2))
.whereIn("bar", asList(1, 2)),
"Invalid Query. You cannot use 'in' filters with 'array_contains_any' filters.");

expectError(
() ->
testCollection()
.whereIn("bar", asList(1, 2))
.whereArrayContainsAny("foo", asList(1, 2)),
"Invalid Query. You cannot use 'array_contains_any' filters with 'in' filters.");

// This is redundant with the above tests, but makes sure our validation doesn't get confused.
expectError(
() ->
testCollection()
.whereIn("bar", asList(1, 2))
.whereArrayContains("foo", 1)
.whereArrayContainsAny("foo", asList(1, 2)),
"Invalid Query. You cannot use 'array_contains_any' filters with 'in' filters.");

expectError(
() ->
testCollection()
.whereArrayContains("foo", 1)
.whereIn("bar", asList(1, 2))
.whereArrayContainsAny("foo", asList(1, 2)),
"Invalid Query. You cannot use 'array_contains_any' filters with 'in' filters.");
}

@Test
public void queriesCanUseInWithArrayContains() {
testCollection().whereArrayContains("foo", 1).whereIn("bar", asList(1, 2));
testCollection().whereIn("bar", asList(1, 2)).whereArrayContains("foo", 1);

expectError(
() ->
testCollection()
.whereIn("bar", asList(1, 2))
.whereArrayContains("foo", 1)
.whereArrayContains("foo", 1),
"Invalid Query. You cannot use more than one 'array_contains' filter.");

expectError(
() ->
testCollection()
.whereArrayContains("foo", 1)
.whereIn("bar", asList(1, 2))
.whereIn("bar", asList(1, 2)),
"Invalid Query. You cannot use more than one 'in' filter.");
}

@Test
public void queriesInAndArrayContainsAnyArrayRules() {
expectError(
() -> testCollection().whereIn("bar", asList()),
"Invalid Query. A non-empty array is required for 'in' filters.");

expectError(
() -> testCollection().whereArrayContainsAny("bar", asList()),
"Invalid Query. A non-empty array is required for 'array_contains_any' filters.");

expectError(
// The 10 element max includes duplicates.
() -> testCollection().whereIn("bar", asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9)),
"Invalid Query. 'in' filters support a maximum of 10 elements in the value array.");

expectError(
// The 10 element max includes duplicates.
() ->
testCollection().whereArrayContainsAny("bar", asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9)),
"Invalid Query. 'array_contains_any' filters support a maximum of 10 elements in the value array.");

expectError(
() -> testCollection().whereIn("bar", asList("foo", null)),
"Invalid Query. 'in' filters cannot contain 'null' in the value array.");

expectError(
() -> testCollection().whereArrayContainsAny("bar", asList("foo", null)),
"Invalid Query. 'array_contains_any' filters cannot contain 'null' in the value array.");

expectError(
() -> testCollection().whereIn("bar", asList("foo", Double.NaN)),
"Invalid Query. 'in' filters cannot contain 'NaN' in the value array.");

expectError(
() -> testCollection().whereArrayContainsAny("bar", asList("foo", Float.NaN)),
"Invalid Query. 'array_contains_any' filters cannot contain 'NaN' in the value array.");
}

@Test
Expand Down Expand Up @@ -576,6 +701,11 @@ public void queriesFilteredByDocumentIDMustUseStringsOrDocumentReferences() {
+ "a valid String or DocumentReference, but it was of type: java.lang.Integer";
expectError(() -> collection.whereGreaterThanOrEqualTo(FieldPath.documentId(), 1), reason);

reason =
"Invalid query. When querying with FieldPath.documentId() you must provide "
+ "a valid String or DocumentReference, but it was of type: java.util.Arrays$ArrayList";
expectError(() -> collection.whereIn(FieldPath.documentId(), asList(1, 2)), reason);

reason =
"Invalid query. When querying a collection group by FieldPath.documentId(), the value "
+ "provided must result in a valid document path, but 'foo' is not because it has "
Expand All @@ -587,10 +717,13 @@ public void queriesFilteredByDocumentIDMustUseStringsOrDocumentReferences() {
.whereGreaterThanOrEqualTo(FieldPath.documentId(), "foo"),
reason);

reason =
"Invalid query. You can't perform array-contains queries on FieldPath.documentId() since "
+ "document IDs are not arrays.";
reason = "Invalid query. You can't perform 'array_contains' queries on FieldPath.documentId().";
expectError(() -> collection.whereArrayContains(FieldPath.documentId(), 1), reason);

reason =
"Invalid query. You can't perform 'array_contains_any' queries on FieldPath.documentId().";
expectError(
() -> collection.whereArrayContainsAny(FieldPath.documentId(), asList(1, 2)), reason);
}

// Helpers
Expand Down
Loading