|
|
|
@ -18,7 +18,6 @@ import (
|
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"math" |
|
|
|
|
"strings" |
|
|
|
|
"unicode/utf8" |
|
|
|
|
|
|
|
|
|
"github.com/oklog/ulid" |
|
|
|
@ -186,55 +185,6 @@ func (q *blockChunkQuerier) Select(ctx context.Context, sortSeries bool, hints *
|
|
|
|
|
return NewBlockChunkSeriesSet(q.blockID, q.index, q.chunks, q.tombstones, p, mint, maxt, disableTrimming) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func findSetMatches(pattern string) []string { |
|
|
|
|
// Return empty matches if the wrapper from Prometheus is missing.
|
|
|
|
|
if len(pattern) < 6 || pattern[:4] != "^(?:" || pattern[len(pattern)-2:] != ")$" { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
escaped := false |
|
|
|
|
sets := []*strings.Builder{{}} |
|
|
|
|
init := 4 |
|
|
|
|
end := len(pattern) - 2 |
|
|
|
|
// If the regex is wrapped in a group we can remove the first and last parentheses
|
|
|
|
|
if pattern[init] == '(' && pattern[end-1] == ')' { |
|
|
|
|
init++ |
|
|
|
|
end-- |
|
|
|
|
} |
|
|
|
|
for i := init; i < end; i++ { |
|
|
|
|
if escaped { |
|
|
|
|
switch { |
|
|
|
|
case isRegexMetaCharacter(pattern[i]): |
|
|
|
|
sets[len(sets)-1].WriteByte(pattern[i]) |
|
|
|
|
case pattern[i] == '\\': |
|
|
|
|
sets[len(sets)-1].WriteByte('\\') |
|
|
|
|
default: |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
escaped = false |
|
|
|
|
} else { |
|
|
|
|
switch { |
|
|
|
|
case isRegexMetaCharacter(pattern[i]): |
|
|
|
|
if pattern[i] == '|' { |
|
|
|
|
sets = append(sets, &strings.Builder{}) |
|
|
|
|
} else { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
case pattern[i] == '\\': |
|
|
|
|
escaped = true |
|
|
|
|
default: |
|
|
|
|
sets[len(sets)-1].WriteByte(pattern[i]) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
matches := make([]string, 0, len(sets)) |
|
|
|
|
for _, s := range sets { |
|
|
|
|
if s.Len() > 0 { |
|
|
|
|
matches = append(matches, s.String()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return matches |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// PostingsForMatchers assembles a single postings iterator against the index reader
|
|
|
|
|
// based on the given matchers. The resulting postings are not ordered by series.
|
|
|
|
|
func PostingsForMatchers(ctx context.Context, ix IndexReader, ms ...*labels.Matcher) (index.Postings, error) { |
|
|
|
@ -376,7 +326,7 @@ func postingsForMatcher(ctx context.Context, ix IndexReader, m *labels.Matcher)
|
|
|
|
|
|
|
|
|
|
// Fast-path for set matching.
|
|
|
|
|
if m.Type == labels.MatchRegexp { |
|
|
|
|
setMatches := findSetMatches(m.GetRegexString()) |
|
|
|
|
setMatches := m.SetMatches() |
|
|
|
|
if len(setMatches) > 0 { |
|
|
|
|
return ix.Postings(ctx, m.Name, setMatches...) |
|
|
|
|
} |
|
|
|
@ -407,7 +357,7 @@ func inversePostingsForMatcher(ctx context.Context, ix IndexReader, m *labels.Ma
|
|
|
|
|
// Inverse of a MatchNotRegexp is MatchRegexp (double negation).
|
|
|
|
|
// Fast-path for set matching.
|
|
|
|
|
if m.Type == labels.MatchNotRegexp { |
|
|
|
|
setMatches := findSetMatches(m.GetRegexString()) |
|
|
|
|
setMatches := m.SetMatches() |
|
|
|
|
if len(setMatches) > 0 { |
|
|
|
|
return ix.Postings(ctx, m.Name, setMatches...) |
|
|
|
|
} |
|
|
|
|