aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-05-21 15:00:41 +0900
committerRyuta Kamizono <kamipo@gmail.com>2019-05-21 23:41:13 +0900
commit82a54be0c6a19336008e18f52bc76791adc3bd67 (patch)
tree801e0ffb599536daa8bf7f331a2ef9994d54159c
parent0810c076de0d9b7879ee240bb08d31fb7c2f5ac9 (diff)
downloadrails-82a54be0c6a19336008e18f52bc76791adc3bd67.tar.gz
rails-82a54be0c6a19336008e18f52bc76791adc3bd67.tar.bz2
rails-82a54be0c6a19336008e18f52bc76791adc3bd67.zip
Fall back to type casting from the connection adapter
Unfortunately, a11a8ff had no effect as long as using bind param, and was not tested. This ensures making the intent of a11a8ff, which fall back to type casting from the connection adapter. Fixes #35205. ``` % ARCONN=postgresql bundle exec ruby -w -Itest test/cases/relation/where_test.rb -n test_type_casting_nested_joins Using postgresql Run options: -n test_type_casting_nested_joins --seed 55730 # Running: E Error: ActiveRecord::WhereTest#test_type_casting_nested_joins: ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "2-foo" rails test test/cases/relation/where_test.rb:30 Finished in 0.245778s, 4.0687 runs/s, 0.0000 assertions/s. 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips ```
-rw-r--r--activerecord/lib/active_record/table_metadata.rb16
-rw-r--r--activerecord/lib/active_record/type_caster/connection.rb26
-rw-r--r--activerecord/test/cases/relation/where_test.rb7
3 files changed, 28 insertions, 21 deletions
diff --git a/activerecord/lib/active_record/table_metadata.rb b/activerecord/lib/active_record/table_metadata.rb
index 073866b894..9a1176db6a 100644
--- a/activerecord/lib/active_record/table_metadata.rb
+++ b/activerecord/lib/active_record/table_metadata.rb
@@ -4,8 +4,9 @@ module ActiveRecord
class TableMetadata # :nodoc:
delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
- def initialize(klass, arel_table, association = nil)
+ def initialize(klass, arel_table, association = nil, types = klass)
@klass = klass
+ @types = types
@arel_table = arel_table
@association = association
end
@@ -29,11 +30,7 @@ module ActiveRecord
end
def type(column_name)
- if klass
- klass.type_for_attribute(column_name)
- else
- Type.default_value
- end
+ types.type_for_attribute(column_name)
end
def has_column?(column_name)
@@ -52,13 +49,12 @@ module ActiveRecord
elsif association && !association.polymorphic?
association_klass = association.klass
arel_table = association_klass.arel_table.alias(table_name)
+ TableMetadata.new(association_klass, arel_table, association)
else
type_caster = TypeCaster::Connection.new(klass, table_name)
- association_klass = nil
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
+ TableMetadata.new(nil, arel_table, association, type_caster)
end
-
- TableMetadata.new(association_klass, arel_table, association)
end
def polymorphic_association?
@@ -74,6 +70,6 @@ module ActiveRecord
end
private
- attr_reader :klass, :arel_table, :association
+ attr_reader :klass, :types, :arel_table, :association
end
end
diff --git a/activerecord/lib/active_record/type_caster/connection.rb b/activerecord/lib/active_record/type_caster/connection.rb
index 7cf8181d8e..f43559f4cb 100644
--- a/activerecord/lib/active_record/type_caster/connection.rb
+++ b/activerecord/lib/active_record/type_caster/connection.rb
@@ -8,21 +8,27 @@ module ActiveRecord
@table_name = table_name
end
- def type_cast_for_database(attribute_name, value)
+ def type_cast_for_database(attr_name, value)
return value if value.is_a?(Arel::Nodes::BindParam)
- column = column_for(attribute_name)
- connection.type_cast_from_column(column, value)
+ type = type_for_attribute(attr_name)
+ type.serialize(value)
end
- private
- attr_reader :table_name
- delegate :connection, to: :@klass
+ def type_for_attribute(attr_name)
+ schema_cache = connection.schema_cache
- def column_for(attribute_name)
- if connection.schema_cache.data_source_exists?(table_name)
- connection.schema_cache.columns_hash(table_name)[attribute_name.to_s]
- end
+ if schema_cache.data_source_exists?(table_name)
+ column = schema_cache.columns_hash(table_name)[attr_name.to_s]
+ type = connection.lookup_cast_type_from_column(column) if column
end
+
+ type || Type.default_value
+ end
+
+ delegate :connection, to: :@klass, private: true
+
+ private
+ attr_reader :table_name
end
end
end
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index 6c1e3e7fec..aad30ddea0 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -18,7 +18,7 @@ require "support/stubs/strong_parameters"
module ActiveRecord
class WhereTest < ActiveRecord::TestCase
- fixtures :posts, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates, :topics
+ fixtures :posts, :comments, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates, :topics
def test_in_clause_is_correctly_sliced
assert_called(Author.connection, :in_clause_length, returns: 1) do
@@ -27,6 +27,11 @@ module ActiveRecord
end
end
+ def test_type_casting_nested_joins
+ comment = comments(:eager_other_comment1)
+ assert_equal [comment], Comment.joins(post: :author).where(authors: { id: "2-foo" })
+ end
+
def test_where_copies_bind_params
author = authors(:david)
posts = author.posts.where("posts.id != 1")