test_validate_format_numeric(ValidationsTest):
ActiveRecord::StatementInvalid: RuntimeError: DB2 error: [IBM][CLI Driver][DB2/6000] SQL0408N A value is not compatible with the data type of its assignment target. Target name is "CONTENT". SQLSTATE=42821
: INSERT INTO topics (author_name, title, type, approved, bonus_time, replies_count, author_email_address, content, written_on, last_read, parent_id)
VALUES(NULL, '1', NULL, 1, NULL, 0, NULL, 6789, '2006-04-12 17:06:56', NULL, NULL)
The SQL is attempting to insert into the content column the integer value 6789
instead of the string value '6789'. On mysql, this is valid, in DB2 it is
not.
This may be a more widespread defect than just DB2, but it is exposed in the
current test cases for DB2. A test case that exposes it for more database
adapters is as follows:
# for use in test/base_rb.rb - BasicsTest
def test_preserving_numeric_string
topic = Topic.new({
"title" => "initialized numeric string from attributes",
"written_on" => "2006-04-10 15:23",
"content" => "123456789"
})
topic.save!
assert_equal("123456789", topic.content)
end
In this test, topic.content returns a Fixnum
There is at least one or more round trips of a string through YAML::load for
attributes, which over a couple of YAML::load iterations which eventualy
converts a numeric string into a Fixnum. An irb example:
irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> x = "'56789'"
=> "'56789'"
irb(main):003:0> y = YAML::load(x)
=> "56789"
irb(main):004:0> z = YAML::load(y)
=> 56789
irb(main):005:0> x.class
=> String
irb(main):006:0> y.class
=> String
irb(main):007:0> z.class
=> Fixnum
It appears from some code traces that Base's @attributes are round tripped
through YAML::load at least 2x's in normal usage, and as such will eventually
convert a numeric string into a Fixnum. Eventually you end up in a case where
an AR value is Fixnum and the associated AR column.type is either :text or
:string.
In this case the SQL that is generated does not quote the numeric string and
at least in DB2, is illegal to insert 6789 into a varchar column. It is
necessary to insert '6789' into that same varchar column.
The attached patch fixes the symptom for DB2, but it may also be a core AR bug
for an AR's column to have a different "type" than the type of the value
associated with that column. Of this I am unsure. It could be the case that
the appropriate action is to have the AR field accessors coerce the actual
@attribute items into an appropriate class that the column represents when
returning.
Outside the DB2 patch, I would just like to know if my more widespread concern
is an actual concern or not.