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 1126 def self.invert(ce) 1127 case ce 1128 when BooleanExpression 1129 case op = ce.op 1130 when :AND, :OR 1131 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)}) 1132 when :IN, :"NOT IN" 1133 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1134 else 1135 if ce.args.length == 2 1136 case ce.args[1] 1137 when Function, LiteralString, PlaceholderLiteralString 1138 # Special behavior to not push down inversion in this case because doing so 1139 # can result in incorrect behavior for ANY/SOME/ALL operators. 1140 BooleanExpression.new(:NOT, ce) 1141 else 1142 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1143 end 1144 else 1145 BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup) 1146 end 1147 end 1148 when StringExpression, NumericExpression 1149 raise(Sequel::Error, "cannot invert #{ce.inspect}") 1150 when Constant 1151 CONSTANT_INVERSIONS[ce] || raise(Sequel::Error, "cannot invert #{ce.inspect}") 1152 else 1153 BooleanExpression.new(:NOT, ce) 1154 end 1155 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 expr = new(:>=, l, r.begin) 1090 unless r.end.nil? 1091 expr = new(:AND, expr, new(r.exclude_end? ? :< : :<=, l, r.end)) 1092 end 1093 expr 1094 when ::Array 1095 r = r.dup.freeze unless r.frozen? 1096 new(:IN, l, r) 1097 when ::String 1098 r = r.dup.freeze unless r.frozen? 1099 new(:'=', l, r) 1100 when ::Sequel::Dataset 1101 new(:IN, l, r) 1102 when NegativeBooleanConstant 1103 new(:"IS NOT", l, r.constant) 1104 when BooleanConstant 1105 new(:IS, l, r.constant) 1106 when NilClass, TrueClass, FalseClass 1107 new(:IS, l, r) 1108 when Regexp 1109 StringExpression.like(l, r) 1110 when DelayedEvaluation 1111 Sequel.delay{|ds| from_value_pair(l, r.call(ds))} 1112 when Dataset::PlaceholderLiteralizer::Argument 1113 r.transform{|v| from_value_pair(l, v)} 1114 else 1115 new(:'=', l, r) 1116 end 1117 end
Public Instance Methods
Always use an AND operator for & on BooleanExpressions
# File lib/sequel/sql.rb 1158 def &(ce) 1159 BooleanExpression.new(:AND, self, ce) 1160 end
Return self instead of creating a new object to save on memory.
# File lib/sequel/sql.rb 1168 def sql_boolean 1169 self 1170 end
Always use an OR operator for | on BooleanExpressions
# File lib/sequel/sql.rb 1163 def |(ce) 1164 BooleanExpression.new(:OR, self, ce) 1165 end