Skip to content

PromQL: Binary operators#98948

Merged
vitlibar merged 5 commits intoClickHouse:masterfrom
vitlibar:promql-binary-ops
Mar 20, 2026
Merged

PromQL: Binary operators#98948
vitlibar merged 5 commits intoClickHouse:masterfrom
vitlibar:promql-binary-ops

Conversation

@vitlibar
Copy link
Member

@vitlibar vitlibar commented Mar 6, 2026

Changelog category (leave one):

  • Not for changelog (changelog entry is not required)

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

PromQL: Adds support for binary operators +, -, *, /, %, ^, atan2

Part of #89356


Note

Medium Risk
Adds new PromQL operator support and introduces non-trivial SQL generation for vector/scalar binary ops (including join/grouping semantics), which could affect query correctness and performance. Switching tag filters from WHERE to PREWHERE changes execution order and may alter planning behavior.

Overview
Adds PromQL binary-operator support for +, -, *, /, %, ^, and atan2 by extending the ANTLR grammar (new ATAN2 token and parsing as a multiplicative operator) and updating the PromQL parse-tree builder to emit the new operator.

Implements SQL conversion for PQT::BinaryOperator nodes via new applyBinaryOperator()/applyMathBinaryOperator() logic, including scalar-vs-vector handling and vector-vector joining with on/ignoring and group_left/group_right modifiers.

Refactors applyDateTimeFunction() to use applySimpleFunctionHelper() and replaces the previous math simple-function path with applyOneArgumentMathFunction(). Updates timeSeriesSelector() SQL to use PREWHERE (instead of WHERE) for tag-based filtering to ensure tags are collected before downstream functions run.

Written by Cursor Bugbot for commit bd91268. This will update automatically on new commits. Configure here.

@vitlibar vitlibar requested a review from Copilot March 6, 2026 19:09
@clickhouse-gh
Copy link
Contributor

clickhouse-gh bot commented Mar 6, 2026

Workflow [PR], commit [bd91268]

Summary:

@vitlibar vitlibar added the comp-promql Issues related to the PromQL support and TimeSeries table engine. label Mar 6, 2026
@clickhouse-gh clickhouse-gh bot added pr-not-for-changelog This PR should not be mentioned in the changelog submodule changed At least one submodule changed in this PR. labels Mar 6, 2026
Copy link
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 extends ClickHouse’s PromQL support by adding math binary operators (+, -, *, /, %, ^, atan2) and implements vector-to-vector matching semantics (on(...), ignoring(...), group_left/right(...)) in the PrometheusQueryToSQL converter, with integration tests covering scalar/scalar, vector/scalar, and vector/vector cases.

Changes:

  • Add parsing support for atan2 as a PromQL binary operator and route binary-operator nodes through the PrometheusQueryToSQL converter.
  • Implement SQL generation for math binary operators, including instant-vector join logic with on/ignoring/group_left/group_right and helper conversions (toVectorGrid, join_group).
  • Expand integration test data and add tests for math binary operators and vector matching behavior.

Reviewed changes

