Skip to content

[ESQL] Adds planner implementation for LIMIT BY#144069

Merged
ncordon merged 32 commits intoelastic:mainfrom
ncordon:esql-limit-by-planner-alt
Mar 19, 2026
Merged

[ESQL] Adds planner implementation for LIMIT BY#144069
ncordon merged 32 commits intoelastic:mainfrom
ncordon:esql-limit-by-planner-alt

Conversation

@ncordon
Copy link
Copy Markdown
Member

@ncordon ncordon commented Mar 11, 2026

This is part of the new LIMIT BY ESQL command. LIMIT N BY expr1, expr2,... retains at most N documents per group, where groups are defined by one or more grouping key expressions.

It introduces a new LimitBy logical plan node and LimitByExec physical plan node. It doesn't modify existing Limit and LimitExec nodes.

This PR knits the parser changes and the planner changes for the compute side, GroupedLimitOperator that was added in #143458.

This means it enables queries like this:

FROM test
| LIMIT 5 BY languages
| KEEP first_name, last_name, salary, languages

but we have restricted using a SORT before the LIMIT BY until #143476 and #144279 have been merged. We have also done this for cleanliness because otherwise this PR would be even bigger. This means queries like this one would fail:

FROM test
| SORT first_name
| LIMIT 5 BY languages
| KEEP first_name, last_name, salary, languages

Part of #112918, https://github.com/elastic/esql-planning/issues/238

@ncordon ncordon added >feature :Analytics/EQL EQL querying Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) v9.4.0 labels Mar 11, 2026
@ncordon ncordon force-pushed the esql-limit-by-planner-alt branch from 77aaad1 to 851d414 Compare March 12, 2026 00:15
@ncordon ncordon marked this pull request as ready for review March 12, 2026 13:24
@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-analytical-engine (Team:Analytics)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces the initial end-to-end plumbing for the new ESQL command LIMIT N BY expr1, expr2, ..., adding parsing support, logical/physical plan nodes, optimizer rules, and compute-engine planning to execute grouped limiting (without supporting SORT directly before LIMIT BY yet).

Changes:

  • Add new logical (LimitBy) and physical (LimitByExec) plan nodes, including (de)serialization and planner wiring.
  • Extend the parser/grammar to recognize LIMIT ... BY ... (dev-version gated) and add verification to reject SORT directly before LIMIT BY.
  • Add logical/physical optimizer rules and tests to handle expression groupings, pruning foldable group keys, and combining/pushing down LIMIT BY.

Reviewed changes

Copilot reviewed 40 out of 41 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.g4 Grammar: adds optional BY ... group key to LIMIT command (dev build gated).
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java Parser: builds LimitBy logical node when BY is present.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/LimitBy.java New logical plan node representing grouped limit and its execution-location hints.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/LimitByExec.java New physical plan node for grouped limit, including row-size estimation and serialization.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/Mapper.java Planner mapping: wires LimitBy -> LimitByExec and injects local limits into fragments under LimitBy.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/mapper/LocalMapper.java Local planner mapping for LimitBy -> LimitByExec.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java Reduction planning: skips “local” pipeline breakers when selecting reduction boundaries.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java Compute planning: adds GroupedLimitOperator planning for LimitByExec; refactors attribute-channel lookup.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java Adds new LIMIT BY optimizer rules to the optimization pipeline.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceLimitByExpressionWithEval.java New rule: extracts non-attribute groupings into synthetic Eval + wraps with Project.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PruneLiteralsInLimitBy.java New rule: drops foldable grouping keys and degenerates to plain LIMIT when all keys are foldable.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineLimitBy.java New rule: combines adjacent LimitBy, pushes/duplicates across certain unary/binary nodes.
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java Adds verification: blocks SORT directly before LIMIT BY (temporary restriction).
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Expressions.java Adds listSemanticEquals utility for comparing grouping lists.
x-pack/plugin/esql/qa/testFixtures/src/main/resources/limit.csv-spec QA coverage: adds LIMIT BY spec tests behind limit_by capability.
x-pack/plugin/esql/src/test/java/... Adds extensive unit tests for parser, verifier, optimizer rules, and physical planning/serialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ncordon ncordon requested a review from ivancea March 12, 2026 15:13
@ncordon ncordon force-pushed the esql-limit-by-planner-alt branch from 18378a7 to 41d3029 Compare March 12, 2026 15:24
@ncordon ncordon changed the title [ESQL] Adds parsing and planner wiring for LIMIT BY [ESQL] Adds planner implementation for LIMIT BY Mar 12, 2026
FROM employees
| WHERE emp_no IN (10001, 10002, 10003, 10005, 10006)
| SORT emp_no
| LIMIT 1000
Copy link
Copy Markdown
Contributor

