aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorSean Griffin <sean@thoughtbot.com>2015-01-24 21:07:55 -0700
committerSean Griffin <sean@thoughtbot.com>2015-01-24 21:07:55 -0700
commit3327cd3f61a22a5834dcbf9bd24ecbc3a23de3de (patch)
tree7b8ce77b5bbf685ee7b09d2e09d3c67292229491 /activerecord/lib/active_record
parentae8cd56c7b1f3130eb3b8f2632a528a8fc78e56c (diff)
downloadrails-3327cd3f61a22a5834dcbf9bd24ecbc3a23de3de.tar.gz
rails-3327cd3f61a22a5834dcbf9bd24ecbc3a23de3de.tar.bz2
rails-3327cd3f61a22a5834dcbf9bd24ecbc3a23de3de.zip
Expand the number of types which can use prepared statements
This will allow all types which require no additional handling to use prepared statements. Specifically, this will allow for `true`, `false`, `Date`, `Time`, and any custom PG type to use prepared statements. This also revealed another source of nil columns in bind params, and an inconsistency in their use. The specific inconsistency comes from a nested query coming from a through association, where one of the inversed associations is not bi-directional. The stop-gap is to simply construct the column at the site it is being used. This should simply go away on its own once we use `Attribute` to represent them instead, since we already have all of the information we need.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb14
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb5
-rw-r--r--activerecord/lib/active_record/table_metadata.rb3
3 files changed, 16 insertions, 6 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 4c49d3eb81..490158f0d5 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -99,15 +99,17 @@ module ActiveRecord
attributes.each do |column_name, value|
case value
- when String, Integer, ActiveRecord::StatementCache::Substitute
- result[column_name] = Arel::Nodes::BindParam.new
- binds.push([table.column(column_name), value])
when Hash
attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value)
result[column_name] = attrs
binds += bvs
when Relation
binds += value.arel.bind_values + value.bind_values
+ else
+ if can_be_bound?(column_name, value)
+ result[column_name] = Arel::Nodes::BindParam.new
+ binds.push([table.column(column_name), value])
+ end
end
end
@@ -137,5 +139,11 @@ module ActiveRecord
def handler_for(object)
@handlers.detect { |klass, _| klass === object }.last
end
+
+ def can_be_bound?(column_name, value)
+ !value.nil? &&
+ handler_for(value).is_a?(BasicObjectHandler) &&
+ !table.associated_with?(column_name)
+ end
end
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 53ff48d82e..e1c74ce90a 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -944,12 +944,11 @@ module ActiveRecord
[@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
when Hash
opts = predicate_builder.resolve_column_aliases(opts)
+ opts = @klass.send(:expand_hash_conditions_for_aggregates, opts)
- tmp_opts, bind_values = predicate_builder.create_binds(opts)
+ attributes, bind_values = predicate_builder.create_binds(opts)
self.bind_values += bind_values
- attributes = @klass.send(:expand_hash_conditions_for_aggregates, tmp_opts)
-
predicate_builder.build_from_hash(attributes)
else
[opts]
diff --git a/activerecord/lib/active_record/table_metadata.rb b/activerecord/lib/active_record/table_metadata.rb
index 31a40adb67..62a0c04a0f 100644
--- a/activerecord/lib/active_record/table_metadata.rb
+++ b/activerecord/lib/active_record/table_metadata.rb
@@ -25,6 +25,9 @@ module ActiveRecord
def column(column_name)
if klass
klass.columns_hash[column_name.to_s]
+ else
+ # FIXME: We really shouldn't need to do this.
+ ConnectionAdapters::Column.new(column_name.to_s, nil, Type::Value.new)
end
end