Search in sources :

Example 51 with GroupingKeyExpression

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));
        }
    }
}
Also used : FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Arrays(java.util.Arrays) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) Bindings(com.apple.foundationdb.record.Bindings) HashMap(java.util.HashMap) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Function(java.util.function.Function) ArrayList(java.util.ArrayList) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) Tuple(com.apple.foundationdb.tuple.Tuple) QueryRecordFunctionWithComparison(com.apple.foundationdb.record.query.expressions.QueryRecordFunctionWithComparison) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) Map(java.util.Map) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Set(java.util.Set) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) RecordQueryScoreForRankPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScoreForRankPlan) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) Collectors(java.util.stream.Collectors) AndOrComponent(com.apple.foundationdb.record.query.expressions.AndOrComponent) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) Index(com.apple.foundationdb.record.metadata.Index) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) Optional(java.util.Optional) API(com.apple.foundationdb.annotation.API) RecordFunction(com.apple.foundationdb.record.RecordFunction) Comparator(java.util.Comparator) ComponentWithChildren(com.apple.foundationdb.record.query.expressions.ComponentWithChildren) Collections(java.util.Collections) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ArrayList(java.util.ArrayList) Index(com.apple.foundationdb.record.metadata.Index) NestedField(com.apple.foundationdb.record.query.expressions.NestedField) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) QueryRecordFunctionWithComparison(com.apple.foundationdb.record.query.expressions.QueryRecordFunctionWithComparison) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison)

Example 52 with GroupingKeyExpression

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;
}
Also used : ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) TextScan(com.apple.foundationdb.record.query.plan.TextScan) QueryToKeyMatcher(com.apple.foundationdb.record.query.QueryToKeyMatcher) Nullable(javax.annotation.Nullable)

Example 53 with GroupingKeyExpression

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();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Nonnull(javax.annotation.Nonnull)

Example 54 with GroupingKeyExpression

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);
        }
    }
}
Also used : GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)

Example 55 with GroupingKeyExpression

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);
        }
    };
}
Also used : IndexValidator(com.apple.foundationdb.record.metadata.IndexValidator) Set(java.util.Set) Nonnull(javax.annotation.Nonnull) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Index(com.apple.foundationdb.record.metadata.Index) MetaDataValidator(com.apple.foundationdb.record.metadata.MetaDataValidator) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Nonnull(javax.annotation.Nonnull)

Aggregations

GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)57 Index (com.apple.foundationdb.record.metadata.Index)41 Test (org.junit.jupiter.api.Test)39 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)35 ArrayList (java.util.ArrayList)29 Nonnull (javax.annotation.Nonnull)25 IndexTypes (com.apple.foundationdb.record.metadata.IndexTypes)23 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)22 List (java.util.List)22 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)21 Message (com.google.protobuf.Message)21 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)21 RecordMetaDataBuilder (com.apple.foundationdb.record.RecordMetaDataBuilder)20 IndexAggregateFunction (com.apple.foundationdb.record.metadata.IndexAggregateFunction)20 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)20 EmptyKeyExpression (com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression)20 Query (com.apple.foundationdb.record.query.expressions.Query)20 Tuple (com.apple.foundationdb.tuple.Tuple)20 Tags (com.apple.test.Tags)20 Tag (org.junit.jupiter.api.Tag)20