Skip to content

Switch id fields to default to BIGINT#1880

Merged
josevalim merged 4 commits intoelixir-ecto:masterfrom
bradleybeddoes:default-primary-key-to-bigint
Dec 31, 2016
Merged

Switch id fields to default to BIGINT#1880
josevalim merged 4 commits intoelixir-ecto:masterfrom
bradleybeddoes:default-primary-key-to-bigint

Conversation

@bradleybeddoes
Copy link
Copy Markdown
Contributor

@bradleybeddoes bradleybeddoes commented Dec 30, 2016

This is an initial cut at implementing BIGINT as the default for primary/foreign keys within Ecto for consideration (especially given this is my first proposed PR for this project).

There are some outstanding issues which I need to document as a second commit within this PR but I wasn't sure on the best place. They are:

PostgreSQL

PostgreSQL will silently ignore differences between foreign key column types and keep functioning, until it doesn’t (This would be right around the id 2147483647 as best I can tell).

Options:

  1. Update the existing Types to be compatible with Ecto (recommended):

    1. Alter the type of the primary key in existing tables to be bigserial
    2. Alter the type of foreign key in existing tables to be bigint
  2. Alter the type option provided to the references function when creating any new foreign key to be :integer

MySQL

MySQL will not ignore differences between foreign_key column types and instead provides the following error:

ERROR 1005 (HY000): Can't create table database.table_name (errno: 150 "Foreign key constraint is incorrectly formed")

Options:

  1. Update the existing Types to be compatible with Ecto:

    1. Alter the type of the primary key in existing tables to be bigint unsigned not null auto_increment
    2. Alter the type of foreign key in existing tables to be bigint unsigned
  2. Alter the type option provided to the references function when creating any new foreign key to be :integer

This change explicitly aligns PG and MySQL implementations to utilise
bigint fields for primary and foreign keys. Previously this relied on
falling through to the definition of serial supplied by the database
engine which differed:

- MySQL resolved serial to `BIGINT UNSIGNED NOT NULL AUTO_INCREMENT
  UNIQUE`
- PostgreSQL resolved serial to an auto incrementing integer with a
  maximum value of 2147483647

n.b. this commit no longer relies on the MySQL definition of serial
as it marks the field UNIQUE which differs to the behaviour within PG.
With this implementation both adaptors should exhibt the same behaviour.

Fixes elixir-ecto#1879
@elixir-bot
Copy link
Copy Markdown

Hello, @bradleybeddoes! This is your first Pull Request that will be reviewed by Ebert, an automatic Code Review service. It will leave comments on this diff with potential issues and style violations found in the code as you push new commits. You can also see all the issues found on this Pull Request on its review page. Please check our documentation for more information.

@josevalim
Copy link
Copy Markdown
Member

Thank you @bradleybeddoes. I don't think we should rename actual types, such as :serial to mean something else. The best would be to introduce :bigserial and translate it accordingly in the adapters.

Also, I don't think we should translate :serial to "not null autoincrementing" on the MySQL side. We already get those properties when we declare the field as primary key.

@bradleybeddoes
Copy link
Copy Markdown
Contributor Author

Thanks @josevalim, happy to make a change to define bigserial in the adaptors as you've suggested.

To your second point the translation on the MySQL side attempted to keep the existing semantics of serial intact per http://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html which was already being used as BIGINT UNSIGNED NOT NULL AUTO_INCREMENT. I guess we could knock out the NOT NULL but the AUTO_INCREMENT component would need to remain at a minimum as I understand it.

@josevalim
Copy link
Copy Markdown
Member

I guess we could knock out the NOT NULL but the AUTO_INCREMENT component would need to remain at a minimum as I understand it.

I see. Let's keep it NOT NULL AUTO_INCREMENT then except it should be INT and we will use BIGINT for :bigserial.

Instead of overloading the semantics of the existing serial type
we introduce a bigserial type and utilise that by default within new
migrations.

The definition of serial is made explicit here but it keeps the
semantics MySQL already has associated with it, namely it was already
using the BIGINT type.
The initial overload of serial left these undesired type changes in
place. Return to initial, valid, state.
@bradleybeddoes
Copy link
Copy Markdown
Contributor Author

Thanks @josevalim - I've finished up the implementation for bigserial.

Note that serial within the MySQL adaptor still utilises BIGINT as this is what they've defined and what Ecto was already doing, seems like less of a surprise to not change to INT imho.

@josevalim josevalim merged commit 8728a6f into elixir-ecto:master Dec 31, 2016
@josevalim
Copy link
Copy Markdown
Member

❤️ 💚 💙 💛 💜

bartekupartek pushed a commit to bartekupartek/ecto that referenced this pull request Mar 19, 2019
@bradleybeddoes
Copy link
Copy Markdown
Contributor Author

Hi @josevalim - Sorry to drag out a really old PR here but I was just looking through master and oddly I can't find these changes having ever landed, or they got backed out somehow, even though this was merged in.

Perhaps the proposed changes didn't work out for some reason. Is there still interest in having id fields default to BIGINT?

@josevalim
Copy link
Copy Markdown
Member

Unfortunately it was a backwards incompatible change, so we reverted it, which means we can't redo it.

@bradleybeddoes
Copy link
Copy Markdown
Contributor Author

Thanks @josevalim, shame it caused backwards compatibility issues. There are real world examples of this causing issues, rails changed this default some years ago rails/rails#26266.

@chulkilee
Copy link
Copy Markdown
Contributor

@josevalim
Copy link
Copy Markdown
Member

josevalim commented Sep 1, 2019 via email

@bradleybeddoes
Copy link
Copy Markdown
Contributor Author

Thanks @chulkilee and @josevalim!! Great to see this landed in some form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants