Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d7474a6
save point
normen662 Mar 3, 2025
c3f424f
pulling up matchedAggregationValueMap works
normen662 Mar 6, 2025
348b025
pre pulling up unmatched values
normen662 Mar 9, 2025
e01e237
pullng up unmatched values
normen662 Mar 11, 2025
2004288
intersection complete
normen662 Mar 12, 2025
1b4c433
intersection complete
normen662 Mar 12, 2025
c3bfa3f
save-point
normen662 Mar 14, 2025
4e6a3d4
serialization for multi intersection implemented
normen662 Mar 15, 2025
09e50d0
first plans
normen662 Mar 18, 2025
21414aa
basic aggregation queries using agg indexes intersections work
normen662 Mar 18, 2025
ae49840
more agg queriers work
normen662 Mar 21, 2025
3c7f6ba
rebased; regular intersections work; pre rollup
normen662 Mar 24, 2025
d7ac66f
roll ups work
normen662 Mar 26, 2025
0d2b456
rollups work
normen662 Mar 29, 2025
352b6f0
ordering sort of works
normen662 Apr 2, 2025
87ace0e
agg testcases run
normen662 Apr 5, 2025
84df936
cleaning up
normen662 Apr 6, 2025
0a406b8
build somewhat stable
normen662 Apr 7, 2025
d322294
some polishing
normen662 Apr 9, 2025
85fa160
updating tests and writing documentation
normen662 Apr 10, 2025
433ab30
fixups after rebasing
normen662 May 26, 2025
ec485ed
regenerated metrics files
normen662 May 27, 2025
80c269e
addressing rebase fallout
normen662 Jul 8, 2025
7a4dac9
addressing some review comments
normen662 Aug 25, 2025
4a486eb
regenerating tests
normen662 Sep 1, 2025
6c00818
extract common code out of ::compensate
normen662 Sep 1, 2025
969e3fd
responding to more comments
normen662 Sep 1, 2025
fe4895f
fixing some additional test case failures
normen662 Sep 1, 2025
d5b001d
changing some unsupported methods implementations
normen662 Sep 3, 2025
db5859d
adding tests
normen662 Sep 3, 2025
4b2c8c1
adding tests
normen662 Sep 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ static <T> EnumeratingIterable<T> singleIterable(@Nonnull final T singleElement)
return new SingleIterable<>(singleElement);
}

static <T> EnumeratingIterable<T> emptyOnEmptyIterable() {
return new SingleIterable<>();
}

