Skip to content

[Analytics Engine] CSE: evaluate a repeated aggregate sub-plan once instead of twice - #22818

Open
LantaoJin wants to merge 5 commits into
opensearch-project:mainfrom
LantaoJin:feature/cse-subplan-reuse
Open

[Analytics Engine] CSE: evaluate a repeated aggregate sub-plan once instead of twice#22818
LantaoJin wants to merge 5 commits into
opensearch-project:mainfrom
LantaoJin:feature/cse-subplan-reuse

Conversation

@LantaoJin

@LantaoJin LantaoJin commented Aug 24, 2026

Copy link
Copy Markdown
Member

Description

Support CSE (common subexpression elimination) optimization to resolve correctness issue introduced by nondeterministic aggregation in subquery.

New configuration:
analytics.planner.subplan_reuse.enabled (default: true)

Related Issues

Resolves #22817

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@LantaoJin
LantaoJin requested a review from a team as a code owner August 24, 2026 08:40
@github-actions github-actions Bot added enhancement Enhancement or improvement to existing feature or request Search:Performance labels Aug 24, 2026
@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 64c6cf5)

Here are some key observations to aid the review process:

🧪 PR contains tests
🔒 No security concerns identified
✅ No TODO sections
🔀 No multiple PR themes
⚡ Recommended focus areas for review

Fragile digest-based equivalence

digestOf uses RelOptUtil.toString(node) with a regex that only strips id=\d+, annotation ids to determine whether two subtrees are equivalent. Any other per-occurrence identifier embedded in the plan text (e.g. correlation ids, generated aliases, unique names introduced by other rules, or additional annotation fields) would either cause false negatives (missed reuse, harmless) or — more concerning — the reverse: two subtrees that normalize equal but aren't semantically identical would be shared, producing silently wrong answers. The class doc acknowledges this risk ("what no internal fallback can catch is a WRONG digest match") and the kill switch is the mitigation, but there's no defensive equivalence check (e.g. RelNode structural comparison or a hash based on stable operator+expression identity) before treating two nodes as the same sub-plan. Consider a stricter equivalence check on candidates before recording them as shared.

private static String digestOf(RelNode node) {
    return ANNOTATION_ID.matcher(RelOptUtil.toString(node)).replaceAll("");
}
Buffered-input check may miss nested references

sharedInputsAreBuffered only counts OpenSearchStageInputScan references to the immediate child stage when the stage has exactly one child. If a shared sub-plan is referenced by a stage with more than one child but its single reference in the fragment is only one scan, that's fine; however, if a stage has one child but the shared input is referenced twice via nested sub-expressions and the streaming reduce sink is nonetheless selected (per inputCount>1 rule) — the doc claims the memtable sink triggers on inputCount > 1, but the check here uses child-stage count, not input-scan count. Verify that "consumer buffers inputs" is truly determined by number of child stages (inputCount) and not by number of scans on those stages; otherwise a single-child stage that scans the child twice would still get the streaming sink and read empty on the second scan, contradicting the comment.

private static boolean sharedInputsAreBuffered(Stage stage) {
    if (stage.getFragment() != null && stage.getChildStages().size() == 1) {
        int childId = stage.getChildStages().getFirst().getStageId();
        int refs = 0;
        for (OpenSearchStageInputScan scan : RelNodeUtils.findNodes(stage.getFragment(), OpenSearchStageInputScan.class)) {
            if (scan.getChildStageId() == childId) {
                refs++;
            }
        }
        if (refs > 1) {
            return false;
        }
    }
    for (Stage child : stage.getChildStages()) {
        if (!sharedInputsAreBuffered(child)) {
            return false;
        }
    }
    return true;
}
Possible dead conditional

The inner if (ipc != null) { } block now contains only the putIfAbsent call, but based on the new-hunk indentation it appears empty in the diff view (the putIfAbsent line is at the same indent as the outer if). If toInject.putIfAbsent(...) was intended to be inside the null-check, confirm the braces enclose it; otherwise a null ipc (build stage not yet captured) would be inserted into the map and later shipped as a null payload to BroadcastInjectionInstructionNode. Please verify the actual source to ensure the null guard still wraps the insertion.

