From 4ac1020d98114270d7a322fc63589b91c4d94a82 Mon Sep 17 00:00:00 2001 From: jian he 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