diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/calculations.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/calculations.rb | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 11256ab3d9..dea7542f03 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -175,21 +175,13 @@ module ActiveRecord # See also #ids. # def pluck(*column_names) - if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty? - return records.pluck(*column_names) - end + _pluck(column_names, @klass.allow_unsafe_raw_sql == :enabled) + end - if has_include?(column_names.first) - relation = apply_join_dependency - relation.pluck(*column_names) - else - relation = spawn - relation.select_values = column_names.map { |cn| - @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn - } - result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) } - result.cast_values(klass.attribute_types) - end + # Same as #pluck but allows raw SQL regardless of `allow_unsafe_raw_sql` + # config setting. + def unsafe_raw_pluck(*column_names) + _pluck(column_names, true) end # Pluck all the ID's for the relation using the table's primary key @@ -202,6 +194,28 @@ module ActiveRecord private + def _pluck(column_names, unsafe_raw) + unrecognized = column_names.reject do |cn| + @klass.respond_to_attribute?(cn) + end + + if loaded? && unrecognized.none? + records.pluck(*column_names) + elsif has_include?(column_names.first) + relation = apply_join_dependency + relation.pluck(*column_names) + elsif unsafe_raw || unrecognized.none? + relation = spawn + relation.select_values = column_names.map { |cn| + @klass.respond_to_attribute?(cn) ? arel_attribute(cn) : cn + } + result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) } + result.cast_values(klass.attribute_types) + else + raise ArgumentError, "Invalid column name: #{unrecognized}" + end + end + def has_include?(column_name) eager_loading? || (includes_values.present? && column_name && column_name != :all) end |