Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

:integer size being set inconsistently by mysql_adapter.rb

#463

The best way to describe the bug that we've run in to is to walk through the steps which lead to its discovery.

When a database (acme_development) schema is loaded from migrations, a typical table definition:

create_table :foo do |t|
  t.references :bar
end

causes a column, bar_id, to be created with a MySQL data type of int(11). Also, :primary_keys are hard-coded to be of type int(11).

Starting (I believe) with Rails 2.1, when invoking a rake task that would (re)generate schema.rb the code examines the MySQL columns (in acme_development) to determine the :limit. If no default :limit was provided in the original migration, this will result in schema.rb being populated with the current acme_development size - 11, for all :integer columns.

When acme_test is populated via schema.rb, the table definition becomes:

create_table :foo do |t|
  t.integer :bar, :limit => 11
end

Specifying :limit => 11 to the column (the same limit as the default size hard-coded in mysql_adapter.rb) causes a different data type to be used: bigint(11). This is the root of the problem - specifying a :limit whose size is identical to Rails' default for :integer causes a different data type to be created when the database is loaded.

We only stumbled across this when foreign keys were being inserted into our test database - MySQL can't create foreign keys across columns with different data types (int != bigint), so it fails.

We'll be working on a patch, will update in a few days if we can't come up with an acceptable, generic solution.

Reported by Rob Sterner · June 20th, 2008 @ 10:23 PM

State: resolved
Milestone: 2.1.1
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: none

Activity

  1. Rob Sterner
    Rob Sterner
    • No changes were found…

    June 20th, 2008 @ 10:23 PM

  2. Rob Sterner
    Rob Sterner

    The best way to describe the bug that we've run in to is to walk through the steps which lead to its discovery.

    When a database (acme_development) schema is loaded from migrations, a typical table definition:

    create_table :foo do |t|
      t.references :bar
    end
    

    causes a column, bar_id, to be created with a MySQL data type of int(11). Also, :primary_keys are hard-coded to be of type int(11).

    Starting (I believe) with Rails 2.1, when invoking a rake task that would (re)generate schema.rb the code examines the MySQL columns (in acme_development) to determine the :limit. If no default :limit was provided in the original migration, this will result in schema.rb being populated with the current acme_development size - 11, for all :integer columns.

    When acme_test is populated via schema.rb, the table definition becomes:

    create_table :foo do |t|
      t.integer :bar, :limit => 11
    end
    

    Specifying :limit => 11 to the column (the same limit as the default size hard-coded in mysql_adapter.rb) causes a different data type to be used: bigint(11). This is the root of the problem - specifying a :limit whose size is identical to Rails' default for :integer causes a different data type to be created when the database is loaded.

    We only stumbled across this when foreign keys were being inserted into our test database - MySQL can't create foreign keys across columns with different data types (int != bigint), so it fails.

    We'll be working on a patch, will update in a few days if we can't come up with an acceptable, generic solution.

    June 20th, 2008 @ 10:23 PM

  3. John Trupiano
    John Trupiano

    Rob, any progress here? I was just about to start a patch....but if you're close to done or already done, I'd just wait it out.

    I think it should be fairly trivial. I'm looking into it as I type....I'm sitting in #rails-contrib (jtrupiano), so get in touch with me if you're in the middle of this.

    June 24th, 2008 @ 05:29 PM

  4. Jeremy Kemper
    Jeremy Kemper
    • Milestone set to 2.1.1
    • Assigned user set to Jeremy Kemper
    • State changed from new to open

    mysql integer limit should be ignored since it's really display width. Limit should be set as byte length according to tinyint/smallint/mediumint/int/bigint.

    Please do submit a patch + tests!

    June 24th, 2008 @ 09:29 PM

  5. Rob Sterner
    Rob Sterner

    Hey Jeremy,

    Just looked for you on IRC to talk about this. I was preparing my patch (patched against 2.1.0) when I ran it against edge (master) Rails, seems like your commits over the last 24 hours have fixed the issue.

    Now the only outstanding thing that I think the source/docs would benefit from is documentation explaining that the fundamental concept of what a :limit is has changed w/r/t Rails :-D

    June 24th, 2008 @ 09:36 PM

  6. Jeremy Kemper
    Jeremy Kemper
    • State changed from open to resolved

    Yeah, should document that. There was no real concept before, just dumped it on the database's lap which led to odd results.

    June 24th, 2008 @ 09:51 PM

  7. John Trupiano
    John Trupiano

    Hey Rob, Jeremy, other interested parties, I blogged about this whole saga here: http://blog.smartlogicsolutions....

    Jeremy, it does include a two-line patch for the 2.1 release. Not sure if that's useful at all...

    Thanks for working on this with me Rob.

    June 24th, 2008 @ 10:05 PM

  8. Rob Sterner
    Rob Sterner

    I figured that docs were TBD as this is a subtle but important change. Thanks Jeremy! Thanks again John, was fun trying to figure this out!

    June 24th, 2008 @ 10:17 PM