Search in sources :

Example 91 with QueryComponent

use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.

the class TextScanPlanner method getScanForAndFilter.

@Nullable
private static TextScan getScanForAndFilter(@Nonnull Index index, @Nonnull KeyExpression textExpression, @Nonnull AndComponent filter, @Nullable ScanComparisons groupingComparisons, boolean hasSort, @Nullable FilterSatisfiedMask filterMask) {
    // Iterate through each of the filters
    final Iterator<FilterSatisfiedMask> subFilterMasks = filterMask != null ? filterMask.getChildren().iterator() : null;
    for (QueryComponent subFilter : filter.getChildren()) {
        final FilterSatisfiedMask childMask = subFilterMasks != null ? subFilterMasks.next() : null;
        TextScan childScan = getScanForFilter(index, textExpression, subFilter, groupingComparisons, hasSort, childMask);
        if (childScan != null) {
            if (filterMask != null && filterMask.getExpression() == null) {
                filterMask.setExpression(textExpression);
            }
            return childScan;
        }
    }
    return null;
}
Also used : QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) TextScan(com.apple.foundationdb.record.query.plan.TextScan) Nullable(javax.annotation.Nullable)

Example 92 with QueryComponent

use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.

the class BindingFunctions method javaComparisonType.

@Nullable
private static Descriptors.FieldDescriptor.JavaType javaComparisonType(@Nonnull QueryComponent fieldComparison, @Nonnull Index index, @Nonnull RecordMetaData metaData) {
    Descriptors.FieldDescriptor.JavaType javaType = null;
    for (RecordType recordType : metaData.recordTypesForIndex(index)) {
        Descriptors.Descriptor descriptor = recordType.getDescriptor();
        QueryComponent component = fieldComparison;
        while (component instanceof NestedField) {
            Descriptors.FieldDescriptor fieldDescriptor = descriptor.findFieldByName(((NestedField) component).getName());
            if (fieldDescriptor == null) {
                return null;
            }
            descriptor = fieldDescriptor.getMessageType();
            component = ((NestedField) component).getChild();
        }
        if (component instanceof FieldWithComparison) {
            Descriptors.FieldDescriptor fieldDescriptor = descriptor.findFieldByName(((FieldWithComparison) component).getName());
            if (fieldDescriptor == null) {
                return null;
            }
            if (javaType == null) {
                javaType = fieldDescriptor.getJavaType();
            } else if (javaType != fieldDescriptor.getJavaType()) {
                return null;
            }
        } else {
            return null;
        }
    }
    return javaType;
}
Also used : NestedField(com.apple.foundationdb.record.query.expressions.NestedField) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) RecordType(com.apple.foundationdb.record.metadata.RecordType) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) Descriptors(com.google.protobuf.Descriptors) Nullable(javax.annotation.Nullable)

Example 93 with QueryComponent

use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.

the class GroupingValidator method matchNestingField.

private static boolean matchNestingField(@Nonnull QueryComponent filter, @Nonnull ComponentWithSingleChild nestingComponent, @Nonnull NestingKeyExpression nesting, @Nonnull List<QueryComponent> groupFilters, @Nonnull List<Comparisons.Comparison> groupComparisons) {
    if (nesting.getChild() instanceof NestingKeyExpression) {
        NestingKeyExpression childNesting = (NestingKeyExpression) nesting.getChild();
        QueryComponent childComponent = nestingComponent.getChild();
        if (childComponent instanceof NestedField || childComponent instanceof OneOfThemWithComponent) {
            if (childNesting.getParent().getFieldName().equals(((BaseField) childComponent).getFieldName()) && matchNestingField(filter, (ComponentWithSingleChild) childComponent, childNesting, groupFilters, groupComparisons)) {
                return true;
            }
        }
    } else if (nesting.getChild() instanceof FieldKeyExpression) {
        FieldKeyExpression childField = (FieldKeyExpression) nesting.getChild();
        if (nestingComponent.getChild() instanceof FieldWithComparison) {
            FieldWithComparison comparisonFilter = (FieldWithComparison) nestingComponent.getChild();
            if (comparisonFilter.getFieldName().equals(childField.getFieldName()) && (comparisonFilter.getComparison().getType() == Comparisons.Type.EQUALS || comparisonFilter.getComparison().getType() == Comparisons.Type.IS_NULL)) {
                groupFilters.add(filter);
                groupComparisons.add(comparisonFilter.getComparison());
                return true;
            }
        }
    }
    return false;
}
Also used : NestedField(com.apple.foundationdb.record.query.expressions.NestedField) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) BaseField(com.apple.foundationdb.record.query.expressions.BaseField) ComponentWithSingleChild(com.apple.foundationdb.record.query.expressions.ComponentWithSingleChild) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) OneOfThemWithComponent(com.apple.foundationdb.record.query.expressions.OneOfThemWithComponent) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison)

Example 94 with QueryComponent

use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.

the class ParameterRelationshipGraph method fromRecordQueryAndBindings.

/**
 * Derive a relationship graph from a {@link RecordQuery} and a set of pre-bound parameters in handing in
 * as a {@link Bindings} object.
 * <p>
 * Note that we do not derive additional relationships (yet). So for instance a query
 * </p>
 * <p>
 * {@code
 * ...
 * WHERE x < $p1 AND x = $p2 AND y < $p2 AND y = $p3
 * }
 * </p>
 * with pre-bindings {@code p1 -> 10, p2 -> 10, p3 -> 10} would result in a graph containing
 * <p>
 * {@code
 * p1 EQUALS p1
 * p1 EQUALS p2
 * p2 EQUALS p1
 * p2 EQUALS p2
 * p2 EQUALS p3
 * p3 EQUALS p2
 * p3 EQUALS p3
 * }
 * </p>
 * but it would not contain
 * <p>
 * {@code
 * p1 EQUALS p3
 * p3 EQUALS p1
 * }
 * </p>
 * @param recordQuery query
 * @param preBoundParameterBindings parameter bindings already known at planning time
 * @return a new {@link ParameterRelationshipGraph}
 */
@Nonnull
public static ParameterRelationshipGraph fromRecordQueryAndBindings(@Nonnull final RecordQuery recordQuery, @Nonnull final Bindings preBoundParameterBindings) {
    final QueryComponent filter = recordQuery.getFilter();
    final ImmutableNetwork.Builder<String, Relationship> networkBuilder = NetworkBuilder.directed().allowsSelfLoops(true).allowsParallelEdges(true).immutable();
    if (filter != null) {
        groupedComparisons(filter).flatMap(entry -> StreamSupport.stream(crossProduct(ImmutableList.of(entry.getValue(), entry.getValue())).spliterator(), false)).map(list -> Pair.of(list.get(0), list.get(1))).forEach(pair -> {
            final Comparisons.ComparisonWithParameter left = pair.getLeft();
            final Comparisons.ComparisonWithParameter right = pair.getRight();
            if (left.getParameter().equals(right.getParameter())) {
                Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
                Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
            } else if (// It is possible that some of the parameters are not pre-bound. That's not an error,
            preBoundParameterBindings.containsBinding(left.getParameter()) && preBoundParameterBindings.containsBinding(right.getParameter())) {
                // it just means we cannot establish any sort of relationship between them.
                final Object leftComparand = preBoundParameterBindings.get(left.getParameter());
                final Object rightComparand = preBoundParameterBindings.get(right.getParameter());
                if (Objects.equals(leftComparand, rightComparand)) {
                    Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
                    Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
                }
            }
        });
    }
    return new ParameterRelationshipGraph(networkBuilder.build());
}
Also used : BooleanComponent.groupedComparisons(com.apple.foundationdb.record.query.expressions.BooleanComponent.groupedComparisons) ImmutableSet(com.google.common.collect.ImmutableSet) NetworkBuilder(com.google.common.graph.NetworkBuilder) Set(java.util.Set) Bindings(com.apple.foundationdb.record.Bindings) Objects(java.util.Objects) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) ImmutableList(com.google.common.collect.ImmutableList) Pair(org.apache.commons.lang3.tuple.Pair) ImmutableNetwork(com.google.common.graph.ImmutableNetwork) CrossProduct.crossProduct(com.apple.foundationdb.record.query.combinatorics.CrossProduct.crossProduct) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) StreamSupport(java.util.stream.StreamSupport) API(com.apple.foundationdb.annotation.API) Network(com.google.common.graph.Network) Nonnull(javax.annotation.Nonnull) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) ImmutableNetwork(com.google.common.graph.ImmutableNetwork) BooleanComponent.groupedComparisons(com.apple.foundationdb.record.query.expressions.BooleanComponent.groupedComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) Nonnull(javax.annotation.Nonnull)

