aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLachlan Sylvester <lachlan.sylvester@publicisfrontfoot.com.au>2018-06-19 11:11:46 +1000
committerLachlan Sylvester <lachlan.sylvester@publicisfrontfoot.com.au>2018-06-19 11:11:46 +1000
commit13f0d6ebd38ad08f7550db784d64c5c6ab7f56f9 (patch)
tree73c9e62507f6ed4eb627dee35d1083a299bf3f1f
parent433a3122697e41bb46c4f072d2d8223233af5dd4 (diff)
downloadrails-13f0d6ebd38ad08f7550db784d64c5c6ab7f56f9.tar.gz
rails-13f0d6ebd38ad08f7550db784d64c5c6ab7f56f9.tar.bz2
rails-13f0d6ebd38ad08f7550db784d64c5c6ab7f56f9.zip
Avoid creating temporary arrays in ActiveRecord::Result#cast_values in order to speed up pluck
-rw-r--r--activerecord/lib/active_record/result.rb19
-rw-r--r--activerecord/test/cases/calculations_test.rb12
2 files changed, 26 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb
index 11626c8e31..ffef229be2 100644
--- a/activerecord/lib/active_record/result.rb
+++ b/activerecord/lib/active_record/result.rb
@@ -97,12 +97,21 @@ module ActiveRecord
end
def cast_values(type_overrides = {}) # :nodoc:
- types = columns.map { |name| column_type(name, type_overrides) }
- result = rows.map do |values|
- types.zip(values).map { |type, value| type.deserialize(value) }
- end
+ if columns.one?
+ # Separated to avoid allocating an array per row
+
+ type = column_type(columns.first, type_overrides)
- columns.one? ? result.map!(&:first) : result
+ rows.map do |(value)|
+ type.deserialize(value)
+ end
+ else
+ types = columns.map { |name| column_type(name, type_overrides) }
+
+ rows.map do |values|
+ Array.new(values.size) { |i| types[i].deserialize(values[i]) }
+ end
+ end
end
def initialize_copy(other)
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 6ceac59eec..5c9ed42173 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -642,6 +642,18 @@ class CalculationsTest < ActiveRecord::TestCase
assert_equal [ topic.written_on ], relation.pluck(:written_on)
end
+ def test_pluck_with_type_cast_does_not_corrupt_the_query_cache
+ topic = topics(:first)
+ relation = Topic.where(id: topic.id)
+ assert_queries 1 do
+ Topic.cache do
+ kind = relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on).class
+ relation.pluck(:written_on)
+ assert_kind_of kind, relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on)
+ end
+ end
+ end
+
def test_pluck_and_distinct
assert_equal [50, 53, 55, 60], Account.order(:credit_limit).distinct.pluck(:credit_limit)
end