1package exp 2 3import ( 4 "reflect" 5 "regexp" 6) 7 8type boolean struct { 9 lhs Expression 10 rhs interface{} 11 op BooleanOperation 12} 13 14func NewBooleanExpression(op BooleanOperation, lhs Expression, rhs interface{}) BooleanExpression { 15 return boolean{op: op, lhs: lhs, rhs: rhs} 16} 17 18func (b boolean) Clone() Expression { 19 return NewBooleanExpression(b.op, b.lhs.Clone(), b.rhs) 20} 21 22func (b boolean) Expression() Expression { 23 return b 24} 25 26func (b boolean) RHS() interface{} { 27 return b.rhs 28} 29 30func (b boolean) LHS() Expression { 31 return b.lhs 32} 33 34func (b boolean) Op() BooleanOperation { 35 return b.op 36} 37 38// used internally to create an equality BooleanExpression 39func eq(lhs Expression, rhs interface{}) BooleanExpression { 40 return checkBoolExpType(EqOp, lhs, rhs, false) 41} 42 43// used internally to create an in-equality BooleanExpression 44func neq(lhs Expression, rhs interface{}) BooleanExpression { 45 return checkBoolExpType(EqOp, lhs, rhs, true) 46} 47 48// used internally to create an gt comparison BooleanExpression 49func gt(lhs Expression, rhs interface{}) BooleanExpression { 50 return NewBooleanExpression(GtOp, lhs, rhs) 51} 52 53// used internally to create an gte comparison BooleanExpression 54func gte(lhs Expression, rhs interface{}) BooleanExpression { 55 return NewBooleanExpression(GteOp, lhs, rhs) 56} 57 58// used internally to create an lt comparison BooleanExpression 59func lt(lhs Expression, rhs interface{}) BooleanExpression { 60 return NewBooleanExpression(LtOp, lhs, rhs) 61} 62 63// used internally to create an lte comparison BooleanExpression 64func lte(lhs Expression, rhs interface{}) BooleanExpression { 65 return NewBooleanExpression(LteOp, lhs, rhs) 66} 67 68// used internally to create an IN BooleanExpression 69func in(lhs Expression, vals ...interface{}) BooleanExpression { 70 if len(vals) == 1 && reflect.Indirect(reflect.ValueOf(vals[0])).Kind() == reflect.Slice { 71 return NewBooleanExpression(InOp, lhs, vals[0]) 72 } 73 return NewBooleanExpression(InOp, lhs, vals) 74} 75 76// used internally to create a NOT IN BooleanExpression 77func notIn(lhs Expression, vals ...interface{}) BooleanExpression { 78 if len(vals) == 1 && reflect.Indirect(reflect.ValueOf(vals[0])).Kind() == reflect.Slice { 79 return NewBooleanExpression(NotInOp, lhs, vals[0]) 80 } 81 return NewBooleanExpression(NotInOp, lhs, vals) 82} 83 84// used internally to create an IS BooleanExpression 85func is(lhs Expression, val interface{}) BooleanExpression { 86 return checkBoolExpType(IsOp, lhs, val, false) 87} 88 89// used internally to create an IS NOT BooleanExpression 90func isNot(lhs Expression, val interface{}) BooleanExpression { 91 return checkBoolExpType(IsOp, lhs, val, true) 92} 93 94// used internally to create a LIKE BooleanExpression 95func like(lhs Expression, val interface{}) BooleanExpression { 96 return checkLikeExp(LikeOp, lhs, val, false) 97} 98 99// used internally to create an ILIKE BooleanExpression 100func iLike(lhs Expression, val interface{}) BooleanExpression { 101 return checkLikeExp(ILikeOp, lhs, val, false) 102} 103 104// used internally to create a NOT LIKE BooleanExpression 105func notLike(lhs Expression, val interface{}) BooleanExpression { 106 return checkLikeExp(LikeOp, lhs, val, true) 107} 108 109// used internally to create a NOT ILIKE BooleanExpression 110func notILike(lhs Expression, val interface{}) BooleanExpression { 111 return checkLikeExp(ILikeOp, lhs, val, true) 112} 113 114// used internally to create a LIKE BooleanExpression 115func regexpLike(lhs Expression, val interface{}) BooleanExpression { 116 return checkLikeExp(RegexpLikeOp, lhs, val, false) 117} 118 119// used internally to create an ILIKE BooleanExpression 120func regexpILike(lhs Expression, val interface{}) BooleanExpression { 121 return checkLikeExp(RegexpILikeOp, lhs, val, false) 122} 123 124// used internally to create a NOT LIKE BooleanExpression 125func regexpNotLike(lhs Expression, val interface{}) BooleanExpression { 126 return checkLikeExp(RegexpLikeOp, lhs, val, true) 127} 128 129// used internally to create a NOT ILIKE BooleanExpression 130func regexpNotILike(lhs Expression, val interface{}) BooleanExpression { 131 return checkLikeExp(RegexpILikeOp, lhs, val, true) 132} 133 134// checks an like rhs to create the proper like expression for strings or regexps 135func checkLikeExp(op BooleanOperation, lhs Expression, val interface{}, invert bool) BooleanExpression { 136 rhs := val 137 138 if t, ok := val.(*regexp.Regexp); ok { 139 if op == LikeOp { 140 op = RegexpLikeOp 141 } else if op == ILikeOp { 142 op = RegexpILikeOp 143 } 144 rhs = t.String() 145 } 146 if invert { 147 op = operatorInversions[op] 148 } 149 return NewBooleanExpression(op, lhs, rhs) 150} 151 152// checks a boolean operation normalizing the operation based on the RHS (e.g. "a" = true vs "a" IS TRUE 153func checkBoolExpType(op BooleanOperation, lhs Expression, rhs interface{}, invert bool) BooleanExpression { 154 if rhs == nil { 155 op = IsOp 156 } else { 157 switch reflect.Indirect(reflect.ValueOf(rhs)).Kind() { 158 case reflect.Bool: 159 op = IsOp 160 case reflect.Slice: 161 // if its a slice of bytes dont treat as an IN 162 if _, ok := rhs.([]byte); !ok { 163 op = InOp 164 } 165 case reflect.Struct: 166 switch rhs.(type) { 167 case SQLExpression: 168 op = InOp 169 case AppendableExpression: 170 op = InOp 171 case *regexp.Regexp: 172 return checkLikeExp(LikeOp, lhs, rhs, invert) 173 } 174 default: 175 } 176 } 177 if invert { 178 op = operatorInversions[op] 179 } 180 return NewBooleanExpression(op, lhs, rhs) 181} 182