v8-0002-make-create-foreign-key-executed-at-the-end-of-CREATE-SCHEMA.nocfbot
application/octet-stream
Filename: v8-0002-make-create-foreign-key-executed-at-the-end-of-CREATE-SCHEMA.nocfbot
Type: application/octet-stream
Part: 0
From 4ac1020d98114270d7a322fc63589b91c4d94a82 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Wed, 17 Dec 2025 20:25:30 +0800
Subject: [PATCH v8 2/2] make create foreign key executed at the end of CREATE
SCHEMA
essentially make the below two example work:
CREATE SCHEMA s1
CREATE TABLE t2(b int, a int references t1) partition by range (b)
CREATE TABLE t1(a int primary key) partition by range (a);
CREATE SCHEMA s2
CREATE TABLE t2(a int, b int, c int, foreign key (a, b) references t1 match full) partition by range (a, b, c)
CREATE TABLE t1(a int, b int, primary key(b, a)) partition by range (a, b);
Discussion: https://postgr.es/m/1075425.1732993688@sss.pgh.pa.us
---
src/backend/commands/schemacmds.c | 79 +++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 09928c58d9d..dc841a772d4 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -198,6 +198,85 @@ CreateSchemaCommand(ParseState *pstate, CreateSchemaStmt *stmt,
stmt->schemaElts,
schemaName);
+ foreach(parsetree_item, parsetree_list)
+ {
+ ListCell *elements;
+ CreateStmt *csstmt;
+
+ Node *stmt = (Node *) lfirst(parsetree_item);
+
+ if (!IsA(stmt, CreateStmt))
+ continue;
+
+ csstmt = castNode(CreateStmt, stmt);
+
+ foreach(elements, csstmt->tableElts)
+ {
+ ColumnDef *entry;
+ Constraint *constr;
+ AlterTableStmt *alterstmt;
+ AlterTableCmd *altercmd;
+ Node *element = lfirst(elements);
+
+ if (!IsA(element, ColumnDef) && !IsA(element, Constraint))
+ continue;
+
+ if (IsA(element, Constraint))
+ {
+ constr = castNode(Constraint, element);
+
+ if (constr->contype != CONSTR_FOREIGN)
+ continue;
+
+ alterstmt = makeNode(AlterTableStmt);
+ altercmd = makeNode(AlterTableCmd);
+
+ alterstmt->relation = csstmt->relation;
+ alterstmt->cmds = NIL;
+ alterstmt->objtype = OBJECT_TABLE;
+
+ altercmd->subtype = AT_AddConstraint;
+ altercmd->name = NULL;
+ altercmd->def = (Node *) constr;
+ alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
+
+ csstmt->tableElts = foreach_delete_current(csstmt->tableElts,
+ elements);
+
+ parsetree_list = lappend(parsetree_list, alterstmt);
+
+ continue;
+ }
+
+ entry = castNode(ColumnDef, element);
+
+ foreach_node(Constraint, cdef, entry->constraints)
+ {
+ if (cdef->contype != CONSTR_FOREIGN)
+ continue;
+
+ alterstmt = makeNode(AlterTableStmt);
+ altercmd = makeNode(AlterTableCmd);
+
+ cdef->fk_attrs = list_make1(makeString(entry->colname));
+
+ alterstmt->relation = csstmt->relation;
+ alterstmt->cmds = NIL;
+ alterstmt->objtype = OBJECT_TABLE;
+
+ altercmd->subtype = AT_AddConstraint;
+ altercmd->name = NULL;
+ altercmd->def = (Node *) cdef;
+ alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
+
+ entry->constraints = foreach_delete_current(entry->constraints,
+ cdef);
+
+ parsetree_list = lappend(parsetree_list, alterstmt);
+ }
+ }
+ }
+
/*
* Execute each command contained in the CREATE SCHEMA. Since the grammar
* allows only utility commands in CREATE SCHEMA, there is no need to pass
--
2.34.1