mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Support updates with joins. Fixes #522.
This commit is contained in:
@@ -306,6 +306,15 @@ module ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
||||
# on mysql (even when aliasing the tables), but mysql allows using JOIN directly in
|
||||
# an UPDATE statement, so in the mysql adapters we redefine this to do that.
|
||||
def join_to_update(update, select) #:nodoc:
|
||||
subselect = select.clone
|
||||
subselect.ast.cores.last.projections = [update.ast.key]
|
||||
update.wheres = [update.ast.key.in(subselect)]
|
||||
end
|
||||
|
||||
protected
|
||||
# Returns an array of record hashes with the column names as keys and
|
||||
# column values as values.
|
||||
|
||||
@@ -577,6 +577,10 @@ module ActiveRecord
|
||||
where_sql
|
||||
end
|
||||
|
||||
def join_to_update(update, select) #:nodoc:
|
||||
update.table select.ast.cores.last.source
|
||||
end
|
||||
|
||||
protected
|
||||
def quoted_columns_for_index(column_names, options = {})
|
||||
length = options[:length] if options.is_a?(Hash)
|
||||
|
||||
@@ -491,6 +491,10 @@ module ActiveRecord
|
||||
execute("RELEASE SAVEPOINT #{current_savepoint_name}")
|
||||
end
|
||||
|
||||
def join_to_update(update, select) #:nodoc:
|
||||
update.table select.ast.cores.last.source
|
||||
end
|
||||
|
||||
# SCHEMA STATEMENTS ========================================
|
||||
|
||||
def structure_dump #:nodoc:
|
||||
|
||||
@@ -217,13 +217,18 @@ module ActiveRecord
|
||||
where(conditions).apply_finder_options(options.slice(:limit, :order)).update_all(updates)
|
||||
else
|
||||
stmt = arel.compile_update(Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates)))
|
||||
stmt.key = table[primary_key]
|
||||
|
||||
if limit = arel.limit
|
||||
stmt.take limit
|
||||
if joins_values.any?
|
||||
@klass.connection.join_to_update(stmt, arel)
|
||||
else
|
||||
if limit = arel.limit
|
||||
stmt.take limit
|
||||
end
|
||||
|
||||
stmt.order(*arel.orders)
|
||||
end
|
||||
|
||||
stmt.order(*arel.orders)
|
||||
stmt.key = table[primary_key]
|
||||
@klass.connection.update stmt, 'SQL', bind_values
|
||||
end
|
||||
end
|
||||
|
||||
@@ -965,4 +965,12 @@ class RelationTest < ActiveRecord::TestCase
|
||||
def test_ordering_with_extra_spaces
|
||||
assert_equal authors(:david), Author.order('id DESC , name DESC').last
|
||||
end
|
||||
|
||||
def test_update_all_with_joins
|
||||
comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
|
||||
count = comments.count
|
||||
|
||||
assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
|
||||
assert_equal posts(:thinking), comments(:greetings).post
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user