Re: pg17 issues with not-null contraints

From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Justin Pryzby <pryzby(at)telsasoft(dot)com>
Cc: Kyotaro Horiguchi <horikyota(dot)ntt(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: pg17 issues with not-null contraints
Date: 2024-04-15 16:30:29
Message-ID: 202404151630.mplmr4mr4coq@alvherre.pgsql
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 2024-Apr-15, Alvaro Herrera wrote:

> On 2024-Apr-15, Justin Pryzby wrote:

> > postgres=# CREATE TABLE iparent(id serial PRIMARY KEY); CREATE TABLE child (id int) INHERITS (iparent); ALTER TABLE child ALTER id DROP NOT NULL; ALTER TABLE child ADD CONSTRAINT p PRIMARY KEY (id);
> >
> > $ pg_dump -h /tmp -p 5678 postgres -Fc |pg_restore -1 -h /tmp -p 5679 -d postgres
> > ERROR: cannot change NO INHERIT status of inherited NOT NULL constraint "pgdump_throwaway_notnull_0" on relation "child"
> > STATEMENT: ALTER TABLE ONLY public.iparent
> > ADD CONSTRAINT iparent_pkey PRIMARY KEY (id);

> Hmm, apparently if the table is "iparent", the primary key is created in
> the child first; if the table is "parent", then the PK is created first
> there. I think the problem is that the ADD CONSTRAINT for the PK should
> not be recursing at all in this case ... seeing in particular that the
> command specifies ONLY. Should be a simple fix, looking now.

So the problem is that the ADD CONSTRAINT PRIMARY KEY in the parent
table wants to recurse to the child, so that a NOT NULL constraint is
created on each column. If the child is created first, there's already
a NOT NULL NO INHERIT constraint in it which was created for its own
primary key, so the internal recursion in the parent's ADD PK fails.

A fix doesn't look all that simple:

- As I said in my earlier reply, my first thought was to have ALTER
TABLE ADD PRIMARY KEY not recurse if the command is ALTER TABLE ONLY.
This doesn't work, because the point of that recursion is precisely to
handle this case, so if we do that, we break the other stuff that this
was added to solve.

- Second thought was to add a bespoke dependency in pg_dump.c so that
the child PK is dumped after the parent PK. I looked at the code,
didn't like the idea of adding such a hack, went looking for other
ideas.

- Third thought was to hack AdjustNotNullInheritance1() so that it
changes the conisnoinherit flag in this particular case. Works great,
except that once we mark this constraint as inherited, we cannot drop
it; and since it's a constraint marked "throwaway", pg_dump expects to
be able to drop it, which means the ALTER TABLE DROP CONSTRAINT throws
an error, and a constraint named pgdump_throwaway_notnull_0 remains in
place.

- Fourth thought: we do as in the third thought, except we also allow
DROP CONSTRAINT a constraint that's marked "local, inherited" to be
simply an inherited constraint (remove its "local" marker).

I'm going to try to implement this fourth idea, which seems promising.
I think if we do that, the end result will be identical to the case
where the child is created after the parent.

However, we'll also need that constraint to have a name better than
pgdump_throwaway_notnull_NN.

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Pavel Borisov 2024-04-15 16:37:39 Re: Table AM Interface Enhancements
Previous Message Nathan Bossart 2024-04-15 16:28:33 Re: allow changing autovacuum_max_workers without restarting