From 7c9851dbb6f841ffbf3ebd16e9f57c04319d3a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarmo=20T=C3=A4nav?= Date: Wed, 10 Sep 2008 13:39:50 +0300 Subject: Support :limit on update_all so that has_many with :limit can be safely updated Signed-off-by: Michael Koziarski --- activerecord/lib/active_record/base.rb | 20 +++++++++++++++++--- .../abstract/database_statements.rb | 4 ++++ .../connection_adapters/mysql_adapter.rb | 4 ++++ 3 files changed, 25 insertions(+), 3 deletions(-) mode change 100644 => 100755 activerecord/lib/active_record/base.rb (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb old mode 100644 new mode 100755 index d7c67bc10d..fc6d762fcd --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -769,10 +769,24 @@ module ActiveRecord #:nodoc: # :order => 'created_at', :limit => 5 ) def update_all(updates, conditions = nil, options = {}) sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} " + scope = scope(:find) - add_conditions!(sql, conditions, scope) - add_order!(sql, options[:order], nil) - add_limit!(sql, options, nil) + + select_sql = "" + add_conditions!(select_sql, conditions, scope) + + if options.has_key?(:limit) || (scope && scope[:limit]) + # Only take order from scope if limit is also provided by scope, this + # is useful for updating a has_many association with a limit. + add_order!(select_sql, options[:order], scope) + + add_limit!(select_sql, options, scope) + sql.concat(connection.limited_update_conditions(select_sql, quoted_table_name, connection.quote_column_name(primary_key))) + else + add_order!(select_sql, options[:order], nil) + sql.concat(select_sql) + end + connection.update(sql, "#{name} Update") end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index aaf9e2e73f..8fc89de22b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -153,6 +153,10 @@ module ActiveRecord "=" end + def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) + "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})" + end + protected # Returns an array of record hashes with the column names as keys and # column values as values. diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index f1d13698c3..c2a0fb72bf 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -523,6 +523,10 @@ module ActiveRecord "= BINARY" end + def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) + where_sql + end + private def connect @connection.reconnect = true if @connection.respond_to?(:reconnect=) -- cgit v1.2.3