Search in sources :

Example 1 with NestedField

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

the class RecordQueryPlanner method planAndWithNesting.

@Nullable
private ScoredPlan planAndWithNesting(@Nonnull CandidateScan candidateScan, @Nonnull NestingKeyExpression indexExpr, @Nonnull AndComponent filter, @Nullable KeyExpression sort) {
    final FieldKeyExpression parent = indexExpr.getParent();
    if (parent.getFanType() == FanType.None) {
        // For non-spread case, we can do a better job trying to match more than one of the filter children if
        // they have the same nesting.
        final List<QueryComponent> nestedFilters = new ArrayList<>();
        final List<QueryComponent> remainingFilters = new ArrayList<>();
        for (QueryComponent filterChild : filter.getChildren()) {
            QueryComponent filterComponent = candidateScan.planContext.rankComparisons.planComparisonSubstitute(filterChild);
            if (filterComponent instanceof NestedField) {
                final NestedField nestedField = (NestedField) filterComponent;
                if (parent.getFieldName().equals(nestedField.getFieldName())) {
                    nestedFilters.add(nestedField.getChild());
                    continue;
                }
            }
            remainingFilters.add(filterChild);
        }
        if (nestedFilters.size() > 1) {
            final NestedField nestedAnd = new NestedField(parent.getFieldName(), Query.and(nestedFilters));
            final ScoredPlan plan = planNestedField(candidateScan, indexExpr, nestedAnd, sort);
            if (plan != null) {
                if (remainingFilters.isEmpty()) {
                    return plan;
                } else {
                    return plan.withUnsatisfiedFilters(remainingFilters);
                }
            } else {
                return null;
            }
        }
    }
    List<QueryComponent> unsatisfiedFilters = new ArrayList<>(filter.getChildren());
    for (QueryComponent filterChild : filter.getChildren()) {
        QueryComponent filterComponent = candidateScan.planContext.rankComparisons.planComparisonSubstitute(filterChild);
        if (filterComponent instanceof NestedField) {
            NestedField nestedField = (NestedField) filterComponent;
            final ScoredPlan plan = planNestedField(candidateScan, indexExpr, nestedField, sort);
            if (plan != null) {
                unsatisfiedFilters.remove(filterChild);
                return plan.withUnsatisfiedFilters(unsatisfiedFilters);
            }
        }
    }
    return null;
}
Also used : NestedField(com.apple.foundationdb.record.query.expressions.NestedField) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) ArrayList(java.util.ArrayList) Nullable(javax.annotation.Nullable)

Example 2 with NestedField

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

the class InExtractor method mapClauses.

private QueryComponent mapClauses(QueryComponent filter, BiFunction<ComponentWithComparison, List<FieldKeyExpression>, QueryComponent> mapper, @Nullable List<FieldKeyExpression> fields) {
    if (filter instanceof ComponentWithComparison) {
        final ComponentWithComparison withComparison = (ComponentWithComparison) filter;
        return mapper.apply(withComparison, fields);
    } else if (filter instanceof ComponentWithChildren) {
        ComponentWithChildren componentWithChildren = (ComponentWithChildren) filter;
        return componentWithChildren.withOtherChildren(componentWithChildren.getChildren().stream().map(component -> mapClauses(component, mapper, fields)).collect(Collectors.toList()));
    } else if (filter instanceof ComponentWithSingleChild) {
        ComponentWithSingleChild componentWithSingleChild = (ComponentWithSingleChild) filter;
        List<FieldKeyExpression> nestedFields = null;
        if (fields != null && (componentWithSingleChild instanceof NestedField || componentWithSingleChild instanceof OneOfThemWithComponent)) {
            nestedFields = new ArrayList<>(fields);
            nestedFields.add(Key.Expressions.field(((BaseField) componentWithSingleChild).getFieldName(), componentWithSingleChild instanceof NestedField ? KeyExpression.FanType.None : KeyExpression.FanType.FanOut));
        }
        return componentWithSingleChild.withOtherChild(mapClauses(componentWithSingleChild.getChild(), mapper, nestedFields));
    } else if (filter instanceof ComponentWithNoChildren) {
        return filter;
    } else {
        throw new Query.InvalidExpressionException("Unsupported query type " + filter.getClass());
    }
}
Also used : BiFunction(java.util.function.BiFunction) Bindings(com.apple.foundationdb.record.Bindings) PlanOrderingKey(com.apple.foundationdb.record.query.plan.PlanOrderingKey) ComponentWithSingleChild(com.apple.foundationdb.record.query.expressions.ComponentWithSingleChild) ComponentWithComparison(com.apple.foundationdb.record.query.expressions.ComponentWithComparison) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) ImmutableList(com.google.common.collect.ImmutableList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) ComponentWithNoChildren(com.apple.foundationdb.record.query.expressions.ComponentWithNoChildren) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) InValuesSource(com.apple.foundationdb.record.query.plan.plans.InValuesSource) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) RecordQueryInParameterJoinPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInParameterJoinPlan) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) OneOfThemWithComponent(com.apple.foundationdb.record.query.expressions.OneOfThemWithComponent) BaseField(com.apple.foundationdb.record.query.expressions.BaseField) OneOfThemWithComparison(com.apple.foundationdb.record.query.expressions.OneOfThemWithComparison) RecordQueryInValuesJoinPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInValuesJoinPlan) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) API(com.apple.foundationdb.annotation.API) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) ComponentWithChildren(com.apple.foundationdb.record.query.expressions.ComponentWithChildren) Collections(java.util.Collections) BaseField(com.apple.foundationdb.record.query.expressions.BaseField) Query(com.apple.foundationdb.record.query.expressions.Query) ComponentWithNoChildren(com.apple.foundationdb.record.query.expressions.ComponentWithNoChildren) ComponentWithChildren(com.apple.foundationdb.record.query.expressions.ComponentWithChildren) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) ComponentWithSingleChild(com.apple.foundationdb.record.query.expressions.ComponentWithSingleChild) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) ComponentWithComparison(com.apple.foundationdb.record.query.expressions.ComponentWithComparison) OneOfThemWithComponent(com.apple.foundationdb.record.query.expressions.OneOfThemWithComponent)

Example 3 with NestedField

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

the class IndexAggregateFunctionCall method extractFieldPaths.

/**
 * Helper method to extract a set of key expressions that are bound through some comparison in the
 * query component passed in.
 * @param queryComponent the query component
 * @param predicate a predicate used for filtering each encountered {@link FieldWithComparison}
 * @return a set of {@link KeyExpression}s where each element is a key expression of a field (i.e. a
 * {@link com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression}) or a simple nesting field
 * (i.e. a {@link com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression}) that is bound
 * through some comparison
 */
@Nonnull
public static Set<KeyExpression> extractFieldPaths(@Nonnull QueryComponent queryComponent, @Nonnull final Predicate<FieldWithComparison> predicate) {
    if (queryComponent instanceof BaseField) {
        final BaseField baseField = (BaseField) queryComponent;
        if (baseField instanceof NestedField) {
            final NestedField nestedField = (NestedField) baseField;
            final Set<KeyExpression> nestedExpressions = extractFieldPaths(nestedField.getChild(), predicate);
            return nestedExpressions.stream().map(nestedExpression -> Key.Expressions.field(nestedField.getFieldName()).nest(nestedExpression)).collect(ImmutableSet.toImmutableSet());
        }
        if (baseField instanceof FieldWithComparison) {
            final FieldWithComparison fieldWithComparison = (FieldWithComparison) baseField;
            if (predicate.test(fieldWithComparison)) {
                return ImmutableSet.of(Key.Expressions.field(fieldWithComparison.getFieldName()));
            }
        }
        return ImmutableSet.of();
    } else if (queryComponent instanceof AndComponent) {
        final Set<KeyExpression> boundFields = Sets.newHashSet();
        final AndComponent andComponent = (AndComponent) queryComponent;
        andComponent.getChildren().forEach(child -> boundFields.addAll(extractEqualityBoundFields(child)));
        return boundFields;
    }
    return ImmutableSet.of();
}
Also used : NestedField(com.apple.foundationdb.record.query.expressions.NestedField) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) Iterables(com.google.common.collect.Iterables) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) Predicate(java.util.function.Predicate) Set(java.util.Set) EnumeratingIterable(com.apple.foundationdb.record.query.combinatorics.EnumeratingIterable) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) Sets(com.google.common.collect.Sets) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) Stream(java.util.stream.Stream) BaseField(com.apple.foundationdb.record.query.expressions.BaseField) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) StreamSupport(java.util.stream.StreamSupport) API(com.apple.foundationdb.annotation.API) Objects(com.google.common.base.Objects) Nonnull(javax.annotation.Nonnull) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) TopologicalSort(com.apple.foundationdb.record.query.combinatorics.TopologicalSort) Nullable(javax.annotation.Nullable) BaseField(com.apple.foundationdb.record.query.expressions.BaseField) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) Nonnull(javax.annotation.Nonnull)

Example 4 with NestedField

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

the class RankComparisons method findComparison.

