24

My version of rails is 4.0.0, my version of mysql is Ver 14.14 Distrib 5.7.9, for Win64 (x86_64). I am operating of an older version of rails as I was getting some clashes with the mysql as per my previous question Here. (check Kalelc's approved answer for my recourse)

upon running

rake db:migrate 

I get the following error

==  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, `first_name` varchar(25), `last_name` varchar(50), `email` varchar(255) DEFAULT '' NOT NULL, `password` varchar(40), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDBC:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
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, `first_name` varchar(25), `last_name` varchar(50), `email` varchar(255) DEFAULT '' NOT NULL, `password` varchar(40), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

I do not set any values to NULL in my code, here is the code

Class CreateUsers < ActiveRecord::Migration

  def up
    create_table :users do |t| 
      t.column "first_name", :string, :limit => 25 
      t.string "last_name", :limit => 50
      t.string "email", :default => "", :null => false 
      t.string "password", :limit => 40
      t.timestamps
    end
  end

  def down
    drop_table :users
  end
end

This code is exactly as shown in the tutorials I am following. I have also investigated other similar issues here on stack overflow and have followed the advice given. I have tried the monkey patch as suggested

# lib/patches/abastract_mysql_adapter.rb
class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

I inserted this file into a folder I have created called patches inside the lib of my simple_cms application. I have saved down the file as "abstract_mysql_adapter.rb" as suggested in the same monkey patch. I have updated my environment.rb of the simple_cms application with the following

require File.expand_path('../../lib/patches/abstract_mysql_adapter.rb', __FILE__)

if I then run a rake db:migrate command

rake aborted!
LoadError: cannot load such file -- C:/Users/Lizanne/Documents/Code/Sites/simple_cms/lib/patches/abstract_mysql_adapter.rb
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/config/environment.rb:3:in `<top (required)>'
Tasks: TOP => db:migrate => environment
(See full trace by running task with --trace)

C:/Users/Lizanne/Documents/Code/Sites/simple_cms/lib/patches/abstract_mysql_adapter.rb is most definitely the path to the monkey patch. Have I put the patch in the wrong place? What am I doing wrong here, scratching my head over this one? Apologies if this is obvious to some but I'm returning to coding after a very long abstinence and I cant get my head around the issue. Many thanks in advance for you help :)

Community
  • 1
  • 1
Aerosewall1
  • 351
  • 1
  • 2
  • 8
  • Try editing your monkey-patch to `"int(11) auto_increment PRIMARY KEY NOT NULL"` – Undo Nov 16 '15 at 19:24
  • Hey Undo thanks for quick response, just tried that and I still get the same Load error – Aerosewall1 Nov 16 '15 at 19:27
  • does this monkey patch need to be saved down into the lib of the application or the lib of rails – Aerosewall1 Nov 16 '15 at 19:38
  • you might have luck moving the file: `lib/patches/abastract_mysql_adapter.rb` to `config/initializers/abastract_mysql_adapter.rb` - but if you are just learning rails why not use sqlite (I also favor postgres over mysql, especially if you end up hosting your apps on heroku) – house9 Nov 16 '15 at 19:55
  • Thanks house9, I just tried you suggestion and I am getting exactly the same message, but this time stating it cant load the file in the initilizer even though i changed the path in environment.rb. Really stuck here. I answer to your question I am using mysql as this is the recommended version for the Lynda tutorials I am following. so in order to be able to follow the teacher exactly I thought it best practise to use exactly the same set up as he suggests – Aerosewall1 Nov 16 '15 at 20:30
  • `rake aborted! LoadError: cannot load such file -- C:/Users/Lizanne/Documents/Code/Sites/simple_cms/config/initializers/abstract_mysql_adapter.rb C:/Users/Lizanne/Documents/Code/Sites/simple_cms/config/environment.rb:3:in ``' Tasks: TOP => db:migrate => environment (See full trace by running task with --trace) ` – Aerosewall1 Nov 16 '15 at 20:35
  • just tried a `bundle exec rake db:migrate` and that didn't work either, same error – Aerosewall1 Nov 16 '15 at 20:47
  • Putting your monkey patch in initializers worked for me. Rails 3.2, MySQL 5.7.10. – Kris Jan 14 '16 at 15:00
  • I know this is an old topic, but the issue is indeed a typo. You are trying to load `abstract...` but the file was named `abAstract...` – Gabriel F. Engel Jan 22 '16 at 13:56
  • oh rly thanks you will investigate :D – Aerosewall1 Nov 22 '17 at 17:07

5 Answers5

75

I too recently faced same issue.

MySQL 5.7 no longer supports null default values for the primary key.

By overriding the Native default for primary keys in MySql you can resolve your issue.

In config/initializers/abstract_mysql_adapter.rb:

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

For mysql2 it should be config/initializers/abstract_mysql2_adapter.rb:

class ActiveRecord::ConnectionAdapters::Mysql2Adapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
paljoshi
  • 751
  • 4
  • 3
  • Thank you this makes sense, a) I didn't spot the type on address, good effort for spotting that, and I'm also using mysql2 so I guess lib/patches/abastract_mysql_adapter.rb call would not work. didn't even think of that. thanks so much :) – Aerosewall1 Jan 23 '16 at 16:14
  • 7
    This is the right answer. Don't see how it's low quality. – Subimage Mar 14 '16 at 20:34
  • One could just monkeypatch `class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter ` as described, independent of actual adapter. – niels Oct 12 '16 at 11:12
  • I'm also facing the same issue when trying to db migrate. please let me know the file path of the config/initializers/abstract_mysql2_adapter.rb – George Varghese Dec 04 '16 at 04:00
  • Works for Rails 3.2. – Joshua Pinter May 01 '17 at 16:22
  • Had same issue, this resolved. Arguably this is where we're trying to use older 4.0.2 rails on newer MySQL. – Jetblackstar May 14 '20 at 15:24
  • NOTE, this no longer works on Rails 5.1. The good news is Rails 5.1 made the default column type for primary keys be `bigint`, but the bad news is that it is `signed` instead of `unsigned`. And it's not as easy to override the default like you're doing here. If you want `unsigned bigint` to be the default, check out this Github issue and show your support: https://github.com/rails/rails/issues/40967 – Joshua Pinter Dec 29 '20 at 21:53
