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;
}
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;
}
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());
}
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());
}
}
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))));
}
Aggregations