Skip to content

Commit 6cb4d89

Browse files
committed
serialization for multi intersection implemented
1 parent 3c0d29e commit 6cb4d89

File tree

5 files changed

+114
-22
lines changed

5 files changed

+114
-22
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/AggregateIndexExpansionVisitor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ private ConstructSelectHavingResult constructSelectHaving(@Nonnull final Quantif
290290
groupByExpression.getGroupingValue() == null
291291
? null : FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
292292

293-
final var aggregateValueReference = FieldValue.ofOrdinalNumberAndFuseIfPossible(FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), groupingValueReference == null ? 0 : 1), 0);
293+
final var aggregateValueReference =
294+
FieldValue.ofOrdinalNumberAndFuseIfPossible(FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(),
295+
groupingValueReference == null ? 0 : 1), 0);
294296

295297
final var placeholderAliases = ImmutableList.<CorrelationIdentifier>builder();
296298
final var selectHavingGraphExpansionBuilder = GraphExpansion.builder().addQuantifier(groupByQun);

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/AggregateIndexMatchCandidate.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan;
5151
import com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan;
5252
import com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan;
53+
import com.apple.foundationdb.record.util.pair.NonnullPair;
5354
import com.google.common.base.Preconditions;
5455
import com.google.common.base.Verify;
5556
import com.google.common.collect.ImmutableList;
@@ -424,6 +425,23 @@ protected int getGroupingCount() {
424425
: keyExpressionGroupingCount;
425426
}
426427

