Closed sdepold closed 11 years ago
Well, Dataset#unfiltered
removes all WHERE/HAVING conditions. If you want to remove a specific condition, you'll have to modify the abstract syntax tree storing the conditions, which you can access via dataset.opts[:where]
and dataset.opts[:having]
. The Sequel::ASTTransformer
class may be helpful to do that.
Note that removing specific conditions would generally be considered a code smell. If it's possible to modify the plugin so that it isn't required (e.g. by saving a copy of the dataset before such conditions are added), that would be my recommendation.
Also note that in the future, questions about how to use Sequel should be posted to the sequel-talk Google Group. GitHub Issues should only be used to report bugs in Sequel.
In real production code it's not always possible to prevent some code smell. I have implemented a Dataset#unfilter
method.
Except that nobody should ever use this, except in bad smelly code, should I submit this as a pull request?
def unfilter(*cond, &block)
cond = cond.first if cond.size == 1 # De-array
# Empty unfilter -> Do nothing
if cond.respond_to?(:empty?) && cond.empty? && !block
return clone
end
# Compile expression
cond = filter_expr(cond, &block)
# Get top level of WHERE-clause AST
top = @opts[:where]
# Empty original filter -> Do nothing
return clone if top.nil?
# If the only condition on top is the to-be-unfiltered condition, remove all
# conditions.
return clone(:where => nil) if top == cond
# Skip everything except AND expressions
if top != ::Sequel::SQL::BooleanExpression and top.op == :AND
return clone
end
# We can do this, because AND conditions always collapse and are not nested
# (are they?)
if top.args.include? cond
# Remove the to-be-unfiltered condition from the ANDs and return.
expr = ::Sequel::SQL::BooleanExpression.new(:AND, *top.args.reject{|x| x == cond})
clone(:where => expr)
else
return clone
end
end
The issue with your method is that it only works in certain cases. You can handle cases such as:
ds.where(cond).unfilter(cond)
ds.where(cond).where(other_code).unfilter(cond)
but not
ds.where(cond).or(other_cond).unfilter(cond)
ds.where(cond).where(other_cond).or(other_cond2).unfilter(cond)
even though those should arguably resolve to:
ds.where(other_cond)
ds.where(other_cond).or(other_cond2)
That's not to say it couldn't be included as an extension that ships with Sequel, but you'd have to ask on sequel-talk and see if anyone else is interested in such an extension, and add tests and RDoc for it.
Hi.
I really like Sequel, but while my current development on a plugin, I found the need for a way to remove a specific where condition from a dataset. Is this somehow (hacks are OK) possible?
Greetings, sdepold