Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #8838: duplicate_join_table_names_fix_with_tests.2.diff

File duplicate_join_table_names_fix_with_tests.2.diff, 4.2 kB (added by jcoglan, 1 year ago)
  • activerecord/lib/active_record/base.rb

    old new  
    11671167          connection.add_lock!(sql, options) 
    11681168        end 
    11691169 
     1170        # Returns the names (or aliases if used) of each table used in a JOIN fragment 
     1171        def table_aliases_from_join_fragment(sql) 
     1172          return [] if sql.blank? 
     1173          return sql.scan(/JOIN\s+(`[^`]`|\S+)(?:\s+(?:AS\s+)?(`[^`]`|\S+))?/i).collect do |name| 
     1174            ((name[1] =~ /ON/i) ? name[0] : (name[1] || name[0])).gsub(/^`(.*)`$/, '\1') 
     1175          end 
     1176        end 
     1177 
    11701178        # The optional scope argument is for the current :find scope. 
    11711179        def add_joins!(sql, options, scope = :auto) 
    11721180          scope = scope(:find) if :auto == scope 
    11731181          join = (scope && scope[:joins]) || options[:joins] 
    1174           sql << " #{join} " if join 
     1182          return unless join 
     1183          used_table_aliases = table_aliases_from_join_fragment(join) 
     1184          table_aliases_from_join_fragment(sql).each_with_index do |join_table_alias, i| 
     1185            if used_table_aliases.include?(join_table_alias) 
     1186              new_alias = "renamed_join_table_#{i}" 
     1187              convert_table_name_to_new_alias!(sql, join_table_alias, new_alias) 
     1188            end 
     1189            used_table_aliases << (new_alias || join_table_alias) 
     1190          end 
     1191          sql << " #{join} " 
    11751192        end 
    11761193 
     1194        # Modifies the SQL fragment such that every instance of +old_table_name+ 
     1195        # is replaced by or aliased using (in JOIN ... AS blocks) +new_alias+. 
     1196        def convert_table_name_to_new_alias!(sql, old_table_name, new_alias) 
     1197          regex = Regexp.new("(?:(?:JOIN|AS)?\\s+|\\()`?#{old_table_name}`?(?:\s+(?:AS\s+)?(?:`[^`]`|\S+))?(?:\\.|\\s)", Regexp::IGNORECASE) 
     1198          sql.gsub!(regex) do |match| 
     1199            logger.info "\n\n======\n#{match.inspect}\n======\n\n" 
     1200            first_char = (match =~ /^\(/) ? '(' : '' 
     1201            last_char = (match =~ /\s$/) ? ' ' : '.' 
     1202            # If the table name is already aliased within this match, don't replace it 
     1203            return match if match =~ /^JOIN\s+(?:`[^`]`|\S+)\s+(?:AS\s+)?(?:`[^`]`|\S+)/i 
     1204            replacement = "JOIN `#{old_table_name}` AS #{new_alias}" if match =~ /^JOIN\s/i 
     1205            replacement = "AS #{new_alias}" if match =~ /^AS\s/i 
     1206            replacement = " #{new_alias}" unless match =~ /^(JOIN|AS)\s/i 
     1207            "#{first_char}#{replacement}#{last_char}" 
     1208          end 
     1209        end 
     1210 
    11771211        # Adds a sanitized version of +conditions+ to the +sql+ string. Note that the passed-in +sql+ string is changed. 
    11781212        # The optional scope argument is for the current :find scope. 
    11791213        def add_conditions!(sql, conditions, scope = :auto) 
  • activerecord/test/associations/eager_test.rb

    old new  
    240240    assert posts[1].categories.include?(categories(:general)) 
    241241  end 
    242242 
     243  def test_eager_association_loading_with_circular_habtm 
     244    assert_equal 4, categories(:general).posts.find(:all, :include => :categories).size 
     245    assert_equal 2, categories(:general).posts.find(:first, :include => :categories, :conditions => 'posts.id = 1').categories.size 
     246  end 
     247 
    243248  def test_eager_with_inheritance 
    244249    posts = SpecialPost.find(:all, :include => [ :comments ]) 
    245250  end 
     
    390395      assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15") 
    391396    end 
    392397  end 
     398 
     399  def test_eager_load_with_inner_join 
     400    assert_not_nil posts(:welcome) 
     401    assert posts(:welcome).people.size > 0 
     402    assert posts(:welcome).people.find(:all).size > 0 
     403    id = posts(:welcome).id 
     404    assert_equal posts(:welcome).people.find(:all).size, posts(:welcome).people.find(:all, :include => :posts).size 
     405    assert_equal posts(:welcome).people.find(:all).size, Person.find(:all, :include => :posts, :joins => 'inner join readers on readers.person_id = people.id', :conditions => ['readers.post_id = ?',id]).size 
     406  end 
    393407end