42
42
import com .apple .foundationdb .record .query .plan .cascades .typing .TypeRepository ;
43
43
import com .apple .foundationdb .record .query .plan .cascades .values .FieldValue ;
44
44
import com .apple .foundationdb .record .query .plan .cascades .values .QuantifiedObjectValue ;
45
+ import com .apple .foundationdb .record .query .plan .cascades .values .RecordConstructorValue ;
45
46
import com .apple .foundationdb .record .query .plan .cascades .values .Value ;
46
47
import com .apple .foundationdb .record .query .plan .cascades .values .Values ;
47
48
import com .apple .foundationdb .record .query .plan .cascades .values .simplification .OrderingValueComputationRuleSet ;
49
+ import com .apple .foundationdb .record .query .plan .cascades .values .translation .PullUp ;
48
50
import com .apple .foundationdb .record .query .plan .plans .RecordQueryAggregateIndexPlan ;
49
51
import com .apple .foundationdb .record .query .plan .plans .RecordQueryFetchFromPartialRecordPlan ;
50
52
import com .apple .foundationdb .record .query .plan .plans .RecordQueryIndexPlan ;
51
53
import com .apple .foundationdb .record .query .plan .plans .RecordQueryPlan ;
54
+ import com .apple .foundationdb .record .query .plan .plans .RecordQueryStreamingAggregationPlan ;
52
55
import com .apple .foundationdb .record .util .pair .NonnullPair ;
53
56
import com .google .common .base .Preconditions ;
54
57
import com .google .common .base .Verify ;
@@ -171,7 +174,7 @@ public KeyExpression getFullKeyExpression() {
171
174
172
175
@ Override
173
176
public String toString () {
174
- return "Agg [" + getName () + "; " + index .getType () + "]" ;
177
+ return "AGG [" + getName () + "; " + index .getType () + "]" ;
175
178
}
176
179
177
180
@ Override
@@ -359,6 +362,33 @@ public Ordering computeOrderingFromScanComparisons(@Nonnull final ScanComparison
359
362
return Ordering .ofOrderingSequence (bindingMapBuilder .build (), orderingSequenceBuilder .build (), isDistinct );
360
363
}
361
364
365
+ @ Nullable
366
+ @ Override
367
+ public PullUp .UnificationPullUp prepareForUnification (@ Nonnull final PartialMatch partialMatch ,
368
+ @ Nonnull final CorrelationIdentifier topAlias ,
369
+ @ Nonnull final CorrelationIdentifier topCandidateAlias ) {
370
+ final var regularMatchInfo = partialMatch .getRegularMatchInfo ();
371
+ if (regularMatchInfo .getRollUpToGroupingValues () != null ) {
372
+ final var groupingAndAggregateAccessors =
373
+ getGroupingAndAggregateAccessors (topCandidateAlias );
374
+ final var groupingAccessorValues = groupingAndAggregateAccessors .getLeft ();
375
+ final var aggregateAccessorValue = groupingAndAggregateAccessors .getRight ();
376
+ final var allFields =
377
+ ((Type .Record )selectHavingExpression .getResultValue ().getResultType ()).getFields ();
378
+ final var rollUpColumnsBuilder =
379
+ ImmutableList .<Column <? extends Value >>builder ();
380
+ final var numGroupings = regularMatchInfo .getRollUpToGroupingValues ().size ();
381
+ for (int i = 0 ; i < numGroupings ; i ++) {
382
+ final var field = allFields .get (i );
383
+ rollUpColumnsBuilder .add (Column .of (field , groupingAccessorValues .get (i )));
384
+ }
385
+ rollUpColumnsBuilder .add (Column .of (allFields .get (allFields .size () - 1 ), aggregateAccessorValue ));
386
+ return PullUp .forUnification (topAlias , RecordConstructorValue .ofColumns (rollUpColumnsBuilder .build ()),
387
+ ImmutableSet .of (topCandidateAlias ));
388
+ }
389
+ return null ;
390
+ }
391
+
362
392
@ Nonnull
363
393
@ Override
364
394
public RecordQueryPlan toEquivalentPlan (@ Nonnull final PartialMatch partialMatch ,
@@ -369,13 +399,14 @@ public RecordQueryPlan toEquivalentPlan(@Nonnull final PartialMatch partialMatch
369
399
final var baseRecordType = Type .Record .fromFieldDescriptorsMap (RecordMetaData .getFieldDescriptorMapFromTypes (recordTypes ));
370
400
371
401
final var selectHavingResultValue = selectHavingExpression .getResultValue ();
372
- final var resultType = selectHavingResultValue .getResultType ();
402
+ final var resultType = ( Type . Record ) selectHavingResultValue .getResultType ();
373
403
final var messageDescriptor =
374
404
Objects .requireNonNull (TypeRepository .newBuilder ()
375
405
.addTypeIfNeeded (resultType )
376
406
.build ()
377
407
.getMessageDescriptor (resultType ));
378
- final var constraintMaybe = partialMatch .getRegularMatchInfo ().getConstraint ();
408
+ final var regularMatchInfo = partialMatch .getRegularMatchInfo ();
409
+ final var constraintMaybe = regularMatchInfo .getConstraint ();
379
410
380
411
final var indexEntryConverter = createIndexEntryConverter (messageDescriptor );
381
412
final var aggregateIndexScan = new RecordQueryIndexPlan (index .getName (),
@@ -389,12 +420,45 @@ public RecordQueryPlan toEquivalentPlan(@Nonnull final PartialMatch partialMatch
389
420
baseRecordType ,
390
421
QueryPlanConstraint .tautology ());
391
422
392
- return new RecordQueryAggregateIndexPlan (aggregateIndexScan ,
423
+ var plan = new RecordQueryAggregateIndexPlan (aggregateIndexScan ,
393
424
recordTypes .get (0 ).getName (),
394
425
indexEntryConverter ,
395
426
selectHavingResultValue ,
396
427
groupByResultValue ,
397
428
constraintMaybe );
429
+ if (regularMatchInfo .getRollUpToGroupingValues () != null ) {
430
+ //
431
+ // We need to perform a roll up.
432
+ //
433
+ final var aggregateIndexScanReference = memoizer .memoizePlans (plan );
434
+ final var aggregateIndexScanAlias = Quantifier .uniqueId ();
435
+
436
+ //final var recordValues = Values.deconstructRecord(recordValue);
437
+ final var groupingAndAggregateAccessors =
438
+ getGroupingAndAggregateAccessors (regularMatchInfo .getRollUpToGroupingValues ().size (),
439
+ aggregateIndexScanAlias );
440
+ final var groupingAccessorValues = groupingAndAggregateAccessors .getLeft ();
441
+ final var aggregateAccessorValue = groupingAndAggregateAccessors .getRight ();
442
+ final var allFields = resultType .getFields ();
443
+ final var rollUpGroupingColumnsBuilder =
444
+ ImmutableList .<Column <? extends Value >>builder ();
445
+ for (int i = 0 ; i < groupingAccessorValues .size (); i ++) {
446
+ final var field = allFields .get (i );
447
+ rollUpGroupingColumnsBuilder .add (Column .of (field , groupingAccessorValues .get (i )));
448
+ }
449
+
450
+ final var rollUpAggregateValueOptional =
451
+ AggregateIndexExpansionVisitor .rollUpAggregateValueMaybe (index ,
452
+ aggregateAccessorValue );
453
+
454
+ final var aggregateIndexScanQuantifier =
455
+ Quantifier .physical (aggregateIndexScanReference , aggregateIndexScanAlias );
456
+
457
+ return RecordQueryStreamingAggregationPlan .ofFlattened (aggregateIndexScanQuantifier ,
458
+ RecordConstructorValue .ofColumns (rollUpGroupingColumnsBuilder .build (), resultType .isNullable ()),
459
+ rollUpAggregateValueOptional .orElseThrow (() -> new RecordCoreException ("unknown rollup operation" )));
460
+ }
461
+ return plan ;
398
462
}
399
463
400
464
@ Nonnull
@@ -411,19 +475,22 @@ protected int getGroupingCount() {
411
475
}
412
476
413
477
@ Nonnull
414
- public NonnullPair <List <Value >, Value > getGroupingAndAggregateAccessors () {
478
+ public NonnullPair <List <Value >, Value > getGroupingAndAggregateAccessors (@ Nonnull final CorrelationIdentifier alias ) {
479
+ return getGroupingAndAggregateAccessors (getGroupingCount (), alias );
480
+ }
481
+
482
+ @ Nonnull
483
+ public NonnullPair <List <Value >, Value > getGroupingAndAggregateAccessors (final int numGroupings ,
484
+ @ Nonnull final CorrelationIdentifier alias ) {
415
485
final var selectHavingResultValue = selectHavingExpression .getResultValue ();
416
486
final var selectHavingResultType = (Type .Record )selectHavingResultValue .getResultType ();
417
487
final var unbasedResultValue =
418
- QuantifiedObjectValue .of (Quantifier .current (), selectHavingResultType );
419
-
420
- final var groupingCount = getGroupingCount ();
421
- Verify .verify (selectHavingResultType .getFields ().size () >= groupingCount );
422
-
488
+ QuantifiedObjectValue .of (alias , selectHavingResultType );
423
489
final var deconstructedRecord = Values .deconstructRecord (unbasedResultValue );
490
+ Verify .verify (deconstructedRecord .size () > numGroupings );
424
491
final var groupingAccessorValues =
425
- ImmutableList .copyOf (deconstructedRecord .subList (0 , groupingCount ));
426
- final var aggregateAccessorValue = deconstructedRecord .get (groupingCount );
492
+ ImmutableList .copyOf (deconstructedRecord .subList (0 , numGroupings ));
493
+ final var aggregateAccessorValue = deconstructedRecord .get (deconstructedRecord . size () - 1 );
427
494
return NonnullPair .of (groupingAccessorValues , aggregateAccessorValue );
428
495
}
429
496
0 commit comments