diff options
Diffstat (limited to 'activerecord/lib/active_record/result.rb')
-rw-r--r-- | activerecord/lib/active_record/result.rb | 67 |
1 files changed, 60 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index bea195e9b8..228b2aa60f 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -3,11 +3,36 @@ module ActiveRecord # This class encapsulates a Result returned from calling +exec_query+ on any # database connection adapter. For example: # - # x = ActiveRecord::Base.connection.exec_query('SELECT * FROM foo') - # x # => #<ActiveRecord::Result:0xdeadbeef> + # result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts') + # result # => #<ActiveRecord::Result:0xdeadbeef> + # + # # Get the column names of the result: + # result.columns + # # => ["id", "title", "body"] + # + # # Get the record values of the result: + # result.rows + # # => [[1, "title_1", "body_1"], + # [2, "title_2", "body_2"], + # ... + # ] + # + # # Get an array of hashes representing the result (column => value): + # result.to_hash + # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"}, + # {"id" => 2, "title" => "title_2", "body" => "body_2"}, + # ... + # ] + # + # # ActiveRecord::Result also includes Enumerable. + # result.each do |row| + # puts row['title'] + " " + row['body'] + # end class Result include Enumerable + IDENTITY_TYPE = Class.new { def type_cast(v); v; end }.new # :nodoc: + attr_reader :columns, :rows, :column_types def initialize(columns, rows, column_types = {}) @@ -17,8 +42,20 @@ module ActiveRecord @column_types = column_types end + def identity_type # :nodoc: + IDENTITY_TYPE + end + + def column_type(name) + @column_types[name] || identity_type + end + def each - hash_rows.each { |row| yield row } + if block_given? + hash_rows.each { |row| yield row } + else + hash_rows.to_enum { @rows.size } + end end def to_hash @@ -46,12 +83,14 @@ module ActiveRecord end def initialize_copy(other) - @columns = columns.dup - @rows = rows.dup - @hash_rows = nil + @columns = columns.dup + @rows = rows.dup + @column_types = column_types.dup + @hash_rows = nil end private + def hash_rows @hash_rows ||= begin @@ -59,7 +98,21 @@ module ActiveRecord # used as keys in ActiveRecord::Base's @attributes hash columns = @columns.map { |c| c.dup.freeze } @rows.map { |row| - Hash[columns.zip(row)] + # In the past we used Hash[columns.zip(row)] + # though elegant, the verbose way is much more efficient + # both time and memory wise cause it avoids a big array allocation + # this method is called a lot and needs to be micro optimised + hash = {} + + index = 0 + length = columns.length + + while index < length + hash[columns[index]] = row[index] + index += 1 + end + + hash } end end |