Copilot reviewed 23 out of 31 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/integration/test_prometheus_protocols/test_evaluation.py Adds dataset and assertions for binary-operator evaluation (scalar/scalar, vector/scalar, vector/vector with matching modifiers).
src/Storages/TimeSeries/TimeSeriesColumnNames.h Adds internal columns used for binary-operator joins (original_group, join_group); removes unused Scalar.
src/Storages/TimeSeries/PrometheusQueryToSQL/toVectorGrid.h / .cpp Adds helper to normalize instant-vector store methods into VECTOR_GRID for consistent join/aggregation.
src/Storages/TimeSeries/PrometheusQueryToSQL/makeASTForBinaryOperatorJoinGroup.h / .cpp Builds join_group expression implementing on(...) / ignoring(...) semantics for vector matching.
src/Storages/TimeSeries/PrometheusQueryToSQL/applySimpleFunctionHelper.h / .cpp Adds reusable helper to apply “per-sample” transformations across scalar/vector and grid forms.
src/Storages/TimeSeries/PrometheusQueryToSQL/applyOneArgumentMathFunction.h / .cpp Refactors one-argument math function handling to use the new simple-function helper.
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathSimpleFunction.h / .cpp Removed in favor of the new one-argument math function implementation + helper.
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathBinaryOperator.h / .cpp Implements math binary operators, including vector matching and group modifiers via SQL joins.
src/Storages/TimeSeries/PrometheusQueryToSQL/applyBinaryOperator.h / .cpp Adds dispatcher for PromQL binary operators (currently math operators).
src/Storages/TimeSeries/PrometheusQueryToSQL/applyFunction.cpp Switches math function detection to isOneArgumentMathFunction.
src/Storages/TimeSeries/PrometheusQueryToSQL/applyDateTimeFunction.cpp Refactors date/time functions to use applySimpleFunctionHelper.
src/Storages/TimeSeries/PrometheusQueryToSQL/Converter.cpp Adds handling for NodeType::BinaryOperator in PromQL AST traversal.
src/Storages/StorageTimeSeriesSelector.cpp Uses PREWHERE (instead of WHERE) to enforce tags-collection ordering semantics.
src/Parsers/Prometheus/PrometheusQueryParsingUtil-antlr.cpp Adds atan2 operator mapping in the Antlr parse-to-AST adapter.
contrib/antlr4-grammars/promql/PromQLParser.g4 / PromQLLexer.g4 Extends grammar/lexer to recognize atan2 as a mult-op and keyword.
contrib/antlr4-grammars-cmake/generated/antlr4_grammars/* Updates generated Antlr artifacts to match the grammar change (adds ATAN2).

@vitlibar vitlibar force-pushed the promql-binary-ops branch from 2822f60 to 9c14de9 Compare March 6, 2026 19:28
@vitlibar vitlibar marked this pull request as ready for review March 6, 2026 19:41
@vitlibar vitlibar force-pushed the promql-binary-ops branch from 9c14de9 to 0fc298d Compare March 6, 2026 20:04
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

///
/// if with group_left/group_right:
/// SELECT timeSeriesCopyTag(timeSeriesRemoveTag(side_many.original_group, '__name__'), side_one.original_group, extra_labels) AS group,
/// arrayMap(x, y -> f(x, y), left.values, right.values) AS values
Copy link
Member

Choose a reason for hiding this comment

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

Interesting that here we access the columns from the both sides - left and right while the SEMI JOIN implies a filtering of one table based on the other.

Copy link
Member

Choose a reason for hiding this comment

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

In fact I guess in both cases we should execute the LEFT/RIGHT INNER ANY JOIN.

Copy link
Member Author

Choose a reason for hiding this comment

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

We need to find matching rows from side_many and side_one. For each match there can be many matching rows on side_many, and only one matching row is expected on side_one. If there are unmatched rows then they don't go to the result. I think it's SEMI JOIN.

Copy link
Member Author

@vitlibar vitlibar Mar 20, 2026

Choose a reason for hiding this comment

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

It seems just INNER JOIN would also work here, but I thought SEMI JOIN can be faster because it avoids cartesian product.

@vitlibar vitlibar added this pull request to the merge queue Mar 20, 2026
Merged via the queue into ClickHouse:master with commit 8f93f9a Mar 20, 2026
150 checks passed
@vitlibar vitlibar deleted the promql-binary-ops branch March 20, 2026 17:04
@robot-ch-test-poll4 robot-ch-test-poll4 added the pr-synced-to-cloud The PR is synced to the cloud repo label Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp-promql Issues related to the PromQL support and TimeSeries table engine. pr-not-for-changelog This PR should not be mentioned in the changelog pr-synced-to-cloud The PR is synced to the cloud repo submodule changed At least one submodule changed in this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants