Fix failing assert in deferred constraint trigger

Started by Fabrizio Mello14 days ago11 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253716
psql -h localhost -U postgres

Built from patchset v9 (message #9), September 16, 2026 at 04:05 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253716_9 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253716_9 && git checkout t253716_9

Patchset v9 (message #9) is on t253716_9

Jump to latest
#1Fabrizio Mello
fabrizio@planetscale.com

Hi all,

This SQL crashes assert-enabled builds:

CREATE TABLE t(a int);
CREATE FUNCTION f() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
BEGIN
PERFORM 1 / 0;
EXCEPTION WHEN division_by_zero THEN
NULL;
END;
RETURN NEW;
END
$$;
CREATE CONSTRAINT TRIGGER trg
AFTER INSERT ON t
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW EXECUTE FUNCTION f();
BEGIN;
INSERT INTO t VALUES (1);
COMMIT; -- backend aborts here on assert builds

The failure in the logs is:

TRAP: failed Assert("s->blockState == TBLOCK_SUBINPROGRESS || s->blockState
== TBLOCK_INPROGRESS || s->blockState == TBLOCK_IMPLICIT_INPROGRESS ||
s->blockState == TBLOCK_PARALLEL_INPROGRESS || s->blockState ==
TBLOCK_STARTED"), File: "xact.c", Line: 4851, PID: 73455
0 postgres 0x0000000104e6b330 ExceptionalCondition + 108
1 postgres 0x0000000104a33620 AbortSubTransaction + 0
2 plpgsql.dylib 0x00000001056b14b8 exec_stmt_block + 640
3 plpgsql.dylib 0x00000001056b1d00 exec_stmts + 188

`PREPARE TRANSACTION 'tx'` in place of the final `COMMIT` crashes in the
same way.

fa0e318 updated BeginInternalSubTransaction to allow creating a
subtransaction with a parent of TBLOCK_END and TBLOCK_PREPARE but didn't
add those states to the assert in RollbackAndReleaseCurrentSubTransaction.

The `division_by_zero` exception in the example forces a subtransaction to
abort in the context of the final `COMMIT`, so
RollbackAndReleaseCurrentSubTransaction needs to allow TBLOCK_PREPARE and
TBLOCK_END.

Check the attached patch for the fix.

Regards,

--
Fabrízio Mello
PlanetScale Postgres Core Team

Attachments:

t253716_1
v1-0001-Fix-failing-assert-in-deferred-constraint-trigger.patchapplication/octet-stream; name=v1-0001-Fix-failing-assert-in-deferred-constraint-trigger.patchDownload+2-1
#2Fujii Masao
masao.fujii@gmail.com
In reply to: Fabrizio Mello (#1)
Re: Fix failing assert in deferred constraint trigger

On Wed, Sep 9, 2026 at 4:04 AM Fabrizio Mello <fabrizio@planetscale.com> wrote:

Check the attached patch for the fix.

Thanks for the patch! It looks good to me.

One comment: isn't it be better to add a test for exception handling
in a deferred constraint trigger at COMMIT? For example, in triggers.sql:

----------------------------------------------------
@@ -1590,6 +1590,31 @@ create constraint trigger crtr
   after insert on foo not enforced
   for each row execute procedure foo ();
+-- Test exception handling in a deferred constraint trigger at COMMIT.
+create table deferred_trigger_test (a int);
+create function deferred_trigger_func() returns trigger
+  language plpgsql as $$
+begin
+  perform 1 / 0;
+  return new;
+exception when division_by_zero then
+  raise notice 'caught division_by_zero';
+  return new;
+end;
+$$;
+create constraint trigger deferred_trigger
+  after insert on deferred_trigger_test
+  deferrable initially deferred
+  for each row execute function deferred_trigger_func();
+
+begin;
+insert into deferred_trigger_test values (1);
+commit;
+select * from deferred_trigger_test;
+
+drop table deferred_trigger_test;
+drop function deferred_trigger_func();
+
 --
 -- Constraint triggers and partitioned tables
 create table parted_constr_ancestor (a int, b text)
----------------------------------------------------

BTW, WITH HOLD cursor seems to be able to cause the same issue:

CREATE FUNCTION hoge() RETURNS integer
LANGUAGE plpgsql VOLATILE AS $$
BEGIN
PERFORM 1 / 0;
RETURN 0;
EXCEPTION WHEN division_by_zero THEN
RETURN 1;
END;
$$;

BEGIN;
DECLARE c NO SCROLL CURSOR WITH HOLD FOR SELECT hoge();
COMMIT;

Regards,

--
Fujii Masao

#3Fujii Masao
masao.fujii@gmail.com
In reply to: Fujii Masao (#2)
Re: Fix failing assert in deferred constraint trigger

On Wed, Sep 9, 2026 at 12:51 PM Fujii Masao <masao.fujii@gmail.com> wrote:

One comment: isn't it be better to add a test for exception handling
in a deferred constraint trigger at COMMIT? For example, in triggers.sql:

I've added this test. Attached is the updated version of the patch.

BTW, I found that Patrick Reynolds <patrick@piki.org> is listed in the
From field of the patch. Does that mean he is the author of the patch,
rather than you? I'm just asking because I need to know who to list in the
Author tag of the commit message.

Regards,

--
Fujii Masao

Attachments:

t253716_3
v2-0001-Fix-failing-assert-in-deferred-constraint-trigger.patchapplication/octet-stream; name=v2-0001-Fix-failing-assert-in-deferred-constraint-trigger.patchDownload+55-1
#4Chao Li
li.evan.chao@gmail.com
In reply to: Fujii Masao (#3)
Re: Fix failing assert in deferred constraint trigger

On Sep 11, 2026, at 09:44, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Sep 9, 2026 at 12:51 PM Fujii Masao <masao.fujii@gmail.com> wrote:

One comment: isn't it be better to add a test for exception handling
in a deferred constraint trigger at COMMIT? For example, in triggers.sql:

I've added this test. Attached is the updated version of the patch.

BTW, I found that Patrick Reynolds <patrick@piki.org> is listed in the
From field of the patch. Does that mean he is the author of the patch,
rather than you? I'm just asking because I need to know who to list in the
Author tag of the commit message.

Regards,

--
Fujii Masao
<v2-0001-Fix-failing-assert-in-deferred-constraint-trigger.patch>

V2 LGTM.

One nitpick is that, the fix covers both COMMIT and PREPARE TRANSACTION, but v2 only adds a regression test for the COMMIT case. Should we test both paths?

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#5Fujii Masao
masao.fujii@gmail.com
In reply to: Chao Li (#4)
Re: Fix failing assert in deferred constraint trigger

On Fri, Sep 11, 2026 at 11:33 AM Chao Li <li.evan.chao@gmail.com> wrote:

V2 LGTM.

Thanks for the review!

One nitpick is that, the fix covers both COMMIT and PREPARE TRANSACTION, but v2 only adds a regression test for the COMMIT case. Should we test both paths?

I think the COMMIT test is enough for this small assert-only fix.

But,iIf many others prefer explicit coverage for PREPARE TRANSACTION as well,
I'm fine with adding that test. It would probably require some additional test
logic to handle environments where max_prepared_transactions is disabled
(e.g., add "skip" like prepared_xacts.sql does).

Regards,

--
Fujii Masao

#6Fabrizio Mello
fabrizio@planetscale.com
In reply to: Fujii Masao (#3)
Re: Fix failing assert in deferred constraint trigger

On Thu, Sep 10, 2026 at 10:44 PM Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Sep 9, 2026 at 12:51 PM Fujii Masao <masao.fujii@gmail.com> wrote:

One comment: isn't it be better to add a test for exception handling
in a deferred constraint trigger at COMMIT? For example, in triggers.sql:

I've added this test. Attached is the updated version of the patch.

Thanks

BTW, I found that Patrick Reynolds <patrick@piki.org> is listed in the
From field of the patch. Does that mean he is the author of the patch,
rather than you? I'm just asking because I need to know who to list in the
Author tag of the commit message.

Yes he is the original author of the patch, which he worked on
internally at PlanetScale. If you don't mind, please use
piki@planetscale.com in the commit message.

Regards,

--
Fabrízio Mello
PlanetScale Postgres Core Team

#7Fabrizio Mello
fabrizio@planetscale.com
In reply to: Fujii Masao (#2)
Re: Fix failing assert in deferred constraint trigger

On Wed, Sep 9, 2026 at 12:52 AM Fujii Masao <masao.fujii@gmail.com> wrote:

[...]

BTW, WITH HOLD cursor seems to be able to cause the same issue:

CREATE FUNCTION hoge() RETURNS integer
LANGUAGE plpgsql VOLATILE AS $$
BEGIN
PERFORM 1 / 0;
RETURN 0;
EXCEPTION WHEN division_by_zero THEN
RETURN 1;
END;
$$;

BEGIN;
DECLARE c NO SCROLL CURSOR WITH HOLD FOR SELECT hoge();
COMMIT;

Having a look into it thanks!

--
Fabrízio Mello
PlanetScale Postgres Core Team

#8Fabrizio Mello
fabrizio@planetscale.com
In reply to: Fabrizio Mello (#7)
Re: Fix failing assert in deferred constraint trigger

On Fri, Sep 11, 2026 at 10:48 AM Fabrizio Mello
<fabrizio@planetscale.com> wrote:

On Wed, Sep 9, 2026 at 12:52 AM Fujii Masao <masao.fujii@gmail.com> wrote:

[...]

BTW, WITH HOLD cursor seems to be able to cause the same issue:

CREATE FUNCTION hoge() RETURNS integer
LANGUAGE plpgsql VOLATILE AS $$
BEGIN
PERFORM 1 / 0;
RETURN 0;
EXCEPTION WHEN division_by_zero THEN
RETURN 1;
END;
$$;

BEGIN;
DECLARE c NO SCROLL CURSOR WITH HOLD FOR SELECT hoge();
COMMIT;

Having a look into it thanks!

Confirmed that the patch works fine also with "WITH HOLD" cursor.

Regards,

--
Fabrízio Mello
PlanetScale Postgres Core Team

#9Fujii Masao
masao.fujii@gmail.com
In reply to: Fabrizio Mello (#6)
Re: Fix failing assert in deferred constraint trigger

On Fri, Sep 11, 2026 at 10:43 PM Fabrizio Mello
<fabrizio@planetscale.com> wrote:

Yes he is the original author of the patch, which he worked on
internally at PlanetScale. If you don't mind, please use
piki@planetscale.com in the commit message.

OK, I've updated the commit log message and used that email address for the
Author tag.

I've also listed your name in this email, "Fabrízio Mello", in the commit
log as Reported-by. However, I found that your name, "Fabrízio de Royes
Mello", was used in some previous commits you were involved in. Which name
would you prefer me to use?

Since this issue can occur in all supported versions, I've also created
patches for the back branches. The patches are attached.

Regards,

--
Fujii Masao

Attachments:

t253716_9
nocfbot-v3-0001-PG14_PG15-Fix-assertion-after-aborting-internal-subtransact.patchapplication/octet-stream; name=nocfbot-v3-0001-PG14_PG15-Fix-assertion-after-aborting-internal-subtransact.patchDownload+55-1
nocfbot-v3-0001-PG16-Fix-assertion-after-aborting-internal-subtransact.patchapplication/octet-stream; name=nocfbot-v3-0001-PG16-Fix-assertion-after-aborting-internal-subtransact.patchDownload+55-1
nocfbot-v3-0001-PG17_PG18-Fix-assertion-after-aborting-internal-subtransact.patchapplication/octet-stream; name=nocfbot-v3-0001-PG17_PG18-Fix-assertion-after-aborting-internal-subtransact.patchDownload+55-1
v3-0001-Fix-assertion-after-aborting-internal-subtransact.patchapplication/octet-stream; name=v3-0001-Fix-assertion-after-aborting-internal-subtransact.patchDownload+55-1
#10Fabrizio Mello
fabrizio@planetscale.com
In reply to: Fujii Masao (#9)
Re: Fix failing assert in deferred constraint trigger

On Tue, Sep 15, 2026 at 12:51 PM Fujii Masao <masao.fujii@gmail.com> wrote:

On Fri, Sep 11, 2026 at 10:43 PM Fabrizio Mello
<fabrizio@planetscale.com> wrote:

Yes he is the original author of the patch, which he worked on
internally at PlanetScale. If you don't mind, please use
piki@planetscale.com in the commit message.

OK, I've updated the commit log message and used that email address for the
Author tag.

Thanks!

I've also listed your name in this email, "Fabrízio Mello", in the commit
log as Reported-by. However, I found that your name, "Fabrízio de Royes
Mello", was used in some previous commits you were involved in. Which name
would you prefer me to use?

Fabrízio de Royes Mello

Since this issue can occur in all supported versions, I've also created
patches for the back branches. The patches are attached.

LGTM thanks!

Regards,

--
Fabrízio de Royes Mello
PlanetScale Postgres Core Team

#11Fujii Masao
masao.fujii@gmail.com
In reply to: Fabrizio Mello (#10)
Re: Fix failing assert in deferred constraint trigger

On Thu, Sep 17, 2026 at 5:13 AM Fabrizio Mello <fabrizio@planetscale.com> wrote:

Since this issue can occur in all supported versions, I've also created
patches for the back branches. The patches are attached.

LGTM thanks!

I've pushed the patch. Thanks!

Regards,

--
Fujii Masao