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 1167 1167 connection.add_lock!(sql, options) 1168 1168 end 1169 1169 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 1170 1178 # The optional scope argument is for the current :find scope. 1171 1179 def add_joins!(sql, options, scope = :auto) 1172 1180 scope = scope(:find) if :auto == scope 1173 1181 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} " 1175 1192 end 1176 1193 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 1177 1211 # Adds a sanitized version of +conditions+ to the +sql+ string. Note that the passed-in +sql+ string is changed. 1178 1212 # The optional scope argument is for the current :find scope. 1179 1213 def add_conditions!(sql, conditions, scope = :auto) -
activerecord/test/associations/eager_test.rb
old new 240 240 assert posts[1].categories.include?(categories(:general)) 241 241 end 242 242 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 243 248 def test_eager_with_inheritance 244 249 posts = SpecialPost.find(:all, :include => [ :comments ]) 245 250 end … … 390 395 assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15") 391 396 end 392 397 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 393 407 end