Search in sources :

Example 11 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class OrderedIndexComponentTest method testPreferredIndexProperties.

/**
 * Tests the preferred index of the component.
 */
@Test
public void testPreferredIndexProperties() {
    List<Property> preferredIndex = newIndex("P1", "P2", "P3");
    assertThat(orderedComponent.preferredIndexProperties()).isEqualTo(preferredIndex);
    Property noDirectionProperty = new Property().setName("P1");
    IndexComponent directionlessComponent = new OrderedIndexComponent(Lists.newArrayList(noDirectionProperty, newProperty("P2"), newProperty("P3")));
    // With a directionless property, the preferred index property should have an ASC direction.
    assertThat(directionlessComponent.preferredIndexProperties()).isEqualTo(preferredIndex);
}
Also used : Property(com.google.storage.onestore.v3.OnestoreEntity.Index.Property) Test(org.junit.Test)

Example 12 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class IndexTranslatorTest method testIgnoreGeoMode.

/**
 * Ensures that an Index with a GEOSPATIAL mode can be converted (even though for now we're
 * ignoring the mode).
 */
// TODO add support for Mode, so that it can be surfaced to the app
@Test
public void testIgnoreGeoMode() {
    OnestoreEntity.CompositeIndex ci = new OnestoreEntity.CompositeIndex();
    ci.setAppId("foo");
    ci.setId(1);
    ci.setState(OnestoreEntity.CompositeIndex.State.WRITE_ONLY);
    OnestoreEntity.Index indexPb = new OnestoreEntity.Index().setEntityType("Mountain").setAncestor(false);
    indexPb.addProperty(new OnestoreEntity.Index.Property().setName("location").setMode(OnestoreEntity.Index.Property.Mode.GEOSPATIAL));
    ci.setDefinition(indexPb);
    Index index = IndexTranslator.convertFromPb(ci);
    assertThat(index.getProperties()).hasSize(1);
    Property property = index.getProperties().get(0);
    assertThat(property.getName()).isEqualTo("location");
    assertThat(property.getDirection()).isNull();
}
Also used : OnestoreEntity(com.google.storage.onestore.v3.OnestoreEntity) Property(com.google.appengine.api.datastore.Index.Property) Test(org.junit.Test)

Example 13 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class DataTypeTranslator method addPropertyToPb.

/**
 * Adds a property to {@code entity}.
 *
 * @param name the property name
 * @param value the property value
 * @param indexed whether this property should be indexed. This may be overridden by property
 *     types like Blob and Text that are never indexed.
 * @param forceIndexedEmbeddedEntity whether indexed embedded entities should actually be indexed,
 *     as opposed to silently moved to unindexed properties (legacy behavior)
 * @param multiple whether this property has multiple values
 * @param entity the entity to populate
 */
private static void addPropertyToPb(String name, @Nullable Object value, boolean indexed, boolean forceIndexedEmbeddedEntity, boolean multiple, EntityProto entity) {
    Property property = new Property();
    property.setName(name);
    property.setMultiple(multiple);
    PropertyValue newValue = property.getMutableValue();
    if (value != null) {
        Type<?> type = getType(value.getClass());
        Meaning meaning = type.getV3Meaning();
        if (meaning != property.getMeaningEnum()) {
            property.setMeaning(meaning);
        }
        type.toV3Value(value, newValue);
        if (indexed && forceIndexedEmbeddedEntity && DataTypeUtils.isUnindexableType(value.getClass())) {
            // with collections whose contents have been changed in the meantime.
            throw new UnsupportedOperationException("Value must be indexable.");
        }
        if (!forceIndexedEmbeddedEntity || !(value instanceof EmbeddedEntity)) {
            // If client was trying to index a type that they shouldn't then clear the index flag for
            // them.
            indexed &= type.canBeIndexed();
        }
    }
    if (indexed) {
        entity.addProperty(property);
    } else {
        entity.addRawProperty(property);
    }
}
Also used : PropertyValue(com.google.storage.onestore.v3.OnestoreEntity.PropertyValue) Property(com.google.storage.onestore.v3.OnestoreEntity.Property) Meaning(com.google.storage.onestore.v3.OnestoreEntity.Property.Meaning)

Example 14 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class QueryRunnerV3 method addMissingIndexData.

private void addMissingIndexData(DatastoreV3Pb.Query queryProto, DatastoreNeedIndexException e) {
    IndexComponentsOnlyQuery indexQuery = new IndexComponentsOnlyQuery(queryProto);
    CompositeIndexManager mgr = new CompositeIndexManager();
    OnestoreEntity.Index index = mgr.compositeIndexForQuery(indexQuery);
    if (index != null) {
        String xml = mgr.generateXmlForIndex(index, IndexSource.manual);
        e.setMissingIndexDefinitionXml(xml);
    } else {
    // Prod says we need an index but the index manager says we don't.
    // Probably a bug in the index manager.  DatastoreNeedIndexException
    // will report this in the exception message.
    }
}
Also used : IndexComponentsOnlyQuery(com.google.appengine.api.datastore.CompositeIndexManager.IndexComponentsOnlyQuery) OnestoreEntity(com.google.storage.onestore.v3.OnestoreEntity)

