use of com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression in project fdb-record-layer by FoundationDB.
the class RelationalExpression method fromRecordQuery.
@Nonnull
static RelationalExpression fromRecordQuery(@Nonnull PlanContext context, @Nonnull RecordQuery query) {
query.validate(context.getMetaData());
Quantifier.ForEach quantifier = Quantifier.forEach(GroupExpressionRef.of(new FullUnorderedScanExpression(context.getMetaData().getRecordTypes().keySet())));
if (!context.getRecordTypes().isEmpty()) {
quantifier = Quantifier.forEach(GroupExpressionRef.of(new LogicalTypeFilterExpression(new HashSet<>(context.getRecordTypes()), quantifier)));
}
final SelectExpression selectExpression;
if (query.getFilter() != null) {
selectExpression = query.getFilter().expand(quantifier.getAlias()).buildSelectWithBase(quantifier);
} else {
selectExpression = GraphExpansion.empty().buildSelectWithBase(quantifier);
}
quantifier = Quantifier.forEach(GroupExpressionRef.of(selectExpression));
if (query.removesDuplicates()) {
quantifier = Quantifier.forEach(GroupExpressionRef.of(new LogicalDistinctExpression(quantifier)));
}
if (query.getSort() != null) {
quantifier = Quantifier.forEach(GroupExpressionRef.of(new LogicalSortExpression(query.getSort(), query.isSortReverse(), quantifier)));
} else {
quantifier = Quantifier.forEach(GroupExpressionRef.of(new LogicalSortExpression(null, false, quantifier)));
}
if (query.getRequiredResults() != null) {
final List<? extends Value> projectedValues = Value.fromKeyExpressions(query.getRequiredResults().stream().flatMap(keyExpression -> keyExpression.normalizeKeyForPositions().stream()).collect(ImmutableList.toImmutableList()), quantifier.getAlias());
quantifier = Quantifier.forEach(GroupExpressionRef.of(new LogicalProjectionExpression(projectedValues, quantifier)));
}
return quantifier.getRangesOver().get();
}
use of com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression in project fdb-record-layer by FoundationDB.
the class ValueIndexLikeExpansionVisitor method visitExpression.
@Nonnull
@Override
public GraphExpansion visitExpression(@Nonnull FieldKeyExpression fieldKeyExpression) {
final String fieldName = fieldKeyExpression.getFieldName();
final KeyExpression.FanType fanType = fieldKeyExpression.getFanType();
final VisitorState state = getCurrentState();
final List<String> fieldNamePrefix = state.getFieldNamePrefix();
final CorrelationIdentifier baseAlias = state.getBaseAlias();
final List<String> fieldNames = ImmutableList.<String>builder().addAll(fieldNamePrefix).add(fieldName).build();
final Value value;
final Placeholder predicate;
switch(fanType) {
case FanOut:
// explode this field and prefixes of this field
final Quantifier childBase = fieldKeyExpression.explodeField(baseAlias, fieldNamePrefix);
value = state.registerValue(QuantifiedObjectValue.of(childBase.getAlias()));
final GraphExpansion childExpansion;
if (state.isKey()) {
predicate = value.asPlaceholder(newParameterAlias());
childExpansion = GraphExpansion.ofPlaceholder(value, predicate);
} else {
childExpansion = GraphExpansion.ofResultValue(value);
}
final SelectExpression selectExpression = childExpansion.buildSelectWithBase(childBase);
final Quantifier childQuantifier = Quantifier.forEach(GroupExpressionRef.of(selectExpression));
final GraphExpansion.Sealed sealedChildExpansion = childExpansion.seal();
return sealedChildExpansion.derivedWithQuantifier(childQuantifier);
case None:
value = state.registerValue(new FieldValue(QuantifiedColumnValue.of(baseAlias, 0), fieldNames));
if (state.isKey()) {
predicate = value.asPlaceholder(newParameterAlias());
return GraphExpansion.ofPlaceholder(value, predicate);
}
return GraphExpansion.ofResultValue(value);
// TODO collect/concatenate function
case Concatenate:
default:
}
throw new UnsupportedOperationException();
}
use of com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression in project fdb-record-layer by FoundationDB.
the class ImplementInUnionRule method onMatch.
@SuppressWarnings({ "unchecked", "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 commonPrimaryKey = context.getCommonPrimaryKey();
if (commonPrimaryKey == null) {
return;
}
final var selectExpression = bindings.get(root);
if (!selectExpression.getPredicates().isEmpty()) {
return;
}
final var explodeQuantifiers = bindings.get(explodeQuantifiersMatcher);
if (explodeQuantifiers.isEmpty()) {
return;
}
final var explodeAliases = Quantifiers.aliases(explodeQuantifiers);
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 var explodeToQuantifierBiMap = quantifierToExplodeBiMap.inverse();
final var sourcesBuilder = ImmutableList.<InSource>builder();
for (final var explodeExpression : explodeExpressions) {
final var explodeQuantifier = Objects.requireNonNull(explodeToQuantifierBiMap.getUnwrapped(explodeExpression));
final List<? extends Value> explodeResultValues = explodeExpression.getResultValues();
if (explodeResultValues.size() != 1) {
return;
}
final Value explodeValue = Iterables.getOnlyElement(explodeResultValues);
//
// Create the source for the in-union plan
//
final InSource inSource;
if (explodeValue instanceof LiteralValue<?>) {
final Object literalValue = ((LiteralValue<?>) explodeValue).getLiteralValue();
if (literalValue instanceof List<?>) {
inSource = new InValuesSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), (List<Object>) literalValue);
} else {
return;
}
} else if (explodeValue instanceof QuantifiedColumnValue) {
inSource = new InParameterSource(CORRELATION.bindingName(explodeQuantifier.getAlias().getId()), ((QuantifiedColumnValue) explodeValue).getAlias().getId());
} else {
return;
}
sourcesBuilder.add(inSource);
}
final var inSources = sourcesBuilder.build();
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())));
final int attemptFailedInJoinAsUnionMaxSize = call.getContext().getPlannerConfiguration().getAttemptFailedInJoinAsUnionMaxSize();
for (final Map.Entry<Ordering, ImmutableList<RecordQueryPlan>> providedOrderingEntry : groupedByOrdering.entrySet()) {
for (final RequestedOrdering requestedOrdering : requestedOrderings) {
final var providedOrdering = providedOrderingEntry.getKey();
final var matchingKeyExpressionsBuilder = ImmutableSet.<KeyExpression>builder();
for (Map.Entry<KeyExpression, Comparisons.Comparison> expressionComparisonEntry : providedOrdering.getEqualityBoundKeyMap().entries()) {
final Comparisons.Comparison comparison = expressionComparisonEntry.getValue();
if (comparison.getType() == Comparisons.Type.EQUALS && comparison instanceof Comparisons.ParameterComparison) {
final Comparisons.ParameterComparison parameterComparison = (Comparisons.ParameterComparison) comparison;
if (parameterComparison.isCorrelation() && explodeAliases.containsAll(parameterComparison.getCorrelatedTo())) {
matchingKeyExpressionsBuilder.add(expressionComparisonEntry.getKey());
}
}
}
// Compute a comparison key that satisfies the requested ordering
final Optional<Ordering> combinedOrderingOptional = orderingForInUnion(providedOrdering, requestedOrdering, matchingKeyExpressionsBuilder.build());
if (combinedOrderingOptional.isEmpty()) {
continue;
}
final Ordering combinedOrdering = combinedOrderingOptional.get();
final List<KeyPart> orderingKeyParts = combinedOrdering.getOrderingKeyParts();
final List<KeyExpression> orderingKeys = orderingKeyParts.stream().map(KeyPart::getNormalizedKeyExpression).collect(ImmutableList.toImmutableList());
//
// At this point we know we can implement the distinct union over the partitions of compatibly ordered plans
//
final KeyExpression comparisonKey = orderingKeys.size() == 1 ? Iterables.getOnlyElement(orderingKeys) : Key.Expressions.concat(orderingKeys);
final GroupExpressionRef<RecordQueryPlan> newInnerPlanReference = GroupExpressionRef.from(providedOrderingEntry.getValue());
final Quantifier.Physical newInnerQuantifier = Quantifier.physical(newInnerPlanReference);
call.yield(call.ref(new RecordQueryInUnionPlan(newInnerQuantifier, inSources, comparisonKey, RecordQueryUnionPlanBase.isReversed(ImmutableList.of(newInnerQuantifier)), attemptFailedInJoinAsUnionMaxSize)));
}
}
}
use of com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression in project fdb-record-layer by FoundationDB.
the class InComparisonToExplodeRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final SelectExpression selectExpression = bindings.get(root);
// we don't need iteration stability
final List<? extends ValuePredicate> inPredicatesList = bindings.getAll(inPredicateMatcher);
if (inPredicatesList.isEmpty()) {
return;
}
final Set<QueryPredicate> inPredicates = Sets.newIdentityHashSet();
inPredicates.addAll(inPredicatesList);
final ImmutableList.Builder<Quantifier> transformedQuantifiers = ImmutableList.builder();
final ImmutableList.Builder<QueryPredicate> transformedPredicates = ImmutableList.builder();
for (final QueryPredicate predicate : selectExpression.getPredicates()) {
if (inPredicates.contains(predicate)) {
final ValuePredicate valuePredicate = (ValuePredicate) predicate;
final Comparisons.Comparison comparison = valuePredicate.getComparison();
Verify.verify(comparison.getType() == Comparisons.Type.IN);
final ExplodeExpression explodeExpression;
if (comparison instanceof Comparisons.ListComparison) {
explodeExpression = new ExplodeExpression(new LiteralValue<>(comparison.getComparand()));
} else if (comparison instanceof Comparisons.ParameterComparison) {
explodeExpression = new ExplodeExpression(QuantifiedColumnValue.of(CorrelationIdentifier.of(((Comparisons.ParameterComparison) comparison).getParameter()), 0));
} else {
throw new RecordCoreException("unknown in comparison " + comparison.getClass().getSimpleName());
}
final Quantifier.ForEach newQuantifier = Quantifier.forEach(GroupExpressionRef.of(explodeExpression));
transformedPredicates.add(new ValuePredicate(((ValuePredicate) predicate).getValue(), new Comparisons.ParameterComparison(Comparisons.Type.EQUALS, Bindings.Internal.CORRELATION.bindingName(newQuantifier.getAlias().toString()), Bindings.Internal.CORRELATION)));
transformedQuantifiers.add(newQuantifier);
} else {
transformedPredicates.add(predicate);
}
}
transformedQuantifiers.addAll(bindings.getAll(innerQuantifierMatcher));
call.yield(call.ref(new SelectExpression(selectExpression.getResultValues(), transformedQuantifiers.build(), transformedPredicates.build())));
}
use of com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression in project fdb-record-layer by FoundationDB.
the class OrToLogicalUnionRule method onMatch.
@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
final PlannerBindings bindings = call.getBindings();
final SelectExpression selectExpression = bindings.get(root);
final List<? extends Value> resultValues = selectExpression.getResultValues();
final List<? extends Quantifier> quantifiers = bindings.getAll(qunMatcher);
final List<? extends QueryPredicate> orTermPredicates = bindings.getAll(orTermPredicateMatcher);
final List<ExpressionRef<RelationalExpression>> relationalExpressionRefs = new ArrayList<>(orTermPredicates.size());
for (final QueryPredicate orTermPredicate : orTermPredicates) {
relationalExpressionRefs.add(call.ref(new SelectExpression(resultValues, quantifiers, ImmutableList.of(orTermPredicate))));
}
call.yield(GroupExpressionRef.of(new LogicalUnionExpression(Quantifiers.forEachQuantifiers(relationalExpressionRefs))));
}
Aggregations