active_record_upsert icon indicating copy to clipboard operation
active_record_upsert copied to clipboard

Upsert tries to insert NOT NULL columns as NULL

Open andrewclink opened this issue 5 years ago • 1 comments

When upserting a record in a database column is not nullable and has a default value, ActiveRecord::Upsert attemps to insert a nil value. This raises an exception:

PG::NotNullViolation: ERROR:  null value in column "uuid" violates not-null constraint

The table looks like this:

CREATE TABLE public.defaulting_records (
    id bigint NOT NULL,
    uuid uuid DEFAULT public.gen_random_uuid() NOT NULL,
    name character varying,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

And the SQL generated for the upsert is as follows:

INSERT INTO "defaulting_records" ("uuid", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) ON CONFLICT  ("id")  DO UPDATE  SET "name" = $5, "updated_at" = $6 RETURNING *, (xmax = 0) AS _upsert_created_record

Failing test available in this branch: https://github.com/andrewclink/active_record_upsert/tree/upsert_null

andrewclink avatar Jan 27 '20 23:01 andrewclink

One way to solve this is to continue the class-level and opts: API to allow passing an excluded_keys array. This would be easy to implement in e.g. rails51.rb by removing the excluded keys from upsert_keys

I'd be happy to submit a PR.

andrewclink avatar Jan 27 '20 23:01 andrewclink