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

Attachment: v1-0001-Fix-failing-assert-in-deferred-constraint-trigger.patch
Description: Binary data

Reply via email to