@@ -222,11 +222,10 @@ type aggregators struct {
222
222
// a single metric. It may apply pushdowns to functions.
223
223
func getAggregators (metadata * promqlMetadata ) (* aggregators , parser.Node , error ) {
224
224
// 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
230
229
}
231
230
232
231
defaultAggregators := & aggregators {
@@ -238,13 +237,6 @@ func getAggregators(metadata *promqlMetadata) (*aggregators, parser.Node, error)
238
237
return defaultAggregators , nil , nil
239
238
}
240
239
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
-
248
240
// tryPushDown inspects the AST above the current node to determine if it's
249
241
// possible to make use of a known pushdown function.
250
242
//
@@ -271,39 +263,57 @@ func tryPushDown(metadata *promqlMetadata) (*aggregators, parser.Node, error) {
271
263
queryHints := metadata .queryHints
272
264
selectHints := metadata .selectHints
273
265
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
+
274
278
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
283
295
}
296
+ }
284
297
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 ),
306
315
}
316
+ return & qf , queryHints .CurrentNode , nil
307
317
}
308
318
return nil , nil , nil
309
319
}
0 commit comments