From f31e5dceafa458da55297fe2c38913eb2f6dac13 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 2 Mar 2026 10:35:26 +0800 Subject: [PATCH v8 2/2] CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled discussion: https://postgr.es/m/CACJufxHJAr2FjbeB6ghg_-N5dxX5JVnjKSLOUxOyt4TeaAWQkg@mail.gmail.com commitfest: https://commitfest.postgresql.org/patch/6087 --- src/backend/catalog/index.c | 1 + src/backend/commands/tablecmds.c | 4 ++++ src/backend/commands/trigger.c | 1 + src/backend/parser/gram.y | 2 ++ src/backend/tcop/utility.c | 12 ++++++++---- src/include/nodes/parsenodes.h | 1 + src/test/regress/expected/triggers.out | 9 +++++++-- src/test/regress/sql/triggers.sql | 3 +++ 8 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index b0b5a886fa1..d4570626e0b 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2021,6 +2021,7 @@ index_constraint_create(Relation heapRelation, CreateTrigStmt *trigger = makeNode(CreateTrigStmt); trigger->replace = false; + trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; trigger->isconstraint = true; trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ? "PK_ConstraintTrigger" : diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 4a3f46c914d..68455939ad3 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -13836,6 +13836,7 @@ CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, */ fk_trigger = makeNode(CreateTrigStmt); fk_trigger->replace = false; + fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; fk_trigger->isconstraint = true; fk_trigger->trigname = "RI_ConstraintTrigger_c"; fk_trigger->relation = NULL; @@ -13897,6 +13898,7 @@ createForeignKeyActionTriggers(Oid myRelOid, Oid refRelOid, Constraint *fkconstr */ fk_trigger = makeNode(CreateTrigStmt); fk_trigger->replace = false; + fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; fk_trigger->isconstraint = true; fk_trigger->trigname = "RI_ConstraintTrigger_a"; fk_trigger->relation = NULL; @@ -13959,6 +13961,7 @@ createForeignKeyActionTriggers(Oid myRelOid, Oid refRelOid, Constraint *fkconstr */ fk_trigger = makeNode(CreateTrigStmt); fk_trigger->replace = false; + fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; fk_trigger->isconstraint = true; fk_trigger->trigname = "RI_ConstraintTrigger_a"; fk_trigger->relation = NULL; @@ -20908,6 +20911,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) trigStmt = makeNode(CreateTrigStmt); trigStmt->replace = false; + trigStmt->tgenabled = trigForm->tgenabled; trigStmt->isconstraint = OidIsValid(trigForm->tgconstraint); trigStmt->trigname = NameStr(trigForm->tgname); trigStmt->relation = NULL; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 95550022b5b..baca02648d8 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -6947,6 +6947,7 @@ generateClonedTriggerStmt(RangeVar *heapRel, Oid source_trigid, trigStmt = makeNode(CreateTrigStmt); trigStmt->replace = false; + trigStmt->tgenabled = trigForm->tgenabled; trigStmt->isconstraint = OidIsValid(trigForm->tgconstraint); trigStmt->trigname = pstrdup(NameStr(trigForm->tgname)); trigStmt->relation = heapRel; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f96853b1aa1..969a8ed3a79 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6137,6 +6137,7 @@ CreateTrigStmt: CreateTrigStmt *n = makeNode(CreateTrigStmt); n->replace = $2; + n->tgenabled = TRIGGER_FIRES_ON_ORIGIN; n->isconstraint = false; n->trigname = $4; n->relation = $8; @@ -6188,6 +6189,7 @@ CreateTrigStmt: (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"), parser_errposition(@1))); + n->tgenabled = TRIGGER_FIRES_ON_ORIGIN; n->isconstraint = true; n->trigname = $5; n->relation = $9; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index bf707f2d57f..259282e8e22 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1701,10 +1701,14 @@ ProcessUtilitySlow(ParseState *pstate, break; case T_CreateTrigStmt: - address = CreateTrigger((CreateTrigStmt *) parsetree, - queryString, InvalidOid, InvalidOid, - InvalidOid, InvalidOid, InvalidOid, - InvalidOid, NULL, false, false); + { + CreateTrigStmt *stmt = (CreateTrigStmt *) parsetree; + + address = CreateTriggerFiringOn(stmt, queryString, InvalidOid, InvalidOid, + InvalidOid, InvalidOid, InvalidOid, + InvalidOid, NULL, false, + false, stmt->tgenabled); + } break; case T_CreatePLangStmt: diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 135e69a25db..d96fb166ce4 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3139,6 +3139,7 @@ typedef struct CreateTrigStmt { NodeTag type; bool replace; /* replace trigger if already exists */ + char tgenabled; /* trigger's firing configuration */ bool isconstraint; /* This is a constraint trigger */ char *trigname; /* TRIGGER's name */ RangeVar *relation; /* relation trigger is on */ diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index aa0755dc6d4..359d28c67c2 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -476,6 +476,9 @@ NOTICE: dummy_update_func(afterb) called: action = UPDATE, old = (t), new = (f) UPDATE some_t SET some_col = TRUE; NOTICE: dummy_update_func(before) called: action = UPDATE, old = (f), new = (t) NOTICE: dummy_update_func(aftera) called: action = UPDATE, old = (f), new = (t) +ALTER TABLE some_t ENABLE REPLICA TRIGGER some_trig_aftera; +ALTER TABLE some_t DISABLE TRIGGER some_trig_afterb; +ALTER TABLE some_t ENABLE ALWAYS TRIGGER some_trig_before; CREATE TABLE some_t1 (c INT, LIKE some_t INCLUDING TRIGGERS INCLUDING COMMENTS); \d+ some_t1 Table "public.some_t1" @@ -485,10 +488,12 @@ CREATE TABLE some_t1 (c INT, LIKE some_t INCLUDING TRIGGERS INCLUDING COMMENTS); some_col | boolean | | not null | | plain | | Not-null constraints: "some_t_some_col_not_null" NOT NULL "some_col" -Triggers: - some_trig_aftera AFTER UPDATE ON some_t1 FOR EACH ROW WHEN (NOT old.some_col AND new.some_col) EXECUTE FUNCTION dummy_update_func('aftera') +Disabled user triggers: some_trig_afterb AFTER UPDATE ON some_t1 FOR EACH ROW WHEN (NOT new.some_col) EXECUTE FUNCTION dummy_update_func('afterb') +Triggers firing always: some_trig_before BEFORE UPDATE ON some_t1 FOR EACH ROW EXECUTE FUNCTION dummy_update_func('before') +Triggers firing on replica only: + some_trig_aftera AFTER UPDATE ON some_t1 FOR EACH ROW WHEN (NOT old.some_col AND new.some_col) EXECUTE FUNCTION dummy_update_func('aftera') DROP TABLE some_t; DROP TABLE some_t1; diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 5495ca6caca..9d711ee4672 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -286,6 +286,9 @@ INSERT INTO some_t VALUES (TRUE); UPDATE some_t SET some_col = TRUE; UPDATE some_t SET some_col = FALSE; UPDATE some_t SET some_col = TRUE; +ALTER TABLE some_t ENABLE REPLICA TRIGGER some_trig_aftera; +ALTER TABLE some_t DISABLE TRIGGER some_trig_afterb; +ALTER TABLE some_t ENABLE ALWAYS TRIGGER some_trig_before; CREATE TABLE some_t1 (c INT, LIKE some_t INCLUDING TRIGGERS INCLUDING COMMENTS); \d+ some_t1 DROP TABLE some_t; -- 2.34.1