safing-portbase/database/query/query.go

77 lines
1.5 KiB
Go

package query
import (
"fmt"
"regexp"
"strings"
)
// Example:
// q.New("core:/",
// q.Where("a", q.GreaterThan, 0),
// q.Where("b", q.Equals, 0),
// q.Or(
// q.Where("c", q.StartsWith, "x"),
// q.Where("d", q.Contains, "y")
// )
// )
var (
prefixExpr = regexp.MustCompile("^[a-z-]+:")
)
// Query contains a compiled query.
type Query struct {
prefix string
condition Condition
}
// New creates a new query.
func New(prefix string, condition Condition) (*Query, error) {
// check prefix
if !prefixExpr.MatchString(prefix) {
return nil, fmt.Errorf("invalid prefix: %s", prefix)
}
// check condition
if condition != nil {
err := condition.check()
if err != nil {
return nil, err
}
} else {
condition = &noCond{}
}
// return query
return &Query{
prefix: prefix,
condition: condition,
}, nil
}
// MustCompile creates a new query and panics on an error.
func MustCompile(prefix string, condition Condition) *Query {
q, err := New(prefix, condition)
if err != nil {
panic(err)
}
return q
}
// Matches checks whether the query matches the supplied data object.
func (q *Query) Matches(f Fetcher) bool {
return q.condition.complies(f)
}
// String returns the string representation of the query.
func (q *Query) String() string {
text := q.condition.string()
if text == "" {
return fmt.Sprintf("query %s", q.prefix)
}
if strings.HasPrefix(text, "(") {
text = text[1 : len(text)-1]
}
return fmt.Sprintf("query %s where %s", q.prefix, text)
}