25
25
import com .apple .foundationdb .record .query .plan .cascades .PredicateMultiMap .PredicateMapping ;
26
26
import com .apple .foundationdb .record .query .plan .cascades .expressions .RelationalExpression ;
27
27
import com .apple .foundationdb .record .query .plan .cascades .predicates .QueryPredicate ;
28
+ import com .apple .foundationdb .record .query .plan .cascades .values .Value ;
28
29
import com .apple .foundationdb .record .query .plan .cascades .values .translation .MaxMatchMap ;
29
30
import com .apple .foundationdb .record .query .plan .cascades .values .translation .PullUp ;
30
31
import com .google .common .base .Equivalence ;
@@ -68,11 +69,42 @@ default boolean isRegular() {
68
69
Map <QueryPredicate , PredicateMapping > collectPulledUpPredicateMappings (@ Nonnull RelationalExpression candidateExpression ,
69
70
@ Nonnull Set <QueryPredicate > interestingPredicates );
70
71
72
+ @ Nonnull
73
+ Map <Value , Value > getMatchedAggregateValueMap ();
74
+
71
75
@ Nonnull
72
76
default AdjustedBuilder adjustedBuilder () {
73
77
return new AdjustedBuilder (this ,
74
78
getMatchedOrderingParts (),
75
- getMaxMatchMap ());
79
+ getMaxMatchMap (),
80
+ getMatchedAggregateValueMap ());
81
+ }
82
+
83
+ @ Nonnull
84
+ default Map <Value , Value > adjustMatchedAggregateMap (@ Nonnull final PartialMatch partialMatch ,
85
+ @ Nonnull final Quantifier candidateQuantifier ) {
86
+ final var matchedAggregateValueMapBuilder = ImmutableMap .<Value , Value >builder ();
87
+ final var matchedAggregateValueMap = getMatchedAggregateValueMap ();
88
+ for (final var matchedAggregateValueMapEntry : matchedAggregateValueMap .entrySet ()) {
89
+ final var queryAggregateValue = matchedAggregateValueMapEntry .getKey ();
90
+ final var candidateAggregateValue = matchedAggregateValueMapEntry .getValue ();
91
+ final var candidateLowerExpression =
92
+ Iterables .getOnlyElement (partialMatch .getCandidateRef ().getMembers ());
93
+ final var candidateLowerResultValue = candidateLowerExpression .getResultValue ();
94
+ final var candidatePullUpMap =
95
+ candidateLowerResultValue .pullUp (ImmutableList .of (candidateAggregateValue ),
96
+ AliasMap .emptyMap (),
97
+ Sets .difference (candidateAggregateValue .getCorrelatedToWithoutChildren (),
98
+ candidateLowerExpression .getCorrelatedTo ()),
99
+ candidateQuantifier .getAlias ());
100
+ final var pulledUpCandidateAggregateValue = candidatePullUpMap .get (candidateAggregateValue );
101
+ if (pulledUpCandidateAggregateValue == null ) {
102
+ return ImmutableMap .of ();
103
+ }
104
+ matchedAggregateValueMapBuilder .put (queryAggregateValue , pulledUpCandidateAggregateValue );
105
+ }
106
+
107
+ return matchedAggregateValueMapBuilder .build ();
76
108
}
77
109
78
110
/**
@@ -113,6 +145,9 @@ class RegularMatchInfo implements MatchInfo {
113
145
@ Nonnull
114
146
private final MaxMatchMap maxMatchMap ;
115
147
148
+ @ Nonnull
149
+ private final Map <Value , Value > matchedAggregateValueMap ;
150
+
116
151
/**
117
152
* Field to hold additional query plan constraints that need to be imposed on the potentially realized match.
118
153
*/
@@ -125,6 +160,7 @@ private RegularMatchInfo(@Nonnull final Map<CorrelationIdentifier, ComparisonRan
125
160
@ Nonnull final PredicateMultiMap predicateMap ,
126
161
@ Nonnull final List <MatchedOrderingPart > matchedOrderingParts ,
127
162
@ Nonnull final MaxMatchMap maxMatchMap ,
163
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ,
128
164
@ Nonnull final QueryPlanConstraint additionalPlanConstraint ) {
129
165
this .parameterBindingMap = ImmutableMap .copyOf (parameterBindingMap );
130
166
this .bindingAliasMap = bindingAliasMap ;
@@ -138,6 +174,7 @@ private RegularMatchInfo(@Nonnull final Map<CorrelationIdentifier, ComparisonRan
138
174
this .predicateMap = predicateMap ;
139
175
this .matchedOrderingParts = ImmutableList .copyOf (matchedOrderingParts );
140
176
this .maxMatchMap = maxMatchMap ;
177
+ this .matchedAggregateValueMap = ImmutableMap .copyOf (matchedAggregateValueMap );
141
178
this .additionalPlanConstraint = additionalPlanConstraint ;
142
179
}
143
180
@@ -208,6 +245,12 @@ public MaxMatchMap getMaxMatchMap() {
208
245
return maxMatchMap ;
209
246
}
210
247
248
+ @ Nonnull
249
+ @ Override
250
+ public Map <Value , Value > getMatchedAggregateValueMap () {
251
+ return matchedAggregateValueMap ;
252
+ }
253
+
211
254
@ Nonnull
212
255
public QueryPlanConstraint getAdditionalPlanConstraint () {
213
256
return additionalPlanConstraint ;
@@ -247,7 +290,7 @@ public static Optional<MatchInfo> tryFromMatchMap(@Nonnull final AliasMap bindin
247
290
@ Nonnull final IdentityBiMap <Quantifier , PartialMatch > partialMatchMap ,
248
291
@ Nonnull final MaxMatchMap maxMatchMap ) {
249
292
return tryMerge (bindingAliasMap , partialMatchMap , ImmutableMap .of (), PredicateMap .empty (),
250
- maxMatchMap , maxMatchMap .getQueryPlanConstraint ());
293
+ maxMatchMap , ImmutableMap . of (), maxMatchMap .getQueryPlanConstraint ());
251
294
}
252
295
253
296
@ Nonnull
@@ -256,6 +299,7 @@ public static Optional<MatchInfo> tryMerge(@Nonnull final AliasMap bindingAliasM
256
299
@ Nonnull final Map <CorrelationIdentifier , ComparisonRange > parameterBindingMap ,
257
300
@ Nonnull final PredicateMultiMap predicateMap ,
258
301
@ Nonnull final MaxMatchMap maxMatchMap ,
302
+ @ Nonnull final Map <Value , Value > additionalMatchedAggregateValueMap ,
259
303
@ Nonnull final QueryPlanConstraint additionalPlanConstraint ) {
260
304
final var parameterMapsBuilder = ImmutableList .<Map <CorrelationIdentifier , ComparisonRange >>builder ();
261
305
final var matchInfos = PartialMatch .matchInfosFromMap (partialMatchMap );
@@ -281,13 +325,18 @@ public static Optional<MatchInfo> tryMerge(@Nonnull final AliasMap bindingAliasM
281
325
final Optional <Map <CorrelationIdentifier , ComparisonRange >> mergedParameterBindingsOptional =
282
326
tryMergeParameterBindings (parameterMapsBuilder .build ());
283
327
328
+ final var matchedAggregateValueMap =
329
+ pullUpAndMergeMatchedAggregateMap (bindingAliasMap , partialMatchMap ,
330
+ additionalMatchedAggregateValueMap );
331
+
284
332
return mergedParameterBindingsOptional
285
333
.map (mergedParameterBindings -> new RegularMatchInfo (mergedParameterBindings ,
286
334
bindingAliasMap ,
287
335
partialMatchMap ,
288
336
predicateMap ,
289
337
orderingParts ,
290
338
maxMatchMap ,
339
+ matchedAggregateValueMap ,
291
340
additionalPlanConstraint ));
292
341
}
293
342
@@ -312,6 +361,51 @@ public static Optional<Map<CorrelationIdentifier, ComparisonRange>> tryMergePara
312
361
313
362
return Optional .of (resultMap );
314
363
}
364
+
365
+ @ Nonnull
366
+ private static Map <Value , Value > pullUpAndMergeMatchedAggregateMap (@ Nonnull final AliasMap bindingAliasMap ,
367
+ @ Nonnull final IdentityBiMap <Quantifier , PartialMatch > partialMatchMap ,
368
+ @ Nonnull final Map <Value , Value > additionalMatchedAggregateValueMap ) {
369
+ final var matchedAggregateValueMapBuilder = ImmutableMap .<Value , Value >builder ();
370
+ matchedAggregateValueMapBuilder .putAll (additionalMatchedAggregateValueMap );
371
+ for (final var partialMatchMapEntry : partialMatchMap .entrySet ()) {
372
+ final var quantifier = partialMatchMapEntry .getKey ().get ();
373
+ if (quantifier instanceof Quantifier .ForEach ) {
374
+ final var partialMatch = partialMatchMapEntry .getValue ().get ();
375
+ final var matchInfo = partialMatch .getMatchInfo ();
376
+ final var matchedAggregateValueMap = matchInfo .getMatchedAggregateValueMap ();
377
+ for (final var matchedAggregateValueMapEntry : matchedAggregateValueMap .entrySet ()) {
378
+ final var queryAggregateValue = matchedAggregateValueMapEntry .getKey ();
379
+ final var lowerQueryExpression = partialMatch .getQueryExpression ();
380
+ final var lowerResultValue = lowerQueryExpression .getResultValue ();
381
+ final var pullUpMap =
382
+ lowerResultValue .pullUp (ImmutableList .of (queryAggregateValue ), AliasMap .emptyMap (),
383
+ Sets .difference (queryAggregateValue .getCorrelatedToWithoutChildren (),
384
+ lowerQueryExpression .getCorrelatedTo ()), quantifier .getAlias ());
385
+ final var pulledUpQueryAggregateValue = pullUpMap .get (queryAggregateValue );
386
+ if (pulledUpQueryAggregateValue == null ) {
387
+ return ImmutableMap .of ();
388
+ }
389
+ final var candidateAggregateValue = matchedAggregateValueMapEntry .getValue ();
390
+ final var candidateLowerExpression =
391
+ Iterables .getOnlyElement (partialMatch .getCandidateRef ().getMembers ());
392
+ final var candidateLowerResultValue = candidateLowerExpression .getResultValue ();
393
+ final var candidatePullUpMap =
394
+ candidateLowerResultValue .pullUp (ImmutableList .of (candidateAggregateValue ),
395
+ AliasMap .emptyMap (),
396
+ Sets .difference (candidateAggregateValue .getCorrelatedToWithoutChildren (),
397
+ candidateLowerExpression .getCorrelatedTo ()),
398
+ Objects .requireNonNull (bindingAliasMap .getTarget (quantifier .getAlias ())));
399
+ final var pulledUpCandidateAggregateValue = candidatePullUpMap .get (candidateAggregateValue );
400
+ if (pulledUpCandidateAggregateValue == null ) {
401
+ return ImmutableMap .of ();
402
+ }
403
+ matchedAggregateValueMapBuilder .put (pulledUpQueryAggregateValue , pulledUpCandidateAggregateValue );
404
+ }
405
+ }
406
+ }
407
+ return matchedAggregateValueMapBuilder .build ();
408
+ }
315
409
}
316
410
317
411
/**
@@ -346,12 +440,17 @@ class AdjustedMatchInfo implements MatchInfo {
346
440
@ Nonnull
347
441
private final MaxMatchMap maxMatchMap ;
348
442
349
- public AdjustedMatchInfo (@ Nonnull final MatchInfo underlying ,
350
- @ Nonnull final List <MatchedOrderingPart > matchedOrderingParts ,
351
- @ Nonnull final MaxMatchMap maxMatchMap ) {
443
+ @ Nonnull
444
+ private final Map <Value , Value > matchedAggregateValueMap ;
445
+
446
+ private AdjustedMatchInfo (@ Nonnull final MatchInfo underlying ,
447
+ @ Nonnull final List <MatchedOrderingPart > matchedOrderingParts ,
448
+ @ Nonnull final MaxMatchMap maxMatchMap ,
449
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
352
450
this .underlying = underlying ;
353
451
this .matchedOrderingParts = matchedOrderingParts ;
354
452
this .maxMatchMap = maxMatchMap ;
453
+ this .matchedAggregateValueMap = ImmutableMap .copyOf (matchedAggregateValueMap );
355
454
}
356
455
357
456
@ Nonnull
@@ -371,6 +470,12 @@ public MaxMatchMap getMaxMatchMap() {
371
470
return maxMatchMap ;
372
471
}
373
472
473
+ @ Nonnull
474
+ @ Override
475
+ public Map <Value , Value > getMatchedAggregateValueMap () {
476
+ return matchedAggregateValueMap ;
477
+ }
478
+
374
479
@ Override
375
480
public boolean isAdjusted () {
376
481
return true ;
@@ -424,6 +529,9 @@ class AdjustedBuilder {
424
529
@ Nonnull
425
530
private List <MatchedOrderingPart > matchedOrderingParts ;
426
531
532
+ @ Nonnull
533
+ private Map <Value , Value > matchedAggregateValueMap ;
534
+
427
535
/**
428
536
* A map of maximum matches between the query result {@code Value} and the corresponding candidate's result
429
537
* {@code Value}.
@@ -433,10 +541,12 @@ class AdjustedBuilder {
433
541
434
542
private AdjustedBuilder (@ Nonnull final MatchInfo underlying ,
435
543
@ Nonnull final List <MatchedOrderingPart > matchedOrderingParts ,
436
- @ Nonnull final MaxMatchMap maxMatchMap ) {
544
+ @ Nonnull final MaxMatchMap maxMatchMap ,
545
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
437
546
this .underlying = underlying ;
438
547
this .matchedOrderingParts = matchedOrderingParts ;
439
548
this .maxMatchMap = maxMatchMap ;
549
+ this .matchedAggregateValueMap = matchedAggregateValueMap ;
440
550
}
441
551
442
552
@ Nonnull
@@ -449,22 +559,37 @@ public AdjustedBuilder setMatchedOrderingParts(@Nonnull final List<MatchedOrderi
449
559
return this ;
450
560
}
451
561
562
+ @ Nonnull
563
+ public AdjustedBuilder setMatchedAggregateValueMap (@ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
564
+ this .matchedAggregateValueMap = matchedAggregateValueMap ;
565
+ return this ;
566
+ }
567
+
452
568
@ Nonnull
453
569
public MaxMatchMap getMaxMatchMap () {
454
570
return maxMatchMap ;
455
571
}
456
572
573
+ @ Nonnull
457
574
public AdjustedBuilder setMaxMatchMap (@ Nonnull final MaxMatchMap maxMatchMap ) {
458
575
this .maxMatchMap = maxMatchMap ;
459
576
return this ;
460
577
}
461
578
579
+
580
+
581
+ @ Nonnull
582
+ public Map <Value , Value > getMatchedAggregateValueMap () {
583
+ return matchedAggregateValueMap ;
584
+ }
585
+
462
586
@ Nonnull
463
587
public MatchInfo build () {
464
588
return new AdjustedMatchInfo (
465
589
underlying ,
466
590
matchedOrderingParts ,
467
- maxMatchMap );
591
+ maxMatchMap ,
592
+ matchedAggregateValueMap );
468
593
}
469
594
}
470
595
}
0 commit comments