PromQL: Binary operators#98948
Conversation
There was a problem hiding this comment.
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
atan2as 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_rightand 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). |
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathBinaryOperator.cpp
Show resolved
Hide resolved
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathBinaryOperator.cpp
Outdated
Show resolved
Hide resolved
src/Storages/TimeSeries/PrometheusQueryToSQL/applyOneArgumentMathFunction.cpp
Show resolved
Hide resolved
src/Storages/TimeSeries/PrometheusQueryToSQL/applyBinaryOperator.cpp
Outdated
Show resolved
Hide resolved
src/Storages/TimeSeries/PrometheusQueryToSQL/makeASTForBinaryOperatorJoinGroup.cpp
Show resolved
Hide resolved
…ntextTimeSeriesTagsCollector before we use them
2822f60 to
9c14de9
Compare
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathBinaryOperator.cpp
Show resolved
Hide resolved
9c14de9 to
0fc298d
Compare
src/Storages/TimeSeries/PrometheusQueryToSQL/applyMathBinaryOperator.cpp
Outdated
Show resolved
Hide resolved
0fc298d to
bd91268
Compare
| /// | ||
| /// 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
In fact I guess in both cases we should execute the LEFT/RIGHT INNER ANY JOIN.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
It seems just INNER JOIN would also work here, but I thought SEMI JOIN can be faster because it avoids cartesian product.
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
PromQL: Adds support for binary operators
+,-,*,/,%,^,atan2Part 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
WHEREtoPREWHEREchanges execution order and may alter planning behavior.Overview
Adds PromQL binary-operator support for
+,-,*,/,%,^, andatan2by extending the ANTLR grammar (newATAN2token and parsing as a multiplicative operator) and updating the PromQL parse-tree builder to emit the new operator.Implements SQL conversion for
PQT::BinaryOperatornodes via newapplyBinaryOperator()/applyMathBinaryOperator()logic, including scalar-vs-vector handling and vector-vector joining withon/ignoringandgroup_left/group_rightmodifiers.Refactors
applyDateTimeFunction()to useapplySimpleFunctionHelper()and replaces the previous math simple-function path withapplyOneArgumentMathFunction(). UpdatestimeSeriesSelector()SQL to usePREWHERE(instead ofWHERE) 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.