Example 95 with QueryComponent

use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.

the class QueryToKeyMatcher method matches.

@Nonnull
private Match matches(@Nonnull AndComponent query, @Nonnull KeyExpression key, @Nonnull MatchingMode matchingMode, @Nullable FilterSatisfiedMask filterMask) {
    final List<QueryComponent> listOfQueries = query.getChildren();
    final Iterator<KeyExpression> keyChildIterator;
    final int keyChildSize = key.getColumnSize();
    if (key instanceof ThenKeyExpression) {
        List<KeyExpression> children = ((ThenKeyExpression) key).getChildren();
        keyChildIterator = children.iterator();
    } else {
        keyChildIterator = Iterators.singletonIterator(key);
    }
    // Keep a local mask so that if we can only partially fulfill queries we don't pollute the main
    // one with our state
    FilterSatisfiedMask localMask = FilterSatisfiedMask.of(query);
    localMask.setExpression(key);
    List<Comparison> comparisons = new ArrayList<>(keyChildSize);
    while (keyChildIterator.hasNext()) {
        KeyExpression exp = keyChildIterator.next();
        // Look for a query segment that matches this expression
        boolean found = false;
        boolean foundInequality = false;
        final Iterator<FilterSatisfiedMask> childMaskIterator = localMask.getChildren().iterator();
        for (QueryComponent querySegment : listOfQueries) {
            Match match = matches(querySegment, exp, matchingMode, childMaskIterator.next());
            if (match.getType() != MatchType.NO_MATCH) {
                found = true;
                comparisons.addAll(match.getComparisons());
                if (match.getType() == MatchType.INEQUALITY) {
                    foundInequality = true;
                }
                break;
            }
        }
        if (!found) {
            return Match.none();
        }
        // Only the last comparison in the list can be inequality.
        if (localMask.allSatisfied() || foundInequality) {
            break;
        }
    }
    if (matchingMode.equals(MatchingMode.SATISFY_QUERY) && !localMask.allSatisfied() || matchingMode.equals(MatchingMode.COVER_KEY) && comparisons.size() < keyChildSize) {
        // filters that have not yet been satisfied.
        return Match.none();
    }
    if (filterMask != null) {
        filterMask.mergeWith(localMask);
    }
    return new Match(comparisons);
}
Also used : QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) FunctionKeyExpression(com.apple.foundationdb.record.metadata.expressions.FunctionKeyExpression) LiteralKeyExpression(com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) BaseKeyExpression(com.apple.foundationdb.record.metadata.expressions.BaseKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) ArrayList(java.util.ArrayList) Comparison(com.apple.foundationdb.record.query.expressions.Comparisons.Comparison) QueryKeyExpressionWithComparison(com.apple.foundationdb.record.query.expressions.QueryKeyExpressionWithComparison) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) OneOfThemWithComparison(com.apple.foundationdb.record.query.expressions.OneOfThemWithComparison) RecordTypeKeyComparison(com.apple.foundationdb.record.query.expressions.RecordTypeKeyComparison) FilterSatisfiedMask(com.apple.foundationdb.record.query.plan.planning.FilterSatisfiedMask) Nonnull(javax.annotation.Nonnull)

Aggregations

QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)96 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)58 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)44 Test (org.junit.jupiter.api.Test)41 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)37 ArrayList (java.util.ArrayList)30 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)29 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)25 Index (com.apple.foundationdb.record.metadata.Index)24 Nonnull (javax.annotation.Nonnull)23 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)22 Message (com.google.protobuf.Message)22 Query (com.apple.foundationdb.record.query.expressions.Query)20 RecordQueryPlanner (com.apple.foundationdb.record.query.plan.RecordQueryPlanner)20 List (java.util.List)20 Collections (java.util.Collections)19 Nullable (javax.annotation.Nullable)18 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)18 PlanHashable (com.apple.foundationdb.record.PlanHashable)17 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)17