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
Message: Re: CREATE SCHEMA ... CREATE DOMAIN support
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