Skip to content

Commit

Permalink
Add note about modify/3 and NOT NULL. Resolve #10
Browse files Browse the repository at this point in the history
  • Loading branch information
dbernheisel committed Oct 10, 2023
1 parent a2f2441 commit f7557b4
Showing 1 changed file with 13 additions and 9 deletions.
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ end

These migrations can be in the same deployment, but make sure they are separate migrations.

**Note on empty tables**: when the table creating the referenced column is empty, you may be able to
create the column and validate at the same time since the time difference would be milliseconds
**Note on empty tables**: when the table creating the referenced column is empty, you may be able to
create the column and validate at the same time since the time difference would be milliseconds
which may not be noticeable, no matter if you have 1 million or 100 million records in the referenced table.

**Note on populated tables**: the biggest difference depends on your scale. For 1 million records in
both tables, you may lock writes to both tables when creating the column for milliseconds
(you should benchmark for yourself) which could be acceptable for you. However, once your table has
100+ million records, the difference becomes seconds which is more likely to be felt and cause timeouts.
both tables, you may lock writes to both tables when creating the column for milliseconds
(you should benchmark for yourself) which could be acceptable for you. However, once your table has
100+ million records, the difference becomes seconds which is more likely to be felt and cause timeouts.
The differentiating metric is the time that both tables are locked from writes. Therefore, err on the side
of safety and separate constraint validation from referenced column creation when there is any data in the table.

Expand Down Expand Up @@ -506,15 +506,19 @@ If you're using Postgres 12+, you can add the NOT NULL to the column after valid
> a valid CHECK constraint is found which proves no NULL
> can exist, then the table scan is skipped.
**However** we cannot use [`modify/3`](https://hexdocs.pm/ecto_sql/Ecto.Migration.html#modify/3)
as it will include updating the column type as well unnecessarily, causing
Postgres to rewrite the table. For more information, [see this example](https://github.com/fly-apps/safe-ecto-migrations/issues/10).

```elixir
# **Postgres 12+ only**

def change do
execute "ALTER TABLE products VALIDATE CONSTRAINT active_not_null", ""
execute "ALTER TABLE products VALIDATE CONSTRAINT active_not_null",
""

alter table("products") do
modify :active, :boolean, null: false
end
execute "ALTER TABLE products ALTER COLUMN active SET NOT NULL",
"ALTER TABLE products ALTER COLUMN active DROP NOT NULL"

drop constraint("products", :active_not_null)
end
Expand Down

0 comments on commit f7557b4

Please sign in to comment.