private void findComparison(@Nonnull QueryRecordFunctionWithComparison comparison, @Nonnull List<Index> indexes, @Nonnull List<QueryComponent> potentialGroupFilters, @Nonnull AtomicInteger counter) {
    RecordFunction<?> recordFunction = comparison.getFunction();
    // TODO: Should share with indexMaintainerForAggregateFunction
    // TODO: Move index-specific query planning behavior outside of planner (https://github.com/FoundationDB/fdb-record-layer/issues/17)
    List<String> requiredIndexTypes;
    if (recordFunction.getName().equals(FunctionNames.RANK)) {
        requiredIndexTypes = Arrays.asList(IndexTypes.RANK, IndexTypes.TIME_WINDOW_LEADERBOARD);
    } else if (recordFunction.getName().equals(FunctionNames.TIME_WINDOW_RANK)) {
        requiredIndexTypes = Collections.singletonList(IndexTypes.TIME_WINDOW_LEADERBOARD);
    } else {
        requiredIndexTypes = null;
    }
    if (requiredIndexTypes != null) {
        final GroupingKeyExpression operand = ((IndexRecordFunction) recordFunction).getOperand();
        Optional<Index> matchingIndex = indexes.stream().filter(index -> requiredIndexTypes.contains(index.getType()) && index.getRootExpression().equals(operand)).min(Comparator.comparing(Index::getColumnSize));
        if (matchingIndex.isPresent()) {
            final KeyExpression groupBy = operand.getGroupingSubKey();
            final List<QueryComponent> groupFilters = new ArrayList<>();
            final List<Comparisons.Comparison> groupComparisons = new ArrayList<>();
            if (!GroupingValidator.findGroupKeyFilters(potentialGroupFilters, groupBy, groupFilters, groupComparisons)) {
                return;
            }
            QueryComponent substitute = null;
            String bindingName = null;
            final Comparisons.Type comparisonType = comparison.getComparison().getType();
            if (!operand.createsDuplicates() && !comparisonType.isUnary()) {
                bindingName = Bindings.Internal.RANK.bindingName(Integer.toString(counter.getAndIncrement()));
                Comparisons.Comparison substituteComparison = new Comparisons.ParameterComparison(comparisonType, bindingName, Bindings.Internal.RANK);
                final KeyExpression grouped = operand.getGroupedSubKey();
                if (grouped instanceof FieldKeyExpression) {
                    substitute = new FieldWithComparison(((FieldKeyExpression) grouped).getFieldName(), substituteComparison);
                } else if (grouped instanceof NestingKeyExpression) {
                    NestingKeyExpression nesting = (NestingKeyExpression) grouped;
                    if (nesting.getChild() instanceof FieldKeyExpression) {
                        substitute = new NestedField(nesting.getParent().getFieldName(), new FieldWithComparison(((FieldKeyExpression) nesting.getChild()).getFieldName(), substituteComparison));
                    }
                }
                if (substitute == null) {
                    bindingName = null;
                }
            }
            comparisons.put(comparison, new RankComparison(comparison, matchingIndex.get(), groupFilters, groupComparisons, substitute, bindingName));
        }
    }
}
Also used : FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Arrays(java.util.Arrays) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) Bindings(com.apple.foundationdb.record.Bindings) HashMap(java.util.HashMap) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Function(java.util.function.Function) ArrayList(java.util.ArrayList) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) Tuple(com.apple.foundationdb.tuple.Tuple) QueryRecordFunctionWithComparison(com.apple.foundationdb.record.query.expressions.QueryRecordFunctionWithComparison) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) Map(java.util.Map) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Set(java.util.Set) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) RecordQueryScoreForRankPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScoreForRankPlan) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) Collectors(java.util.stream.Collectors) AndOrComponent(com.apple.foundationdb.record.query.expressions.AndOrComponent) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) Index(com.apple.foundationdb.record.metadata.Index) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) RecordFunction(com.apple.foundationdb.record.RecordFunction) Comparator(java.util.Comparator) ComponentWithChildren(com.apple.foundationdb.record.query.expressions.ComponentWithChildren) Collections(java.util.Collections) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ArrayList(java.util.ArrayList) Index(com.apple.foundationdb.record.metadata.Index) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) QueryRecordFunctionWithComparison(com.apple.foundationdb.record.query.expressions.QueryRecordFunctionWithComparison) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison)

Example 5 with NestedField

use of com.apple.foundationdb.record.query.expressions.NestedField 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)

Aggregations

NestedField (com.apple.foundationdb.record.query.expressions.NestedField)6 QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)6 FieldWithComparison (com.apple.foundationdb.record.query.expressions.FieldWithComparison)5 Nullable (javax.annotation.Nullable)5 FieldKeyExpression (com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression)4 API (com.apple.foundationdb.annotation.API)3 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)3 NestingKeyExpression (com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression)3 BaseField (com.apple.foundationdb.record.query.expressions.BaseField)3 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)3 List (java.util.List)3 Nonnull (javax.annotation.Nonnull)3 Bindings (com.apple.foundationdb.record.Bindings)2 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)2 AndComponent (com.apple.foundationdb.record.query.expressions.AndComponent)2 ComponentWithChildren (com.apple.foundationdb.record.query.expressions.ComponentWithChildren)2 ComponentWithSingleChild (com.apple.foundationdb.record.query.expressions.ComponentWithSingleChild)2 OneOfThemWithComponent (com.apple.foundationdb.record.query.expressions.OneOfThemWithComponent)2 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)2 ArrayList (java.util.ArrayList)2