public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Support :limit on update_all so that has_many with :limit can be safely updated

Signed-off-by: Michael Koziarski <michael@koziarski.com>
Tarmo Tänav (author)
Wed Sep 10 03:39:50 -0700 2008
NZKoz (committer)
Wed Sep 10 04:41:49 -0700 2008
commit  7c9851dbb6f841ffbf3ebd16e9f57c04319d3a39
tree    adc55140a573c0c7cd99a405f2f593e721f1efb3
parent  14d1560e85d5c4795c21ddb00953cf55e0525ee3
...
769
770
771
 
772
773
774
775
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776
777
778
...
769
770
771
772
773
 
 
 
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
0
@@ -769,10 +769,24 @@ module ActiveRecord #:nodoc:
0
       #                         :order => 'created_at', :limit => 5 )
0
       def update_all(updates, conditions = nil, options = {})
0
         sql  = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "
0
+
0
         scope = scope(:find)
0
-        add_conditions!(sql, conditions, scope)
0
-        add_order!(sql, options[:order], nil)
0
-        add_limit!(sql, options, nil)
0
+
0
+        select_sql = ""
0
+        add_conditions!(select_sql, conditions, scope)
0
+
0
+        if options.has_key?(:limit) || (scope && scope[:limit])
0
+          # Only take order from scope if limit is also provided by scope, this
0
+          # is useful for updating a has_many association with a limit.
0
+          add_order!(select_sql, options[:order], scope)
0
+
0
+          add_limit!(select_sql, options, scope)
0
+          sql.concat(connection.limited_update_conditions(select_sql, quoted_table_name, connection.quote_column_name(primary_key)))
0
+        else
0
+          add_order!(select_sql, options[:order], nil)
0
+          sql.concat(select_sql)
0
+        end
0
+
0
         connection.update(sql, "#{name} Update")
0
       end
0
 
...
153
154
155
 
 
 
 
156
157
158
...
153
154
155
156
157
158
159
160
161
162
0
@@ -153,6 +153,10 @@ module ActiveRecord
0
         "="
0
       end
0
 
0
+      def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
0
+        "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
0
+      end
0
+
0
       protected
0
         # Returns an array of record hashes with the column names as keys and
0
         # column values as values.
...
523
524
525
 
 
 
 
526
527
528
...
523
524
525
526
527
528
529
530
531
532
0
@@ -523,6 +523,10 @@ module ActiveRecord
0
         "= BINARY"
0
       end
0
 
0
+      def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
0
+        where_sql
0
+      end
0
+
0
       private
0
         def connect
0
           @connection.reconnect = true if @connection.respond_to?(:reconnect=)
...
76
77
78
79
 
80
81
82
...
664
665
666
667
668
 
 
669
670
 
 
 
 
 
 
 
 
 
 
 
 
671
672
673
...
76
77
78
 
79
80
81
82
...
664
665
666
 
 
667
668
669
 
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
0
@@ -76,7 +76,7 @@ class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
0
 end
0
 
0
 class BasicsTest < ActiveRecord::TestCase
0
-  fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories
0
+  fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts
0
 
0
   def test_table_exists
0
     assert !NonExistentTable.table_exists?
0
@@ -664,10 +664,21 @@ class BasicsTest < ActiveRecord::TestCase
0
     end
0
   end
0
 
0
-  def test_update_all_ignores_order_limit_from_association
0
-    author = Author.find(1)
0
+  def test_update_all_ignores_order_without_limit_from_association
0
+    author = authors(:david)
0
     assert_nothing_raised do
0
-      assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all("body = 'bulk update!'")
0
+      assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
0
+    end
0
+  end
0
+
0
+  def test_update_all_with_order_and_limit_updates_subset_only
0
+    author = authors(:david)
0
+    assert_nothing_raised do
0
+      assert_equal 1, author.posts_sorted_by_id_limited.size
0
+      assert_equal 2, author.posts_sorted_by_id_limited.find(:all, :limit => 2).size
0
+      assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
0
+      assert_equal "bulk update!", posts(:welcome).body
0
+      assert_not_equal "bulk update!", posts(:thinking).body
0
     end
0
   end
0
 
...
2
3
4
 
5
6
7
...
2
3
4
5
6
7
8
0
@@ -2,6 +2,7 @@ class Author < ActiveRecord::Base
0
   has_many :posts, :accessible => true
0
   has_many :posts_with_comments, :include => :comments, :class_name => "Post"
0
   has_many :posts_with_comments_sorted_by_comment_id, :include => :comments, :class_name => "Post", :order => 'comments.id'
0
+  has_many :posts_sorted_by_id_limited, :class_name => "Post", :order => 'posts.id', :limit => 1
0
   has_many :posts_with_categories, :include => :categories, :class_name => "Post"
0
   has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post"
0
   has_many :posts_containing_the_letter_a, :class_name => "Post"

Comments