use of com.apple.foundationdb.record.query.plan.TextScan in project fdb-record-layer by FoundationDB.
the class TextScanPlanner method getScanForNestedField.
@Nullable
private static TextScan getScanForNestedField(@Nonnull Index index, @Nonnull NestingKeyExpression textExpression, @Nonnull NestedField filter, @Nullable ScanComparisons groupingComparisons, boolean hasSort, @Nullable FilterSatisfiedMask filterMask) {
if (textExpression.getParent().getFanType().equals(KeyExpression.FanType.None) && textExpression.getParent().getFieldName().equals(filter.getFieldName())) {
final FilterSatisfiedMask childMask = filterMask != null ? filterMask.getChild(filter.getChild()) : null;
TextScan foundScan = getScanForFilter(index, textExpression.getChild(), filter.getChild(), groupingComparisons, hasSort, childMask);
if (foundScan != null && filterMask != null && filterMask.getExpression() == null) {
filterMask.setExpression(textExpression);
}
return foundScan;
}
return null;
}
use of com.apple.foundationdb.record.query.plan.TextScan in project fdb-record-layer by FoundationDB.
the class TextScanPlanner method getScanForRepeatedNestedField.
@Nullable
private static TextScan getScanForRepeatedNestedField(@Nonnull Index index, @Nonnull NestingKeyExpression textExpression, @Nonnull OneOfThemWithComponent filter, @Nullable ScanComparisons groupingComparisons, boolean hasSort, @Nullable FilterSatisfiedMask filterMask) {
if (textExpression.getParent().getFanType().equals(KeyExpression.FanType.FanOut) && textExpression.getParent().getFieldName().equals(filter.getFieldName())) {
// This doesn't work for certain complex queries on child fields.
// There are more details in this issue and there is an example of mis-planned query in the
// unit tests for this class:
// FIXME: Full Text: The Planner doesn't always correctly handle ands with nesteds (https://github.com/FoundationDB/fdb-record-layer/issues/53)
FilterSatisfiedMask childMask = filterMask != null ? filterMask.getChild(filter.getChild()) : null;
TextScan foundScan = getScanForFilter(index, textExpression.getChild(), filter.getChild(), groupingComparisons, hasSort, childMask);
if (foundScan != null && filterMask != null && filterMask.getExpression() != null) {
filterMask.setExpression(textExpression);
}
return foundScan;
}
return null;
}
use of com.apple.foundationdb.record.query.plan.TextScan 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.plan.TextScan in project fdb-record-layer by FoundationDB.
the class TextScanPlanner method getScanForQuery.
/**
* Get a scan that matches a filter in the list of filters provided. It looks to satisfy the grouping
* key of the index, and then it looks for a text filter within the list of filters and checks to
* see if the given index is compatible with the filter. If it is, it will construct a scan that
* satisfies that filter using the index.
*
* @param index the text index to check
* @param filter a filter that the query must satisfy
* @param hasSort whether the query has a sort associated with it
* @param filterMask a mask over the filter containing state about which filters have been satisfied
* @return a text scan or <code>null</code> if none is found
*/
@Nullable
public static TextScan getScanForQuery(@Nonnull Index index, @Nonnull QueryComponent filter, boolean hasSort, @Nonnull FilterSatisfiedMask filterMask) {
final KeyExpression indexExpression = index.getRootExpression();
final KeyExpression groupedKey;
final FilterSatisfiedMask localMask = FilterSatisfiedMask.of(filter);
final ScanComparisons groupingComparisons;
if (indexExpression instanceof GroupingKeyExpression) {
// Grouping expression present. Make sure this is satisfied.
final KeyExpression groupingKey = ((GroupingKeyExpression) indexExpression).getGroupingSubKey();
groupedKey = ((GroupingKeyExpression) indexExpression).getGroupedSubKey();
QueryToKeyMatcher groupingQueryMatcher = new QueryToKeyMatcher(filter);
QueryToKeyMatcher.Match groupingMatch = groupingQueryMatcher.matchesCoveringKey(groupingKey, localMask);
if (!groupingMatch.getType().equals(QueryToKeyMatcher.MatchType.EQUALITY)) {
return null;
}
groupingComparisons = new ScanComparisons(groupingMatch.getEqualityComparisons(), Collections.emptySet());
} else {
// Grouping expression not present. Use first column.
groupedKey = indexExpression;
groupingComparisons = null;
}
final KeyExpression textExpression = groupedKey.getSubKey(0, 1);
final TextScan foundScan = getScanForFilter(index, textExpression, filter, groupingComparisons, hasSort, localMask);
if (foundScan != null) {
filterMask.mergeWith(localMask);
return foundScan;
}
return null;
}
Aggregations