Search in sources :

Example 6 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class ImplementInJoinRule method onMatch.

@SuppressWarnings("java:S135")
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final var context = call.getContext();
    final var bindings = call.getBindings();
    final var requestedOrderingsOptional = call.getInterestingProperty(OrderingAttribute.ORDERING);
    if (requestedOrderingsOptional.isEmpty()) {
        return;
    }
    final var requestedOrderings = requestedOrderingsOptional.get();
    final var selectExpression = bindings.get(root);
    if (!selectExpression.getPredicates().isEmpty()) {
        return;
    }
    final var explodeQuantifiers = bindings.get(explodeQuantifiersMatcher);
    if (explodeQuantifiers.isEmpty()) {
        return;
    }
    final var explodeAliasToQuantifierMap = Quantifiers.aliasToQuantifierMap(explodeQuantifiers);
    final var explodeAliases = explodeAliasToQuantifierMap.keySet();
    final var innerQuantifierOptional = findInnerQuantifier(selectExpression, explodeQuantifiers, explodeAliases);
    if (innerQuantifierOptional.isEmpty()) {
        return;
    }
    final var innerQuantifier = innerQuantifierOptional.get();
    final List<? extends Value> resultValues = selectExpression.getResultValues();
    if (resultValues.stream().anyMatch(resultValue -> !(resultValue instanceof QuantifiedColumnValue) || !((QuantifiedColumnValue) resultValue).getAlias().equals(innerQuantifier.getAlias()))) {
        return;
    }
    final var explodeExpressions = bindings.getAll(explodeExpressionMatcher);
    final var quantifierToExplodeBiMap = computeQuantifierToExplodeMap(explodeQuantifiers, explodeExpressions.stream().collect(LinkedIdentitySet.toLinkedIdentitySet()));
    final Map<Ordering, ImmutableList<RecordQueryPlan>> groupedByOrdering = innerQuantifier.getRangesOver().getMembers().stream().flatMap(relationalExpression -> relationalExpression.narrowMaybe(RecordQueryPlan.class).stream()).flatMap(plan -> {
        final Optional<Ordering> orderingForLegOptional = OrderingProperty.evaluate(plan, context);
        return orderingForLegOptional.stream().map(ordering -> Pair.of(ordering, plan));
    }).collect(Collectors.groupingBy(Pair::getLeft, Collectors.mapping(Pair::getRight, ImmutableList.toImmutableList())));
    for (final Map.Entry<Ordering, ImmutableList<RecordQueryPlan>> providedOrderingEntry : groupedByOrdering.entrySet()) {
        final var providedOrdering = providedOrderingEntry.getKey();
        for (final RequestedOrdering requestedOrdering : requestedOrderings) {
            final ImmutableList<InSource> sources = getInSourcesForRequestedOrdering(explodeAliasToQuantifierMap, explodeAliases, quantifierToExplodeBiMap, providedOrdering, requestedOrdering);
            if (sources.isEmpty()) {
                continue;
            }
            final var reverseSources = Lists.reverse(sources);
            GroupExpressionRef<RecordQueryPlan> newInnerPlanReference = GroupExpressionRef.from(providedOrderingEntry.getValue());
            for (final InSource inSource : reverseSources) {
                final var inJoinPlan = inSource.toInJoinPlan(Quantifier.physical(newInnerPlanReference));
                newInnerPlanReference = GroupExpressionRef.of(inJoinPlan);
            }
            call.yield(newInnerPlanReference);
        }
    }
}
Also used : PlannerRuleCall(com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall) OrderingAttribute(com.apple.foundationdb.record.query.plan.temp.OrderingAttribute) LinkedIdentitySet(com.apple.foundationdb.record.query.plan.temp.LinkedIdentitySet) GroupExpressionRef(com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef) HashMultimap(com.google.common.collect.HashMultimap) Pair(org.apache.commons.lang3.tuple.Pair) RelationalExpressionMatchers.selectExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.selectExpression) Map(java.util.Map) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) Set(java.util.Set) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression) LiteralValue(com.apple.foundationdb.record.query.predicates.LiteralValue) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) Value(com.apple.foundationdb.record.query.predicates.Value) List(java.util.List) RecordQueryInUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionPlan) CorrelationIdentifier(com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier) OrderingProperty(com.apple.foundationdb.record.query.plan.temp.properties.OrderingProperty) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) InParameterSource(com.apple.foundationdb.record.query.plan.plans.InParameterSource) CORRELATION(com.apple.foundationdb.record.Bindings.Internal.CORRELATION) Iterables(com.google.common.collect.Iterables) PlannerRule(com.apple.foundationdb.record.query.plan.temp.PlannerRule) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) CollectionMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.CollectionMatcher) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) Quantifiers(com.apple.foundationdb.record.query.plan.temp.Quantifiers) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RelationalExpressionMatchers.explodeExpression(com.apple.foundationdb.record.query.plan.temp.matchers.RelationalExpressionMatchers.explodeExpression) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier(com.apple.foundationdb.record.query.plan.temp.rules.PushInterestingOrderingThroughInLikeSelectRule.findInnerQuantifier) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) InValuesSource(com.apple.foundationdb.record.query.plan.plans.InValuesSource) MultiMatcher.some(com.apple.foundationdb.record.query.plan.temp.matchers.MultiMatcher.some) Nonnull(javax.annotation.Nonnull) SortedInValuesSource(com.apple.foundationdb.record.query.plan.plans.SortedInValuesSource) KeyPart(com.apple.foundationdb.record.query.plan.temp.KeyPart) SortedInParameterSource(com.apple.foundationdb.record.query.plan.plans.SortedInParameterSource) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) QuantifierMatchers.forEachQuantifier(com.apple.foundationdb.record.query.plan.temp.matchers.QuantifierMatchers.forEachQuantifier) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) ExplodeExpression(com.apple.foundationdb.record.query.plan.temp.expressions.ExplodeExpression) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Optional(java.util.Optional) ImmutableList(com.google.common.collect.ImmutableList) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) RequestedOrdering(com.apple.foundationdb.record.query.plan.temp.RequestedOrdering) Ordering(com.apple.foundationdb.record.query.plan.temp.Ordering) InSource(com.apple.foundationdb.record.query.plan.plans.InSource) Map(java.util.Map) IdentityBiMap(com.apple.foundationdb.record.query.plan.temp.IdentityBiMap) Pair(org.apache.commons.lang3.tuple.Pair)

