Permalink
Browse files

PG column consults oid types when typecasting

  • Loading branch information...
1 parent fa6cda5 commit c50cb4aa393f2cee30ad85b32db532eb955f6637 @tenderlove tenderlove committed Feb 11, 2012
@@ -28,6 +28,12 @@ def write_attribute(attr_name, value)
@attributes_cache.delete(attr_name)
column = column_for_attribute(attr_name)
+ # If we're dealing with a binary column, write the data to the cache
+ # so we don't attempt to typecast multiple times.
+ if column && column.binary?
+ @attributes_cache[attr_name] = value
+ end
+
if column || @attributes.has_key?(attr_name)
@attributes[attr_name] = type_cast_attribute_for_write(column, value)
else
@@ -66,6 +66,10 @@ def klass
end
end
+ def binary?
+ type == :binary
+ end
+
# Casts a Ruby value to something appropriate for writing to the database.
def type_cast_for_write(value)
return value unless number?
@@ -98,7 +102,6 @@ def type_cast(value)
when :date then klass.value_to_date(value)
when :binary then klass.binary_to_string(value)
when :boolean then klass.value_to_boolean(value)
- when :hstore then klass.string_to_hstore(value)
else value
end
end
@@ -20,7 +20,7 @@ def type_cast(value)
class Bytea < Type
def type_cast(value)
- PGconn.unescape_bytea value if value
+ PGconn.unescape_bytea value
end
end
@@ -180,7 +180,6 @@ def fetch(ftype, fmod)
h[k] = OID::Identity.new
}
-
# Register an OID type named +name+ with a typcasting object in
# +type+. +name+ should correspond to the `typname` column in
# the `pg_type` table.
@@ -207,6 +206,8 @@ def self.registered_type?(name)
register_type 'text', OID::Identity.new
alias_type 'varchar', 'text'
alias_type 'char', 'text'
+ alias_type 'bpchar', 'text'
+ alias_type 'xml', 'text'
# FIXME: why are we keeping these types as strings?
alias_type 'tsvector', 'text'
@@ -35,7 +35,8 @@ module ConnectionAdapters
# PostgreSQL-specific extensions to column definitions in a table.
class PostgreSQLColumn < Column #:nodoc:
# Instantiates a new PostgreSQL column definition in a table.
- def initialize(name, default, sql_type = nil, null = true)
+ def initialize(name, default, oid_type, sql_type = nil, null = true)
+ @oid_type = oid_type
super(name, self.class.extract_value_from_default(default), sql_type, null)
end
@@ -154,6 +155,13 @@ def self.extract_value_from_default(default)
end
end
+ def type_cast(value)
+ return if value.nil?
+ return super if encoded?
+
+ @oid_type.type_cast value
+ end
+
private
def extract_limit(sql_type)
case sql_type
@@ -931,8 +939,11 @@ def indexes(table_name, name = nil)
# Returns the list of all column definitions for a table.
def columns(table_name)
# Limit, precision, and scale are all handled by the superclass.
- column_definitions(table_name).collect do |column_name, type, default, notnull|
- PostgreSQLColumn.new(column_name, default, type, notnull == 'f')
+ column_definitions(table_name).map do |column_name, type, default, notnull, oid, fmod|
+ oid = OID::TYPE_MAP.fetch(oid.to_i, fmod.to_i) {
+ OID::Identity.new
+ }
+ PostgreSQLColumn.new(column_name, default, oid, type, notnull == 'f')
end
end
@@ -1334,7 +1345,7 @@ def select_raw(sql, name = nil)
# - ::regclass is a function that gives the id for a table name
def column_definitions(table_name) #:nodoc:
exec_query(<<-end_sql, 'SCHEMA').rows
- SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
+ SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
@@ -126,17 +126,20 @@ def test_has_default_should_return_false_for_blog_and_test_data_types
if current_adapter?(:PostgreSQLAdapter)
def test_bigint_column_should_map_to_integer
- bigint_column = PostgreSQLColumn.new('number', nil, "bigint")
+ oid = PostgreSQLAdapter::OID::Identity.new
+ bigint_column = PostgreSQLColumn.new('number', nil, oid, "bigint")
assert_equal :integer, bigint_column.type
end
def test_smallint_column_should_map_to_integer
- smallint_column = PostgreSQLColumn.new('number', nil, "smallint")
+ oid = PostgreSQLAdapter::OID::Identity.new
+ smallint_column = PostgreSQLColumn.new('number', nil, oid, "smallint")
assert_equal :integer, smallint_column.type
end
def test_uuid_column_should_map_to_string
- uuid_column = PostgreSQLColumn.new('unique_id', nil, "uuid")
+ oid = PostgreSQLAdapter::OID::Identity.new
+ uuid_column = PostgreSQLColumn.new('unique_id', nil, oid, "uuid")
assert_equal :string, uuid_column.type
end
end

0 comments on commit c50cb4a

Please sign in to comment.