Package com.google.appengine.tck.datastore

Source Code of com.google.appengine.tck.datastore.QueryOptimizationsTest

/*
* Copyright 2013 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.appengine.tck.datastore;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.PropertyProjection;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.RawValue;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import static com.google.appengine.api.datastore.Query.FilterOperator.GREATER_THAN;
import static com.google.appengine.api.datastore.Query.FilterOperator.IN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

/**
* Datastore querying optimizations tests.
*
* @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
* @author <a href="mailto:marko.luksa@gmail.com">Marko Luksa</a>
*/
@RunWith(Arquillian.class)
public class QueryOptimizationsTest extends QueryTestBase {

    @Test
    public void testKeysOnly() throws Exception {
        Entity parent = createTestEntityWithUniqueMethodNameKey("Person", "testKeysOnly");
        Key key = parent.getKey();

        Entity john = createEntity("Person", key)
            .withProperty("name", "John")
            .withProperty("surname", "Doe")
            .store();

        Query query = new Query("Person")
            .setAncestor(key)
            .setKeysOnly();

        PreparedQuery preparedQuery = service.prepare(query);

        Entity entity = preparedQuery.asSingleEntity();
        assertEquals(john.getKey(), entity.getKey());
        assertNull(entity.getProperty("name"));
        assertNull(entity.getProperty("surname"));
    }

    @Test
    public void testProjections() throws Exception {
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", "testProjections");
        Key key = parent.getKey();

        Entity e = createEntity("Product", key)
            .withProperty("price", 123L)
            .withProperty("percent", 0.123)
            .withProperty("x", -0.321)
            .withProperty("diff", -5L)
            .withProperty("weight", 10L)
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("price", Long.class))
            .addProjection(new PropertyProjection("percent", Double.class))
            .addProjection(new PropertyProjection("x", Double.class))
            .addProjection(new PropertyProjection("diff", Long.class));

