@@ -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,31 +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
-
246
- switch {
247
- // We can't push down without hints.
248
- case queryHints == nil || selectHints == nil :
249
- return false
250
- // We can't do pushdowns without the extension.
251
- case hasSubquery (path ):
252
- return false
253
- // We can't handle subqueries in pushdowns.
254
- case ! extension .ExtensionIsInstalled :
255
- return false
256
- default :
257
- // We can't handle offsets in pushdowns.
258
- vs , isVectorSelector := queryHints .CurrentNode .(* parser.VectorSelector )
259
- if isVectorSelector && vs .Offset != 0 {
260
- return false
261
- }
262
- return true
263
- }
264
- }
265
-
266
240
// tryPushDown inspects the AST above the current node to determine if it's
267
241
// possible to make use of a known pushdown function.
268
242
//
@@ -289,39 +263,57 @@ func tryPushDown(metadata *promqlMetadata) (*aggregators, parser.Node, error) {
289
263
queryHints := metadata .queryHints
290
264
selectHints := metadata .selectHints
291
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
+
292
278
vs , isVectorSelector := queryHints .CurrentNode .(* parser.VectorSelector )
293
- if isVectorSelector {
294
- if len (path ) >= 2 {
295
- grandparent := path [len (path )- 2 ]
296
- funcName , canPushDown := tryExtractPushdownableFunctionName (grandparent )
297
- if canPushDown {
298
- agg , err := callAggregator (selectHints , funcName )
299
- return agg , grandparent , err
300
- }
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
301
295
}
296
+ }
302
297
303
- //TODO: handle the instant query (hints.Step==0) case too.
304
-
305
- // vector selector pushdown improves performance by selecting from the
306
- // database only the last point in a vector selector window(step).
307
- // This decreases the number of samples transferred from the DB to
308
- // Promscale by orders of magnitude. A vector selector aggregate also
309
- // does not require ordered inputs which saves a sort and allows for
310
- // parallel evaluation.
311
- if selectHints .Step > 0 &&
312
- selectHints .Range == 0 && // So this is not an aggregate. That's optimized above
313
- ! calledByTimestamp (path ) &&
314
- vs .OriginalOffset == time .Duration (0 ) &&
315
- vs .Offset == time .Duration (0 ) &&
316
- vectorSelectorExtensionRange (extension .PromscaleExtensionVersion ) {
317
- qf := aggregators {
318
- valueClause : "vector_selector($%d, $%d, $%d, $%d, time, value)" ,
319
- valueParams : []interface {}{queryHints .StartTime , queryHints .EndTime , selectHints .Step , queryHints .Lookback .Milliseconds ()},
320
- unOrdered : true ,
321
- tsSeries : newRegularTimestampSeries (queryHints .StartTime , queryHints .EndTime , time .Duration (selectHints .Step )* time .Millisecond ),
322
- }
323
- 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 ),
324
315
}
316
+ return & qf , queryHints .CurrentNode , nil
325
317
}
326
318
return nil , nil , nil
327
319
}
0 commit comments