for (OpenSearchBroadcastScan scan : scans) {
    byte[] ipc = capturedByBuildId.get(scan.getBuildStageId());
    if (ipc != null) {
        toInject.putIfAbsent(scan.getBuildStageId(), ipc);
    }
}

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Latest suggestions up to 64c6cf5

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Strengthen sub-plan equivalence digest

Using {@code RelOptUtil.toString} as an equivalence digest is fragile: any RelNode
field that prints an object identity, a mutable list order, or a synthetic name
(e.g. correlation ids, generated field aliases, unique node ids) can make
semantically equal subtrees produce different strings — leading to missed reuse —
or, worse, unequal subtrees to normalize identical (a "wrong digest match" the class
doc calls out as a silent-wrong-answer risk). Consider using Calcite's structural
digest ({@code RelNode#getDigest} / {@code RelDigest}) or {@code
RelOptUtil.areRowTypesEqual} plus a canonical traversal, and add safeguards for
correlation ids beyond the annotation id pattern.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [153-155]

 private static String digestOf(RelNode node) {
+    // TODO: replace text-based digest with a structural digest (RelNode#getDigest / explicit tree walk)
+    //  to eliminate the silent wrong-match risk called out in the class docs.
     return ANNOTATION_ID.matcher(RelOptUtil.toString(node)).replaceAll("");
 }
Suggestion importance[1-10]: 5

__

Why: Text-based digests via RelOptUtil.toString do carry the risk noted in the class docs. However, the suggestion only adds a TODO comment rather than fixing the issue, and the class docs already acknowledge this trade-off explicitly, so the actionable value is modest.

Low
Possible issue
Avoid double-counting nested aggregate candidates

The traversal visits every node, and when a candidate aggregate is found it still
descends into its children — meaning a nested aggregate inside another aggregate's
subtree gets counted, and if the outer subtree is later shared, {@code sever} will
only see the OUTER candidate. Worse, if the outer aggregate is shared, this counts
the inner aggregate as a separate candidate that could ALSO be marked shared, but
{@code sharedDigestOf} would then return non-null for it during recursion after cut,
potentially cutting it a second time out of the shared subtree. Stop descent once a
candidate is recorded so inner candidates are only counted at the outermost matching
level.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [82-92]

 static SharedSubplanReuse detect(RelNode root) {
     Map<String, Integer> counts = new HashMap<>();
     Deque<RelNode> queue = new ArrayDeque<>();
     queue.push(root);
     while (!queue.isEmpty()) {
         RelNode node = queue.pop();
         if (isCandidate(node)) {
             counts.merge(digestOf(node), 1, Integer::sum);
+            continue;
         }
         for (RelNode input : node.getInputs()) {
             queue.push(input);
         }
     }
Suggestion importance[1-10]: 4

__

Why: The suggestion raises a plausible concern about nested aggregate candidates, but adding continue would prevent detecting shared sub-plans nested inside other aggregates, which could be a valid optimization. The impact and correctness of the change are debatable without more context on how sever handles nested shared subtrees.

Low
Fix buffered-input detection for multi-child stages

The buffering check only inspects stages with exactly one child, but a stage may
have multiple children where two scans still target the SAME child stage id (the
shared one) — that stage would still get the streaming reduce sink only if
inputCount is 1, but the current guard misses shapes where {@code
getChildStages().size() > 1} yet only one distinct child is actually referenced by
scans, and, more importantly, it can miss the case where inputCount is 1 because
deduping in the child list collapses references. Verify by counting distinct scanned
child stage ids against the fragment's read pattern rather than by child list size
alone.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [103-114]

-if (stage.getFragment() != null && stage.getChildStages().size() == 1) {
-    int childId = stage.getChildStages().getFirst().getStageId();
-    int refs = 0;
+if (stage.getFragment() != null) {
+    Map<Integer, Integer> refsByChild = new HashMap<>();
     for (OpenSearchStageInputScan scan : RelNodeUtils.findNodes(stage.getFragment(), OpenSearchStageInputScan.class)) {
-        if (scan.getChildStageId() == childId) {
-            refs++;
+        refsByChild.merge(scan.getChildStageId(), 1, Integer::sum);
+    }
+    long distinctChildrenScanned = refsByChild.size();
+    for (Map.Entry<Integer, Integer> e : refsByChild.entrySet()) {
+        if (e.getValue() > 1 && distinctChildrenScanned < 2) {
+            return false;
         }
-    }
-    if (refs > 1) {
-        return false;
     }
 }
Suggestion importance[1-10]: 3

__

Why: The suggestion is somewhat unclear and the proposed improved_code logic seems flawed. The original check targets specifically the shape where the streaming (once-consumable) reduce sink would be selected (inputCount==1), which is documented. The alternative proposed does not clearly improve correctness.

Low

Previous suggestions

Suggestions up to commit 4872a29
CategorySuggestion                                                                                                                                    Impact
General
Use a digest-safe stringification for subtree comparison

The digest uses RelOptUtil.toString(node) with only the annotation id stripped.
RelOptUtil.toString includes node ids and other per-instance metadata that will
differ between two structurally identical subtrees, causing legitimate duplicates to
hash differently and defeating reuse detection. Use RelOptUtil.toString(node,
SqlExplainLevel.DIGEST_ATTRIBUTES) or the node's getDigest() which is designed for
structural equality.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [70]

+private static final Pattern ANNOTATION_ID = Pattern.compile("id=\\d+, ");
 
-
Suggestion importance[1-10]: 6

__

Why: The suggestion raises a legitimate concern that RelOptUtil.toString may include per-instance metadata beyond annotation ids, which could defeat structural equality. However, the improved_code is identical to the existing_code, providing no actual fix, and the PR author appears to have chosen the annotation-id-stripping approach deliberately based on the q15 test.

Low
Avoid static mutable state for test provisioning

A static mutable flag dataProvisioned shared across test instances is fragile — if
tests run in parallel or if a prior test class leaves indices in an inconsistent
state, subsequent tests will silently skip provisioning and fail unpredictably.
Prefer an idempotent existence check against the cluster (e.g. HEAD /index) or use
@BeforeClass provisioning so state is tied to the class lifecycle rather than a
static flag.

sandbox/qa/analytics-engine-rest/src/test/java/org/opensearch/analytics/qa/SharedSubplanReuseIT.java [57]

+private static boolean dataProvisioned = false;
 
-
Suggestion importance[1-10]: 3

__

Why: A valid minor concern about test robustness, but the improved_code is identical to existing_code and provides no concrete fix. Impact is low for an IT test class.

Low
Document fragment-scoped reuse boundary behavior

When the root goes through the else branch and sever is called with a non-null
reuse, the reuse scope is created at the root but subsequent cut
helpers call
severFragment which creates a NEW SharedSubplanReuse scope per fragment. However,
the root-level sever recursion may descend through inputs that themselves reach
exchanges via cutAtExchange/etc., which then re-detect within the child fragment. If
a shared subtree spans across an exchange boundary at the root level, the first
occurrence may be cut but the second (in a different fragment) won't see it in
cutStageIdByDigest. Consider documenting or asserting that reuse is only meaningful
within a single fragment.
*

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [155-169]

+SharedSubplanReuse reuse = null;
+if (subplanReuseEnabled) {
+    SharedSubplanReuse detected = SharedSubplanReuse.detect(cboOutput);
+    reuse = detected.isEmpty() ? null : detected;
+}
+rootFragment = sever(
+    cboOutput,
+    counter,
+    childStages,
+    registry,
+    clusterService,
+    indexNameExpressionResolver,
+    reuse,
+    subplanReuseEnabled
+);
 
-
Suggestion importance[1-10]: 2

__

Why: The suggestion only asks to document behavior already extensively documented in the PR (e.g., severFragment javadoc explicitly explains per-fragment scoping), and the improved_code is identical to existing_code.

Low
Suggestions up to commit 5acca8e
CategorySuggestion                                                                                                                                    Impact
General
Detect unbuffered shared input more robustly

The buffering check only inspects stages with exactly one child, but a stage with
multiple children could still reference one particular child twice while another
child has zero references (e.g., a broadcast build with no scan). Broaden the check
to detect any child stage referenced more than once when the total number of
distinct referenced child stages is one — which is the actual condition that selects
the streaming sink.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [102-114]

 private static boolean sharedInputsAreBuffered(Stage stage) {
-    if (stage.getFragment() != null && stage.getChildStages().size() == 1) {
-        int childId = stage.getChildStages().getFirst().getStageId();
-        int refs = 0;
+    if (stage.getFragment() != null && !stage.getChildStages().isEmpty()) {
+        Map<Integer, Integer> refsById = new HashMap<>();
         for (OpenSearchStageInputScan scan : RelNodeUtils.findNodes(stage.getFragment(), OpenSearchStageInputScan.class)) {
-            if (scan.getChildStageId() == childId) {
-                refs++;
-            }
+            refsById.merge(scan.getChildStageId(), 1, Integer::sum);
         }
-        if (refs > 1) {
+        if (refsById.size() == 1 && refsById.values().iterator().next() > 1) {
             return false;
         }
     }
Suggestion importance[1-10]: 6

__

Why: The suggestion identifies a potentially narrow check that only handles the single-child case; broadening it to catch other shapes where the streaming sink might be selected could prevent correctness issues, though it depends on the exact sink-selection rules (inputCount > 1).

Low
Possible issue
Avoid detecting nested candidates inside candidates

The traversal descends into a candidate aggregate's own children, so a nested
candidate inside a shared aggregate can also be counted and detected as "shared"
independently. Since the outer aggregate will be cut as a whole, do not recurse into
its children once it is recognized as a candidate — otherwise you may cut an inner
sub-plan that is actually inside a to-be-shared outer one, producing overlapping
shared stages.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [82-92]

 static SharedSubplanReuse detect(RelNode root) {
     Map<String, Integer> counts = new HashMap<>();
     Deque<RelNode> queue = new ArrayDeque<>();
     queue.push(root);
     while (!queue.isEmpty()) {
         RelNode node = queue.pop();
         if (isCandidate(node)) {
             counts.merge(digestOf(node), 1, Integer::sum);
+            continue; // do not recurse into an already-candidate subtree
         }
         for (RelNode input : node.getInputs()) {
             queue.push(input);
         }
     }
Suggestion importance[1-10]: 5

__

Why: Skipping recursion into an already-candidate subtree could avoid overlapping shared cuts, but it's unclear whether nested candidates in the current design cause actual overlap (the outer cut happens first in sever). The suggestion has some merit but the correctness impact is speculative.

Low
Use a safer structural digest

Using RelOptUtil.toString(node) and stripping id=\d+, as the equality digest is
fragile: any other per-query counter, alias, or field name renamed uniquely could
cause a false digest match between semantically different subtrees, which the class
itself warns would be a silent wrong answer. Consider using Calcite's
RelDigest/getDigest() which is designed for structural equality, or at minimum also
stripping other potentially query-scoped identifiers you know may appear.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [70]

 private static final Pattern ANNOTATION_ID = Pattern.compile("id=\\d+, ");
+// TODO: prefer RelNode.getDigest() / RelDigest for structural equality — string scrubbing risks a false match, which would be a silent wrong answer.
Suggestion importance[1-10]: 4

__

Why: The concern about digest fragility is legitimate — a false digest match is the class's own documented silent-wrong-answer risk — but the "improved_code" only adds a TODO comment rather than fixing the issue, limiting its impact.

Low
Suggestions up to commit f5f7a5b
CategorySuggestion                                                                                                                                    Impact
Possible issue
Avoid double-counting shared nodes during traversal

The DFS traversal will revisit shared nodes (already common in Calcite via
HepRelVertex/RelSubset or DAG-shaped plans), causing false duplicate counts on a
single logical occurrence and incorrectly triggering sharing. Track visited nodes by
identity to count each subtree once.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [80-100]

 static SharedSubplanReuse detect(RelNode root) {
     Map<String, Integer> counts = new HashMap<>();
     Deque<RelNode> queue = new ArrayDeque<>();
+    Set<RelNode> visited = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
     queue.push(root);
     while (!queue.isEmpty()) {
         RelNode node = queue.pop();
+        if (!visited.add(node)) {
+            continue;
+        }
         if (isCandidate(node)) {
             counts.merge(digestOf(node), 1, Integer::sum);
         }
         for (RelNode input : node.getInputs()) {
             queue.push(input);
         }
     }
Suggestion importance[1-10]: 6

__

Why: Valid concern: if the input plan is already DAG-shaped (shared nodes present pre-detection), the DFS would over-count. However, at this planner stage the input is typically tree-shaped post-CBO, and duplicates arise from repeated identical subtrees (different node identities) which is exactly what the digest matching is designed to catch. Adding identity-based visited tracking is a reasonable defensive measure.

Low
Align buffering check with sink-selection predicate

sharedInputsAreBuffered only rejects stages with exactly one child that is scanned
more than once, but a stage could have multiple children where the shared child is
scanned twice and other children are absent from the fragment — the memtable sink
selection is based on inputCount which counts declared child stages, not scans.
Verify the buffering condition matches the actual sink-selection logic to avoid a
silent wrong-answer path.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [444-450]

 if (sharedInputsAreBuffered(shared.rootStage())) {
     return shared;
 }
 LOGGER.debug("Rebuilding the DAG without sub-plan sharing: the consumer would not buffer the shared input");
+// TODO: confirm sharedInputsAreBuffered mirrors the exact predicate used to select
+// DatafusionMemtableReduceSink (inputCount > 1 on child-stage count), not just fragment scan count.
Suggestion importance[1-10]: 3

__

Why: The suggestion only asks to verify alignment and adds a TODO comment without concrete improvement. The improved_code is essentially identical to existing_code, offering minimal actionable value.

Low
Suggestions up to commit 87bd880
CategorySuggestion                                                                                                                                    Impact
Possible issue
Strengthen sub-plan digest to avoid false matches

The digest relies on RelOptUtil.toString(node) after stripping annotation ids, but
this text-based digest can produce false positives — two structurally different
subtrees may normalize to the same string if the printer omits distinguishing
metadata, causing incorrect sharing and silent wrong answers (as the setting's own
javadoc warns). Consider incorporating stronger identity such as the RelNode digest
combined with row-type and trait-set signatures, or add a structural equivalence
check before accepting a match.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanReuse.java [153-155]

 private static String digestOf(RelNode node) {
-    return ANNOTATION_ID.matcher(RelOptUtil.toString(node)).replaceAll("");
+    String plan = ANNOTATION_ID.matcher(RelOptUtil.toString(node)).replaceAll("");
+    return plan + "|rowType=" + node.getRowType().getFullTypeString() + "|traits=" + node.getTraitSet();
 }
Suggestion importance[1-10]: 6

__

Why: The suggestion raises a legitimate concern about digest correctness that the PR's own javadoc acknowledges as the residual risk (silent wrong answers from a wrong digest match). Adding row type and trait set to the digest is a reasonable hardening, though RelOptUtil.toString may already include some of this information.

Low
General
Verify buffering check covers all stage shapes

The buffering check only triggers when a stage has exactly one child, but a stage
with multiple children could still reference one shared child stage multiple times
while all other inputs are single-reference — however, if the memtable sink is
selected on inputCount > 1, that would be fine. Conversely, a stage with one child
whose fragment reads it twice is correctly rejected. However, the condition misses
the case where the ROOT stage itself (with getFragment() == null for a gather-only
root) shares an input; verify the root-stage shape is impossible or handle it
explicitly.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [102-114]

+private static boolean sharedInputsAreBuffered(Stage stage) {
+    if (stage.getFragment() != null && stage.getChildStages().size() == 1) {
+        int childId = stage.getChildStages().getFirst().getStageId();
+        int refs = 0;
+        for (OpenSearchStageInputScan scan : RelNodeUtils.findNodes(stage.getFragment(), OpenSearchStageInputScan.class)) {
+            if (scan.getChildStageId() == childId) {
+                refs++;
+            }
+        }
+        if (refs > 1) {
+            return false;
+        }
+    }
 
-
Suggestion importance[1-10]: 3

__

Why: The suggestion is primarily a request to verify behavior rather than a concrete fix, and the improved_code is identical to the existing_code. It raises a valid question but does not provide an actionable change.

Low
Suggestions up to commit 9046c78
CategorySuggestion                                                                                                                                    Impact
Possible issue
Guard against digest collisions causing wrong sharing

The digest relies on RelOptUtil.toString which is a human-readable format —
collisions here would produce a silently wrong answer (two non-equivalent subtrees
sharing one evaluation), the exact class of incident the kill switch is documented
to guard against. Add a structural equality guard: when a digest matches, also
verify the candidate subtrees are structurally equal (e.g. via RelNode.deepEquals or
by comparing digests of all descendants), rejecting the share on mismatch.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/SharedSubplanCse.java [153-155]

 private static String digestOf(RelNode node) {
+    // RelOptUtil.toString is human-readable; a wrong digest match would silently return wrong answers.
+    // Callers must additionally verify structural equivalence before sharing.
     return ANNOTATION_ID.matcher(RelOptUtil.toString(node)).replaceAll("");
 }
Suggestion importance[1-10]: 6

__

Why: The concern about digest collisions in RelOptUtil.toString-based digests is legitimate and aligns with the PR's own documented "wrong digest match" risk. However, the improved_code only adds a comment without actually implementing the structural equality guard, weakening the suggestion's impact.

Low
Broaden the buffered-input safety check

The safety check only considers stages with exactly one child stage, but a stage
with multiple children could still reference one child's StageInputScan more than
once while the streaming sink is chosen based on other criteria. Widen the check to
detect ANY child stage scanned more than once by its parent's fragment, regardless
of sibling count, so the fallback triggers whenever a once-consumable input would be
re-read.

sandbox/plugins/analytics-engine/src/main/java/org/opensearch/analytics/planner/dag/DAGBuilder.java [102-114]

 private static boolean sharedInputsAreBuffered(Stage stage) {
-    if (stage.getFragment() != null && stage.getChildStages().size() == 1) {
-        int childId = stage.getChildStages().getFirst().getStageId();
-        int refs = 0;
+    if (stage.getFragment() != null && !stage.getChildStages().isEmpty()) {
+        Map<Integer, Integer> refsByChildId = new HashMap<>();
         for (OpenSearchStageInputScan scan : RelNodeUtils.findNodes(stage.getFragment(), OpenSearchStageInputScan.class)) {
-            if (scan.getChildStageId() == childId) {
-                refs++;
-            }
+            refsByChildId.merge(scan.getChildStageId(), 1, Integer::sum);
         }
-        if (refs > 1) {
+        // Streaming (once-consumable) sink is selected when inputCount == 1; any child scanned more than
+        // once under that shape returns an empty second read.
+        if (stage.getChildStages().size() == 1 && refsByChildId.values().stream().anyMatch(c -> c > 1)) {
             return false;
         }
     }
Suggestion importance[1-10]: 3

__

Why: The suggestion's improved_code ends up equivalent to the original logic (only checks the single-child case), so it does not actually broaden the check as claimed. The concern about multi-child stages is speculative given the memtable sink is selected on inputCount > 1.

Low

Signed-off-by: Lantao Jin <ltjin@amazon.com>
@LantaoJin
LantaoJin force-pushed the feature/cse-subplan-reuse branch from 9046c78 to 87bd880 Compare August 24, 2026 09:10
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 87bd880

@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 87bd880: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for 87bd880: SUCCESS

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.59%. Comparing base (608d710) to head (64c6cf5).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main   #22818      +/-   ##
============================================
+ Coverage     71.58%   71.59%   +0.01%     
+ Complexity    77341    77323      -18     
============================================
  Files          6170     6170              
  Lines        359775   359774       -1     
  Branches      52478    52478              
============================================
+ Hits         257541   257577      +36     
+ Misses        81770    81714      -56     
- Partials      20464    20483      +19     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit f5f7a5b

@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for f5f7a5b: SUCCESS

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 5acca8e

@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 5acca8e: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 4872a29

@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for 4872a29: SUCCESS

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 64c6cf5

@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for 64c6cf5: SUCCESS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Enhancement or improvement to existing feature or request Search:Performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Equality filter against a repeated float-aggregate subquery intermittently returns 0 rows

1 participant