On Mon, 07 Sep 2026, Chao Li <[email protected]> wrote:
> My understanding is that PG doesn’t intend to support cyclic inheritance. The 
> code explicitly rejects it:

To me it seems like that it discourages it and tries to prevent it
where it's possible to do so with reasonable effort, but it ends up
trying to support it because it's a valid scenario that can happen in
some workloads (as long as that also doesn't require too much effort).

> A cycle can cause it to exceed the stack depth limit, so it is reasonable to 
> fail the command when a cycle is detected.

Or it might succeed in other cases.

Here's a repro with an isolation test. Perm 1 fails on master, works
with the patch. Perm 2 works on master, fails with the patch.
We could improve this by only using the new function in the enforced
direction, I don't have a better idea currently. With that, the
patched behavior would be the same as on master.

setup
{
  CREATE TABLE r (x int CONSTRAINT cc CHECK (x > 0));
  CREATE TABLE a (x int CONSTRAINT cc CHECK (x > 0));
  CREATE TABLE b (x int CONSTRAINT cc CHECK (x > 0));
  CREATE TABLE c (x int CONSTRAINT cc CHECK (x > 0));
  CREATE TABLE d (x int CONSTRAINT cc CHECK (x > 0));
  ALTER TABLE a INHERIT r;
  ALTER TABLE b INHERIT a;
  ALTER TABLE d INHERIT c;
}

teardown
{
  DROP TABLE IF EXISTS r, a, b, c, d CASCADE;
}

session s1
step s1b  { BEGIN; }
step s1i  { ALTER TABLE c INHERIT b; }
step s1c  { COMMIT; }

session s2
step s2b  { BEGIN; }
step s2i  { ALTER TABLE a INHERIT d; }
step s2c  { COMMIT; }

session s3
step s3pre { ALTER TABLE r ALTER CONSTRAINT cc NOT ENFORCED;
             ALTER TABLE c ALTER CONSTRAINT cc NOT ENFORCED; }
step s3e   { SELECT inhrelid::regclass::text AS child,
                    inhparent::regclass::text AS parent
             FROM pg_inherits
             WHERE inhrelid::regclass::text IN ('r','a','b','c','d')
             ORDER BY 1, 2; }
step s3not { ALTER TABLE r ALTER CONSTRAINT cc NOT ENFORCED; }
step s3enf { ALTER TABLE r ALTER CONSTRAINT cc ENFORCED; }
step s3s   { SELECT conrelid::regclass::text AS rel, conenforced
             FROM pg_constraint
             WHERE conname = 'cc'
               AND conrelid::regclass::text IN ('r','a','b','c','d')
             ORDER BY 1; }

permutation s1b s2b s1i s2i s1c s2c s3e s3not s3s
permutation s1b s2b s3pre s1i s2i s1c s2c s3e s3enf s3s


Reply via email to