- package indexer
-
- import (
- "time"
-
- "github.com/tendermint/tendermint/internal/pubsub/query/syntax"
- )
-
- // QueryRanges defines a mapping between a composite event key and a QueryRange.
- //
- // e.g.account.number => queryRange{lowerBound: 1, upperBound: 5}
- type QueryRanges map[string]QueryRange
-
- // QueryRange defines a range within a query condition.
- type QueryRange struct {
- LowerBound interface{} // int || time.Time
- UpperBound interface{} // int || time.Time
- Key string
- IncludeLowerBound bool
- IncludeUpperBound bool
- }
-
- // AnyBound returns either the lower bound if non-nil, otherwise the upper bound.
- func (qr QueryRange) AnyBound() interface{} {
- if qr.LowerBound != nil {
- return qr.LowerBound
- }
-
- return qr.UpperBound
- }
-
- // LowerBoundValue returns the value for the lower bound. If the lower bound is
- // nil, nil will be returned.
- func (qr QueryRange) LowerBoundValue() interface{} {
- if qr.LowerBound == nil {
- return nil
- }
-
- if qr.IncludeLowerBound {
- return qr.LowerBound
- }
-
- switch t := qr.LowerBound.(type) {
- case int64:
- return t + 1
-
- case time.Time:
- return t.Unix() + 1
-
- default:
- panic("not implemented")
- }
- }
-
- // UpperBoundValue returns the value for the upper bound. If the upper bound is
- // nil, nil will be returned.
- func (qr QueryRange) UpperBoundValue() interface{} {
- if qr.UpperBound == nil {
- return nil
- }
-
- if qr.IncludeUpperBound {
- return qr.UpperBound
- }
-
- switch t := qr.UpperBound.(type) {
- case int64:
- return t - 1
-
- case time.Time:
- return t.Unix() - 1
-
- default:
- panic("not implemented")
- }
- }
-
- // LookForRanges returns a mapping of QueryRanges and the matching indexes in
- // the provided query conditions.
- func LookForRanges(conditions []syntax.Condition) (ranges QueryRanges, indexes []int) {
- ranges = make(QueryRanges)
- for i, c := range conditions {
- if IsRangeOperation(c.Op) {
- r, ok := ranges[c.Tag]
- if !ok {
- r = QueryRange{Key: c.Tag}
- }
-
- switch c.Op {
- case syntax.TGt:
- r.LowerBound = conditionArg(c)
-
- case syntax.TGeq:
- r.IncludeLowerBound = true
- r.LowerBound = conditionArg(c)
-
- case syntax.TLt:
- r.UpperBound = conditionArg(c)
-
- case syntax.TLeq:
- r.IncludeUpperBound = true
- r.UpperBound = conditionArg(c)
- }
-
- ranges[c.Tag] = r
- indexes = append(indexes, i)
- }
- }
-
- return ranges, indexes
- }
-
- // IsRangeOperation returns a boolean signifying if a query Operator is a range
- // operation or not.
- func IsRangeOperation(op syntax.Token) bool {
- switch op {
- case syntax.TGt, syntax.TGeq, syntax.TLt, syntax.TLeq:
- return true
-
- default:
- return false
- }
- }
-
- func conditionArg(c syntax.Condition) interface{} {
- if c.Arg == nil {
- return nil
- }
- switch c.Arg.Type {
- case syntax.TNumber:
- return int64(c.Arg.Number())
- case syntax.TTime, syntax.TDate:
- return c.Arg.Time()
- default:
- return c.Arg.Value() // string
- }
- }
|