Skip to content

Conversation

@LantaoJin
Copy link
Member

@LantaoJin LantaoJin commented Dec 23, 2025

Description

Support enumerable TopK, check #4982 for details.

The CalciteEnumerableTopK is derived from EnumerableLimitSort which has the corrected cost computation.

Related Issues

Resolves #4982

Check List

  • New functionality includes testing.
  • New functionality has been documented.
  • New functionality has javadoc added.
  • New functionality has a user manual doc added.
  • New PPL command checklist all confirmed.
  • API changes companion pull request created.
  • Commits are signed per the DCO using --signoff or -s.
  • Public documentation issue/PR created.

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.

Signed-off-by: Lantao Jin <ltjin@amazon.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • Performance Improvements
    • Optimized query execution plans through operator fusion, combining limit and sort operations into single efficient steps.
    • Introduced TopK optimization strategy for improved limit-based query performance and planner efficiency.
    • Enhanced query planner with new rules to generate more effective execution strategies for complex queries.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

This PR introduces a TopK optimization that fuses EnumerableLimit and EnumerableSort operators into a single EnumerableLimitSort operator, reducing memory overhead during execution. A new Calcite optimization rule (EnumerableTopKRule) transforms matching logical sorts into a dedicated CalciteEnumerableTopK physical node with cost optimization. Supporting changes include guard logic in the pushdown layer and test expectation updates.

Changes

Cohort / File(s) Summary
New TopK Physical Operator
opensearch/.../planner/physical/CalciteEnumerableTopK.java
Introduces new class extending EnumerableLimitSort with overridden cost computation to model cheaper TopK execution; includes static factory method.
New Optimization Rule
opensearch/.../planner/rules/EnumerableTopKRule.java
Implements Calcite rule matching LogicalSort with non-empty collation and fetch/offset; transforms to CalciteEnumerableTopK physical node. Includes immutable Config interface with default configuration.
Rule Registration
opensearch/.../planner/rules/OpenSearchIndexRules.java
Registers new ENUMERABLE_TOP_K_RULE in OPEN_SEARCH_INDEX_SCAN_RULES list.
Pushdown Safety Guards
opensearch/.../storage/scan/CalciteLogicalIndexScan.java
Modifies pushDownLimit to use precomputed digest object and adds early return guard detecting duplicate top digest to prevent stack overflow during recursive pushdown.
Context Helper
opensearch/.../storage/scan/context/PushDownContext.java
Adds public method containsDigestOnTop(Object digest) to check if most recent operation in queue matches given digest.
Test Expectation Updates
integ-test/.../expectedOutput/calcite/{q28,q29,explain_exists_correlated_subquery,explain_limit_agg_pushdown5,explain_multisearch_timestamp,explain_streamstats_distinct_count,explain_streamstats_earliest_latest,explain_streamstats_earliest_latest_custom_time,explain_streamstats_global_null_bucket,explain_streamstats_null_bucket,explain_streamstats_reset_null_bucket}.{yaml,json}
Updates physical plan expectations across 11 test files to reflect new EnumerableLimitSort operator fusion replacing separate nested EnumerableLimitEnumerableSort sequences.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • opensearch-project/sql#4957: Modifies planner rule registration in OpenSearchIndexRules, adding new rules to the scan rule set similar to this PR's rule registration pattern.
  • opensearch-project/sql#4884: Modifies pushdown machinery in CalciteLogicalIndexScan and PushDownContext with state/guard logic, overlapping code areas with this PR's digest guard changes.

Suggested labels

clickbench, backport-manually, backport 2.19-dev

