module Sequel::SQL::BooleanExpression::ClassMethods
Public Instance Methods
Source
# File lib/sequel/sql.rb 1085 def from_value_pairs(pairs, op=:AND, negate=false) 1086 pairs = pairs.map{|l,r| from_value_pair(l, r)} 1087 pairs.map!{|ce| invert(ce)} if negate 1088 pairs.length == 1 ? pairs[0] : new(op, *pairs) 1089 end
Take pairs of values (e.g. a hash or array of two element arrays) and converts it to a BooleanExpression. The operator and args used depends on the case of the right (2nd) argument:
- 0..10
-
left >= 0 AND left <= 10
- 1,2
-
left IN (1,2)
-
- nil
-
left IS NULL
- true
-
left IS TRUE
- false
-
left IS FALSE
- /as/
-
left ~ βasβ
- :blah
-
left = blah
- βblahβ
-
left = βblahβ
If multiple arguments are given, they are joined with the op given (AND by default, OR possible). If negate is set to true, all subexpressions are inverted before used. Therefore, the following expressions are equivalent:
~from_value_pairs(hash) from_value_pairs(hash, :OR, true)
Source
# File lib/sequel/sql.rb 1150 def invert(ce) 1151 case ce 1152 when BooleanExpression 1153 case op = ce.op 1154 when :AND, :OR 1155 BooleanExpression.new(ComplexExpression::OPERATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)}) 1156 when :IN, :"NOT IN" 1157 BooleanExpression.new(ComplexExpression::OPERATOR_INVERSIONS[op], *ce.args.dup) 1158 else 1159 if ce.args.length == 2 1160 case ce.args[1] 1161 when Function, LiteralString, PlaceholderLiteralString 1162 # Special behavior to not push down inversion in this case because doing so 1163 # can result in incorrect behavior for ANY/SOME/ALL operators. 1164 BooleanExpression.new(:NOT, ce) 1165 else 1166 BooleanExpression.new(ComplexExpression::OPERATOR_INVERSIONS[op], *ce.args.dup) 1167 end 1168 else 1169 BooleanExpression.new(ComplexExpression::OPERATOR_INVERSIONS[op], *ce.args.dup) 1170 end 1171 end 1172 when StringExpression, NumericExpression 1173 raise(Sequel::Error, "cannot invert #{ce.inspect}") 1174 when Constant 1175 ComplexExpression::CONSTANT_INVERSIONS[ce] || raise(Sequel::Error, "cannot invert #{ce.inspect}") 1176 else 1177 BooleanExpression.new(:NOT, ce) 1178 end 1179 end
Invert the expression, if possible. If the expression cannot be inverted, raise an error. An inverted expression should match everything that the uninverted expression did not match, and vice-versa, except for possible issues with SQL NULL (i.e. 1 == NULL is NULL and 1 != NULL is also NULL).
BooleanExpression.invert(:a) # NOT "a"
Private Instance Methods
Source
# File lib/sequel/sql.rb 1092 def from_value_pair(l, r) 1093 case r 1094 when Range 1095 unless r.begin.nil? 1096 begin_expr = new(:>=, l, r.begin) 1097 end 1098 unless r.end.nil? 1099 end_expr = new(r.exclude_end? ? :< : :<=, l, r.end) 1100 end 1101 if begin_expr 1102 if end_expr 1103 new(:AND, begin_expr, end_expr) 1104 else 1105 begin_expr 1106 end 1107 elsif end_expr 1108 end_expr 1109 else 1110 new(:'=', 1, 1) 1111 end 1112 when ::Array, ::Set 1113 r = r.dup.freeze unless r.frozen? 1114 new(:IN, l, r) 1115 when ::String 1116 r = r.dup.freeze unless r.frozen? 1117 new(:'=', l, r) 1118 when ::Sequel::Dataset 1119 new(:IN, l, r) 1120 when NegativeBooleanConstant 1121 new(:"IS NOT", l, r.constant) 1122 when BooleanConstant 1123 new(:IS, l, r.constant) 1124 when NilClass, TrueClass, FalseClass 1125 new(:IS, l, r) 1126 when Regexp 1127 StringExpression.like(l, r) 1128 when DelayedEvaluation 1129 Sequel.delay{|ds| from_value_pair(l, r.call(ds))} 1130 when Dataset::PlaceholderLiteralizer::Argument 1131 prev_transform = r.instance_variable_get(:@transformer) 1132 r.transform do |v| 1133 if prev_transform 1134 v = prev_transform.call(v) 1135 end 1136 from_value_pair(l, v) 1137 end 1138 else 1139 new(:'=', l, r) 1140 end 1141 end
Return a BooleanExpression based on the right side of the pair.