class Sequel::Unbinder
DB.where(:a + 1 < 0)
But it cannot handle cases like:
DB.where(:a=>1).exclude(:b=>2).where{c > 3}
So it can handle cases like:
a second argument that’s an instance of a member of UNBIND_VALUE_CLASSES.
first argument that’s an instance of a member of UNBIND_KEY_CLASSES, and
are <tt>SQL::ComplexExpression<tt> with an operator in UNBIND_OPS, a
and values can be associated unambiguously. The only cases it handles
This class only does a limited form of unbinding where the variable names
and use the bound variables to execute it with the same values.
placeholders and a hash of bind values. You can then prepare the dataset
that unbinds already bound values and returns a dataset with bound valueUnbinder is used to take a dataset filter and return a modified version
def bind_key(obj)
Create a suitable bound variable key for the object, which should be
def bind_key(obj) case obj when Symbol obj when String obj.to_sym when SQL::Identifier bind_key(obj.value) when SQL::QualifiedIdentifier :"#{bind_key(obj.table)}.#{bind_key(obj.column)}" else raise Error, "unhandled object in Sequel::Unbinder#bind_key: #{obj}" end end
def initialize
def initialize Sequel::Deprecation.deprecate("Sequel::Unbinder", 'There is no replacement') @binds = {} end
def v(o)
and arguments, substituting the value with a bound variable placeholder
Handle SQL::ComplexExpression instances with suitable ops
def v(o) if o.is_a?(SQL::ComplexExpression) && UNBIND_OPS.include?(o.op) l, r = o.args l = l.value if l.is_a?(Sequel::SQL::Wrapper) r = r.value if r.is_a?(Sequel::SQL::Wrapper) if UNBIND_KEY_CLASSES.any?{|c| l.is_a?(c)} && UNBIND_VALUE_CLASSES.any?{|c| r.is_a?(c)} && !r.is_a?(LiteralString) key = bind_key(l) if (old = binds[key]) && old != r raise UnbindDuplicate, "two different values for #{key.inspect}: #{[r, old].inspect}" end binds[key] = r SQL::ComplexExpression.new(o.op, l, :"$#{key}") else super end else super end end