Skip to content

Implement PromQL set operator: top-level or (UNION) - #151486

Merged
felixbarny merged 10 commits into
elastic:mainfrom
felixbarny:promql-set-operator
Jun 18, 2026
Merged

felixbarny merged 10 commits into
elastic:mainfrom
felixbarny:promql-set-operator

Conversation

@felixbarny

Copy link
Copy Markdown
Member

Summary

Implements the PromQL or (UNION) set operator for top-level instant-vector expressions.

  • A contiguous top-level chain of or operators (e.g. a or b or c) is flattened into a single UnionAll + TopNBy plan. The synthetic _branch ordering column ensures left-branch precedence: a series from the left operand shadows any matching series from the right, exactly matching PromQL semantics.
  • VectorBinarySet.output() now returns the union of both operands' label sets (left first), and the dropMetricName flag is false for set operators so __name__ is preserved.
  • The verifier allows top-level or between instant vectors and rejects and/unless (still unsupported), nested unions, scalar operands, and chains exceeding Fork.MAX_BRANCHES (8 operands).
  • PROMQL_SET_OPERATOR_UNION capability gate added.
  • applyNullOutputFilter now locates the value column by name rather than by position, which was incorrect in the multi-branch path where the value column appears at the end of each branch's output before projection.

New tests:

  • PromqlVerifierTests: verifier acceptance/rejection coverage for the new supported and still-unsupported shapes.
  • PromqlPlanSetOperatorTests: golden-plan tests asserting the UnionAll + TopNBy structure.
  • PrometheusSetOperatorRestIT: end-to-end REST tests via the native Prometheus query endpoints.
  • CSV-spec cases covering: combining series, left precedence, vector(0) fallback, rate or irate idiom, heterogeneous groupings, and a three-branch chain.

Translates a top-level PromQL `or` chain into a UnionAll + TopNBy plan.
Left-branch precedence is enforced via a synthetic _branch ordering
column. and/unless remain unsupported and are rejected by the verifier.
@felixbarny felixbarny self-assigned this Jun 17, 2026
@elasticsearchmachine elasticsearchmachine added the external-contributor Pull request authored by a developer outside the Elasticsearch team label Jun 17, 2026
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

Hi @felixbarny, I've created a changelog YAML for you.

# Conflicts:
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/TranslatePromqlToEsqlPlan.java
@github-actions

github-actions Bot commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

🔍 Preview links for changed docs

@github-actions

Copy link
Copy Markdown
Contributor

ℹ️ Important: Docs version tagging

👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version.

We use applies_to tags to mark version-specific features and changes.

Expand for a quick overview

When to use applies_to tags:

✅ At the page level to indicate which products/deployments the content applies to (mandatory)
✅ When features change state (e.g. preview, ga) in a specific version
✅ When availability differs across deployments and environments

What NOT to do:

❌ Don't remove or replace information that applies to an older version
❌ Don't add new information that applies to a specific version without an applies_to tag
❌ Don't forget that applies_to tags can be used at the page, section, and inline level

🤔 Need help?

The new set_operator_union_* CSV-spec cases omitted the
promql_command_v0 capability, so GenerativeForkIT did not skip
them and failed with "FORK after subquery is not supported".
# Conflicts:
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
Distinguish the three set-operator failures with specific
messages: scalar operands are illegal in PromQL itself (align
wording with Prometheus), while unsupported and/unless and
non-top-level or remain current implementation limitations.
Also reuse VectorBinarySet#output dedup logic for the union
branch output in translation.
Explain why top-level `or` is special-cased and where `and`/`unless`
will translate. Replace the redundant branch-limit throw with an
assert, since PromqlCommand.verify already enforces it.
@felixbarny
felixbarny marked this pull request as ready for review June 18, 2026 06:14
@felixbarny
felixbarny requested a review from sidosera June 18, 2026 06:14
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-storage-engine (Team:StorageEngine)

Top-level `or` between instant vectors is now supported; only
`and`/`unless` and non-top-level/scalar `or` remain unsupported.
@felixbarny
felixbarny requested a review from a team as a code owner June 18, 2026 06:16
Scalar/instant-vector operand rules are standard PromQL behavior,
not Elasticsearch-specific; only the top-level restriction remains.
@felixbarny
felixbarny merged commit 74b78e4 into elastic:main Jun 18, 2026
37 checks passed
@felixbarny
felixbarny deleted the promql-set-operator branch June 18, 2026 12:12
@sidosera

Copy link
Copy Markdown
Contributor

lgtm

szybia added a commit to szybia/elasticsearch that referenced this pull request Jun 18, 2026
* upstream/main: (83 commits)
  [Inference API] Refactor Llama service settings to use ObjectParser (elastic#151225)
  Implement PromQL set operator: top-level `or` (UNION) (elastic#151486)
  Mute org.elasticsearch.gradle.internal.precommit.PomValidationPrecommitPluginFuncTest detects missing POM elements and reports structured problems elastic#151636
  Fix native library setup for JMH benchmark forks (elastic#149866)
  [Test] Fix SearchCommitPrefetcherIT.testSearchNodePrefetchesOnlyLatestGenerationOnFirstCommitNotification (elastic#151424)
  Refactor bulk byte vector implementations to not split by parts (elastic#151518)
  Add missing release notes for bundled JDK 26 and 26.0.1 upgrades (elastic#151616)
  ES|QL: Load flattened mapped-root from _source (elastic#151415)
  [ML-CPS] Default project_routing to _alias:_origin on first-time UIAM datafeed migration (elastic#146651)
  Clarify default index type for byte and bit vectors (elastic#151557)
  Fix issue with CacheRegion and PinnedWindowEvictionPolicyTests (elastic#151620)
  [ML] Fix DatafeedConfigTests mutation no-op (elastic#151484)
  Mute org.elasticsearch.xpack.stateless.cluster.coordination.BlobStoreSyncDirectoryTests testCloseCancelsOnGoingUploads elastic#151622
  ESQL:DS: Add in all dataset-supported params (elastic#151551)
  Make an expensive views test faster by reducing index count (elastic#151555)
  Mute org.elasticsearch.xpack.stateless.StatelessMergePreWarmingIT testMergePreWarmingFailureDoesNotFailTheEngine elastic#151618
  Add timestamp to CacheFileRegion (elastic#151240)
  Both PanamaESVectorUtilSupport and DefaultESVectorUtilSupport computed   the inverse norm as a float before multiplying each byte element:
  [slices] Add Yaml tests (elastic#151435)
  Disable BCC slow upload hot threads logging (elastic#151612)
  ...
Kubik42 pushed a commit to Kubik42/elasticsearch that referenced this pull request Jun 18, 2026
Translates a top-level PromQL `or` chain into a UnionAll + TopNBy plan.
Left-branch precedence is enforced via a synthetic _branch ordering
column. and/unless remain unsupported and are rejected by the verifier.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>enhancement external-contributor Pull request authored by a developer outside the Elasticsearch team :StorageEngine/PromQL PromQL support for Elastic Team:StorageEngine v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants