Merge pull request #27122 from kamipo/fix_unscope_with_subquery

Fix unscope with subquery
This commit is contained in:
Rafael França 2017-02-13 01:35:28 -03:00 committed by GitHub
commit efe121eab0
2 changed files with 40 additions and 16 deletions

@ -25,10 +25,7 @@ def merge(other)
end
def except(*columns)
WhereClause.new(
predicates_except(columns),
binds_except(columns),
)
WhereClause.new(*except_predicates_and_binds(columns))
end
def or(other)
@ -134,20 +131,35 @@ def invert_predicate(node)
end
end
def predicates_except(columns)
predicates.reject do |node|
case node
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
columns.include?(subrelation.name.to_s)
end
end
end
def except_predicates_and_binds(columns)
except_binds = []
binds_index = 0
def binds_except(columns)
binds.reject do |attr|
columns.include?(attr.name)
predicates = self.predicates.reject do |node|
except = \
case node
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
binds_contains = node.grep(Arel::Nodes::BindParam).size
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
columns.include?(subrelation.name.to_s)
end
if except && binds_contains > 0
(binds_index...(binds_index + binds_contains)).each do |i|
except_binds[i] = true
end
binds_index += binds_contains
end
except
end
binds = self.binds.reject.with_index do |_, i|
except_binds[i]
end
[predicates, binds]
end
def predicates_with_wrapped_sql_literals

@ -1935,6 +1935,18 @@ def test_presence
assert !Post.all.respond_to?(:by_lifo)
end
def test_unscope_with_subquery
p1 = Post.where(id: 1)
p2 = Post.where(id: 2)
assert_not_equal p1, p2
comments = Comment.where(post: p1).unscope(where: :post_id).where(post: p2)
assert_not_equal p1.first.comments, comments
assert_equal p2.first.comments, comments
end
def test_unscope_removes_binds
left = Post.where(id: Arel::Nodes::BindParam.new)
column = Post.columns_hash["id"]