class Sequel::SQL::BooleanExpression
Subclass of ComplexExpression
where the expression results in a boolean value in SQL
.
Public Class Methods
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)
# File lib/sequel/sql.rb 1079 def self.from_value_pairs(pairs, op=:AND, negate=false) 1080 pairs = pairs.map{|l,r| from_value_pair(l, r)} 1081 pairs.map!{|ce| invert(ce)} if negate 1082 pairs.length == 1 ? pairs[0] : new(op, *pairs) 1083 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"
# File lib/sequel/sql.rb 1138 def self.invert(ce) 1139 case ce 1140 when BooleanExpression 1141 case op = ce.op 1142 when :AND, :OR 1143 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)}) 1144 when :IN, :"NOT IN" 1145 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1146 else 1147 if ce.args.length == 2 1148 case ce.args[1] 1149 when Function, LiteralString, PlaceholderLiteralString 1150 # Special behavior to not push down inversion in this case because doing so 1151 # can result in incorrect behavior for ANY/SOME/ALL operators. 1152 BooleanExpression.new(:NOT, ce) 1153 else 1154 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1155 end 1156 else 1157 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1158 end 1159 end 1160 when StringExpression, NumericExpression 1161 raise(Sequel::Error, "cannot invert #{ce.inspect}") 1162 when Constant 1163 CONSTANT_INVERSIONS[ce] || raise(Sequel::Error, "cannot invert #{ce.inspect}") 1164 else 1165 BooleanExpression.new(:NOT, ce) 1166 end 1167 end
Private Class Methods
Return a BooleanExpression
based on the right side of the pair.
# File lib/sequel/sql.rb 1086 def self.from_value_pair(l, r) 1087 case r 1088 when Range 1089 unless r.begin.nil? 1090 begin_expr = new(:>=, l, r.begin) 1091 end 1092 unless r.end.nil? 1093 end_expr = new(r.exclude_end? ? :< : :<=, l, r.end) 1094 end 1095 if begin_expr 1096 if end_expr 1097 new(:AND, begin_expr, end_expr) 1098 else 1099 begin_expr 1100 end 1101 elsif end_expr 1102 end_expr 1103 else 1104 new(:'=', 1, 1) 1105 end 1106 when ::Array 1107 r = r.dup.freeze unless r.frozen? 1108 new(:IN, l, r) 1109 when ::String 1110 r = r.dup.freeze unless r.frozen? 1111 new(:'=', l, r) 1112 when ::Sequel::Dataset 1113 new(:IN, l, r) 1114 when NegativeBooleanConstant 1115 new(:"IS NOT", l, r.constant) 1116 when BooleanConstant 1117 new(:IS, l, r.constant) 1118 when NilClass, TrueClass, FalseClass 1119 new(:IS, l, r) 1120 when Regexp 1121 StringExpression.like(l, r) 1122 when DelayedEvaluation 1123 Sequel.delay{|ds| from_value_pair(l, r.call(ds))} 1124 when Dataset::PlaceholderLiteralizer::Argument 1125 r.transform{|v| from_value_pair(l, v)} 1126 else 1127 new(:'=', l, r) 1128 end 1129 end
Public Instance Methods
Always use an AND operator for & on BooleanExpressions
# File lib/sequel/sql.rb 1170 def &(ce) 1171 BooleanExpression.new(:AND, self, ce) 1172 end
Return self instead of creating a new object to save on memory.
# File lib/sequel/sql.rb 1180 def sql_boolean 1181 self 1182 end
Always use an OR operator for | on BooleanExpressions
# File lib/sequel/sql.rb 1175 def |(ce) 1176 BooleanExpression.new(:OR, self, ce) 1177 end