        PreparedQuery preparedQuery = service.prepare(query);
        Entity result = preparedQuery.asSingleEntity();
        assertEquals(e.getKey(), result.getKey());
        assertEquals(e.getProperty("price"), result.getProperty("price"));
        assertEquals(e.getProperty("percent"), result.getProperty("percent"));
        assertEquals(e.getProperty("x"), result.getProperty("x"));
        assertEquals(e.getProperty("diff"), result.getProperty("diff"));
        assertNull(result.getProperty("weight"));
    }

    @Test
    public void testProjectionQueryOnlyReturnsEntitiesContainingProjectedProperty() throws Exception {
        String methodName = "testProjectionQueryOnlyReturnsEntitiesContainingProjectedProperty";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Kind", methodName);
        Key key = parent.getKey();

        Entity e1 = createEntity("Kind", key)
            .withProperty("foo", "foo")
            .store();

        Entity e2 = createEntity("Kind", key)
            .withProperty("bar", "bar")
            .store();

        Query query = new Query("Kind")
            .setAncestor(key)
            .addProjection(new PropertyProjection("foo", String.class));

        List<Entity> results = service.prepare(query).asList(withDefaults());
        assertEquals(Collections.singletonList(e1), results);
    }

    @Test
    public void testProjectionQueryReturnsEntitiesContainingProjectedPropertyEvenIfPropertyValueIsNull() throws Exception {
        String methodName = "testProjectionQueryOnlyReturnsEntitiesContainingProjectedPropertyEvenIfPropertyValueIsNull";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Kind", methodName);
        Key key = parent.getKey();

        Entity e1 = createEntity("Kind", key)
            .withProperty("foo", null)
            .store();

        Query query = new Query("Kind")
            .setAncestor(key)
            .addProjection(new PropertyProjection("foo", String.class));

        List<Entity> results = service.prepare(query).asList(withDefaults());
        assertEquals(Collections.singletonList(e1), results);
    }

    @Test
    public void testProjectionQueryOnlyReturnsEntitiesContainingAllProjectedProperties() throws Exception {
        String methodName = "testProjectionQueryOnlyReturnsEntitiesContainingAllProjectedProperties";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Kind", methodName);
        Key key = parent.getKey();

        Entity e1 = createEntity("Kind", key)
            .withProperty("foo", "foo")
            .withProperty("bar", "bar")
            .store();

        Entity e2 = createEntity("Kind", key)
            .withProperty("foo", "foo")
            .store();

        Entity e3 = createEntity("Kind", key)
            .withProperty("bar", "bar")
            .store();

        Entity e4 = createEntity("Kind", key)
            .withProperty("baz", "baz")
            .store();

        Query query = new Query("Kind")
            .setAncestor(key)
            .addProjection(new PropertyProjection("foo", String.class))
            .addProjection(new PropertyProjection("bar", String.class));

        List<Entity> results = service.prepare(query).asList(withDefaults());
        assertEquals(Collections.singletonList(e1), results);
    }

    @Test
    public void testProjectionsWithoutType() throws Exception {
        String methodName = "testProjectionsWithoutType";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity e = createEntity("Product", key)
            .withProperty("long", 123L)
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("long", null));

        PreparedQuery preparedQuery = service.prepare(query);
        Entity result = preparedQuery.asSingleEntity();
        assertEquals(e.getKey(), result.getKey());

        RawValue rawValue = (RawValue) result.getProperty("long");
        assertEquals(Long.valueOf(123L), rawValue.asType(Long.class));
        assertEquals(Long.valueOf(123L), rawValue.asStrictType(Long.class));
    }

    @Test
    public void testProjectionOfCollectionProperties() throws Exception {
        String methodName = "testProjectionOfCollectionProperties";
        String entityKind = "test-proj";
        Entity parent = createTestEntityWithUniqueMethodNameKey(entityKind, methodName);
        Key key = parent.getKey();

        Entity e = createEntity(entityKind, key)
            .withProperty("prop", Arrays.asList("bbb", "ccc", "aaa"))
            .store();

        Query query = new Query(entityKind)
            .setAncestor(key)
            .addProjection(new PropertyProjection("prop", String.class))
            .addSort("prop");

        PreparedQuery preparedQuery = service.prepare(query);
        List<Entity> results = preparedQuery.asList(withDefaults());
        assertEquals(3, results.size());

        Entity firstResult = results.get(0);
        Entity secondResult = results.get(1);
        Entity thirdResult = results.get(2);

        assertEquals(e.getKey(), firstResult.getKey());
        assertEquals(e.getKey(), secondResult.getKey());
        assertEquals(e.getKey(), thirdResult.getKey());
        assertEquals("aaa", firstResult.getProperty("prop"));
        assertEquals("bbb", secondResult.getProperty("prop"));
        assertEquals("ccc", thirdResult.getProperty("prop"));
    }

    @Test
    public void testProjectionOfCollectionPropertyWithFilterOnCollectionProperty() throws Exception {
        String methodName = "testProjectionOfCollectionPropertyWithFilterOnCollectionProperty";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity e = createEntity("Product", key)
            .withProperty("name", Arrays.asList("aaa", "bbb"))
            .withProperty("price", Arrays.asList(10L, 20L))
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("name", String.class))
            .setFilter(new Query.FilterPredicate("price", GREATER_THAN, 0L))
            .addSort("price")
            .addSort("name");

        PreparedQuery preparedQuery = service.prepare(query);
        List<Entity> results = preparedQuery.asList(withDefaults());
        assertEquals(4, results.size());

        assertEquals(e.getKey(), results.get(0).getKey());
        assertEquals(e.getKey(), results.get(1).getKey());
        assertEquals(e.getKey(), results.get(2).getKey());
        assertEquals(e.getKey(), results.get(3).getKey());

        assertEquals("aaa", results.get(0).getProperty("name"));
        assertEquals("bbb", results.get(1).getProperty("name"));
        assertEquals("aaa", results.get(2).getProperty("name"));
        assertEquals("bbb", results.get(3).getProperty("name"));
    }

    @Test
    public void testProjectionQueriesHandleEntityModificationProperly() throws Exception {
        String methodName = "testProjectionAfterRemove";
        Entity parent = createTestEntityWithUniqueMethodNameKey("test", methodName);
        Key key = parent.getKey();

        Entity e = createEntity("test", key)
            .withProperty("prop", Arrays.asList("aaa", "bbb", "ccc"))
            .store();

        Query query = new Query("test")
            .setAncestor(key)
            .addProjection(new PropertyProjection("prop", String.class))
            .addSort("prop");

        assertEquals(3, service.prepare(query).asList(withDefaults()).size());

        e = createEntity(e.getKey())
            .withProperty("prop", Arrays.asList("aaa", "bbb"))
            .store();

        assertEquals(2, service.prepare(query).asList(withDefaults()).size());

        service.delete(e.getKey());

        assertEquals(0, service.prepare(query).asList(withDefaults()).size());
    }

    @Ignore("According to the docs, ordering of query results is undefined when no sort order is specified. They are " +
        "currently ordered according to the index, but this may change in the future and so it shouldn't be tested by the TCK.")
    @Test
    public void testProjectionQueryDefaultSortOrderIsDefinedByIndexDefinition() throws Exception {
        String methodName = "testProjectionQueryDefaultSortOrderIsDefinedByIndexDefinition";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity b1 = createEntity("Product", key)
            .withProperty("name", "b")
            .withProperty("price", 1L)
            .withProperty("group", "x")
            .store();

        Entity c2 = createEntity("Product", key)
            .withProperty("name", "c")
            .withProperty("price", 2L)
            .withProperty("group", "y")
            .store();

        Entity c1 = createEntity("Product", key)
            .withProperty("name", "c")
            .withProperty("price", 1L)
            .withProperty("group", "y")
            .store();

        Entity a1 = createEntity("Product", key)
            .withProperty("name", "a")
            .withProperty("price", 1L)
            .withProperty("group", "z")
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("name", String.class))
            .addProjection(new PropertyProjection("price", Long.class));
        assertResultsInOrder(query, a1, b1, c1, c2);

        query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("name", String.class))
            .addProjection(new PropertyProjection("group", String.class))
            .addProjection(new PropertyProjection("price", Long.class));
        assertResultsInOrder(query, c1, c2, b1, a1);
    }

    @Test
    public void testOrderOfReturnedResultsIsSameAsOrderOfElementsInInStatementWhenUsingProjections() throws Exception {
        String methodName = "testOrderOfReturnedResultsIsSameAsOrderOfElementsInInStatementWhenUsingProjections";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity b = createEntity("Product", key)
            .withProperty("name", "b")
            .withProperty("price", 1L)
            .store();

        Entity a = createEntity("Product", key)
            .withProperty("name", "a")
            .withProperty("price", 2L)
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("price", Long.class))
            .setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("a", "b")));
        assertResultsInOrder(query, a, b);

        query = query.setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("b", "a")));
        assertResultsInOrder(query, b, a);
    }

    @Test
    public void testOrderOfReturnedResultsIsSameAsOrderOfElementsInInStatementWhenUsingKeysOnly() throws Exception {
        String methodName = "testOrderOfReturnedResultsIsSameAsOrderOfElementsInInStatementWhenUsingKeysOnly";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity b = createEntity("Product", key)
            .withProperty("name", "b")
            .store();

        Entity a = createEntity("Product", key)
            .withProperty("name", "a")
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .setKeysOnly()
            .setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("a", "b")));
        assertResultsInOrder(query, a, b);

        query = query.setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("b", "a")));
        assertResultsInOrder(query, b, a);
    }

    @Test
    public void testEntityOnlyContainsProjectedProperties() throws Exception {
        String methodName = "testEntityOnlyContainsProjectedProperties";
        Entity parent = createTestEntityWithUniqueMethodNameKey("Product", methodName);
        Key key = parent.getKey();

        Entity b = createEntity("Product", key)
            .withProperty("name", "b")
            .withProperty("price", 1L)
            .store();

        Entity a = createEntity("Product", key)
            .withProperty("name", "a")
            .withProperty("price", 2L)
            .store();

        Query query = new Query("Product")
            .setAncestor(key)
            .addProjection(new PropertyProjection("price", Long.class))
            .setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("a", "b")));
        Entity firstResult = service.prepare(query).asList(FetchOptions.Builder.withDefaults()).get(0);

        assertEquals(1, firstResult.getProperties().size());
        assertEquals("price", firstResult.getProperties().keySet().iterator().next());

        query = new Query("Product")
            .setKeysOnly()
            .setFilter(new Query.FilterPredicate("name", IN, Arrays.asList("a", "b")));
        firstResult = service.prepare(query).asList(FetchOptions.Builder.withDefaults()).get(0);

        assertEquals(0, firstResult.getProperties().size());
    }

    private void assertResultsInOrder(Query query, Entity... expectedResults) {
        List<Key> expected = getKeys(Arrays.asList(expectedResults));
        List<Key> results = getKeys(service.prepare(query).asList(withDefaults()));
        assertEquals(expected, results);
    }

    private List<Key> getKeys(List<Entity> entities) {
        List<Key> keys = new ArrayList<Key>();
        for (Entity entity : entities) {
            keys.add(entity.getKey());
        }
        return keys;
    }
}
TOP

Related Classes of com.google.appengine.tck.datastore.QueryOptimizationsTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.