1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Do not consider PG array columns as number or text columns

The code uses these checks in several places to know what to do with a
particular column, for instance AR attribute query methods has a branch
like this:

    if column.number?
      !value.zero?
    end

This should never be true for array columns, since it would be the same
as running [].zero?, which results in a NoMethodError exception.

Fixing this by ensuring that array columns in PostgreSQL never return
true for number?/text? checks.

Since most of the array support was based on the postgres_ext lib, it's
worth noting it does the same thing for numeric array columns too:

https://github.com/dockyard/postgres_ext/blob/v1.0.0/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb#L72

This extended the same logic for text columns to ensure consistency.
This commit is contained in:
Carlos Antonio da Silva 2013-12-19 17:39:20 -02:00
parent 618d5317d3
commit 56510091fb
3 changed files with 33 additions and 3 deletions

View file

@ -1,3 +1,21 @@
* Do not consider PostgreSQL array columns as number or text columns.
The code uses these checks in several places to know what to do with a
particular column, for instance AR attribute query methods has a branch
like this:
if column.number?
!value.zero?
end
This should never be true for array columns, since it would be the same
as running [].zero?, which results in a NoMethodError exception.
Fixing this by ensuring that array columns in PostgreSQL never return
true for number?/text? checks.
*Carlos Antonio da Silva*
* When connecting to a non-existant postgresql database, the error: * When connecting to a non-existant postgresql database, the error:
`ActiveRecord::NoDatabaseError` will now be raised. When being used with Rails `ActiveRecord::NoDatabaseError` will now be raised. When being used with Rails
the error message will include information on how to create a database: the error message will include information on how to create a database:

View file

@ -46,7 +46,7 @@ module ActiveRecord
# PostgreSQL-specific extensions to column definitions in a table. # PostgreSQL-specific extensions to column definitions in a table.
class PostgreSQLColumn < Column #:nodoc: class PostgreSQLColumn < Column #:nodoc:
attr_accessor :array attr_accessor :array
# Instantiates a new PostgreSQL column definition in a table.
def initialize(name, default, oid_type, sql_type = nil, null = true) def initialize(name, default, oid_type, sql_type = nil, null = true)
@oid_type = oid_type @oid_type = oid_type
default_value = self.class.extract_value_from_default(default) default_value = self.class.extract_value_from_default(default)
@ -62,6 +62,14 @@ module ActiveRecord
@default_function = default if has_default_function?(default_value, default) @default_function = default if has_default_function?(default_value, default)
end end
def number?
!array && super
end
def text?
!array && super
end
# :stopdoc: # :stopdoc:
class << self class << self
include ConnectionAdapters::PostgreSQLColumn::Cast include ConnectionAdapters::PostgreSQLColumn::Cast

View file

@ -26,6 +26,12 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def test_column def test_column
assert_equal :string, @column.type assert_equal :string, @column.type
assert @column.array assert @column.array
assert_not @column.text?
ratings_column = PgArray.columns_hash['ratings']
assert_equal :integer, ratings_column.type
assert ratings_column.array
assert_not ratings_column.number?
end end
def test_change_column_with_array def test_change_column_with_array
@ -50,8 +56,6 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
end end
def test_type_cast_array def test_type_cast_array
assert @column
data = '{1,2,3}' data = '{1,2,3}'
oid_type = @column.instance_variable_get('@oid_type').subtype oid_type = @column.instance_variable_get('@oid_type').subtype
# we are getting the instance variable in this test, but in the # we are getting the instance variable in this test, but in the