Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #4716 (new defect)

Opened 3 years ago

Last modified 2 years ago

[PATCH] fix DB2 Error in test_validate_format_numeric

Reported by: anonymous Assigned to: David
Priority: high Milestone:
Component: ActiveRecord Version: 0.14.2
Severity: major Keywords:
Cc:

Description

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.

Attachments

test_validate_format_numeric_DB2_patch.diff (0.7 kB) - added by jeremy@hinegardner.org on 04/12/06 23:23:37.

Change History

04/12/06 23:23:37 changed by jeremy@hinegardner.org

  • attachment test_validate_format_numeric_DB2_patch.diff added.

04/12/06 23:24:38 changed by jeremy@hinegardner.org

forgot to put my email in as 'reported by'