Fix query result cache for PromQL queries#110887
Conversation
`ParserPrometheusQuery` set `table_expression` of `ASTTablesInSelectQueryElement` without linking it into `children`, so in-place AST visitors never saw the transpiled `prometheusQuery` table function. In particular, `astContainsNonDeterministicFunctions` missed `now()` (the 'auto' evaluation time), so with `use_query_cache = 1` the default `query_cache_nondeterministic_function_handling = 'throw'` protection was silently bypassed and stale `now()`-anchored results were served from the cache for up to the entry TTL. The cache key itself was unaffected because it is computed on a clone of the AST, and `clone` rebuilds `children` from the typed members. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`PrometheusHTTPProtocolAPI::executePromQLQuery` destroyed the `PullingPipelineExecutor` (whose destructor cancels all pipeline processors even after normal completion) before `finishExecutedQuery`, so `StreamInQueryResultCacheTransform::finalizeWriteInQueryResultCache` saw `isCancelled()` and silently dropped every pending cache write - the query cache could never be populated through `/api/v1/query` and `/api/v1/query_range`. Store the buffered result while the executor is still alive, as already done for scalar subqueries and prepared sets. This also commits the entry before the HTTP response is finalized, so a client observing the response completion also observes the cache entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Workflow [PR], commit [d8bef86] Summary: ❌
AI ReviewSummaryThis PR fixes two real query-cache regressions in PromQL handling, and I did not find a remaining correctness issue in the current code. The Missing context / blind spots
Final Verdict✅ No new findings. |
The style check requires queries to `system.query_log` to filter by `current_database = currentDatabase()`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LLVM Coverage Report
Changed lines: Changed C/C++ lines covered: 9/9 (100.00%) · Uncovered code |
|
@groeneai help investigate the test failures. |
|
Both red checks are unrelated to the PromQL parser/API changes here (the diff touches only 1. 2. Neither failure is caused by this PR; a re-run should clear both. |
|
@groeneai investigate all the tests separately and submit a PR for each. |
|
Acknowledged. I'll investigate 04408_array_fold_cancellation and the "Input nodes size mismatch in dag" logical error separately and follow up here with a fixing PR for each (or the existing fixing-PR link where one already covers the failure). |
|
@nikitamikhaylov done, one PR per failure: 1. Pre-existing flaky, unrelated to this PR: 60 FAIL / 36,777 OK (~0.16%) over 30 days across 15 unrelated PRs, 0 on master; the job's own same-settings rerun passes 6/6. Always the same diff line, the Root cause: arrayFold folds a block in one 2. "Input nodes size mismatch in dag" Pre-existing chronic trunk error, unrelated to this PR (no PromQL/parser code on the path). The instance here is the duplicate-qualified-input variant ( |
The query result cache did not work correctly for PromQL queries, in both directions.
The
promqldialect transpiles a query intoSELECT * FROM prometheusQuery('table', '<promql>', now()), butParserPrometheusQuerydid not link the table expression into thechildrenofASTTablesInSelectQueryElement. In-place AST visitors traversechildren, soastContainsNonDeterministicFunctionsnever sawnow()and the defaultquery_cache_nondeterministic_function_handling = 'throw'protection was silently bypassed.The Prometheus HTTP API (
/api/v1/query,/api/v1/query_range) could never populate the cache.Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fix the query result cache for PromQL queries. The
promqldialect bypassed the non-deterministic-function check and could serve stale results anchored atnow(); the Prometheus HTTP API (/api/v1/query,/api/v1/query_range) never stored cache entries at all.🤖 Generated with Claude Code