migrateでのintegerの扱い
2009年はエコの年なので(いま決めました)、もったいないを重点的に追求していきます。まず手始めに、DB(MySQL)で安直に int(11)を使っているケースを弾劾します。
Rails2.1.0の場合
class CreateTests < ActiveRecord::Migration def self.up create_table "tests", :force => true do |t| t.integer :int0, :limit => 0 t.integer :int3, :limit => 3 t.integer :int4, :limit => 4 t.integer :int8, :limit => 8 t.integer :int9, :limit => 9 t.integer :int20, :limit => 20 t.integer :int21, :limit => 21 end end
これを『rake:migrete:up VERSION=14桁の日付』で実施すると Testsテーブルにはこんなフィールドが作られます。
int0 smallint(6)
int3 smallint(3)
int4 int(4)
int8 int(8)
int9 bigint(9)
int20 bigint(20)
int21 int(11)
case limit when 0..3 "smallint(#{limit})" when 4..8 "int(#{limit})" when 9..20 "bigint(#{limit})" else 'int(11)' endactiverecord-2.1.0/lib/active_record/connection_adapters/mysql_adapter.rb
limitが 0〜3は smallint、4〜8は int、9〜20は bigint、それ以外(21以上)は int(11)にしています。limit=0の場合の smallint(0)は MySQLでは通らないようですね。smallint(6)になっていますね。
Rails2.2.2の場合
class CreateTests < ActiveRecord::Migration def self.up create_table "tests", :force => true do |t| t.integer :int0, :limit => 0 t.integer :int1, :limit => 1 t.integer :int2, :limit => 2 t.integer :int3, :limit => 3 t.integer :int4, :limit => 4 t.integer :int5, :limit => 5 t.integer :int8, :limit => 8 t.integer :int9, :limit => 9 t.integer :int11, :limit => 11 t.integer :int20, :limit => 20 t.integer :int21, :limit => 21 end end
これを『rake:migrete:up VERSION=14桁の日付』で実施すると Testsテーブルにはこんなフィールドが作られます。
int0 int(11) int1 tinyint(4) int2 smallint(6) int3 mediumint(9) int4 int(11) int5 bigint(20) int8 bigint(20) int9 int(11) int11 int(11) int20 int(11) int21 int(11)
case limit when 1; 'tinyint' when 2; 'smallint' when 3; 'mediumint' when nil, 4, 11; 'int(11)' # compatibility with MySQL default when 5..8; 'bigint' else raise(ActiveRecordError, "No integer type has byte size #{limit}") endactiverecord-2.2.2/lib/active_record/connection_adapters/mysql_adapter.rb
limitが 1は tinyint、2は smallint、3は mediumint、4と11とnil(指定なし)は int(11)、5〜8は bigint、それ以外はエラーにしているはずですが、上の実行結果を見るとエラーのケースは raiseしないでデフォルト値=int(11)をセットするみたいです。(raiseで上がった先までソースを読んでいないのでいい加減です)
まとめ
こんなところが 2.1.0と 2.2.2で大きく変わっているとは思いませんでした。Rails2.2.2で節約するつもりで limit=5とか指定して、実は bigint(20)でとられていたという罠にはまらないよう要注意です。
参考
- http://brass.to/blog/rails_migration_rake_task.html
migrateの使い方を忘れたときに参考にさせていただいています。 - http://tam.qmix.org/wiki/Migration.html
:force => trueってなんだっけの答え