Example 7 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class FDBSelectorPlanTest method testPlanValues.

@DualPlannerTest
void testPlanValues() throws Throwable {
    complexQuerySetup(NO_HOOK);
    RecordQuery query1 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").build();
    RecordQuery query2 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_2").equalsValue(1)).build();
    RecordQueryPlan plan = RecordQuerySelectorPlan.from(plan(query1, query2), List.of(50, 50));
    List<? extends Value> resultValues = plan.getResultValues();
    assertThat(resultValues.size(), is(1));
    ValuePickerValue value = (ValuePickerValue) resultValues.get(0);
    List<Value> subValues = ImmutableList.copyOf(value.getChildren());
    assertThat(subValues.size(), is(2));
    assertThat(subValues.get(0), is(plan.getQuantifiers().get(0).getFlowedValues().get(0)));
    assertThat(subValues.get(1), is(plan.getQuantifiers().get(1).getFlowedValues().get(0)));
}
Also used : ValuePickerValue(com.apple.foundationdb.record.query.predicates.ValuePickerValue) ValuePickerValue(com.apple.foundationdb.record.query.predicates.ValuePickerValue) Value(com.apple.foundationdb.record.query.predicates.Value) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) DualPlannerTest(com.apple.foundationdb.record.provider.foundationdb.query.DualPlannerTest)

Example 8 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class FDBSelectorPlanTest method testTwoInnerPlansWithContinuation.

