spencer.christensen

spencer.christensen

Ecto Migration: `not_null_violation` when modifying column null->non-null & adding default value

Howdy y’all,

I’m brand new to Elixir and have what is likely a simple problem. I created an Ecto schema with a votes column that is type :integer and nullable. I later realized it should be non-nullable and default to 0. I made a migration to perform this update, however I am getting the error:

** (Postgrex.Error) ERROR 23502 (not_null_violation) column "votes" of relation "faqs" contains null values

Migration

defmodule Pento.Repo.Migrations.AlterFaqsAddDefaultVoteValue do
  use Ecto.Migration

  def change do
    alter table(:faqs) do
      modify :votes, :integer, default: 0, null: false
    end
  end
end

See below for my existing table and full error output. I found a comment from Jose Valim stating “The default value in migration is used to set the value for existing rows.” in 2015. I read that as stating that the default value in a migration should change any existing null fields to the stipulated value. Is that not the case and should I just use a separate execute for altering existing rows?

Existing Table

id question answer votes inserted_at updated_at
1 Question 1 Answer 1 NULL 2024-02-04 02:54:39 2024-02-04 12:51:01
2 Question 2 Answer 2 NULL 2024-02-04 02:56:24 2024-02-04 02:56:24
CREATE TABLE "public"."faqs" (
    "id" int8 NOT NULL DEFAULT nextval('faqs_id_seq'::regclass),
    "question" varchar(255),
    "answer" varchar(255),
    "votes" int4,
    "inserted_at" timestamp(0) NOT NULL,
    "updated_at" timestamp(0) NOT NULL,
    PRIMARY KEY ("id")
);

Output

07:05:36.729 [info] == Running 20240204125254 Pento.Repo.Migrations.AlterFaqsAddDefaultVoteValue.change/0 forward

07:05:36.730 [info] alter table faqs
** (Postgrex.Error) ERROR 23502 (not_null_violation) column "votes" of relation "faqs" contains null values

    table: faqs
    column: votes
    (ecto_sql 3.11.1) lib/ecto/adapters/sql.ex:1054: Ecto.Adapters.SQL.raise_sql_call_error/1
    (elixir 1.16.0) lib/enum.ex:1700: Enum."-map/2-lists^map/1-1-"/2
    (ecto_sql 3.11.1) lib/ecto/adapters/sql.ex:1161: Ecto.Adapters.SQL.execute_ddl/4
    (ecto_sql 3.11.1) lib/ecto/migration/runner.ex:348: Ecto.Migration.Runner.log_and_execute_ddl/3
    (elixir 1.16.0) lib/enum.ex:1700: Enum."-map/2-lists^map/1-1-"/2
    (ecto_sql 3.11.1) lib/ecto/migration/runner.ex:311: Ecto.Migration.Runner.perform_operation/3
    (stdlib 5.2) timer.erl:270: :timer.tc/2
    (ecto_sql 3.11.1) lib/ecto/migration/runner.ex:25: Ecto.Migration.Runner.run/8

Thank you for any help!

Most Liked

dimitarvp

dimitarvp

Either make one migration that only introduces the default (without the non-null constraint) or just make a data migration that fills up all null column values with the default value.

I am not sure the former would work at all so I’d go for the latter i.e. something like this:

defmodule YourApp.Repo.Migrations.SetDefaultValueToFaqs do
  use Ecto.migration

  def up do
    execute("UPDATE faqs SET votes = 0 WHERE votes IS NULL")
  end

  def down do
    # Do the reverse here if it makes sense.
  end
end

After this one above, make the one that introduces the non-null constraint.

al2o3cr

al2o3cr

You may need to split this into two migrations, since the alter implementation will always change the NOT NULL constraint before the DEFAULT:

I’d guess this was more relevant in older PGs when setting a default on a nullable column was an expensive “rewrite every row that has a NULL” operation.

dimitarvp

dimitarvp

Will you not lose information this way? What about rows that have, say, faqs = 10?

Where Next?

Popular in Questions Top

nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement