diff --git a/appengine/datastore/src/test/java/com/example/appengine/QueriesTest.java b/appengine/datastore/src/test/java/com/example/appengine/QueriesTest.java index 82283b97106..3976103d693 100644 --- a/appengine/datastore/src/test/java/com/example/appengine/QueriesTest.java +++ b/appengine/datastore/src/test/java/com/example/appengine/QueriesTest.java @@ -44,7 +44,6 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -685,24 +684,24 @@ public void queryRestrictions_sortWrongOrderOnInequality_isInvalid() throws Exce public void queryRestrictions_surprisingMultipleValuesAllMustMatch_returnsNoEntities() throws Exception { Entity a = new Entity("Widget", "a"); - ArrayList xs = new ArrayList<>(); - xs.add(1L); - xs.add(2L); + List xs = Arrays.asList(1L, 2L); a.setProperty("x", xs); datastore.put(a); // [START surprising_behavior_example_1] Query q = new Query("Widget") - .setFilter(new FilterPredicate("x", FilterOperator.GREATER_THAN, 1)) - .setFilter(new FilterPredicate("x", FilterOperator.LESS_THAN, 2)); + .setFilter( + CompositeFilterOperator.and( + new FilterPredicate("x", FilterOperator.GREATER_THAN, 1), + new FilterPredicate("x", FilterOperator.LESS_THAN, 2))); // [END surprising_behavior_example_1] - // Note: The documentation describes that the entity "a" will not match - // because no value matches all filters. When run with the local test - // runner, the entity "a" *is* matched. This may be a difference in - // behavior between the local devserver and Cloud Datastore, so there - // aren't any assertions we can make in this test. + // Entity "a" will not match because no individual value matches all filters. + // See the documentation for more details: + // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways + List results = datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()); + assertThat(results).named("query results").isEmpty(); } @Test @@ -716,21 +715,24 @@ public void queryRestrictions_surprisingMultipleValuesEquals_returnsMatchedEntit c.setProperty("x", ImmutableList.of(-6L, 2L)); Entity d = new Entity("Widget", "d"); d.setProperty("x", ImmutableList.of(-6L, 4L)); - datastore.put(ImmutableList.of(a, b, c, d)); + Entity e = new Entity("Widget", "e"); + e.setProperty("x", ImmutableList.of(1L, 2L, 3L)); + datastore.put(ImmutableList.of(a, b, c, d, e)); // [START surprising_behavior_example_2] Query q = new Query("Widget") - .setFilter(new FilterPredicate("x", FilterOperator.EQUAL, 1)) - .setFilter(new FilterPredicate("x", FilterOperator.EQUAL, 2)); + .setFilter( + CompositeFilterOperator.and( + new FilterPredicate("x", FilterOperator.EQUAL, 1), + new FilterPredicate("x", FilterOperator.EQUAL, 2))); // [END surprising_behavior_example_2] + // Only "a" and "e" have both 1 and 2 in the "x" array-valued property. + // See the documentation for more details: + // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways List results = datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()); - assertThat(getKeys(results)).named("query result keys").contains(a.getKey()); - - // Note: When run in the test server, this matches "c" as expected and does - // not match "d" as expected. For some reason it does *not* match "b". - // The behavior of queries on repeated values is definitely surprising. + assertThat(getKeys(results)).named("query result keys").containsExactly(a.getKey(), e.getKey()); } @Test @@ -752,6 +754,9 @@ public void queryRestrictions_surprisingMultipleValuesNotEquals_returnsMatchedEn Query q = new Query("Widget").setFilter(new FilterPredicate("x", FilterOperator.NOT_EQUAL, 1)); // [END surprising_behavior_example_3] + // The query matches any entity that has a some value other than 1. Only + // entity "e" is not matched. See the documentation for more details: + // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways List results = datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()); assertThat(getKeys(results)) .named("query result keys") @@ -770,17 +775,21 @@ public void queryRestrictions_surprisingMultipleValuesTwoNotEquals_returnsMatche // [START surprising_behavior_example_4] Query q = new Query("Widget") - .setFilter(new FilterPredicate("x", FilterOperator.NOT_EQUAL, 1)) - .setFilter(new FilterPredicate("x", FilterOperator.NOT_EQUAL, 2)); + .setFilter( + CompositeFilterOperator.and( + new FilterPredicate("x", FilterOperator.NOT_EQUAL, 1), + new FilterPredicate("x", FilterOperator.NOT_EQUAL, 2))); // [END surprising_behavior_example_4] + // The two NOT_EQUAL filters in the query become like the combination of queries: + // x < 1 OR (x > 1 AND x < 2) OR x > 2 + // + // Only "b" has some value which matches the "x > 2" portion of this query. + // + // See the documentation for more details: + // https://cloud.google.com/appengine/docs/java/datastore/query-restrictions#properties_with_multiple_values_can_behave_in_surprising_ways List results = datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()); - assertThat(getKeys(results)).named("query result keys").contains(b.getKey()); - - // Note: The documentation describes that the entity "a" will not match. - // When run with the local test runner, the entity "a" *is* matched. This - // may be a difference in behavior between the local devserver and Cloud - // Datastore. + assertThat(getKeys(results)).named("query result keys").containsExactly(b.getKey()); } private Entity retrievePersonWithLastName(String targetLastName) {