@DualPlannerTest
void testTwoInnerPlansWithContinuation() throws Throwable {
    complexQuerySetup(NO_HOOK);
    RecordQuery query1 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").build();
    RecordQuery query2 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_2").equalsValue(1)).build();
    // This will select plan 1 for the first execution and later some illegal value. The idea is that after the
    // first iteration, the continuation should determine the selected plan and not the relative priorities
    RecordQueryPlan planUnderTest = RecordQuerySelectorPlan.from(plan(query1, query2), mockSelector());
    // Iteration 1, start with empty continuation
    RecordCursorResult<FDBQueriedRecord<Message>> result = querySimpleRecordStoreWithContinuation(NO_HOOK, planUnderTest, EvaluationContext::empty, null, ExecuteProperties.newBuilder().setReturnedRowLimit(15).build(), count -> assertThat(count, is(15)), record -> assertThat(record.getNumValue2(), is(1)), context -> assertDiscardedAtMost(30, context));
    assertThat(result.getNoNextReason(), is(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED));
    // Iteration 2, start with previous continuation
    byte[] continuation = result.getContinuation().toBytes();
    result = querySimpleRecordStoreWithContinuation(NO_HOOK, planUnderTest, EvaluationContext::empty, continuation, ExecuteProperties.newBuilder().setReturnedRowLimit(15).build(), count -> assertThat(count, is(15)), record -> assertThat(record.getNumValue2(), is(1)), context -> assertDiscardedAtMost(30, context));
    assertThat(result.getNoNextReason(), is(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED));
    // Iteration 3, start with previous continuation, reach end
    continuation = result.getContinuation().toBytes();
    result = querySimpleRecordStoreWithContinuation(NO_HOOK, planUnderTest, EvaluationContext::empty, continuation, ExecuteProperties.newBuilder().setReturnedRowLimit(15).build(), count -> assertThat(count, is(3)), record -> assertThat(record.getNumValue2(), is(1)), context -> assertDiscardedAtMost(8, context));
    assertThat(result.hasNext(), is(false));
    assertThat(result.getNoNextReason(), is(RecordCursor.NoNextReason.SOURCE_EXHAUSTED));
}
Also used : FDBRecordStoreQueryTestBase(com.apple.foundationdb.record.provider.foundationdb.query.FDBRecordStoreQueryTestBase) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) ValuePickerValue(com.apple.foundationdb.record.query.predicates.ValuePickerValue) BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) ImmutableList(com.google.common.collect.ImmutableList) DualPlannerTest(com.apple.foundationdb.record.provider.foundationdb.query.DualPlannerTest) Tag(org.junit.jupiter.api.Tag) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nonnull(javax.annotation.Nonnull) Query(com.apple.foundationdb.record.query.expressions.Query) Tags(com.apple.test.Tags) RecordCoreArgumentException(com.apple.foundationdb.record.RecordCoreArgumentException) Collectors(java.util.stream.Collectors) Test(org.junit.jupiter.api.Test) Value(com.apple.foundationdb.record.query.predicates.Value) List(java.util.List) TestHelpers.assertDiscardedAtMost(com.apple.foundationdb.record.TestHelpers.assertDiscardedAtMost) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) Matchers.is(org.hamcrest.Matchers.is) Collections(java.util.Collections) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) DualPlannerTest(com.apple.foundationdb.record.provider.foundationdb.query.DualPlannerTest)

Example 9 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class RecordQueryChooserPlanBase method calculateChildrenValues.

/**
 * This utility calculates the list of values that are returned by the plan. The plan returns a list of
 * {@link ValuePickerValue} that each represent the values returned by one of the child plans.
 * Each {@link ValuePickerValue} holds a "selected index" that determines which of the sub-values it references, so
 * that, in all, when the same "selected index" is chosen for all picker value, one would get back a consistent set
 * of values, representing one of the child plans for this plan.
 *
 * @return list of {@link ValuePickerValue} representing all the values from all the sub plans
 */
private List<? extends Value> calculateChildrenValues() {
    // Store all values in a multimap, indexed by the ordinal of the value in the returned list
    // Each list represents all the i'th Value from each of the sub plans
    ImmutableListMultimap.Builder<Integer, Value> mapBuilder = ImmutableListMultimap.builder();
    quantifiers.forEach(quantifier -> {
        List<? extends Value> values = quantifier.getFlowedValues();
        for (int i = 0; i < values.size(); i++) {
            mapBuilder.put(i, values.get(i));
        }
    });
    ImmutableListMultimap<Integer, ? extends Value> valuesMap = mapBuilder.build();
    ImmutableList.Builder<ValuePickerValue> resultBuilder = ImmutableList.builder();
    for (int i = 0; i < valuesMap.keySet().size(); i++) {
        ImmutableList<? extends Value> subValues = valuesMap.get(i);
        // For now, fix all the picker values to return the first sub value
        resultBuilder.add(new ValuePickerValue(0, subValues));
    }
    return resultBuilder.build();
}
Also used : ValuePickerValue(com.apple.foundationdb.record.query.predicates.ValuePickerValue) ImmutableList(com.google.common.collect.ImmutableList) ValuePickerValue(com.apple.foundationdb.record.query.predicates.ValuePickerValue) Value(com.apple.foundationdb.record.query.predicates.Value) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap)

Example 10 with Value

use of com.apple.foundationdb.record.query.predicates.Value in project fdb-record-layer by FoundationDB.

the class ValueIndexExpansionVisitor method expand.

