diff options
author | Sean Griffin <sean@thoughtbot.com> | 2015-01-24 21:07:55 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2015-01-24 21:07:55 -0700 |
commit | 3327cd3f61a22a5834dcbf9bd24ecbc3a23de3de (patch) | |
tree | 7b8ce77b5bbf685ee7b09d2e09d3c67292229491 /activerecord/lib | |
parent | ae8cd56c7b1f3130eb3b8f2632a528a8fc78e56c (diff) | |
download | rails-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')
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 |