Skip to content

Commit

Permalink
ActiveRecord::Result#each to yield regular Hash
Browse files Browse the repository at this point in the history
Followup: rails#51744
Fix: rails#53081
Closes: rails#53088

While the yielded type wasn't specified and we could always
return the more efficient format, there's too many code out
there that depend on this behavior.

Ultimately, queries done with `exec_query` are rare, as long as
Active Record itself use the more efficient path to instantiate
records, most of the gain is obtained.
  • Loading branch information
byroot committed Oct 1, 2024
1 parent a79c753 commit 88fb34b
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -725,8 +725,6 @@ def table_structure_with_collation(table_name, basic_structure)
end

basic_structure.map do |column|
column = column.to_h

column_name = column["name"]

if collation_hash.has_key? column_name
Expand Down
4 changes: 2 additions & 2 deletions activerecord/lib/active_record/querying.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ def _load_from_sql(result_set, &block) # :nodoc:

message_bus.instrument("instantiation.active_record", payload) do
if result_set.includes_column?(inheritance_column)
result_set.map { |record| instantiate(record, column_types, &block) }
result_set.indexed_rows.map { |record| instantiate(record, column_types, &block) }
else
# Instantiate a homogeneous set
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
result_set.indexed_rows.map { |record| instantiate_instance_of(self, record, column_types, &block) }
end
end
end
Expand Down
19 changes: 10 additions & 9 deletions activerecord/lib/active_record/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ def length
# Returns an +Enumerator+ if no block is given.
def each(&block)
if block_given?
indexed_rows.each(&block)
hash_rows.each(&block)
else
indexed_rows.to_enum { @rows.size }
hash_rows.to_enum { @rows.size }
end
end

Expand Down Expand Up @@ -191,6 +191,7 @@ def cast_values(type_overrides = {}) # :nodoc:
def initialize_copy(other)
@rows = rows.dup
@column_types = column_types.dup
@hash_rows = nil
end

def freeze # :nodoc:
Expand All @@ -212,6 +213,13 @@ def column_indexes # :nodoc:
end
end

def indexed_rows # :nodoc:
@indexed_rows ||= begin
columns = column_indexes
@rows.map { |row| IndexedRow.new(columns, row) }.freeze
end
end

private
def column_type(name, index, type_overrides)
type_overrides.fetch(name) do
Expand All @@ -221,13 +229,6 @@ def column_type(name, index, type_overrides)
end
end

def indexed_rows
@indexed_rows ||= begin
columns = column_indexes
@rows.map { |row| IndexedRow.new(columns, row) }.freeze
end
end

def hash_rows
# We use transform_values to rows.
# This is faster because we avoid any reallocs and avoid hashing entirely.
Expand Down

0 comments on commit 88fb34b

Please sign in to comment.