Search in sources :

Example 1 with FieldKeyExpression

use of com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression 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 FieldKeyExpression

use of com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planFieldWithComparison.

@Nullable
private ScoredPlan planFieldWithComparison(@Nonnull CandidateScan candidateScan, @Nonnull KeyExpression indexExpr, @Nonnull FieldWithComparison singleField, @Nullable KeyExpression sort, boolean fullKey) {
    final Comparisons.Comparison comparison = singleField.getComparison();
    final ScanComparisons scanComparisons = ScanComparisons.from(comparison);
    if (scanComparisons == null) {
        // this index, but this should be handled elsewhere by the planner.
        return null;
    }
    if (indexExpr instanceof FieldKeyExpression) {
        FieldKeyExpression field = (FieldKeyExpression) indexExpr;
        if (Objects.equals(singleField.getFieldName(), field.getFieldName())) {
            if (sort != null) {
                if (sort instanceof FieldKeyExpression) {
                    FieldKeyExpression sortField = (FieldKeyExpression) sort;
                    if (Objects.equals(sortField.getFieldName(), field.getFieldName())) {
                        // everything matches, yay!! Hopefully that comparison can be for tuples
                        return new ScoredPlan(1, valueScan(candidateScan, scanComparisons, fullKey));
                    }
                }
            } else {
                return new ScoredPlan(1, valueScan(candidateScan, scanComparisons, false));
            }
        }
        return null;
    } else if (indexExpr instanceof ThenKeyExpression) {
        ThenKeyExpression then = (ThenKeyExpression) indexExpr;
        if ((sort == null || sort.equals(then.getChildren().get(0))) && !then.createsDuplicates() && !(then.getChildren().get(0) instanceof RecordTypeKeyExpression)) {
            // First column will do it all or not.
            return planFieldWithComparison(candidateScan, then.getChildren().get(0), singleField, sort, false);
        } else {
            // May need second column to do sort, so handle like And, which does such cases.
            return new AndWithThenPlanner(candidateScan, then, Collections.singletonList(singleField), sort).plan();
        }
    }
    return null;
}
Also used : ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) TimeWindowScanComparisons(com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowScanComparisons) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) TimeWindowScanComparisons(com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowScanComparisons) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) RankComparisons(com.apple.foundationdb.record.query.plan.planning.RankComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) Nullable(javax.annotation.Nullable)

Example 3 with FieldKeyExpression

use of com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression in project fdb-record-layer by FoundationDB.

the class InExtractor method extractInClauses.

@SuppressWarnings("unchecked")
private QueryComponent extractInClauses() {
    final AtomicInteger bindingIndex = new AtomicInteger();
    return mapClauses(filter, (withComparison, fields) -> {
        if (withComparison.getComparison().getType() == Comparisons.Type.IN) {
            String bindingName = Bindings.Internal.IN.bindingName(withComparison.getName() + "__" + bindingIndex.getAndIncrement());
            List<FieldKeyExpression> nestedFields = null;
            if (fields != null && (withComparison instanceof FieldWithComparison || withComparison instanceof OneOfThemWithComparison)) {
                nestedFields = new ArrayList<>(fields);
                nestedFields.add(Key.Expressions.field(((BaseField) withComparison).getFieldName(), withComparison instanceof FieldWithComparison ? KeyExpression.FanType.None : KeyExpression.FanType.FanOut));
            }
            KeyExpression orderingKey = getOrderingKey(nestedFields);
            if (withComparison.getComparison() instanceof Comparisons.ComparisonWithParameter) {
                final String parameterName = ((Comparisons.ComparisonWithParameter) withComparison.getComparison()).getParameter();
                inClauses.add(new InParameterClause(bindingName, parameterName, orderingKey));
            } else {
                final List<Object> comparand = (List<Object>) withComparison.getComparison().getComparand();
                // ListComparison does not allow empty/null
                if (comparand != null && comparand.size() == 1) {
                    return withComparison.withOtherComparison(new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, comparand.get(0)));
                }
                inClauses.add(new InValuesClause(bindingName, comparand, orderingKey));
            }
            return withComparison.withOtherComparison(new Comparisons.ParameterComparison(Comparisons.Type.EQUALS, bindingName, Bindings.Internal.IN));
        } else {
            return withComparison;
        }
    }, Collections.emptyList());
}
Also used : BaseField(com.apple.foundationdb.record.query.expressions.BaseField) OneOfThemWithComparison(com.apple.foundationdb.record.query.expressions.OneOfThemWithComparison) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List)

Example 4 with FieldKeyExpression

use of com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression 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 5 with FieldKeyExpression

use of com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression in project fdb-record-layer by FoundationDB.

the class ScalarTranslationVisitor method visitExpression.

@Nonnull
@Override
public Value visitExpression(@Nonnull final NestingKeyExpression nestingKeyExpression) {
    final FieldKeyExpression parent = nestingKeyExpression.getParent();
    final KeyExpression.FanType fanType = parent.getFanType();
    if (fanType != KeyExpression.FanType.None) {
        throw new RecordCoreException("cannot expand fan outs in scalar expansion");
    }
    final ScalarVisitorState state = getCurrentState();
    final List<String> fieldNamePrefix = state.getFieldNamePrefix();
    final KeyExpression child = nestingKeyExpression.getChild();
    final List<String> newPrefix = ImmutableList.<String>builder().addAll(fieldNamePrefix).add(parent.getFieldName()).build();
    return pop(child.expand(push(state.withFieldNamePrefix(newPrefix))));
}
Also used : RecordCoreException(com.apple.foundationdb.record.RecordCoreException) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) Nonnull(javax.annotation.Nonnull)

Aggregations

FieldKeyExpression (com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression)24 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)17 ThenKeyExpression (com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression)16 Nullable (javax.annotation.Nullable)15 Nonnull (javax.annotation.Nonnull)14 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)13 ArrayList (java.util.ArrayList)13 EmptyKeyExpression (com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression)12 List (java.util.List)12 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)12 Collections (java.util.Collections)11 Collectors (java.util.stream.Collectors)11 FunctionNames (com.apple.foundationdb.record.FunctionNames)10 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)10 FDBError (com.apple.foundationdb.FDBError)9 FDBException (com.apple.foundationdb.FDBException)9 Range (com.apple.foundationdb.Range)9 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)9 CloseableAsyncIterator (com.apple.foundationdb.async.CloseableAsyncIterator)9 EvaluationContext (com.apple.foundationdb.record.EvaluationContext)9