Re: Unexpected behavior with inherited constraints

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: William Yager <wyager(at)janestreet(dot)com>
Cc: pgsql-novice(at)lists(dot)postgresql(dot)org
Subject: Re: Unexpected behavior with inherited constraints
Date: 2017-12-23 16:31:13
Message-ID: 23832.1514046673@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-novice

William Yager <wyager(at)janestreet(dot)com> writes:
> I was recently debugging some database infrastructure and I ran across an
> issue with postgres "merging" inherited constraints with pre-existing
> constraints. Please see the following minimal example (run on postgres 9.5):

AFAICS this is all expected behavior. The concept you're missing is that
a single constraint can have multiple origins, either "local" to a table
or inherited from parent table(s). It doesn't go away as long as any of
those origins is in effect.

> create table my_table (my_col int);
> create table my_table_child () inherits (my_table);
> -- Experiment with constraint on child table.
> alter table my_table_child add constraint my_col_constraint check (my_col
> >= 0);

At this point you have

select conrelid::regclass, conislocal, coninhcount from pg_constraint where conname = 'my_col_constraint';
conrelid | conislocal | coninhcount
----------------+------------+-------------
my_table_child | t | 0
(1 row)

> -- Some time later, add it to the parent table.
> alter table my_table add constraint my_col_constraint check (my_col >= 0);
> -- Postgres gives a warning, not an error, and says it will merge the
> constraints.

You get

NOTICE: merging constraint "my_col_constraint" with inherited definition

and now the situation is

select conrelid::regclass, conislocal, coninhcount from pg_constraint where conname = 'my_col_constraint';
conrelid | conislocal | coninhcount
----------------+------------+-------------
my_table | t | 0
my_table_child | t | 1
(2 rows)

> -- Now we want to update the constraint.
> alter table my_table drop constraint my_col_constraint;

This leaves us back at

select conrelid::regclass, conislocal, coninhcount from pg_constraint where conname = 'my_col_constraint';
conrelid | conislocal | coninhcount
----------------+------------+-------------
my_table_child | t | 0
(1 row)

You'd need to drop the child's constraint too, ie reverse both of your
ADD CONSTRAINT actions not just one of them, before the constraint would
disappear from the child.

regards, tom lane

In response to

Browse pgsql-novice by date

  From Date Subject
Next Message john snow 2017-12-27 11:14:04 postgresql 10's numeric data type maps to xxx in c# golang rust drivers??
Previous Message William Yager 2017-12-22 19:44:54 Unexpected behavior with inherited constraints