428+
@Nonnull
429+
public NonnullPair<List<Value>, Value> getGroupingAndAggregateAccessors() {
430+
final var selectHavingResultValue = selectHavingExpression.getResultValue();
431+
final var selectHavingResultType = (Type.Record)selectHavingResultValue.getResultType();
432+
final var unbasedResultValue =
433+
QuantifiedObjectValue.of(Quantifier.current(), selectHavingResultType);
434+
435+
final var groupingCount = getGroupingCount();
436+
Verify.verify(selectHavingResultType.getFields().size() >= groupingCount);
437+
438+
final var deconstructedRecord = Values.deconstructRecord(unbasedResultValue);
439+
final var groupingAccessorValues =
440+
ImmutableList.copyOf(deconstructedRecord.subList(0, groupingCount));
441+
final var aggregateAccessorValue = deconstructedRecord.get(groupingCount);
442+
return NonnullPair.of(groupingAccessorValues, aggregateAccessorValue);
443+
}
444+
427445
/**
428446
* Creates a new {@link IndexKeyValueToPartialRecord} to facilitate the correct copying of information from the
429447
* index-tuple structure to a partial record (which in this case is dynamically-typed).

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryIntersectionPlan.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression;
5151
import com.apple.foundationdb.record.query.plan.cascades.explain.ExplainPlanVisitor;
5252
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
53+
import com.apple.foundationdb.record.query.plan.explain.ExplainPlanVisitor;
54+
import com.google.common.base.Suppliers;
5355
import com.google.common.base.Verify;
5456
import com.google.common.collect.ImmutableList;
5557
import com.google.common.collect.ImmutableMap;
@@ -64,6 +66,7 @@
6466
import java.util.Objects;
6567
import java.util.Set;
6668
import java.util.function.Function;
69+
import java.util.function.Supplier;
6770
import java.util.stream.Collectors;
6871
import java.util.stream.Stream;
6972

@@ -90,7 +93,7 @@ public abstract class RecordQueryIntersectionPlan implements RecordQueryPlanWith
9093
protected final boolean reverse;
9194

9295
@Nonnull
93-
private final Value resultValue;
96+
private final Supplier<Value> resultValueSupplier;
9497

9598
protected RecordQueryIntersectionPlan(@Nonnull final PlanSerializationContext serializationContext,
9699
@Nonnull final PRecordQueryIntersectionPlan recordQueryIntersectionPlanProto) {
@@ -102,7 +105,7 @@ protected RecordQueryIntersectionPlan(@Nonnull final PlanSerializationContext se
102105
this.quantifiers = quantifiersBuilder.build();
103106
this.comparisonKeyFunction = ComparisonKeyFunction.fromComparisonKeyFunctionProto(serializationContext, Objects.requireNonNull(recordQueryIntersectionPlanProto.getComparisonKeyFunction()));
104107
this.reverse = recordQueryIntersectionPlanProto.getReverse();
105-
this.resultValue = RecordQuerySetPlan.mergeValues(quantifiers);
108+
this.resultValueSupplier = Suppliers.memoize(this::computeResultValue);
106109
}
107110

108111
@SuppressWarnings("PMD.UnusedFormalParameter")
@@ -112,7 +115,7 @@ protected RecordQueryIntersectionPlan(@Nonnull List<Quantifier.Physical> quantif
112115
this.quantifiers = ImmutableList.copyOf(quantifiers);
113116
this.comparisonKeyFunction = comparisonKeyFunction;
114117
this.reverse = reverse;
115-
this.resultValue = RecordQuerySetPlan.mergeValues(quantifiers);
118+
this.resultValueSupplier = Suppliers.memoize(this::computeResultValue);
116119
}
117120

118121
@Nonnull
@@ -179,7 +182,12 @@ public Set<CorrelationIdentifier> getCorrelatedToWithoutChildren() {
179182
@Nonnull
180183
@Override
181184
public Value getResultValue() {
182-
return resultValue;
185+
return resultValueSupplier.get();
186+
}
187+
188+
@Nonnull
189+
protected Value computeResultValue() {
190+
return RecordQuerySetPlan.mergeValues(quantifiers);
183191
}
184192

185193
@Override

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/plans/RecordQueryMultiIntersectionOnValuesPlan.java

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@
2121
package com.apple.foundationdb.record.query.plan.plans;
2222

2323
import com.apple.foundationdb.record.EvaluationContext;
24-
import com.apple.foundationdb.record.EvaluationContextBuilder;
2524
import com.apple.foundationdb.record.ExecuteProperties;
2625
import com.apple.foundationdb.record.PlanDeserializer;
2726
import com.apple.foundationdb.record.PlanSerializationContext;
2827
import com.apple.foundationdb.record.RecordCoreException;
2928
import com.apple.foundationdb.record.RecordCursor;
3029
import com.apple.foundationdb.record.metadata.expressions.KeyExpression;
31-
import com.apple.foundationdb.record.planprotos.PRecordQueryIntersectionOnValuesPlan;
30+
import com.apple.foundationdb.record.planprotos.PRecordQueryMultiIntersectionOnValuesPlan;
3231
import com.apple.foundationdb.record.planprotos.PRecordQueryPlan;
3332
import com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase;
34-
import com.apple.foundationdb.record.provider.foundationdb.cursors.IntersectionCursor;
3533
import com.apple.foundationdb.record.provider.foundationdb.cursors.IntersectionMultiCursor;
34+
import com.apple.foundationdb.record.query.plan.cascades.Column;
3635
import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier;
3736
import com.apple.foundationdb.record.query.plan.cascades.Memoizer;
3837
import com.apple.foundationdb.record.query.plan.cascades.OrderingPart.ProvidedOrderingPart;
3938
import com.apple.foundationdb.record.query.plan.cascades.Quantifier;
4039
import com.apple.foundationdb.record.query.plan.cascades.Quantifiers;
4140
import com.apple.foundationdb.record.query.plan.cascades.Reference;
4241
import com.apple.foundationdb.record.query.plan.cascades.typing.Type;
42+
import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue;
4343
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
4444
import com.apple.foundationdb.record.query.plan.cascades.values.translation.TranslationMap;
4545
import com.google.auto.service.AutoService;
@@ -72,20 +72,34 @@ public class RecordQueryMultiIntersectionOnValuesPlan extends RecordQueryInterse
7272
private final Value resultValue;
7373

7474
protected RecordQueryMultiIntersectionOnValuesPlan(@Nonnull final PlanSerializationContext serializationContext,
75-
@Nonnull final PRecordQueryIntersectionOnValuesPlan recordQueryIntersectionOnValuesPlanProto) {
76-
super(serializationContext, Objects.requireNonNull(recordQueryIntersectionOnValuesPlanProto.getSuper()));
75+
@Nonnull final PRecordQueryMultiIntersectionOnValuesPlan recordQueryMultiIntersectionOnValuesPlanProto) {
76+
super(serializationContext, Objects.requireNonNull(recordQueryMultiIntersectionOnValuesPlanProto.getSuper()));
7777
this.comparisonKeyOrderingParts = null;
78+
this.resultValue = Value.fromValueProto(serializationContext,
79+
recordQueryMultiIntersectionOnValuesPlanProto.getResultValue());
7880
}
7981

8082
private RecordQueryMultiIntersectionOnValuesPlan(@Nonnull final List<Quantifier.Physical> quantifiers,
8183
@Nullable final List<ProvidedOrderingPart> comparisonKeyOrderingParts,
8284
@Nonnull final List<? extends Value> comparisonKeyValues,
85+
@Nonnull final List<Value> commonValues,
86+
@Nonnull final List<Value> pickupValues,
87+
final boolean reverse) {
88+
this(quantifiers, comparisonKeyOrderingParts, comparisonKeyValues,
89+
computeResultValue(quantifiers, commonValues, pickupValues), reverse);
90+
}
91+
92+
private RecordQueryMultiIntersectionOnValuesPlan(@Nonnull final List<Quantifier.Physical> quantifiers,
93+
@Nullable final List<ProvidedOrderingPart> comparisonKeyOrderingParts,
94+
@Nonnull final List<? extends Value> comparisonKeyValues,
95+
@Nonnull final Value resultValue,
8396
final boolean reverse) {
8497
super(quantifiers,
8598
new ComparisonKeyFunction.OnValues(Quantifier.current(), comparisonKeyValues),
8699
reverse);
87100
this.comparisonKeyOrderingParts =
88101
comparisonKeyOrderingParts == null ? null : ImmutableList.copyOf(comparisonKeyOrderingParts);
102+
this.resultValue = resultValue;
89103
}
90104

91105
@Nonnull
@@ -122,7 +136,38 @@ public List<? extends Value> getComparisonKeyValues() {
122136
@Nonnull
123137
@Override
124138
public Set<Type> getDynamicTypes() {
125-
return getComparisonKeyValues().stream().flatMap(comparisonKeyValue -> comparisonKeyValue.getDynamicTypes().stream()).collect(ImmutableSet.toImmutableSet());
139+
return getComparisonKeyValues().stream()
140+
.flatMap(comparisonKeyValue ->
141+
comparisonKeyValue.getDynamicTypes().stream()).collect(ImmutableSet.toImmutableSet());
142+
}
143+
144+
@Nonnull
145+
@Override
146+
protected Value computeResultValue() {
147+
return resultValue;
148+
}
149+
150+
@Nonnull
151+
private static Value computeResultValue(@Nonnull final List<? extends Quantifier> quantifiers,
152+
@Nonnull final List<Value> commonValues,
153+
@Nonnull final List<Value> pickupValues) {
154+
final var columnBuilder = ImmutableList.<Column<? extends Value>>builder();
155+
156+
// grab the common values from the first quantifier
157+
final var commonTranslationMap =
158+
TranslationMap.ofAliases(Quantifier.current(), quantifiers.get(0).getAlias());
159+
for (final var commonValue : commonValues) {
160+
columnBuilder.add(Column.unnamedOf(commonValue.translateCorrelations(commonTranslationMap)));
161+
}
162+
163+
for (int i = 0; i < quantifiers.size(); i++) {
164+
final var quantifier = quantifiers.get(i);
165+
final var pickUpTranslationMap =
166+
TranslationMap.ofAliases(Quantifier.current(), quantifier.getAlias());
167+
columnBuilder.add(Column.unnamedOf(pickupValues.get(i).translateCorrelations(pickUpTranslationMap)));
168+
}
169+
170+
return RecordConstructorValue.ofColumns(columnBuilder.build());
126171
}
127172

128173
@Nonnull
@@ -153,7 +198,7 @@ public <M extends Message> RecordCursor<QueryResult> executePlan(@Nonnull final
153198
}
154199
final var childEvaluationContext =
155200
childEvaluationContextBuilder.build(context.getTypeRepository());
156-
201+
return QueryResult.ofComputed(getResultValue().eval(store, childEvaluationContext));
157202
})
158203
.skipThenLimit(executeProperties.getSkip(), executeProperties.getReturnedRowLimit());
159204
}
@@ -166,6 +211,7 @@ public RecordQueryMultiIntersectionOnValuesPlan translateCorrelations(@Nonnull f
166211
return new RecordQueryMultiIntersectionOnValuesPlan(Quantifiers.narrow(Quantifier.Physical.class, translatedQuantifiers),
167212
comparisonKeyOrderingParts,
168213
getComparisonKeyValues(),
214+
resultValue,
169215
isReverse());
170216
}
171217

@@ -178,6 +224,7 @@ public RecordQueryMultiIntersectionOnValuesPlan withChildrenReferences(@Nonnull
178224
.collect(ImmutableList.toImmutableList()),
179225
comparisonKeyOrderingParts,
180226
getComparisonKeyValues(),
227+
resultValue,
181228
isReverse());
182229
}
183230

@@ -188,48 +235,56 @@ public RecordQueryMultiIntersectionOnValuesPlan strictlySorted(@Nonnull final Me
188235

189236
@Nonnull
190237
@Override
191-
public PRecordQueryIntersectionOnValuesPlan toProto(@Nonnull final PlanSerializationContext serializationContext) {
192-
return PRecordQueryIntersectionOnValuesPlan.newBuilder().setSuper(toRecordQueryIntersectionPlan(serializationContext)).build();
238+
public PRecordQueryMultiIntersectionOnValuesPlan toProto(@Nonnull final PlanSerializationContext serializationContext) {
239+
return PRecordQueryMultiIntersectionOnValuesPlan.newBuilder()
240+
.setSuper(toRecordQueryIntersectionPlan(serializationContext))
241+
.setResultValue(resultValue.toValueProto(serializationContext))
242+
.build();
193243
}
194244

195245
@Nonnull
196246
@Override
197247
public PRecordQueryPlan toRecordQueryPlanProto(@Nonnull final PlanSerializationContext serializationContext) {
198-
return PRecordQueryPlan.newBuilder().setIntersectionOnValuesPlan(toProto(serializationContext)).build();
248+
return PRecordQueryPlan.newBuilder()
249+
.setMultiIntersectionOnValuesPlan(toProto(serializationContext)).build();
199250
}
200251

201252
@Nonnull
202253
public static RecordQueryMultiIntersectionOnValuesPlan fromProto(@Nonnull final PlanSerializationContext serializationContext,
203-
@Nonnull final PRecordQueryIntersectionOnValuesPlan recordQueryIntersectionOnValuesPlanProto) {
204-
return new RecordQueryMultiIntersectionOnValuesPlan(serializationContext, recordQueryIntersectionOnValuesPlanProto);
254+
@Nonnull final PRecordQueryMultiIntersectionOnValuesPlan recordQueryMultiIntersectionOnValuesPlanProto) {
255+
return new RecordQueryMultiIntersectionOnValuesPlan(serializationContext, recordQueryMultiIntersectionOnValuesPlanProto);
205256
}
206257

207258
@Nonnull
208259
public static RecordQueryMultiIntersectionOnValuesPlan intersection(@Nonnull final List<Quantifier.Physical> quantifiers,
209260
@Nonnull final List<ProvidedOrderingPart> comparisonKeyOrderingParts,
261+
@Nonnull final List<Value> commonValues,
262+
@Nonnull final List<Value> pickupValues,
210263
final boolean isReverse) {
211264
return new RecordQueryMultiIntersectionOnValuesPlan(quantifiers,
212265
comparisonKeyOrderingParts,
213266
ProvidedOrderingPart.comparisonKeyValues(comparisonKeyOrderingParts, isReverse),
267+
commonValues,
268+
pickupValues,
214269
isReverse);
215270
}
216271

217272
/**
218273
* Deserializer.
219274
*/
220275
@AutoService(PlanDeserializer.class)
221-
public static class Deserializer implements PlanDeserializer<PRecordQueryIntersectionOnValuesPlan, RecordQueryMultiIntersectionOnValuesPlan> {
276+
public static class Deserializer implements PlanDeserializer<PRecordQueryMultiIntersectionOnValuesPlan, RecordQueryMultiIntersectionOnValuesPlan> {
222277
@Nonnull
223278
@Override
224-
public Class<PRecordQueryIntersectionOnValuesPlan> getProtoMessageClass() {
225-
return PRecordQueryIntersectionOnValuesPlan.class;
279+
public Class<PRecordQueryMultiIntersectionOnValuesPlan> getProtoMessageClass() {
280+
return PRecordQueryMultiIntersectionOnValuesPlan.class;
226281
}
227282

228283
@Nonnull
229284
@Override
230285
public RecordQueryMultiIntersectionOnValuesPlan fromProto(@Nonnull final PlanSerializationContext serializationContext,
231-
@Nonnull final PRecordQueryIntersectionOnValuesPlan recordQueryIntersectionOnValuesPlanProto) {
232-
return RecordQueryMultiIntersectionOnValuesPlan.fromProto(serializationContext, recordQueryIntersectionOnValuesPlanProto);
286+
@Nonnull final PRecordQueryMultiIntersectionOnValuesPlan recordQueryMultiIntersectionOnValuesPlanProto) {
287+
return RecordQueryMultiIntersectionOnValuesPlan.fromProto(serializationContext, recordQueryMultiIntersectionOnValuesPlanProto);
233288
}
234289
}
235290
}

fdb-record-layer-core/src/main/proto/record_query_plan.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,7 @@ message PRecordQueryPlan {
14191419
PRecursiveUnionQueryPlan recursive_union_query_plan = 36;
14201420
PRecordQueryTableFunctionPlan table_function_plan = 37;
14211421
PRecordQueryStreamingAggregationPlan2 streaming_aggregation_plan2 = 38;
1422+
PRecordQueryMultiIntersectionOnValuesPlan multi_intersection_on_values_plan = 39;
14221423
}
14231424
}
14241425

@@ -1782,6 +1783,14 @@ message PRecordQueryIntersectionOnValuesPlan {
17821783
optional PRecordQueryIntersectionPlan super = 1;
17831784
}
17841785

1786+
//
1787+
// PRecordQueryMultiIntersectionOnValuesPlan
1788+
//
1789+
message PRecordQueryMultiIntersectionOnValuesPlan {
1790+
optional PRecordQueryIntersectionPlan super = 1;
1791+
optional PValue result_value = 2;
1792+
}
1793+
17851794
//
17861795
// PRecordQueryInUnionPlan
17871796
//

0 commit comments

Comments
 (0)