/**
* An implementation of {@link EnumeratingIterable} that is optimized to work for empty
* input sets.
Expand Down Expand Up @@ -84,13 +88,17 @@ public EnumeratingIterator<T> iterator() {
* @param <T> type
*/
class SingleIterable<T> implements EnumeratingIterable<T> {
@Nonnull
@Nullable
private final T singleElement;

private SingleIterable(@Nonnull final T singleElement) {
this.singleElement = singleElement;
}

private SingleIterable() {
this.singleElement = null;
}

@Nonnull
@Override
public EnumeratingIterator<T> iterator() {
Expand All @@ -103,12 +111,12 @@ public EnumeratingIterator<T> iterator() {
* @param <T> type of the element
*/
class SingleIterator<T> extends AbstractIterator<List<T>> implements EnumeratingIterator<T> {
@Nonnull
@Nullable
private final T singleElement;

boolean atFirst = true;

private SingleIterator(@Nonnull final T singleElement) {
private SingleIterator(@Nullable final T singleElement) {
this.singleElement = singleElement;
}

Expand All @@ -128,6 +136,9 @@ protected List<T> computeNext() {

atFirst = false;

if (singleElement == null) {
return ImmutableList.of();
}
return ImmutableList.of(singleElement);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,6 @@ public static <T, P> Iterable<List<T>> satisfyingPermutations(@Nonnull final Par
@Nonnull final List<P> targetPermutation,
@Nonnull final Function<T, P> domainMapper,
@Nonnull final Function<List<T>, Integer> satisfiabilityFunction) {
if (partiallyOrderedSet.isEmpty()) {
return ImmutableList.of();
}

if (partiallyOrderedSet.size() < targetPermutation.size()) {
return ImmutableList.of();
}
Expand All @@ -565,9 +561,11 @@ protected Iterator<T> domain(final int t) {
}
}
};
} else {
Verify.verify(partiallyOrderedSet.size() == 1);
} else if (partiallyOrderedSet.size() == 1) {
enumeratingIterator = EnumeratingIterable.singleIterable(Iterables.getOnlyElement(partiallyOrderedSet.getSet())).iterator();
} else {
Verify.verify(partiallyOrderedSet.isEmpty());
enumeratingIterator = EnumeratingIterable.<T>emptyOnEmptyIterable().iterator();
}

return () -> new AbstractIterator<>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ public QueryPredicate getPredicate() {
return predicate;
}

public boolean isTautology() {
return predicate.isTautology();
}

public boolean isConstrained() {
return !getPredicate().isTautology();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.apple.foundationdb.record.query.plan.cascades.expressions.SelectExpression;
import com.apple.foundationdb.record.query.plan.cascades.predicates.Placeholder;
import com.apple.foundationdb.record.query.plan.cascades.predicates.PredicateWithValueAndRanges;
import com.apple.foundationdb.record.query.plan.cascades.values.AggregateValue;
import com.apple.foundationdb.record.query.plan.cascades.values.ArithmeticValue;
import com.apple.foundationdb.record.query.plan.cascades.values.CountValue;
import com.apple.foundationdb.record.query.plan.cascades.values.EmptyValue;
Expand All @@ -57,10 +58,10 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;

Expand All @@ -72,7 +73,12 @@
public class AggregateIndexExpansionVisitor extends KeyExpressionExpansionVisitor
implements ExpansionVisitor<KeyExpressionExpansionVisitor.VisitorState> {
@Nonnull
static final Supplier<Map<String, BuiltInFunction<? extends Value>>> aggregateMap = Suppliers.memoize(AggregateIndexExpansionVisitor::computeAggregateMap);
static final Supplier<Map<String, BuiltInFunction<? extends Value>>> aggregateMap =
Suppliers.memoize(AggregateIndexExpansionVisitor::computeAggregateMap);

@Nonnull
static final Supplier<Map<String, BuiltInFunction<? extends Value>>> rollUpAggregateMap =
Suppliers.memoize(AggregateIndexExpansionVisitor::computeRollUpAggregateMap);

@Nonnull
protected final Index index;
Expand All @@ -92,7 +98,8 @@ public class AggregateIndexExpansionVisitor extends KeyExpressionExpansionVisito
* @param recordTypes The indexed record types.
*/
public AggregateIndexExpansionVisitor(@Nonnull final Index index, @Nonnull final Collection<RecordType> recordTypes) {
Preconditions.checkArgument(IndexTypes.BITMAP_VALUE.equals(index.getType()) || aggregateMap.get().containsKey(index.getType()));
Preconditions.checkArgument(IndexTypes.BITMAP_VALUE.equals(index.getType()) ||
aggregateMap.get().containsKey(index.getType()));
Preconditions.checkArgument(index.getRootExpression() instanceof GroupingKeyExpression);
this.index = index;
this.groupingKeyExpression = ((GroupingKeyExpression)index.getRootExpression());
Expand Down Expand Up @@ -139,9 +146,9 @@ public MatchCandidate expand(@Nonnull final Supplier<Quantifier.ForEach> baseQua
.addAll(groupByPlaceholders).build();

// 3. construct SELECT-HAVING with SORT on top.
final var selectHavingAndPlaceholderAliases = constructSelectHaving(groupByQun, placeholders);
final var selectHaving = selectHavingAndPlaceholderAliases.getLeft();
final var placeHolderAliases = selectHavingAndPlaceholderAliases.getRight();
final var constructSelectHavingResult = constructSelectHaving(groupByQun, placeholders);
final var selectHaving = constructSelectHavingResult.getSelectExpression();
final var placeHolderAliases = constructSelectHavingResult.getPlaceholderAliases();

// 4. add sort on top, if necessary, this will be absorbed later on as an ordering property of the match candidate.
final var maybeWithSort = placeHolderAliases.isEmpty()
Expand Down Expand Up @@ -243,7 +250,8 @@ protected NonnullPair<Quantifier, List<Placeholder>> constructGroupBy(@Nonnull f
throw new RecordCoreException("unable to plan group by with non-field value")
.addLogInfo(LogMessageKeys.VALUE, groupedValue);
}
final var aggregateValue = (Value)aggregateMap.get().get(index.getType()).encapsulate(ImmutableList.of(argument));
final var aggregateValue =
aggregateValue(index, argument).orElseThrow(() -> new RecordCoreException("unknown aggregation type"));
// add an RCV column representing the grouping columns as the first result set column
// also, make sure to set the field type names correctly for each field value in the grouping keys RCV.

Expand Down Expand Up @@ -278,19 +286,25 @@ protected NonnullPair<Quantifier, List<Placeholder>> constructGroupBy(@Nonnull f
}

@Nonnull
private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSelectHaving(@Nonnull final Quantifier groupByQun,
@Nonnull final List<Placeholder> selectWherePlaceholders) {
private ConstructSelectHavingResult constructSelectHaving(@Nonnull final Quantifier groupByQun,
@Nonnull final List<Placeholder> selectWherePlaceholders) {
final var rangesOverExpression = groupByQun.getRangesOver().get();
Verify.verify(rangesOverExpression instanceof GroupByExpression);
final var groupByExpression = (GroupByExpression)rangesOverExpression;

// the grouping value in GroupByExpression comes first (if set).
@Nullable final var groupingValueReference =
(groupByQun.getRangesOver().get() instanceof GroupByExpression && ((GroupByExpression)groupByQun.getRangesOver().get()).getGroupingValue() == null)
? null
: FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
groupByExpression.getGroupingValue() == null
? null : FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);

final var aggregateValueReference = FieldValue.ofOrdinalNumberAndFuseIfPossible(FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), groupingValueReference == null ? 0 : 1), 0);
final var aggregateValueReference =
FieldValue.ofOrdinalNumberAndFuseIfPossible(FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(),
groupingValueReference == null ? 0 : 1), 0);

final var placeholderAliases = ImmutableList.<CorrelationIdentifier>builder();
final var selectHavingGraphExpansionBuilder = GraphExpansion.builder().addQuantifier(groupByQun);
final List<Value> groupingValues = groupingValueReference == null ? Collections.emptyList() : Values.deconstructRecord(groupingValueReference);
final List<Value> groupingValues = groupingValueReference == null
? ImmutableList.of() : Values.deconstructRecord(groupingValueReference);
if (groupingValueReference != null) {
int i = 0;
for (final var groupingValue : groupingValues) {
Expand Down Expand Up @@ -322,7 +336,15 @@ private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSele
} else {
finalPlaceholders = placeholderAliases.build();
}
return NonnullPair.of(selectHavingGraphExpansionBuilder.build().buildSelect(), finalPlaceholders);

return new ConstructSelectHavingResult(selectHavingGraphExpansionBuilder.build().buildSelect(),
finalPlaceholders);
}

@Nonnull
public static Optional<AggregateValue> aggregateValue(@Nonnull final Index index, @Nonnull final Value argument) {
return Optional.of((AggregateValue)aggregateMap.get()
.get(index.getType()).encapsulate(ImmutableList.of(argument)));
}

@Nonnull
Expand All @@ -339,4 +361,53 @@ private static Map<String, BuiltInFunction<? extends Value>> computeAggregateMap
mapBuilder.put(IndexTypes.PERMUTED_MIN, new NumericAggregationValue.MinFn());
return mapBuilder.build();
}

public static boolean canBeRolledUp(@Nonnull final String indexType) {
return rollUpAggregateMap.get().containsKey(indexType);
}

@Nonnull
public static Optional<AggregateValue> rollUpAggregateValueMaybe(@Nonnull final String indexType, @Nonnull final Value argument) {
return Optional.ofNullable(rollUpAggregateMap.get()
.get(indexType))
.map(fn -> (AggregateValue)fn.encapsulate(ImmutableList.of(argument)));
}

@Nonnull
private static Map<String, BuiltInFunction<? extends Value>> computeRollUpAggregateMap() {
final ImmutableMap.Builder<String, BuiltInFunction<? extends Value>> mapBuilder = ImmutableMap.builder();
mapBuilder.put(IndexTypes.MAX_EVER_LONG, new NumericAggregationValue.MaxFn());
mapBuilder.put(IndexTypes.MIN_EVER_LONG, new NumericAggregationValue.MinFn());
mapBuilder.put(IndexTypes.MAX_EVER_TUPLE, new NumericAggregationValue.MaxFn());
mapBuilder.put(IndexTypes.MIN_EVER_TUPLE, new NumericAggregationValue.MinFn());
mapBuilder.put(IndexTypes.SUM, new NumericAggregationValue.SumFn());
mapBuilder.put(IndexTypes.COUNT, new NumericAggregationValue.SumFn());
mapBuilder.put(IndexTypes.COUNT_NOT_NULL, new NumericAggregationValue.SumFn());
mapBuilder.put(IndexTypes.PERMUTED_MAX, new NumericAggregationValue.MaxFn());
mapBuilder.put(IndexTypes.PERMUTED_MIN, new NumericAggregationValue.MinFn());
return mapBuilder.build();
}

private static class ConstructSelectHavingResult {
@Nonnull
private final SelectExpression selectExpression;
@Nonnull
private final List<CorrelationIdentifier> placeholderAliases;

private ConstructSelectHavingResult(@Nonnull final SelectExpression selectExpression,
@Nonnull final List<CorrelationIdentifier> placeholderAliases) {
this.selectExpression = selectExpression;
this.placeholderAliases = placeholderAliases;
}

@Nonnull
public SelectExpression getSelectExpression() {
return selectExpression;
}

@Nonnull
public List<CorrelationIdentifier> getPlaceholderAliases() {
return placeholderAliases;
}
}
}
Loading
Loading