Example 15 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalDatastoreService method runQuery.

// status
@SuppressWarnings("unused")
public QueryResult runQuery(Status status, Query query) {
    // Construct a validated query right away so we can fail fast
    // if something is wrong.
    final LocalCompositeIndexManager.ValidatedQuery validatedQuery = new LocalCompositeIndexManager.ValidatedQuery(query);
    query = validatedQuery.getV3Query();
    // LocalCompositeIndexManager.ValidatedQuery.  I don't know why.
    try {
        CursorModernizer.modernizeQueryCursors(query);
    } catch (InvalidConversionException e) {
        throw newError(ErrorCode.BAD_REQUEST, "Invalid cursor");
    }
    String app = query.getApp();
    Profile profile = getOrCreateProfile(app);
    synchronized (profile) {
        // ancestor does not imply we have a transaction.
        if (query.hasTransaction() || query.hasAncestor()) {
            // Query can only have a txn if it is an ancestor query.  Either way we
            // know we've got an ancestor.
            Path groupPath = getGroup(query.getAncestor());
            Profile.EntityGroup eg = profile.getGroup(groupPath);
            if (query.hasTransaction()) {
                if (!app.equals(query.getTransaction().getApp())) {
                    throw newError(ErrorCode.INTERNAL_ERROR, "Can't query app " + app + "in a transaction on app " + query.getTransaction().getApp());
                }
                LiveTxn liveTxn = profile.getTxn(query.getTransaction().getHandle());
                // this will throw an exception if we attempt to read from
                // the wrong entity group
                eg.addTransaction(liveTxn);
                // Use snapshot profile.
                profile = eg.getSnapshot(liveTxn);
            }
            if (query.hasAncestor()) {
                if (query.hasTransaction() || !query.hasFailoverMs()) {
                    // Either we have a transaction or the user has requested strongly
                    // consistent results.  Either way, we need to apply jobs.
                    eg.rollForwardUnappliedJobs();
                }
            }
        }
        if (query.hasSearchQuery()) {
            throw newError(ErrorCode.BAD_REQUEST, "full-text search unsupported");
        }
        // Run as a PseudoKind query if necessary, otherwise check the actual local datastore
        List<EntityProto> queryEntities = pseudoKinds.runQuery(query);
        Map<Reference, Long> versions = null;
        if (queryEntities == null) {
            Collection<VersionedEntity> versionedEntities = null;
            Map<String, Extent> extents = profile.getExtents();
            Extent extent = extents.get(query.getKind());
            if (extent != null) {
                // Make a copy of the list of all the entities in the extent
                versionedEntities = extent.getAllEntities();
            } else if (!query.hasKind()) {
                // Kind-less query, so we need a list containing all entities of
                // all kinds.
                versionedEntities = profile.getAllEntities();
                if (query.orderSize() == 0) {
                    // add a sort by key asc to match the behavior of prod
                    query.addOrder(new Order().setDirection(Query.Order.Direction.ASCENDING).setProperty(Entity.KEY_RESERVED_PROPERTY));
                }
            } else {
            // no extent - we're querying for a kind without any entities
            }
            if (versionedEntities != null) {
                queryEntities = new ArrayList<>();
                versions = new HashMap<>();
                for (VersionedEntity entity : versionedEntities) {
                    queryEntities.add(entity.entityProto());
                    versions.put(entity.entityProto().getKey(), entity.version());
                }
            }
        }
        // Give all entity groups with unapplied jobs the opportunity to catch
        // up.  Note that this will not impact the result of the query we're
        // currently fulfilling since we already have the (unfiltered) result
        // set.
        profile.groom();
        if (queryEntities == null) {
            // so we don't need to check for null anywhere else down below
            queryEntities = Collections.emptyList();
        }
        // Building filter predicate
        List<Predicate<EntityProto>> predicates = new ArrayList<>();
        // apply ancestor restriction
        if (query.hasAncestor()) {
            final List<Element> ancestorPath = query.getAncestor().getPath().elements();
            predicates.add(new Predicate<EntityProto>() {

                @Override
                public boolean apply(EntityProto entity) {
                    List<Element> path = entity.getKey().getPath().elements();
                    return path.size() >= ancestorPath.size() && path.subList(0, ancestorPath.size()).equals(ancestorPath);
                }
            });
        }
        if (query.isShallow()) {
            final long keyPathLength = query.hasAncestor() ? query.getAncestor().getPath().elementSize() + 1 : 1;
            predicates.add(new Predicate<EntityProto>() {

                @Override
                public boolean apply(EntityProto entity) {
                    return entity.getKey().getPath().elementSize() == keyPathLength;
                }
            });
        }
        // apply namespace restriction
        final boolean hasNamespace = query.hasNameSpace();
        final String namespace = query.getNameSpace();
        predicates.add(new Predicate<EntityProto>() {

            @Override
            public boolean apply(EntityProto entity) {
                Reference ref = entity.getKey();
                // Filter all elements not in the query's namespace.
                if (hasNamespace) {
                    if (!ref.hasNameSpace() || !namespace.equals(ref.getNameSpace())) {
                        return false;
                    }
                } else {
                    if (ref.hasNameSpace()) {
                        return false;
                    }
                }
                return true;
            }
        });
        // Get entityComparator with filter matching capability
        final EntityProtoComparator entityComparator = new EntityProtoComparator(validatedQuery.getQuery().orders(), validatedQuery.getQuery().filters());
        // applying filter restrictions
        predicates.add(new Predicate<EntityProto>() {

            @Override
            public boolean apply(EntityProto entity) {
                return entityComparator.matches(entity);
            }
        });
        Predicate<EntityProto> queryPredicate = Predicates.<EntityProto>not(Predicates.<EntityProto>and(predicates));
        // The ordering of the following operations is important to maintain correct
        // query functionality.
        // Filtering entities
        Iterables.removeIf(queryEntities, queryPredicate);
        // Expanding projections
        if (query.propertyNameSize() > 0) {
            queryEntities = createIndexOnlyQueryResults(queryEntities, entityComparator);
        }
        // Sorting entities
        Collections.sort(queryEntities, entityComparator);
        // Apply group by. This must happen after sorting to select the correct first entity.
        queryEntities = applyGroupByProperties(queryEntities, query);
        // store the query and return the results
        LiveQuery liveQuery = new LiveQuery(queryEntities, versions, query, entityComparator, clock);
        // CompositeIndexManager does some filesystem reads/writes, so needs to
        // be privileged.
        AccessController.doPrivileged(new PrivilegedAction<Object>() {

            @Override
            public Object run() {
                LocalCompositeIndexManager.getInstance().processQuery(validatedQuery.getV3Query());
                return null;
            }
        });
        // Using next function to prefetch results and return them from runQuery
        QueryResult result = liveQuery.nextResult(query.hasOffset() ? query.getOffset() : null, query.hasCount() ? query.getCount() : null, query.isCompile());
        if (query.isCompile()) {
            result.setCompiledQuery(liveQuery.compileQuery());
        }
        if (result.isMoreResults()) {
            long cursor = queryId.getAndIncrement();
            profile.addQuery(cursor, liveQuery);
            result.getMutableCursor().setApp(query.getApp()).setCursor(cursor);
        }
        // Copy the index list for the query into the result.
        for (Index index : LocalCompositeIndexManager.getInstance().queryIndexList(query)) {
            result.addIndex(wrapIndexInCompositeIndex(app, index));
        }
        // for
        return result;
    }
}
Also used : Element(com.google.storage.onestore.v3.OnestoreEntity.Path.Element) Utils.getLastElement(com.google.appengine.api.datastore.dev.Utils.getLastElement) ArrayList(java.util.ArrayList) Index(com.google.storage.onestore.v3.OnestoreEntity.Index) CompositeIndex(com.google.storage.onestore.v3.OnestoreEntity.CompositeIndex) ByteString(com.google.protobuf.ByteString) Predicate(com.google.common.base.Predicate) QueryResult(com.google.apphosting.datastore.DatastoreV3Pb.QueryResult) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) EntityProto(com.google.storage.onestore.v3.OnestoreEntity.EntityProto) Path(com.google.storage.onestore.v3.OnestoreEntity.Path) Order(com.google.apphosting.datastore.DatastoreV3Pb.Query.Order) EntityProtoComparator(com.google.appengine.api.datastore.EntityProtoComparators.EntityProtoComparator) Reference(com.google.storage.onestore.v3.OnestoreEntity.Reference) InvalidConversionException(com.google.cloud.datastore.core.exception.InvalidConversionException) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Aggregations

