diff --git a/pkg/logql/syntax/ast.go b/pkg/logql/syntax/ast.go index e5e80b4d0c..2e7b8a2e0e 100644 --- a/pkg/logql/syntax/ast.go +++ b/pkg/logql/syntax/ast.go @@ -318,9 +318,14 @@ func (e *PipelineExpr) Pipeline() (log.Pipeline, error) { // HasFilter returns true if the pipeline contains stage that can filter out lines. func (e *PipelineExpr) HasFilter() bool { for _, p := range e.MultiStages { - switch p.(type) { - case *LineFilterExpr, *LabelFilterExpr: + switch v := p.(type) { + case *LabelFilterExpr: return true + case *LineFilterExpr: + // ignore empty matchers as they match everything + if !((v.Ty == log.LineMatchEqual || v.Ty == log.LineMatchRegexp) && v.Match == "") { + return true + } default: continue } diff --git a/pkg/logql/syntax/ast_test.go b/pkg/logql/syntax/ast_test.go index d75ff2d026..cb36cb2e7c 100644 --- a/pkg/logql/syntax/ast_test.go +++ b/pkg/logql/syntax/ast_test.go @@ -1039,6 +1039,23 @@ func TestParseLargeQuery(t *testing.T) { require.NoError(t, err) } +func TestLogSelectorExprHasFilter(t *testing.T) { + for query, hasFilter := range map[string]bool{ + `{foo="bar"} |= ""`: false, + `{foo="bar"} |= "" |= ""`: false, + `{foo="bar"} |~ ""`: false, + `{foo="bar"} |= "notempty"`: true, + `{foo="bar"} |= "" |= "notempty"`: true, + `{foo="bar"} != ""`: true, + `{foo="bar"} | lbl="notempty"`: true, + `{foo="bar"} |= "" | lbl="notempty"`: true, + } { + expr, err := ParseExpr(query) + require.NoError(t, err) + require.Equal(t, hasFilter, expr.(LogSelectorExpr).HasFilter()) + } +} + func TestGroupingString(t *testing.T) { g := Grouping{ Groups: []string{"a", "b"},