=== Applying patches on top of PostgreSQL commit ID 451871b740d7ad252b8aeaf16a20bcf831a39254 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Tue Aug 4 19:26:28 UTC 2026 On branch cf/6089 nothing to commit, working tree clean === using 'git am' to apply patch ./v3-0001-let-SET-DATA-TYPE-cope-with-trigger-dependency.patch === Applying: let SET DATA TYPE cope with trigger dependency Using index info to reconstruct a base tree... M src/backend/catalog/index.c M src/backend/commands/tablecmds.c M src/backend/commands/trigger.c M src/backend/parser/gram.y M src/backend/utils/adt/ruleutils.c M src/include/commands/trigger.h M src/include/nodes/parsenodes.h M src/include/utils/ruleutils.h M src/test/modules/test_ddl_deparse/test_ddl_deparse.c M src/test/regress/expected/foreign_data.out M src/test/regress/expected/triggers.out M src/test/regress/sql/foreign_data.sql M src/test/regress/sql/triggers.sql Falling back to patching base and 3-way merge... Auto-merging src/test/regress/sql/triggers.sql Auto-merging src/test/regress/sql/foreign_data.sql Auto-merging src/test/regress/expected/triggers.out Auto-merging src/test/regress/expected/foreign_data.out Auto-merging src/test/modules/test_ddl_deparse/test_ddl_deparse.c Auto-merging src/include/utils/ruleutils.h Auto-merging src/include/nodes/parsenodes.h Auto-merging src/include/commands/trigger.h Auto-merging src/backend/utils/adt/ruleutils.c Auto-merging src/backend/parser/gram.y Auto-merging src/backend/commands/trigger.c CONFLICT (content): Merge conflict in src/backend/commands/trigger.c Auto-merging src/backend/commands/tablecmds.c CONFLICT (content): Merge conflict in src/backend/commands/tablecmds.c Auto-merging src/backend/catalog/index.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 let SET DATA TYPE cope with trigger dependency When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v3-0001-let-SET-DATA-TYPE-cope-with-trigger-dependency.patch === patching file src/backend/catalog/index.c Hunk #1 succeeded at 2069 (offset 32 lines). patching file src/backend/commands/tablecmds.c Hunk #1 succeeded at 211 (offset 3 lines). Hunk #2 succeeded at 593 (offset 45 lines). Hunk #3 succeeded at 701 (offset 46 lines). Hunk #4 succeeded at 5564 (offset 94 lines). Hunk #5 succeeded at 6857 (offset 96 lines). Hunk #6 succeeded at 9833 (offset 97 lines). Hunk #7 succeeded at 14396 (offset 497 lines). Hunk #8 succeeded at 14443 (offset 497 lines). Hunk #9 succeeded at 14505 (offset 497 lines). Hunk #10 FAILED at 15221. Hunk #11 succeeded at 16161 (offset 665 lines). Hunk #12 succeeded at 16332 (offset 665 lines). Hunk #13 succeeded at 16421 (offset 665 lines). Hunk #14 succeeded at 16474 (offset 665 lines). Hunk #15 succeeded at 16629 (offset 665 lines). Hunk #16 succeeded at 21779 (offset 732 lines). 1 out of 16 hunks FAILED -- saving rejects to file src/backend/commands/tablecmds.c.rej patching file src/backend/commands/trigger.c Hunk #1 succeeded at 31 with fuzz 1 (offset 1 line). Hunk #2 succeeded at 216 (offset 2 lines). Hunk #3 succeeded at 573 (offset 14 lines). Hunk #4 succeeded at 587 (offset 14 lines). Hunk #5 succeeded at 613 (offset 14 lines). Hunk #6 succeeded at 1220 (offset 14 lines). Hunk #7 succeeded at 1434 (offset 14 lines). Hunk #8 succeeded at 6984 with fuzz 2 (offset 214 lines). patching file src/backend/parser/gram.y Hunk #1 succeeded at 6219 (offset 69 lines). Hunk #2 succeeded at 6271 (offset 69 lines). patching file src/backend/utils/adt/ruleutils.c Hunk #1 succeeded at 895 (offset 14 lines). patching file src/include/commands/trigger.h Hunk #1 succeeded at 162 (offset 2 lines). Hunk #2 succeeded at 171 (offset 2 lines). patching file src/include/nodes/parsenodes.h Hunk #1 succeeded at 2628 (offset 119 lines). Hunk #2 succeeded at 3274 (offset 119 lines). patching file src/include/utils/ruleutils.h Hunk #1 succeeded at 54 with fuzz 1 (offset 1 line). patching file src/test/modules/test_ddl_deparse/test_ddl_deparse.c Hunk #1 succeeded at 315 (offset 1 line). patching file src/test/regress/expected/foreign_data.out Hunk #1 succeeded at 1423 (offset 29 lines). patching file src/test/regress/expected/triggers.out Hunk #5 succeeded at 2251 (offset 8 lines). Hunk #6 succeeded at 2419 (offset 8 lines). patching file src/test/regress/sql/foreign_data.sql Hunk #1 succeeded at 644 (offset 19 lines). patching file src/test/regress/sql/triggers.sql Hunk #5 succeeded at 1535 (offset 1 line). Hunk #6 succeeded at 1654 (offset 1 line). Unstaged changes after reset: M src/backend/catalog/index.c M src/backend/commands/tablecmds.c M src/backend/commands/trigger.c M src/backend/parser/gram.y M src/backend/utils/adt/ruleutils.c M src/include/commands/trigger.h M src/include/nodes/parsenodes.h M src/include/utils/ruleutils.h M src/test/modules/test_ddl_deparse/test_ddl_deparse.c M src/test/regress/expected/foreign_data.out M src/test/regress/expected/triggers.out M src/test/regress/sql/foreign_data.sql M src/test/regress/sql/triggers.sql Removing src/backend/commands/tablecmds.c.rej === using 'git apply' to apply patch ./v3-0001-let-SET-DATA-TYPE-cope-with-trigger-dependency.patch === Applied patch to 'src/backend/catalog/index.c' cleanly. Applied patch to 'src/backend/commands/tablecmds.c' with conflicts. Applied patch to 'src/backend/commands/trigger.c' with conflicts. Applied patch to 'src/backend/parser/gram.y' cleanly. Applied patch to 'src/backend/utils/adt/ruleutils.c' cleanly. Applied patch to 'src/include/commands/trigger.h' cleanly. Applied patch to 'src/include/nodes/parsenodes.h' cleanly. Applied patch to 'src/include/utils/ruleutils.h' cleanly. Applied patch to 'src/test/modules/test_ddl_deparse/test_ddl_deparse.c' cleanly. Applied patch to 'src/test/regress/expected/foreign_data.out' cleanly. Applied patch to 'src/test/regress/expected/triggers.out' cleanly. Applied patch to 'src/test/regress/sql/foreign_data.sql' cleanly. Applied patch to 'src/test/regress/sql/triggers.sql' cleanly. U src/backend/commands/tablecmds.c U src/backend/commands/trigger.c diff --cc src/backend/commands/tablecmds.c index 2fa534413ea,a892bd4d001..00000000000 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@@ -15677,21 -15221,13 +15718,22 @@@ RememberAllDependentForRebuilding(Alter case TriggerRelationId: /* - * A trigger can depend on a column because the column is - * specified as an update target, or because the column is - * used in the trigger's WHEN condition. The first case would - * not require any extra work, but the second case would - * require updating the WHEN expression, which has the same - * issues as above. Since we can't easily tell which case - * applies, we punt for both. FIXME someday. + * Internally-generated trigger for a constraint will have + * internal dependency of the constraint. It won't have direct + * dependency with the relation. So no need to worry about + * internal trigger here. */ if (subtype == AT_AlterColumnType) ++<<<<<<< ours + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter type of a column used in a trigger definition"), + errdetail("%s depends on column \"%s\".", + getObjectDescription(&foundObject, false), + colName))); ++======= + RememberTriggerForRebuilding(foundObject.objectId, tab); ++>>>>>>> theirs break; case PolicyRelationId: diff --cc src/backend/commands/trigger.c index 401baddbfc6,2a5c6d71283..00000000000 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@@ -31,9 -30,9 +31,10 @@@ #include "catalog/pg_proc.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" + #include "commands/comment.h" #include "commands/trigger.h" #include "executor/executor.h" +#include "executor/instrument.h" #include "miscadmin.h" #include "nodes/bitmapset.h" #include "nodes/makefuncs.h" @@@ -6849,83 -6772,70 +6904,152 @@@ check_modified_virtual_generated(TupleD } /* ++<<<<<<< ours + * RegisterAfterTriggerBatchCallback + * Register a function to be called when the current trigger-firing + * batch completes. + * + * Must be called from within a trigger function's execution context + * (i.e., while afterTriggers state is active). + * + * The callback list is cleared after invocation, so the caller must + * re-register for each new batch if needed. + */ +void +RegisterAfterTriggerBatchCallback(AfterTriggerBatchCallback callback, + void *arg) +{ + AfterTriggerCallbackItem *item; + MemoryContext oldcxt; + + /* + * Allocate in TopTransactionContext so the item survives for the duration + * of the batch, which may span multiple trigger invocations. + * + * Must be called while afterTriggers is active; callbacks registered + * outside a trigger-firing context would never fire. + */ + Assert(afterTriggers.firing_depth > 0); + Assert(!afterTriggers.firing_batch_callbacks); + oldcxt = MemoryContextSwitchTo(TopTransactionContext); + item = palloc(sizeof(AfterTriggerCallbackItem)); + item->callback = callback; + item->arg = arg; + if (afterTriggers.query_depth >= 0) + { + AfterTriggersQueryData *qs = + &afterTriggers.query_stack[afterTriggers.query_depth]; + + qs->batch_callbacks = lappend(qs->batch_callbacks, item); + } + else + afterTriggers.batch_callbacks = + lappend(afterTriggers.batch_callbacks, item); + MemoryContextSwitchTo(oldcxt); +} + +/* + * FireAfterTriggerBatchCallbacks + * Invoke all callbacks in the given list. + * + * Memory cleanup of the list and its items is handled by the caller + * (AfterTriggerFreeQuery for query-level callbacks, AfterTriggerEndXact + * for top-level deferred callbacks). + */ +static void +FireAfterTriggerBatchCallbacks(List *callbacks) +{ + ListCell *lc; + + Assert(afterTriggers.firing_depth > 0); + afterTriggers.firing_batch_callbacks = true; + foreach(lc, callbacks) + { + AfterTriggerCallbackItem *item = lfirst(lc); + + item->callback(item->arg); + } + afterTriggers.firing_batch_callbacks = false; +} + +/* + * AfterTriggerIsActive + * Returns true if we're inside the after-trigger framework where + * registered batch callbacks will actually be invoked. + * + * This is false during validateForeignKeyConstraint(), which calls + * RI trigger functions directly outside the after-trigger framework. + */ +bool +AfterTriggerIsActive(void) +{ + return afterTriggers.firing_depth > 0; ++======= + * transformTriggerStmt - parse analysis for CREATE TRIGGER + * + * To avoid race conditions, it's important that this function relies only on + * the passed-in relid (and not on stmt->relation) to determine the target + * relation. + */ + CreateTrigStmt * + transformTriggerStmt(Oid relid, CreateTrigStmt *stmt, const char *queryString) + { + ParseState *pstate; + ParseNamespaceItem *nsitem; + Relation rel; + + /* + * Nothing to do if statement already transformed. transformed is set to + * true if CreateTrigStmt has no whenClause. + */ + if (stmt->transformed) + return stmt; + else if (!stmt->whenClause) + { + stmt->transformed = true; + + return stmt; + } + + rel = relation_open(relid, NoLock); + + /* Set up a pstate to parse with */ + pstate = make_parsestate(NULL); + pstate->p_sourcetext = queryString; + + /* + * Set up nsitems for OLD and NEW references. + * + * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2. + */ + nsitem = addRangeTableEntryForRelation(pstate, rel, + AccessShareLock, + makeAlias("old", NIL), + false, false); + addNSItemToQuery(pstate, nsitem, false, true, true); + + nsitem = addRangeTableEntryForRelation(pstate, rel, + AccessShareLock, + makeAlias("new", NIL), + false, false); + addNSItemToQuery(pstate, nsitem, false, true, true); + + /* Transform expression. Copy to be sure we don't modify original */ + stmt->whenClause = transformWhereClause(pstate, + copyObject(stmt->whenClause), + EXPR_KIND_TRIGGER_WHEN, + "WHEN"); + /* we have to fix its collations too */ + assign_expr_collations(pstate, stmt->whenClause); + + free_parsestate(pstate); + + /* Close relation */ + table_close(rel, NoLock); + + /* Mark statement as successfully transformed */ + stmt->transformed = true; + + return stmt; ++>>>>>>> theirs }