@Nonnull
@Override
public MatchCandidate expand(@Nonnull final Quantifier.ForEach baseQuantifier, @Nullable final KeyExpression primaryKey, final boolean isReverse) {
    Debugger.updateIndex(ValueComparisonRangePredicate.Placeholder.class, old -> 0);
    final ImmutableList.Builder<GraphExpansion> allExpansionsBuilder = ImmutableList.builder();
    // add the value for the flow of records
    final QuantifiedColumnValue recordValue = QuantifiedColumnValue.of(baseQuantifier.getAlias(), 0);
    allExpansionsBuilder.add(GraphExpansion.ofResultValueAndQuantifier(recordValue, baseQuantifier));
    KeyExpression rootExpression = index.getRootExpression();
    final int keyValueSplitPoint;
    if (rootExpression instanceof KeyWithValueExpression) {
        final KeyWithValueExpression keyWithValueExpression = (KeyWithValueExpression) rootExpression;
        keyValueSplitPoint = keyWithValueExpression.getSplitPoint();
        rootExpression = keyWithValueExpression.getInnerKey();
    } else {
        keyValueSplitPoint = -1;
    }
    final List<Value> keyValues = Lists.newArrayList();
    final List<Value> valueValues = Lists.newArrayList();
    final VisitorState initialState = VisitorState.of(keyValues, valueValues, baseQuantifier.getAlias(), ImmutableList.of(), keyValueSplitPoint, 0);
    final GraphExpansion keyValueExpansion = pop(rootExpression.expand(push(initialState)));
    allExpansionsBuilder.add(keyValueExpansion);
    final int keySize = keyValues.size();
    if (primaryKey != null) {
        // unfortunately we must copy as the returned list is not guaranteed to be mutable which is needed for the
        // trimPrimaryKey() function as it is causing a side-effect
        final List<KeyExpression> trimmedPrimaryKeys = Lists.newArrayList(primaryKey.normalizeKeyForPositions());
        index.trimPrimaryKey(trimmedPrimaryKeys);
        for (int i = 0; i < trimmedPrimaryKeys.size(); i++) {
            final KeyExpression primaryKeyPart = trimmedPrimaryKeys.get(i);
            final VisitorState initialStateForKeyPart = VisitorState.of(keyValues, Lists.newArrayList(), baseQuantifier.getAlias(), ImmutableList.of(), -1, keySize + i);
            final GraphExpansion primaryKeyPartExpansion = pop(primaryKeyPart.expand(push(initialStateForKeyPart)));
            allExpansionsBuilder.add(primaryKeyPartExpansion);
        }
    }
    final GraphExpansion completeExpansion = GraphExpansion.ofOthers(allExpansionsBuilder.build());
    final List<CorrelationIdentifier> parameters = completeExpansion.getPlaceholderAliases();
    final MatchableSortExpression matchableSortExpression = new MatchableSortExpression(parameters, isReverse, completeExpansion.buildSelect());
    return new ValueIndexScanMatchCandidate(index, recordTypes, ExpressionRefTraversal.withRoot(GroupExpressionRef.of(matchableSortExpression)), parameters, recordValue, keyValues, valueValues, fullKey(index, primaryKey));
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ValueComparisonRangePredicate(com.apple.foundationdb.record.query.predicates.ValueComparisonRangePredicate) MatchableSortExpression(com.apple.foundationdb.record.query.plan.temp.expressions.MatchableSortExpression) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) KeyWithValueExpression(com.apple.foundationdb.record.metadata.expressions.KeyWithValueExpression) Nonnull(javax.annotation.Nonnull)

Aggregations

Value (com.apple.foundationdb.record.query.predicates.Value)15 Nonnull (javax.annotation.Nonnull)12 ImmutableList (com.google.common.collect.ImmutableList)9 QuantifiedColumnValue (com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue)8 List (java.util.List)7 Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)6 Set (java.util.Set)6 API (com.apple.foundationdb.annotation.API)5 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)5 ImmutableSet (com.google.common.collect.ImmutableSet)5 Collection (java.util.Collection)5 Optional (java.util.Optional)5 Collectors (java.util.stream.Collectors)5 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)4 RecordQueryFetchFromPartialRecordPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan)3 IdentityBiMap (com.apple.foundationdb.record.query.plan.temp.IdentityBiMap)3 SelectExpression (com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression)3 FieldValue (com.apple.foundationdb.record.query.predicates.FieldValue)3 HashMultimap (com.google.common.collect.HashMultimap)3 Sets (com.google.common.collect.Sets)3