Index (com.google.storage.onestore.v3.OnestoreEntity.Index)8 OnestoreEntity (com.google.storage.onestore.v3.OnestoreEntity)5 Property (com.google.storage.onestore.v3.OnestoreEntity.Index.Property)5 Order (com.google.apphosting.datastore.DatastoreV3Pb.Query.Order)4 Property (com.google.storage.onestore.v3.OnestoreEntity.Property)4 IndexComponentsOnlyQuery (com.google.appengine.api.datastore.CompositeIndexManager.IndexComponentsOnlyQuery)3 DatastoreV3Pb (com.google.apphosting.datastore.DatastoreV3Pb)3 ByteString (com.google.protobuf.ByteString)3 EntityProto (com.google.storage.onestore.v3.OnestoreEntity.EntityProto)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Map (java.util.Map)3 Test (org.junit.Test)3 Filter (com.google.apphosting.datastore.DatastoreV3Pb.Query.Filter)2 ImmutableList (com.google.common.collect.ImmutableList)2 CompositeIndex (com.google.storage.onestore.v3.OnestoreEntity.CompositeIndex)2 PropertyValue (com.google.storage.onestore.v3.OnestoreEntity.PropertyValue)2 Reference (com.google.storage.onestore.v3.OnestoreEntity.Reference)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2