aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/calculations.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/relation/calculations.rb')
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb42
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