github.com/cayleygraph/cayley@v0.7.7/graph/iterator/value_comparison.go (about) 1 // Copyright 2014 The Cayley Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package iterator 16 17 // "Value Comparison" is a unary operator -- a filter across the values in the 18 // relevant subiterator. 19 // 20 // This is hugely useful for things like label, but value ranges in general 21 // come up from time to time. At *worst* we're as big as our underlying iterator. 22 // At best, we're the null iterator. 23 // 24 // This is ripe for backend-side optimization. If you can run a value iterator, 25 // from a sorted set -- some sort of value index, then go for it. 26 // 27 // In MQL terms, this is the [{"age>=": 21}] concept. 28 29 import ( 30 "fmt" 31 "time" 32 33 "github.com/cayleygraph/cayley/graph" 34 "github.com/cayleygraph/quad" 35 ) 36 37 type Operator int 38 39 func (op Operator) String() string { 40 switch op { 41 case CompareLT: 42 return "<" 43 case CompareLTE: 44 return "<=" 45 case CompareGT: 46 return ">" 47 case CompareGTE: 48 return ">=" 49 default: 50 return fmt.Sprintf("op(%d)", int(op)) 51 } 52 } 53 54 const ( 55 CompareLT Operator = iota 56 CompareLTE 57 CompareGT 58 CompareGTE 59 // Why no Equals? Because that's usually an AndIterator. 60 ) 61 62 func NewComparison(sub graph.Iterator, op Operator, val quad.Value, qs graph.Namer) graph.Iterator { 63 return NewValueFilter(qs, sub, func(qval quad.Value) (bool, error) { 64 switch cVal := val.(type) { 65 case quad.Int: 66 if cVal2, ok := qval.(quad.Int); ok { 67 return RunIntOp(cVal2, op, cVal), nil 68 } 69 return false, nil 70 case quad.Float: 71 if cVal2, ok := qval.(quad.Float); ok { 72 return RunFloatOp(cVal2, op, cVal), nil 73 } 74 return false, nil 75 case quad.String: 76 if cVal2, ok := qval.(quad.String); ok { 77 return RunStrOp(string(cVal2), op, string(cVal)), nil 78 } 79 return false, nil 80 case quad.BNode: 81 if cVal2, ok := qval.(quad.BNode); ok { 82 return RunStrOp(string(cVal2), op, string(cVal)), nil 83 } 84 return false, nil 85 case quad.IRI: 86 if cVal2, ok := qval.(quad.IRI); ok { 87 return RunStrOp(string(cVal2), op, string(cVal)), nil 88 } 89 return false, nil 90 case quad.Time: 91 if cVal2, ok := qval.(quad.Time); ok { 92 return RunTimeOp(time.Time(cVal2), op, time.Time(cVal)), nil 93 } 94 return false, nil 95 default: 96 return RunStrOp(quad.StringOf(qval), op, quad.StringOf(val)), nil 97 } 98 }) 99 } 100 101 func RunIntOp(a quad.Int, op Operator, b quad.Int) bool { 102 switch op { 103 case CompareLT: 104 return a < b 105 case CompareLTE: 106 return a <= b 107 case CompareGT: 108 return a > b 109 case CompareGTE: 110 return a >= b 111 default: 112 panic("Unknown operator type") 113 } 114 } 115 116 func RunFloatOp(a quad.Float, op Operator, b quad.Float) bool { 117 switch op { 118 case CompareLT: 119 return a < b 120 case CompareLTE: 121 return a <= b 122 case CompareGT: 123 return a > b 124 case CompareGTE: 125 return a >= b 126 default: 127 panic("Unknown operator type") 128 } 129 } 130 131 func RunStrOp(a string, op Operator, b string) bool { 132 switch op { 133 case CompareLT: 134 return a < b 135 case CompareLTE: 136 return a <= b 137 case CompareGT: 138 return a > b 139 case CompareGTE: 140 return a >= b 141 default: 142 panic("Unknown operator type") 143 } 144 } 145 146 func RunTimeOp(a time.Time, op Operator, b time.Time) bool { 147 switch op { 148 case CompareLT: 149 return a.Before(b) 150 case CompareLTE: 151 return !a.After(b) 152 case CompareGT: 153 return a.After(b) 154 case CompareGTE: 155 return !a.Before(b) 156 default: 157 panic("Unknown operator type") 158 } 159 }