use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class RankComparisons method findComparison.
private void findComparison(@Nonnull QueryRecordFunctionWithComparison comparison, @Nonnull List<Index> indexes, @Nonnull List<QueryComponent> potentialGroupFilters, @Nonnull AtomicInteger counter) {
RecordFunction<?> recordFunction = comparison.getFunction();
// TODO: Should share with indexMaintainerForAggregateFunction
// TODO: Move index-specific query planning behavior outside of planner (https://github.com/FoundationDB/fdb-record-layer/issues/17)
List<String> requiredIndexTypes;
if (recordFunction.getName().equals(FunctionNames.RANK)) {
requiredIndexTypes = Arrays.asList(IndexTypes.RANK, IndexTypes.TIME_WINDOW_LEADERBOARD);
} else if (recordFunction.getName().equals(FunctionNames.TIME_WINDOW_RANK)) {
requiredIndexTypes = Collections.singletonList(IndexTypes.TIME_WINDOW_LEADERBOARD);
} else {
requiredIndexTypes = null;
}
if (requiredIndexTypes != null) {
final GroupingKeyExpression operand = ((IndexRecordFunction) recordFunction).getOperand();
Optional<Index> matchingIndex = indexes.stream().filter(index -> requiredIndexTypes.contains(index.getType()) && index.getRootExpression().equals(operand)).min(Comparator.comparing(Index::getColumnSize));
if (matchingIndex.isPresent()) {
final KeyExpression groupBy = operand.getGroupingSubKey();
final List<QueryComponent> groupFilters = new ArrayList<>();
final List<Comparisons.Comparison> groupComparisons = new ArrayList<>();
if (!GroupingValidator.findGroupKeyFilters(potentialGroupFilters, groupBy, groupFilters, groupComparisons)) {
return;
}
QueryComponent substitute = null;
String bindingName = null;
final Comparisons.Type comparisonType = comparison.getComparison().getType();
if (!operand.createsDuplicates() && !comparisonType.isUnary()) {
bindingName = Bindings.Internal.RANK.bindingName(Integer.toString(counter.getAndIncrement()));
Comparisons.Comparison substituteComparison = new Comparisons.ParameterComparison(comparisonType, bindingName, Bindings.Internal.RANK);
final KeyExpression grouped = operand.getGroupedSubKey();
if (grouped instanceof FieldKeyExpression) {
substitute = new FieldWithComparison(((FieldKeyExpression) grouped).getFieldName(), substituteComparison);
} else if (grouped instanceof NestingKeyExpression) {
NestingKeyExpression nesting = (NestingKeyExpression) grouped;
if (nesting.getChild() instanceof FieldKeyExpression) {
substitute = new NestedField(nesting.getParent().getFieldName(), new FieldWithComparison(((FieldKeyExpression) nesting.getChild()).getFieldName(), substituteComparison));
}
}
if (substitute == null) {
bindingName = null;
}
}
comparisons.put(comparison, new RankComparison(comparison, matchingIndex.get(), groupFilters, groupComparisons, substitute, bindingName));
}
}
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression 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;
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class TextScanPlanner method getOtherFields.
@Nonnull
public static List<KeyExpression> getOtherFields(@Nonnull KeyExpression indexExpression) {
ImmutableList.Builder<KeyExpression> otherFields = ImmutableList.builder();
if (indexExpression instanceof GroupingKeyExpression) {
final GroupingKeyExpression groupingIndexExpression = (GroupingKeyExpression) indexExpression;
final KeyExpression groupedKey = groupingIndexExpression.getGroupedSubKey();
final KeyExpression groupingKey = groupingIndexExpression.getGroupingSubKey();
otherFields.addAll(groupingKey.normalizeKeyForPositions());
otherFields.addAll(groupedKey.getSubKey(1, groupedKey.getColumnSize()).normalizeKeyForPositions());
} else {
otherFields.addAll(indexExpression.getSubKey(1, indexExpression.getColumnSize()).normalizeKeyForPositions());
}
return otherFields.build();
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class IndexValidator method validateVersionInGroupedKeys.
protected void validateVersionInGroupedKeys() {
KeyExpression key = index.getRootExpression();
validateGrouping(1);
if (key instanceof GroupingKeyExpression) {
GroupingKeyExpression grouping = (GroupingKeyExpression) key;
KeyExpression groupingKey = grouping.getGroupingSubKey();
if (groupingKey.versionColumns() != 0) {
throw new KeyExpression.InvalidExpressionException(String.format("there must be no version entries in grouping key in %s index", index.getType()), LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.INDEX_KEY, key);
}
final KeyExpression groupedKey = grouping.getGroupedSubKey();
if (groupedKey.versionColumns() != 1) {
throw new KeyExpression.InvalidExpressionException(String.format("there must be exactly 1 version entry in grouped key in %s index", index.getType()), LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.INDEX_KEY, key);
}
}
}
use of com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression in project fdb-record-layer by FoundationDB.
the class PermutedMinMaxIndexMaintainerFactory method getIndexValidator.
@Override
@Nonnull
public IndexValidator getIndexValidator(Index index) {
return new IndexValidator(index) {
@Override
public void validate(@Nonnull MetaDataValidator metaDataValidator) {
super.validate(metaDataValidator);
validateGrouping(1);
int groupingCount = ((GroupingKeyExpression) index.getRootExpression()).getGroupingCount();
validateNotVersion();
int permutedSize = PermutedMinMaxIndexMaintainer.getPermutedSize(index);
if (permutedSize < 0) {
throw new MetaDataException("permuted size cannot be negative", LogMessageKeys.INDEX_NAME, index.getName());
} else if (permutedSize == 0) {
throw new MetaDataException("no permutation does not need a special index type for MIN and MAX", LogMessageKeys.INDEX_NAME, index.getName());
} else if (permutedSize > groupingCount) {
throw new MetaDataException("permuted size cannot be larger than grouping size", LogMessageKeys.INDEX_NAME, index.getName());
}
}
@Override
public void validateChangedOptions(@Nonnull Index oldIndex, @Nonnull Set<String> changedOptions) {
if (changedOptions.contains(IndexOptions.PERMUTED_SIZE_OPTION)) {
throw new MetaDataException("permuted size changed", LogMessageKeys.INDEX_NAME, index.getName());
}
super.validateChangedOptions(oldIndex, changedOptions);
}
};
}
Aggregations