13

Did not have luck with the solutions above (My env: Rails 3.0.20, MySQL 5.7.13, Ruby 1.9.3p551). Was able to get around it by overwriting the ActiveRecord::ConnectionAdapters::ColumnDefinition class. See below:

class ActiveRecord::ConnectionAdapters::ColumnDefinition
  def sql_type
    type.to_sym == :primary_key ? 'int(11) auto_increment PRIMARY KEY' : base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
  end 
end

Stored this in config/initializers/column_definition.rb

Andy Day
  • 925
  • 9
  • 7
  • 1
    This solution worked for me. The other solutions were working fine for me on `schema:load` but if I ran `rails generate migration` I was presented with an uninitialized constant error for the NATIVE_DATABASE_TYPES. Your solution worked without issue. Thank you. – brightball Jun 15 '17 at 14:08
  • Thanks a lot for this. – Astik Anand Jun 20 '18 at 06:49
  • Getting `TypeError: superclass mismatch for class ColumnDefinition` on rake tests. Am I missing something dumb? – B. Shea Nov 14 '18 at 21:35
4

I had this problem too (mysql 5.7.17 and Rails 4.0.0). I fixed it by adding a file config/initializers/mysql2_adapter.rb

require 'active_record/connection_adapters/mysql2_adapter'
class ActiveRecord::ConnectionAdapters::Mysql2Adapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

and then, in my environment.rb file:

require File.expand_path('../initializers/mysql2_adapter', __FILE__)
mattes
  • 8,936
  • 5
  • 48
  • 73
TsaiKoga
  • 12,914
  • 2
  • 19
  • 28
  • NOTE, this no longer works on Rails 5.1. The good news is Rails 5.1 made the default column type for primary keys be `bigint`, but the bad news is that it is `signed` instead of `unsigned`. And it's not as easy to override the default like you're doing here. If you want `unsigned bigint` to be the default, check out this Github issue and show your support: https://github.com/rails/rails/issues/40967 – Joshua Pinter Dec 29 '20 at 21:52
2

Since MySQL 5.7.3 a primary key declared as NULL produces an error:

Columns in a PRIMARY KEY must be NOT NULL, but if declared explicitly as NULL produced no error. Now an error occurs. For example, a statement such as CREATE TABLE t (i INT NULL PRIMARY KEY) is rejected. The same occurs for similar ALTER TABLE statements. (Bug #13995622, Bug #66987, Bug #15967545, Bug #16545198)

But the create_table in your Rails version still wants a DEFAULT or NULL for the PRIMARY KEY. I have solved the issue by updating to a newer rails version.

disco crazy
  • 31,313
  • 12
  • 80
  • 83
  • Thanks very much high 6. :) I actually reverted to an older copy of rails due to some clashes with railties, rails and mysql. I will see if I can find a version where I dont get this clash as described here [http://stackoverflow.com/questions/31766656/nameerror-on-executing-rails-s] – Aerosewall1 Nov 25 '15 at 11:50
  • 1
    May I ask what version of rails are you using? So that i can update to that version . thanks – Aerosewall1 Dec 03 '15 at 23:31
0

I solved this problem with a Rails app on JRuby I'm working on by upgrading the mysql-adapter.

I was using the gem activerecord-jdbcmysql-adapter v1.3.14 and upgraded to v1.3.21

Check your jdbc adapter version before monkey patching a solution.

Nathan Davis
  • 5,636
  • 27
  • 39
Mateus Q.
  • 1
  • 2