From 0f08984a215f180423e6c5d3899d3c3b6b65024e Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 2 Mar 2026 10:35:26 +0800 Subject: [PATCH v10 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 6aaaf738662..576f4d2d00f 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2041,6 +2041,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 09654aba5f0..c74dd98b342 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -14090,6 +14090,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; @@ -14151,6 +14152,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; @@ -14213,6 +14215,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; @@ -21206,6 +21209,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 f55a08f0088..ab085bf1f41 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7096,6 +7096,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 6fca2636116..e0dfce69259 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6196,6 +6196,7 @@ CreateTrigStmt: CreateTrigStmt *n = makeNode(CreateTrigStmt); n->replace = $2; + n->tgenabled = TRIGGER_FIRES_ON_ORIGIN; n->isconstraint = false; n->trigname = $4; n->relation = $8; @@ -6247,6 +6248,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 73a56f1df1d..f708df57ee3 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1705,10 +1705,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 a7d01f5f9fd..c53d9d6bd3e 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3217,6 +3217,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 f675786739d..2e9c352a690 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 1afaeb863f7..9fb16c72323 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -288,6 +288,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