diff --git a/model/labels/regexp.go b/model/labels/regexp.go index de4cfc3b1c..e6909dbeac 100644 --- a/model/labels/regexp.go +++ b/model/labels/regexp.go @@ -366,7 +366,7 @@ func optimizeAlternatingLiterals(s string) (StringMatcher, []string) { // If there are no alternates, check if the string is a literal if estimatedAlternates == 1 { if regexp.QuoteMeta(s) == s { - return &equalStringMatcher{s: s, caseSensitive: true}, nil + return &equalStringMatcher{s: s, caseSensitive: true}, []string{s} } return nil, nil } diff --git a/model/labels/regexp_test.go b/model/labels/regexp_test.go index f0e21b2d5c..a03bbd261d 100644 --- a/model/labels/regexp_test.go +++ b/model/labels/regexp_test.go @@ -342,6 +342,14 @@ func TestFindSetMatches(t *testing.T) { matches, actualCaseSensitive := findSetMatches(parsed) require.Equal(t, c.expMatches, matches) require.Equal(t, c.expCaseSensitive, actualCaseSensitive) + + if c.expCaseSensitive { + // When the regexp is case sensitive, we want to ensure that the + // set matches are maintained in the final matcher. + r, err := newFastRegexMatcherWithoutCache(c.pattern) + require.NoError(t, err) + require.Equal(t, c.expMatches, r.SetMatches()) + } }) } } diff --git a/tsdb/querier_bench_test.go b/tsdb/querier_bench_test.go index 501879d01b..60820eac0f 100644 --- a/tsdb/querier_bench_test.go +++ b/tsdb/querier_bench_test.go @@ -125,6 +125,7 @@ func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) { iNotAlternate := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "(1|2|3|4|5|6|20|55)") iXYZ := labels.MustNewMatcher(labels.MatchRegexp, "i", "X|Y|Z") iNotXYZ := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "X|Y|Z") + literalRegexp := labels.MustNewMatcher(labels.MatchRegexp, "i_times_n", "0") cases := []struct { name string matchers []*labels.Matcher @@ -168,6 +169,7 @@ func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) { {`n="1",i=~".+",i!~"2.*",j="foo"`, []*labels.Matcher{n1, iPlus, iNot2Star, jFoo}}, {`n="1",i=~".+",i!~".*2.*",j="foo"`, []*labels.Matcher{n1, iPlus, iNotStar2Star, jFoo}}, {`n="X",i=~".+",i!~".*2.*",j="foo"`, []*labels.Matcher{nX, iPlus, iNotStar2Star, jFoo}}, + {`i_times_n=~"0"`, []*labels.Matcher{literalRegexp}}, } for _, c := range cases {