mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Fix unscope with subquery
Currently cannot unscope subquery properly. This commit fixes the issue. Fixes #26323.
This commit is contained in:
parent
66076f381a
commit
22ca710f20
2 changed files with 31 additions and 10 deletions
|
@ -25,10 +25,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def except(*columns)
|
def except(*columns)
|
||||||
WhereClause.new(
|
WhereClause.new(*except_predicates_and_binds(columns))
|
||||||
predicates_except(columns),
|
|
||||||
binds_except(columns),
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def or(other)
|
def or(other)
|
||||||
|
@ -132,20 +129,32 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def predicates_except(columns)
|
def except_predicates_and_binds(columns)
|
||||||
predicates.reject do |node|
|
except_binds = []
|
||||||
|
binds_index = 0
|
||||||
|
|
||||||
|
predicates = self.predicates.reject do |node|
|
||||||
case 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
|
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)
|
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
|
||||||
columns.include?(subrelation.name.to_s)
|
columns.include?(subrelation.name.to_s)
|
||||||
|
end.tap do |except|
|
||||||
|
if except && binds_contains > 0
|
||||||
|
(binds_index...(binds_index + binds_contains)).each do |i|
|
||||||
|
except_binds[i] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
binds_index += binds_contains
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def binds_except(columns)
|
binds = self.binds.reject.with_index do |_, i|
|
||||||
binds.reject do |attr|
|
except_binds[i]
|
||||||
columns.include?(attr.name)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
[predicates, binds]
|
||||||
end
|
end
|
||||||
|
|
||||||
def predicates_with_wrapped_sql_literals
|
def predicates_with_wrapped_sql_literals
|
||||||
|
|
|
@ -1962,6 +1962,18 @@ class RelationTest < ActiveRecord::TestCase
|
||||||
assert !Post.all.respond_to?(:by_lifo)
|
assert !Post.all.respond_to?(:by_lifo)
|
||||||
end
|
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
|
def test_unscope_removes_binds
|
||||||
left = Post.where(id: Arel::Nodes::BindParam.new)
|
left = Post.where(id: Arel::Nodes::BindParam.new)
|
||||||
column = Post.columns_hash["id"]
|
column = Post.columns_hash["id"]
|
||||||
|
|
Loading…
Reference in a new issue