Suggested reviewers

  • ps48
  • penghuo
  • kavithacm
  • derek-ho
  • joshuali925
  • MaxKsyunz
  • Swiddis
  • anirudha

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Support enumerable TopK' clearly and concisely summarizes the main feature being added, matching the core changes in the PR.
Description check ✅ Passed The description explains the feature (enumerable TopK support), references the related issue (#4982), and provides context about CalciteEnumerableTopK being derived from EnumerableLimitSort.
Linked Issues check ✅ Passed The PR successfully implements the core objective from #4982: replacing EnumerableLimit+EnumerableSort patterns with EnumerableLimitSort (TopK) to avoid full in-memory sorting and reduce memory usage.
Out of Scope Changes check ✅ Passed The changes are focused on implementing the TopK operator optimization: new CalciteEnumerableTopK class, EnumerableTopKRule for pattern matching, rule integration, and minor supporting changes to handle duplicate digest detection.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/context/PushDownContext.java (1)

142-145: Address the TODO comment and add JavaDoc.

The method logic is correct, but:

  1. The TODO comment "check on adding" is vague and unclear about what needs to be checked and when.
  2. Per coding guidelines, public methods should have proper JavaDoc documentation.
🔎 Proposed fix
-  // TODO check on adding
-  public boolean containsDigestOnTop(Object digest) {
+  /**
+   * Check if the most recently added operation has a digest equal to the provided digest.
+   *
+   * @param digest The digest object to compare against the top operation
+   * @return true if the top operation's digest equals the provided digest, false otherwise
+   */
+  public boolean containsDigestOnTop(Object digest) {
     return this.queue.peekLast() != null && this.queue.peekLast().digest().equals(digest);
   }
opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java (1)

20-21: Add class-level JavaDoc.

Per coding guidelines, public classes should have proper JavaDoc. Consider expanding the single-line comment into a full JavaDoc explaining the TopK optimization purpose and when this node is used.

Suggested JavaDoc
-/** The different between this and {@link EnumerableLimitSort} is the cost. */
+/**
+ * A physical relational node representing a TopK operation with optimized cost computation.
+ *
+ * <p>This node extends {@link EnumerableLimitSort} but computes a lower cost to encourage
+ * the planner to prefer fusing separate Limit and Sort operators into this single TopK node,
+ * thereby reducing memory usage during execution.
+ */
 public class CalciteEnumerableTopK extends EnumerableLimitSort {
opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java (1)

28-42: Add a copy() override to CalciteEnumerableTopK to preserve the custom type.

When Calcite's planning engine clones relational nodes, the parent EnumerableLimitSort.copy() method will be invoked. Without an override, this returns an EnumerableLimitSort instance instead of CalciteEnumerableTopK, losing the custom computeSelfCost() implementation. Following the pattern used in LogicalSystemLimit and other custom Calcite nodes in this codebase, override copy() to return a new CalciteEnumerableTopK instance with the updated parameters.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbcdbd6 and 2a88ae6.

📒 Files selected for processing (16)
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q28.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q29.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_exists_correlated_subquery.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json
  • integ-test/src/test/resources/expectedOutput/calcite/explain_multisearch_timestamp.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_distinct_count.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest_custom_time.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_global_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_reset_null_bucket.yaml
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/OpenSearchIndexRules.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/CalciteLogicalIndexScan.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/context/PushDownContext.java
🧰 Additional context used
📓 Path-based instructions (2)
**/*.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*.java: Use PascalCase for class names (e.g., QueryExecutor)
Use camelCase for method and variable names (e.g., executeQuery)
Use UPPER_SNAKE_CASE for constants (e.g., MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
Prefer Optional<T> for nullable returns in Java
Avoid unnecessary object creation in loops
Use StringBuilder for string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code

Files:

  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/context/PushDownContext.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/OpenSearchIndexRules.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/CalciteLogicalIndexScan.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java

⚙️ CodeRabbit configuration file

**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring

  • Flag classes >500 lines as needing organization review
  • Check for dead code, unused imports, and unused variables
  • Identify code reuse opportunities across similar implementations
  • Assess holistic maintainability - is code easy to understand and modify?
  • Flag code that appears AI-generated without sufficient human review
  • Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
  • Check for proper JavaDoc on public classes and methods
  • Flag redundant comments that restate obvious code
  • Ensure proper error handling with specific exception types
  • Check for Optional usage instead of null returns
  • Validate proper use of try-with-resources for resource management

Files:

  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/context/PushDownContext.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/OpenSearchIndexRules.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/CalciteLogicalIndexScan.java
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java
integ-test/src/test/resources/**/*

⚙️ CodeRabbit configuration file

integ-test/src/test/resources/**/*: - Verify test data is realistic and representative

  • Check data format matches expected schema
  • Ensure test data covers edge cases and boundary conditions

Files:

  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest_custom_time.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q29.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q28.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_distinct_count.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_exists_correlated_subquery.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_global_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_reset_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_multisearch_timestamp.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest.yaml
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Test SQL generation and optimization paths for Calcite integration changes
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Test SQL generation and optimization paths for Calcite integration changes

Applied to files:

  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest_custom_time.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_null_bucket.yaml
  • opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q29.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q28.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_distinct_count.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_exists_correlated_subquery.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_global_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_reset_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_multisearch_timestamp.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest.yaml
  • opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/CalciteLogicalIndexScan.java
📚 Learning: 2025-12-11T05:27:39.856Z
Learnt from: LantaoJin
Repo: opensearch-project/sql PR: 0
File: :0-0
Timestamp: 2025-12-11T05:27:39.856Z
Learning: In opensearch-project/sql, for SEMI and ANTI join types in CalciteRelNodeVisitor.java, the `max` option has no effect because these join types only use the left side to filter records based on the existence of matches in the right side. The join results are identical regardless of max value (max=1, max=2, or max=∞). The early return for SEMI/ANTI joins before processing the `max` option is intentional and correct behavior.

Applied to files:

  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q29.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/clickbench/q28.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_exists_correlated_subquery.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_global_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_reset_null_bucket.yaml
  • integ-test/src/test/resources/expectedOutput/calcite/explain_multisearch_timestamp.yaml
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Follow existing patterns in `CalciteRelNodeVisitor` and `CalciteRexNodeVisitor` for Calcite integration

Applied to files:

  • integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json
🧬 Code graph analysis (1)
opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java (2)
legacy/src/main/java/org/opensearch/sql/legacy/query/planner/logical/node/Sort.java (1)
  • Sort (16-48)
opensearch/src/main/java/org/opensearch/sql/opensearch/planner/physical/CalciteEnumerableTopK.java (1)
  • CalciteEnumerableTopK (21-54)
🔇 Additional comments (16)
integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest_custom_time.yaml (1)

11-14: LGTM!

The test expectation correctly reflects the Limit + Sort fusion into EnumerableLimitSort. The sort key (sort0=[$5]), direction (dir0=[ASC]), and fetch limit (fetch=[10000]) are properly combined into a single operator, which aligns with the PR objective of reducing memory overhead by avoiding full in-memory sorts.

opensearch/src/main/java/org/opensearch/sql/opensearch/storage/scan/CalciteLogicalIndexScan.java (1)

420-429: LGTM!

The guard logic correctly prevents stack overflow by checking if an identical LimitDigest already exists at the top of the pushdown context. This is a sound fix for the recursive pushdown issue, and the precomputed digest variable is properly reused when adding to the context.

integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_reset_null_bucket.yaml (1)

18-40: LGTM!

The test expectation correctly reflects the plan restructuring:

  • EnumerableLimitSort fuses the limit and sort operations
  • EnumerableMergeJoin with 3-key condition requires the corresponding 3-key sorts on both inputs
  • The inner branch projections ([gender, age]) are appropriately minimized for the join/aggregation logic

The plan structure is consistent with the TopK optimization objective.

integ-test/src/test/resources/expectedOutput/calcite/explain_multisearch_timestamp.yaml (1)

16-27: LGTM!

The test expectation correctly reflects the multisearch physical plan with EnumerableMergeUnion. The LIMIT->5 appears twice in each PushDownContext (before and after PROJECT), which is consistent with limit pushdown occurring at multiple stages. The search filter terms (A, B for the first source; E, F for the second) are correctly represented in the query builders.

integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_global_null_bucket.yaml (1)

16-31: LGTM!

The test expectation correctly reflects the TopK optimization with EnumerableLimitSort fusing the limit and sort. The EnumerableMergeJoin with its required sorted inputs and the inner branch's optimized projections ([gender] and [gender, age]) are appropriately structured.

integ-test/src/test/resources/expectedOutput/calcite/explain_limit_agg_pushdown5.json (1)

4-4: LGTM!

The test expectation correctly shows EnumerableLimitSort(sort0=[$0], dir0=[ASC-nulls-first], fetch=[100]) replacing the previous EnumerableSort(fetch=[100]). This fusion is consistent with the PR objective of combining limit and sort into a single TopK operator for improved memory efficiency.

integ-test/src/test/resources/expectedOutput/calcite/clickbench/q28.yaml (1)

13-15: LGTM!

This is the key test expectation for the PR's main objective (issue #4982). The EnumerableLimitSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[25]) directly addresses the OOM issue by maintaining only the top 25 results in memory during sorting, rather than sorting all data first and then limiting. This pattern is correct and will prevent the memory exhaustion observed in Clickbench Q28.

integ-test/src/test/resources/expectedOutput/calcite/clickbench/q29.yaml (1)

14-17: LGTM! Physical plan correctly reflects TopK fusion.

The expected output properly shows the optimization: the inner EnumerableLimit(fetch=[25]) + EnumerableSort pattern is fused into a single EnumerableLimitSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[25]), while preserving the outer system limit (EnumerableLimit(fetch=[10000])). This aligns with the PR objective to reduce memory usage by avoiding full in-memory sorts.

opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/OpenSearchIndexRules.java (2)

44-46: LGTM! Rule registration follows existing patterns.

The new ENUMERABLE_TOP_K_RULE follows the established pattern for rule instantiation and naming conventions (UPPER_SNAKE_CASE for constants).


66-68: Verify rule ordering is intentional.

The ENUMERABLE_TOP_K_RULE is placed before EXPAND_COLLATION_ON_PROJECT_EXPR. Please confirm this ordering is intentional, as the TopK transformation should occur before collation expansion to ensure proper optimization.

integ-test/src/test/resources/expectedOutput/calcite/explain_exists_correlated_subquery.yaml (1)

15-17: Verify semantic equivalence of operator reordering.

The physical plan now has EnumerableLimit(fetch=[10000]) above EnumerableCalc, whereas the previous structure had them in reverse order. While this may be a valid optimization, please verify that limiting before calculating (projection) is semantically equivalent in this correlated subquery context—especially since the projection changes the column ordering (id, name, salary from name, id, salary).

integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_earliest_latest.yaml (1)

11-14: LGTM! Correctly demonstrates Limit+Sort fusion.

The expected output properly reflects the TopK optimization: EnumerableLimit(fetch=[10000]) + EnumerableSort(sort0=[$5], dir0=[ASC]) are fused into EnumerableLimitSort(sort0=[$5], dir0=[ASC], fetch=[10000]). The downstream window operators and index scan remain unchanged.

integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_distinct_count.yaml (1)

11-14: LGTM! Consistent with TopK fusion pattern.

The expected output correctly shows the Limit+Sort operators fused into a single EnumerableLimitSort while preserving downstream window operators and the index scan context.

opensearch/src/main/java/org/opensearch/sql/opensearch/planner/rules/EnumerableTopKRule.java (2)

17-26: LGTM! Well-documented rule implementation.

The class-level JavaDoc clearly explains the transformation purpose. The rule correctly extends InterruptibleRelRule and follows the established pattern in this codebase.


51-58: Rule predicate correctly identifies TopK candidates.

The predicate ensures the rule only matches LogicalSort nodes that have:

  1. A fetch or offset (making it a "top" operation)
  2. Non-empty field collations (actual ordering is specified)

This correctly filters for genuine TopK scenarios.

integ-test/src/test/resources/expectedOutput/calcite/explain_streamstats_null_bucket.yaml (1)

11-15: LGTM! Consistent TopK fusion pattern.

The expected output correctly demonstrates the Limit+Sort fusion into EnumerableLimitSort while preserving the windowing and index scan operators downstream.

Copy link
Collaborator

@yuancu yuancu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@LantaoJin
Copy link
Member Author

LantaoJin commented Dec 25, 2025

Let's suspend on merging until #4992 merged

* CalciteEnumerableTopK}.
*/
@Value.Enclosing
public class EnumerableTopKRule extends InterruptibleRelRule<EnumerableTopKRule.Config> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need copy the license from Calcite?

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Clickbench PPL q28 is easily OOM due to sort all data in memory

3 participants