@idegtiarenko idegtiarenko Mar 13, 2026

Choose a reason for hiding this comment

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

Do we need this limit here and in other cases? I believe we have much fewer records in employees, especially above condition.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it to avoid sorts over the entire result set?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Technically no, as the default "limit 1000" automatically added. We can remove it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe it is to avoid warning about default limit?
I do not think it is suppressed by new limit by, is it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's not, so yes, it could be for the warning 👀

Copy link
Copy Markdown
Member Author

@ncordon ncordon Mar 13, 2026

Choose a reason for hiding this comment

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

We want stable results so we have to use SORT, but we cannot use SORT + LIMIT BY yet because we need a different logical and physical plan for that, so it's disallowed. The intermediate LIMIT is just temporary. I've added removing it as a task to do in the future so we don't forget: https://github.com/elastic/esql-planning/issues/262

FROM employees
| WHERE emp_no IN (10001, 10002, 10003, 10005, 10006)
| SORT emp_no
| LIMIT 1000
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's not, so yes, it could be for the warning 👀

@ncordon ncordon force-pushed the esql-limit-by-planner-alt branch from 35d28e0 to 98d0f9a Compare March 16, 2026 00:24
@ncordon
Copy link
Copy Markdown
Member Author

ncordon commented Mar 17, 2026

@ncordon It looks like the PR you referred to is already merged. #143476 . Should we remove the SORT restriction or you want to do that in a separate PR?

We cannot remove the check in this PR yet. The planner to enable SORT before is the pr we should review after #144279. I've updated the description.

@ncordon ncordon force-pushed the esql-limit-by-planner-alt branch from b3dac22 to 31ffe90 Compare March 17, 2026 18:22
@ncordon ncordon enabled auto-merge (squash) March 18, 2026 09:21
@ncordon ncordon disabled auto-merge March 18, 2026 17:53
@ncordon ncordon enabled auto-merge (squash) March 18, 2026 17:54
@ncordon ncordon merged commit d690e76 into elastic:main Mar 19, 2026
36 checks passed
bartoval added a commit to elastic/kibana that referenced this pull request Mar 19, 2026
## Summary


https://github.com/user-attachments/assets/a2fc7656-935d-4b62-88cc-05418d321b6b

- The BY part of the LIMIT command is currently flagged as
development-only, so it needs to be hidden
- A mysterious voice says that LIMIT BY cannot come before SORT, so we
added a validation and temporarily do not suggest it
elastic/elasticsearch#144069

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Stratou <efstratia.kalafateli@elastic.co>
michalborek pushed a commit to michalborek/elasticsearch that referenced this pull request Mar 23, 2026
---------

Co-authored-by: Iván Cea Fontenla <ivancea96@outlook.com>
jeramysoucy pushed a commit to jeramysoucy/kibana that referenced this pull request Mar 26, 2026
## Summary


https://github.com/user-attachments/assets/a2fc7656-935d-4b62-88cc-05418d321b6b

- The BY part of the LIMIT command is currently flagged as
development-only, so it needs to be hidden
- A mysterious voice says that LIMIT BY cannot come before SORT, so we
added a validation and temporarily do not suggest it
elastic/elasticsearch#144069

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Stratou <efstratia.kalafateli@elastic.co>
ivancea added a commit that referenced this pull request Apr 8, 2026
Generative tests generators for LIMIT BY, which was added in #144069 and #144279
mromaios pushed a commit to mromaios/elasticsearch that referenced this pull request Apr 9, 2026
Generative tests generators for LIMIT BY, which was added in elastic#144069 and elastic#144279
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Analytics/EQL EQL querying >feature Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants