in lib/storage/storage.go [160:210]
func BuildFilters(str string, fields map[string]func(p proto.Message) string) ([][]Filter, error) {
if len(str) == 0 {
return nil, nil
}
var out [][]Filter
ands := strutil.QuoteSplit(str, " and ", false)
for _, a := range ands {
var ors []Filter
a = strings.Trim(a, " ")
brackets := false
if strings.HasPrefix(a, "(") && strings.HasSuffix(a, ")") {
brackets = true
// Strip off the brackets
a = a[1 : len(a)-1]
}
// Perform additional checks to improve error handling.
parts := strutil.QuoteSplit(a, " ", false)
for _, p := range parts {
if strings.HasPrefix(p, `"`) {
continue
}
if strings.Contains(p, "(") || strings.Contains(p, ")") {
return nil, fmt.Errorf("mismatched or nested brackets on filter %q", str)
}
if strings.ToLower(p) == "or" && !brackets && len(ands) > 1 {
return nil, fmt.Errorf("brackets around OR clauses are required in filter %q", str)
}
}
// Use regexp to parse the OR clause or simple expression.
if !orCheckRE.MatchString(a) {
return nil, fmt.Errorf("invalid filter %q", str)
}
match := orFilterRE.FindAllStringSubmatch(a, -1)
if len(match) == 0 {
return nil, fmt.Errorf("invalid filter %q", str)
}
for _, m := range match {
fn, ok := fields[strings.ToLower(m[1])]
if !ok {
return nil, fmt.Errorf("field %q not defined", m[1])
}
val := strings.ToLower(m[3])
if strings.HasPrefix(val, `"`) && strings.HasSuffix(val, `"`) {
val = val[1 : len(val)-1]
}
ors = append(ors, Filter{extract: fn, compare: strings.ToLower(m[2]), value: val})
}
out = append(out, ors)
}
return out, nil
}