1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

reorder bind parameters when merging relations

This commit is contained in:
Aaron Patterson 2013-07-15 16:29:01 -07:00
parent d345ed40b5
commit 9675c7da28
3 changed files with 43 additions and 3 deletions

View file

@ -97,13 +97,29 @@ module ActiveRecord
def merge_multi_values def merge_multi_values
lhs_wheres = relation.where_values lhs_wheres = relation.where_values
rhs_wheres = values[:where] || [] rhs_wheres = values[:where] || []
lhs_binds = relation.bind_values lhs_binds = relation.bind_values
rhs_binds = values[:bind] || [] rhs_binds = values[:bind] || []
removed, kept = partition_overwrites(lhs_wheres, rhs_wheres) removed, kept = partition_overwrites(lhs_wheres, rhs_wheres)
relation.where_values = kept + rhs_wheres where_values = kept + rhs_wheres
relation.bind_values = filter_binds(lhs_binds, removed) + rhs_binds bind_values = filter_binds(lhs_binds, removed) + rhs_binds
conn = relation.klass.connection
bviter = bind_values.each.with_index
where_values.map! do |node|
if Arel::Nodes::Equality === node && Arel::Nodes::BindParam === node.right
(column, _), i = bviter.next
substitute = conn.substitute_at column, i
Arel::Nodes::Equality.new(node.left, substitute)
else
node
end
end
relation.where_values = where_values
relation.bind_values = bind_values
if values[:reordering] if values[:reordering]
# override any order specified in the original relation # override any order specified in the original relation

View file

@ -9,6 +9,9 @@ module ActiveRecord
fixtures :posts, :comments, :authors fixtures :posts, :comments, :authors
class FakeKlass < Struct.new(:table_name, :name) class FakeKlass < Struct.new(:table_name, :name)
def self.connection
Post.connection
end
end end
def test_construction def test_construction
@ -204,6 +207,10 @@ module ActiveRecord
def arel_table def arel_table
Post.arel_table Post.arel_table
end end
def connection
Post.connection
end
end end
def relation def relation
@ -295,7 +302,7 @@ module ActiveRecord
assert_equal({foo: 'bar'}, relation.create_with_value) assert_equal({foo: 'bar'}, relation.create_with_value)
end end
test 'merge!' do def test_merge!
assert relation.merge!(where: :foo).equal?(relation) assert relation.merge!(where: :foo).equal?(relation)
assert_equal [:foo], relation.where_values assert_equal [:foo], relation.where_values
end end

View file

@ -1556,4 +1556,21 @@ class RelationTest < ActiveRecord::TestCase
merged = left.merge(right) merged = left.merge(right)
assert_equal binds, merged.bind_values assert_equal binds, merged.bind_values
end end
def test_merging_reorders_bind_params
post = Post.first
id_column = Post.columns_hash['id']
title_column = Post.columns_hash['title']
bv = Post.connection.substitute_at id_column, 0
right = Post.where(id: bv)
right.bind_values += [[id_column, post.id]]
left = Post.where(title: bv)
left.bind_values += [[title_column, post.title]]
merged = left.merge(right)
assert_equal post, merged.first
end
end end