github.com/badrootd/nibiru-cometbft@v0.37.5-0.20240307173500-2a75559eee9b/state/indexer/query_range.go (about) 1 package indexer 2 3 import ( 4 "math/big" 5 "time" 6 7 "github.com/badrootd/nibiru-cometbft/libs/pubsub/query" 8 "github.com/badrootd/nibiru-cometbft/types" 9 ) 10 11 // QueryRanges defines a mapping between a composite event key and a QueryRange. 12 // 13 // e.g.account.number => queryRange{lowerBound: 1, upperBound: 5} 14 type QueryRanges map[string]QueryRange 15 16 // QueryRange defines a range within a query condition. 17 type QueryRange struct { 18 LowerBound interface{} // int || time.Time 19 UpperBound interface{} // int || time.Time 20 Key string 21 IncludeLowerBound bool 22 IncludeUpperBound bool 23 } 24 25 // AnyBound returns either the lower bound if non-nil, otherwise the upper bound. 26 func (qr QueryRange) AnyBound() interface{} { 27 if qr.LowerBound != nil { 28 return qr.LowerBound 29 } 30 31 return qr.UpperBound 32 } 33 34 // LowerBoundValue returns the value for the lower bound. If the lower bound is 35 // nil, nil will be returned. 36 func (qr QueryRange) LowerBoundValue() interface{} { 37 if qr.LowerBound == nil { 38 return nil 39 } 40 41 if qr.IncludeLowerBound { 42 return qr.LowerBound 43 } 44 45 switch t := qr.LowerBound.(type) { 46 case int64: 47 return t + 1 48 case *big.Int: 49 tmp := new(big.Int) 50 return tmp.Add(t, big.NewInt(1)) 51 52 case time.Time: 53 return t.Unix() + 1 54 55 default: 56 panic("not implemented") 57 } 58 } 59 60 // UpperBoundValue returns the value for the upper bound. If the upper bound is 61 // nil, nil will be returned. 62 func (qr QueryRange) UpperBoundValue() interface{} { 63 if qr.UpperBound == nil { 64 return nil 65 } 66 67 if qr.IncludeUpperBound { 68 return qr.UpperBound 69 } 70 71 switch t := qr.UpperBound.(type) { 72 case int64: 73 return t - 1 74 case *big.Int: 75 tmp := new(big.Int) 76 return tmp.Sub(t, big.NewInt(1)) 77 case time.Time: 78 return t.Unix() - 1 79 80 default: 81 panic("not implemented") 82 } 83 } 84 85 // LookForRangesWithHeight returns a mapping of QueryRanges and the matching indexes in 86 // the provided query conditions. 87 func LookForRangesWithHeight(conditions []query.Condition) (queryRange QueryRanges, indexes []int, heightRange QueryRange) { 88 queryRange = make(QueryRanges) 89 for i, c := range conditions { 90 if IsRangeOperation(c.Op) { 91 heightKey := c.CompositeKey == types.BlockHeightKey || c.CompositeKey == types.TxHeightKey 92 r, ok := queryRange[c.CompositeKey] 93 if !ok { 94 r = QueryRange{Key: c.CompositeKey} 95 if c.CompositeKey == types.BlockHeightKey || c.CompositeKey == types.TxHeightKey { 96 heightRange = QueryRange{Key: c.CompositeKey} 97 } 98 } 99 100 switch c.Op { 101 case query.OpGreater: 102 if heightKey { 103 heightRange.LowerBound = c.Operand 104 } 105 r.LowerBound = c.Operand 106 107 case query.OpGreaterEqual: 108 r.IncludeLowerBound = true 109 r.LowerBound = c.Operand 110 if heightKey { 111 heightRange.IncludeLowerBound = true 112 heightRange.LowerBound = c.Operand 113 } 114 115 case query.OpLess: 116 r.UpperBound = c.Operand 117 if heightKey { 118 heightRange.UpperBound = c.Operand 119 } 120 121 case query.OpLessEqual: 122 r.IncludeUpperBound = true 123 r.UpperBound = c.Operand 124 if heightKey { 125 heightRange.IncludeUpperBound = true 126 heightRange.UpperBound = c.Operand 127 } 128 } 129 130 queryRange[c.CompositeKey] = r 131 indexes = append(indexes, i) 132 } 133 } 134 135 return queryRange, indexes, heightRange 136 } 137 138 // Deprecated: This function is not used anymore and will be replaced with LookForRangesWithHeight 139 func LookForRanges(conditions []query.Condition) (ranges QueryRanges, indexes []int) { 140 ranges = make(QueryRanges) 141 for i, c := range conditions { 142 if IsRangeOperation(c.Op) { 143 r, ok := ranges[c.CompositeKey] 144 if !ok { 145 r = QueryRange{Key: c.CompositeKey} 146 } 147 148 switch c.Op { 149 case query.OpGreater: 150 r.LowerBound = c.Operand 151 152 case query.OpGreaterEqual: 153 r.IncludeLowerBound = true 154 r.LowerBound = c.Operand 155 156 case query.OpLess: 157 r.UpperBound = c.Operand 158 159 case query.OpLessEqual: 160 r.IncludeUpperBound = true 161 r.UpperBound = c.Operand 162 } 163 164 ranges[c.CompositeKey] = r 165 indexes = append(indexes, i) 166 } 167 } 168 169 return ranges, indexes 170 } 171 172 // IsRangeOperation returns a boolean signifying if a query Operator is a range 173 // operation or not. 174 func IsRangeOperation(op query.Operator) bool { 175 switch op { 176 case query.OpGreater, query.OpGreaterEqual, query.OpLess, query.OpLessEqual: 177 return true 178 179 default: 180 return false 181 } 182 }