Skip to content
This repository was archived by the owner on Apr 2, 2024. It is now read-only.

Commit 54235be

Browse files
committed
Do not attempt to push down calls with offsets
We don't correctly handle pushdowns with offsets, so we just skip them instead of returning erroneous results.
1 parent 32c9aa1 commit 54235be

File tree

3 files changed

+56
-41
lines changed

3 files changed

+56
-41
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ We use the following categories for changes:
1919

2020
### Fixed
2121
- Fix spans with end < start. Start and end are swapped in this case. [#1096]
22+
- Disable push downs which use `offset`, as they are broken [#1129]
2223

2324
## [0.9.0] - 2022-02-02
2425

pkg/pgmodel/querier/query_builder.go

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,10 @@ type aggregators struct {
222222
// a single metric. It may apply pushdowns to functions.
223223
func getAggregators(metadata *promqlMetadata) (*aggregators, parser.Node, error) {
224224
// todo: investigate if query hints can have only node and lookback
225-
if canAttemptPushdown(metadata) {
226-
agg, node, err := tryPushDown(metadata)
227-
if err == nil && agg != nil {
228-
return agg, node, nil
229-
}
225+
226+
agg, node, err := tryPushDown(metadata)
227+
if err == nil && agg != nil {
228+
return agg, node, nil
230229
}
231230

232231
defaultAggregators := &aggregators{
@@ -238,13 +237,6 @@ func getAggregators(metadata *promqlMetadata) (*aggregators, parser.Node, error)
238237
return defaultAggregators, nil, nil
239238
}
240239

241-
func canAttemptPushdown(metadata *promqlMetadata) bool {
242-
path := metadata.path // PromQL AST.
243-
queryHints := metadata.queryHints
244-
selectHints := metadata.selectHints
245-
return extension.ExtensionIsInstalled && queryHints != nil && !hasSubquery(path) && selectHints != nil
246-
}
247-
248240
// tryPushDown inspects the AST above the current node to determine if it's
249241
// possible to make use of a known pushdown function.
250242
//
@@ -271,39 +263,57 @@ func tryPushDown(metadata *promqlMetadata) (*aggregators, parser.Node, error) {
271263
queryHints := metadata.queryHints
272264
selectHints := metadata.selectHints
273265

266+
switch {
267+
// We can't push down without hints.
268+
case queryHints == nil || selectHints == nil:
269+
return nil, nil, nil
270+
// We can't handle subqueries in pushdowns.
271+
case hasSubquery(path):
272+
return nil, nil, nil
273+
// We can't do pushdowns without the extension.
274+
case !extension.ExtensionIsInstalled:
275+
return nil, nil, nil
276+
}
277+
274278
vs, isVectorSelector := queryHints.CurrentNode.(*parser.VectorSelector)
275-
if isVectorSelector {
276-
if len(path) >= 2 {
277-
grandparent := path[len(path)-2]
278-
funcName, canPushDown := tryExtractPushdownableFunctionName(grandparent)
279-
if canPushDown {
280-
agg, err := callAggregator(selectHints, funcName)
281-
return agg, grandparent, err
282-
}
279+
280+
switch {
281+
// We can't push down something that isn't a VectorSelector.
282+
case !isVectorSelector:
283+
return nil, nil, nil
284+
// We can't handle offsets in VectorSelector pushdowns.
285+
case vs.OriginalOffset != 0 || vs.Offset != 0:
286+
return nil, nil, nil
287+
}
288+
289+
if len(path) >= 2 {
290+
grandparent := path[len(path)-2]
291+
funcName, canPushDown := tryExtractPushdownableFunctionName(grandparent)
292+
if canPushDown {
293+
agg, err := callAggregator(selectHints, funcName)
294+
return agg, grandparent, err
283295
}
296+
}
284297

285-
//TODO: handle the instant query (hints.Step==0) case too.
286-
287-
// vector selector pushdown improves performance by selecting from the
288-
// database only the last point in a vector selector window(step).
289-
// This decreases the number of samples transferred from the DB to
290-
// Promscale by orders of magnitude. A vector selector aggregate also
291-
// does not require ordered inputs which saves a sort and allows for
292-
// parallel evaluation.
293-
if selectHints.Step > 0 &&
294-
selectHints.Range == 0 && // So this is not an aggregate. That's optimized above
295-
!calledByTimestamp(path) &&
296-
vs.OriginalOffset == time.Duration(0) &&
297-
vs.Offset == time.Duration(0) &&
298-
vectorSelectorExtensionRange(extension.PromscaleExtensionVersion) {
299-
qf := aggregators{
300-
valueClause: "vector_selector($%d, $%d, $%d, $%d, time, value)",
301-
valueParams: []interface{}{queryHints.StartTime, queryHints.EndTime, selectHints.Step, queryHints.Lookback.Milliseconds()},
302-
unOrdered: true,
303-
tsSeries: newRegularTimestampSeries(queryHints.StartTime, queryHints.EndTime, time.Duration(selectHints.Step)*time.Millisecond),
304-
}
305-
return &qf, queryHints.CurrentNode, nil
298+
//TODO: handle the instant query (hints.Step==0) case too.
299+
300+
// vector selector pushdown improves performance by selecting from the
301+
// database only the last point in a vector selector window(step).
302+
// This decreases the number of samples transferred from the DB to
303+
// Promscale by orders of magnitude. A vector selector aggregate also
304+
// does not require ordered inputs which saves a sort and allows for
305+
// parallel evaluation.
306+
if selectHints.Step > 0 &&
307+
selectHints.Range == 0 && // So this is not an aggregate. That's optimized above
308+
!calledByTimestamp(path) &&
309+
vectorSelectorExtensionRange(extension.PromscaleExtensionVersion) {
310+
qf := aggregators{
311+
valueClause: "vector_selector($%d, $%d, $%d, $%d, time, value)",
312+
valueParams: []interface{}{queryHints.StartTime, queryHints.EndTime, selectHints.Step, queryHints.Lookback.Milliseconds()},
313+
unOrdered: true,
314+
tsSeries: newRegularTimestampSeries(queryHints.StartTime, queryHints.EndTime, time.Duration(selectHints.Step)*time.Millisecond),
306315
}
316+
return &qf, queryHints.CurrentNode, nil
307317
}
308318
return nil, nil, nil
309319
}

pkg/tests/end_to_end_tests/promql_query_endpoint_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,6 +2506,10 @@ func TestPromQLQueryEndpoint(t *testing.T) {
25062506
name: "two pushdowns, same metric different matchers",
25072507
query: `sum(rate(metric_2{foo = "bar"}[5m]))/sum(rate(metric_2[5m]))`,
25082508
},
2509+
{
2510+
name: "delta function over range selector with offset",
2511+
query: `delta(metric_2[1m] offset 3m)`,
2512+
},
25092513
}
25102514
start := time.Unix(startTime/1000, 0)
25112515
end := time.Unix(endTime/1000, 0)

0 commit comments

Comments
 (0)