概要
rails4.0でMySQL5.7.3以上と繋いで、db:create
した場合、
Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL;
のエラーが出るため、その解決策を提示する。
実行環境
バージョン | Extra | |
---|---|---|
CentOS | 6.9 | VirtualBox経由でssh接続 |
Rails | 4.0.13 | dot installのRailsの教材がRails4.0を使っていたためv4.0の最新版にした |
MySQL | 5.7.18 | |
Ruby | 2.3.1 | こちらも教材に合わせた。rbenvで管理。 |
Bundler | 1.14.6 | |
mysql2 | 0.4.6 | バージョン指定せず、最新版。 |
エラー詳細
上記の環境で、
$ rails generate scaffold User nickname:string age:integer
として、
$ rake db:migrate
すると、
== 20170514132649 CreateUsers: migrating ======================================
-- create_table(:users)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead: CREATE TABLE `users` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `nickname` varchar(255), `age` int(11), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
/home/vagrant/myapp/db/migrate/20170514132649_create_users.rb:3:in `change'
ActiveRecord::StatementInvalid: Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead: CREATE TABLE `users` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `nickname` varchar(255), `age` int(11), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
と弾かれる。
#原因
ActiveRecord周りのバグ。
/usr/local/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
を見ると、
139 NATIVE_DATABASE_TYPES = {
140 :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY”,
と、primary keyのデフォルトがNULLになっている。
上記の公式サイトによると、
古いバージョンのMySQL(5.7.2以下?)はこのように明示的にNULLを指定すれば、エラー無く通ったが、MySQL5.7.3以上はNULLの指定をエラーで弾く、とのこと。
[MySQL 5.7.3 m13 does not allow DEFAULT NULL
for primary key #13203]
(https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb)
rails4.0のgithubのissueに立てられていて、既にcloseされていた。
rails4.1はこの問題が修正されているとのこと。
(下の対策にあるように'DEFAULT NULL’を削除したと思う)
#解決策
下記のいずれかをすればよい。
- 上記の
abstract_mysql_adapter.rb
内のDEFAULT NULL
という文字列を削除する - MySQLのバージョンを5.7.2以下にダウングレードする
- Railsのバージョンを4.1以上にする
筆者は1.を実行し、
$ rake db:migrate
== 20170514132649 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0224s
== 20170514132649 CreateUsers: migrated (0.0224s) =============================
と、正しくDBが作成された。
#参考にした記事
mysql 5.7でdb:createするとエラー -Qiita