use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class TextScanPlanner method getScanForAndFilter.
@Nullable
private static TextScan getScanForAndFilter(@Nonnull Index index, @Nonnull KeyExpression textExpression, @Nonnull AndComponent filter, @Nullable ScanComparisons groupingComparisons, boolean hasSort, @Nullable FilterSatisfiedMask filterMask) {
// Iterate through each of the filters
final Iterator<FilterSatisfiedMask> subFilterMasks = filterMask != null ? filterMask.getChildren().iterator() : null;
for (QueryComponent subFilter : filter.getChildren()) {
final FilterSatisfiedMask childMask = subFilterMasks != null ? subFilterMasks.next() : null;
TextScan childScan = getScanForFilter(index, textExpression, subFilter, groupingComparisons, hasSort, childMask);
if (childScan != null) {
if (filterMask != null && filterMask.getExpression() == null) {
filterMask.setExpression(textExpression);
}
return childScan;
}
}
return null;
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent 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;
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class GroupingValidator method matchNestingField.
private static boolean matchNestingField(@Nonnull QueryComponent filter, @Nonnull ComponentWithSingleChild nestingComponent, @Nonnull NestingKeyExpression nesting, @Nonnull List<QueryComponent> groupFilters, @Nonnull List<Comparisons.Comparison> groupComparisons) {
if (nesting.getChild() instanceof NestingKeyExpression) {
NestingKeyExpression childNesting = (NestingKeyExpression) nesting.getChild();
QueryComponent childComponent = nestingComponent.getChild();
if (childComponent instanceof NestedField || childComponent instanceof OneOfThemWithComponent) {
if (childNesting.getParent().getFieldName().equals(((BaseField) childComponent).getFieldName()) && matchNestingField(filter, (ComponentWithSingleChild) childComponent, childNesting, groupFilters, groupComparisons)) {
return true;
}
}
} else if (nesting.getChild() instanceof FieldKeyExpression) {
FieldKeyExpression childField = (FieldKeyExpression) nesting.getChild();
if (nestingComponent.getChild() instanceof FieldWithComparison) {
FieldWithComparison comparisonFilter = (FieldWithComparison) nestingComponent.getChild();
if (comparisonFilter.getFieldName().equals(childField.getFieldName()) && (comparisonFilter.getComparison().getType() == Comparisons.Type.EQUALS || comparisonFilter.getComparison().getType() == Comparisons.Type.IS_NULL)) {
groupFilters.add(filter);
groupComparisons.add(comparisonFilter.getComparison());
return true;
}
}
}
return false;
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class ParameterRelationshipGraph method fromRecordQueryAndBindings.
/**
* Derive a relationship graph from a {@link RecordQuery} and a set of pre-bound parameters in handing in
* as a {@link Bindings} object.
* <p>
* Note that we do not derive additional relationships (yet). So for instance a query
* </p>
* <p>
* {@code
* ...
* WHERE x < $p1 AND x = $p2 AND y < $p2 AND y = $p3
* }
* </p>
* with pre-bindings {@code p1 -> 10, p2 -> 10, p3 -> 10} would result in a graph containing
* <p>
* {@code
* p1 EQUALS p1
* p1 EQUALS p2
* p2 EQUALS p1
* p2 EQUALS p2
* p2 EQUALS p3
* p3 EQUALS p2
* p3 EQUALS p3
* }
* </p>
* but it would not contain
* <p>
* {@code
* p1 EQUALS p3
* p3 EQUALS p1
* }
* </p>
* @param recordQuery query
* @param preBoundParameterBindings parameter bindings already known at planning time
* @return a new {@link ParameterRelationshipGraph}
*/
@Nonnull
public static ParameterRelationshipGraph fromRecordQueryAndBindings(@Nonnull final RecordQuery recordQuery, @Nonnull final Bindings preBoundParameterBindings) {
final QueryComponent filter = recordQuery.getFilter();
final ImmutableNetwork.Builder<String, Relationship> networkBuilder = NetworkBuilder.directed().allowsSelfLoops(true).allowsParallelEdges(true).immutable();
if (filter != null) {
groupedComparisons(filter).flatMap(entry -> StreamSupport.stream(crossProduct(ImmutableList.of(entry.getValue(), entry.getValue())).spliterator(), false)).map(list -> Pair.of(list.get(0), list.get(1))).forEach(pair -> {
final Comparisons.ComparisonWithParameter left = pair.getLeft();
final Comparisons.ComparisonWithParameter right = pair.getRight();
if (left.getParameter().equals(right.getParameter())) {
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
} else if (// It is possible that some of the parameters are not pre-bound. That's not an error,
preBoundParameterBindings.containsBinding(left.getParameter()) && preBoundParameterBindings.containsBinding(right.getParameter())) {
// it just means we cannot establish any sort of relationship between them.
final Object leftComparand = preBoundParameterBindings.get(left.getParameter());
final Object rightComparand = preBoundParameterBindings.get(right.getParameter());
if (Objects.equals(leftComparand, rightComparand)) {
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, left.getParameter(), right.getParameter());
Relationship.addEdge(networkBuilder, RelationshipType.EQUALS, right.getParameter(), left.getParameter());
}
}
});
}
return new ParameterRelationshipGraph(networkBuilder.build());
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class QueryToKeyMatcher method matches.
@Nonnull
private Match matches(@Nonnull AndComponent query, @Nonnull KeyExpression key, @Nonnull MatchingMode matchingMode, @Nullable FilterSatisfiedMask filterMask) {
final List<QueryComponent> listOfQueries = query.getChildren();
final Iterator<KeyExpression> keyChildIterator;
final int keyChildSize = key.getColumnSize();
if (key instanceof ThenKeyExpression) {
List<KeyExpression> children = ((ThenKeyExpression) key).getChildren();
keyChildIterator = children.iterator();
} else {
keyChildIterator = Iterators.singletonIterator(key);
}
// Keep a local mask so that if we can only partially fulfill queries we don't pollute the main
// one with our state
FilterSatisfiedMask localMask = FilterSatisfiedMask.of(query);
localMask.setExpression(key);
List<Comparison> comparisons = new ArrayList<>(keyChildSize);
while (keyChildIterator.hasNext()) {
KeyExpression exp = keyChildIterator.next();
// Look for a query segment that matches this expression
boolean found = false;
boolean foundInequality = false;
final Iterator<FilterSatisfiedMask> childMaskIterator = localMask.getChildren().iterator();
for (QueryComponent querySegment : listOfQueries) {
Match match = matches(querySegment, exp, matchingMode, childMaskIterator.next());
if (match.getType() != MatchType.NO_MATCH) {
found = true;
comparisons.addAll(match.getComparisons());
if (match.getType() == MatchType.INEQUALITY) {
foundInequality = true;
}
break;
}
}
if (!found) {
return Match.none();
}
// Only the last comparison in the list can be inequality.
if (localMask.allSatisfied() || foundInequality) {
break;
}
}
if (matchingMode.equals(MatchingMode.SATISFY_QUERY) && !localMask.allSatisfied() || matchingMode.equals(MatchingMode.COVER_KEY) && comparisons.size() < keyChildSize) {
// filters that have not yet been satisfied.
return Match.none();
}
if (filterMask != null) {
filterMask.mergeWith(localMask);
}
return new Match(comparisons);
}
Aggregations