From 981fa017d6d71921586e09bf49f208e2667497f0 Mon Sep 17 00:00:00 2001 From: jian he Date: Tue, 10 Mar 2026 22:03:40 +0800 Subject: [PATCH v10 5/5] CREATE SCHEMA foreign key executed at the end For CREATE SCHEMA, all subcommands are executed in the order they are specified. However, to support foreign key cross referencing, we need transform FOREIGN KEY clause into ALTER TABLE ... ADD FOREIGN KEY command and append them to the end of the CREATE SCHEMA execution queue. All CREATE TABLE commands are executed first, so subsequent ALTER TABLE ... ADD FOREIGN KEY statements will not encounter any conflicts. Discussion: https://postgr.es/m/1075425.1732993688@sss.pgh.pa.us Commitfest: https://commitfest.postgresql.org/patch/5985 --- src/backend/commands/schemacmds.c | 130 ++++++++++++++++++ src/backend/parser/parse_utilcmd.c | 36 +++-- src/include/parser/parse_utilcmd.h | 1 + .../expected/create_schema.out | 25 ++++ .../test_ddl_deparse/sql/create_schema.sql | 11 ++ src/test/regress/expected/create_schema.out | 83 +++++++++++ src/test/regress/expected/event_trigger.out | 2 +- src/test/regress/sql/create_schema.sql | 36 +++++ 8 files changed, 304 insertions(+), 20 deletions(-) diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index d52093c3d9d..621f3806772 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -198,6 +198,136 @@ CreateSchemaCommand(ParseState *pstate, CreateSchemaStmt *stmt, stmt->schemaElts, schemaName); + /* + * Reorder the list of commands embedded in the CREATE SCHEMA statement. + * We only do this for foreign keys. Foreign key constraints are + * transformed into ALTER TABLE ... ADD FOREIGN KEY commands and moved to + * the end of the CREATE SCHEMA to-do list (parsetree_list). + * + * At the same time, the original foreign key Constraint node must removed + * from CreateStmt, since they have already been converted into + * AlterTableCmds. No need to do parse analysis for the original foreign + * key constraint nodes: because foreign key constraint only allow plain + * column references. + * + * See also transformFKConstraints and transformConstraintAttrs. + */ + 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) + { + AlterTableStmt *alterstmt; + AlterTableCmd *altercmd; + + Node *element = lfirst(elements); + + if (IsA(element, Constraint)) + { + Constraint *constr = castNode(Constraint, element); + + if (constr->contype != CONSTR_FOREIGN) + continue; + + alterstmt = makeNode(AlterTableStmt); + alterstmt->relation = copyObject(csstmt->relation); + alterstmt->cmds = NIL; + alterstmt->objtype = OBJECT_TABLE; + + altercmd = makeNode(AlterTableCmd); + altercmd->subtype = AT_AddConstraint; + altercmd->name = NULL; + altercmd->def = (Node *) copyObject(constr); + + alterstmt->cmds = lappend(alterstmt->cmds, altercmd); + + csstmt->tableElts = foreach_delete_current(csstmt->tableElts, + elements); + + parsetree_list = lappend(parsetree_list, alterstmt); + } + else if (IsA(element, ColumnDef)) + { + ColumnDef *entry = castNode(ColumnDef, element); + + transformConstraintAttrs(pstate, entry->constraints); + + for (int constrpos = 0; constrpos < list_length(entry->constraints); constrpos++) + { + Constraint *colconstr = list_nth_node(Constraint, + entry->constraints, + constrpos); + + if (colconstr->contype != CONSTR_FOREIGN) + continue; + + alterstmt = makeNode(AlterTableStmt); + altercmd = makeNode(AlterTableCmd); + + colconstr->fk_attrs = list_make1(makeString(entry->colname)); + + alterstmt->relation = copyObject(csstmt->relation); + alterstmt->cmds = NIL; + alterstmt->objtype = OBJECT_TABLE; + + altercmd->subtype = AT_AddConstraint; + altercmd->name = NULL; + altercmd->def = (Node *) copyObject(colconstr); + alterstmt->cmds = lappend(alterstmt->cmds, altercmd); + + parsetree_list = lappend(parsetree_list, alterstmt); + + /* + * Column constraints separate the Constraint node from + * its attributes; a full column-level foreign key + * constraint may be represented by multiple Constraint + * nodes. After transformConstraintAttrs, the main foreign + * key Constraint node already contains all required + * information. Therefore, when the foreign key Constraint + * node is removed, the associated attribute (e.g. NOT + * ENFORCED) nodes (which are also Constraint nodes) must + * be removed as well. + */ + for (int restpos = constrpos + 1; restpos < list_length(entry->constraints);) + { + Constraint *nextcolconstr = list_nth_node(Constraint, + entry->constraints, + restpos); + + if (nextcolconstr->contype == CONSTR_ATTR_DEFERRABLE || + nextcolconstr->contype == CONSTR_ATTR_NOT_DEFERRABLE || + nextcolconstr->contype == CONSTR_ATTR_DEFERRED || + nextcolconstr->contype == CONSTR_ATTR_IMMEDIATE || + nextcolconstr->contype == CONSTR_ATTR_NOT_ENFORCED) + { + entry->constraints = list_delete_nth_cell(entry->constraints, + restpos); + } + else + break; + } + + entry->constraints = list_delete_nth_cell(entry->constraints, constrpos); + + /* + * We have already removed one FK Constraint node, update + * constrpos now. + */ + constrpos = constrpos - 1; + } + } + } + } + /* * Execute each command contained in the CREATE SCHEMA. Since the grammar * allows only utility commands in CREATE SCHEMA, there is no need to pass diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index b6ee8342fde..8eadfb65523 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -122,8 +122,6 @@ static void transformFKConstraints(CreateStmtContext *cxt, bool isAddConstraint); static void transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation); -static void transformConstraintAttrs(CreateStmtContext *cxt, - List *constraintList); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void checkSchemaName(ParseState *pstate, const char *context_schema, RangeVar *relation); @@ -693,7 +691,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) } /* Process column constraints, if any... */ - transformConstraintAttrs(cxt, column->constraints); + transformConstraintAttrs(cxt->pstate, column->constraints); /* * First, scan the column's constraints to see if a not-null constraint @@ -4195,8 +4193,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be * supported for other constraint types. */ -static void -transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) +void +transformConstraintAttrs(ParseState *pstate, List *constraintList) { Constraint *lastprimarycon = NULL; bool saw_deferrability = false; @@ -4225,12 +4223,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced DEFERRABLE clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_deferrability) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_deferrability = true; lastprimarycon->deferrable = true; break; @@ -4240,12 +4238,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced NOT DEFERRABLE clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_deferrability) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_deferrability = true; lastprimarycon->deferrable = false; if (saw_initially && @@ -4253,7 +4251,7 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); break; case CONSTR_ATTR_DEFERRED: @@ -4261,12 +4259,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced INITIALLY DEFERRED clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_initially) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_initially = true; lastprimarycon->initdeferred = true; @@ -4279,7 +4277,7 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); break; case CONSTR_ATTR_IMMEDIATE: @@ -4287,12 +4285,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced INITIALLY IMMEDIATE clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_initially) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_initially = true; lastprimarycon->initdeferred = false; break; @@ -4304,12 +4302,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced ENFORCED clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_enforced) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_enforced = true; lastprimarycon->is_enforced = true; break; @@ -4321,12 +4319,12 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("misplaced NOT ENFORCED clause"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); if (saw_enforced) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"), - parser_errposition(cxt->pstate, con->location))); + parser_errposition(pstate, con->location))); saw_enforced = true; lastprimarycon->is_enforced = false; diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 34c98e5122f..9afcd91c5db 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -20,6 +20,7 @@ typedef struct AttrMap AttrMap; /* avoid including attmap.h here */ extern List *transformCreateStmt(CreateStmt *stmt, const char *queryString); +extern void transformConstraintAttrs(ParseState *pstate, List *constraintList); extern AlterTableStmt *transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, const char *queryString, List **beforeStmts, diff --git a/src/test/modules/test_ddl_deparse/expected/create_schema.out b/src/test/modules/test_ddl_deparse/expected/create_schema.out index 92da27c813b..89b571fc4c9 100644 --- a/src/test/modules/test_ddl_deparse/expected/create_schema.out +++ b/src/test/modules/test_ddl_deparse/expected/create_schema.out @@ -39,3 +39,28 @@ drop cascades to type element_test.floatrange drop cascades to type element_test.ss drop cascades to type element_test.sss drop cascades to type element_test.rainbow +CREATE SCHEMA regress_schema_1 +CREATE TABLE t4( + b INT, + a INT REFERENCES t5 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) +CREATE TABLE t5 (a INT, b INT, PRIMARY KEY (a)) +CREATE TABLE t6 (a INT, b INT, PRIMARY KEY (a)); +NOTICE: DDL test: type simple, tag CREATE SCHEMA +NOTICE: DDL test: type simple, tag CREATE TABLE +NOTICE: DDL test: type simple, tag CREATE TABLE +NOTICE: DDL test: type simple, tag CREATE INDEX +NOTICE: DDL test: type simple, tag CREATE TABLE +NOTICE: DDL test: type simple, tag CREATE INDEX +NOTICE: DDL test: type alter table, tag ALTER TABLE +NOTICE: subcommand: type ADD CONSTRAINT (and recurse) desc constraint t4_a_fkey on table regress_schema_1.t4 +NOTICE: DDL test: type alter table, tag ALTER TABLE +NOTICE: subcommand: type ADD CONSTRAINT (and recurse) desc constraint t4_a_fkey1 on table regress_schema_1.t4 +NOTICE: DDL test: type alter table, tag ALTER TABLE +NOTICE: subcommand: type ADD CONSTRAINT (and recurse) desc constraint fk on table regress_schema_1.t4 +DROP SCHEMA regress_schema_1 CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table regress_schema_1.t4 +drop cascades to table regress_schema_1.t5 +drop cascades to table regress_schema_1.t6 diff --git a/src/test/modules/test_ddl_deparse/sql/create_schema.sql b/src/test/modules/test_ddl_deparse/sql/create_schema.sql index abe0637c415..411b01bb640 100644 --- a/src/test/modules/test_ddl_deparse/sql/create_schema.sql +++ b/src/test/modules/test_ddl_deparse/sql/create_schema.sql @@ -23,3 +23,14 @@ CREATE SCHEMA element_test CREATE TYPE rainbow AS ENUM ('red', 'orange'); DROP SCHEMA element_test CASCADE; + +CREATE SCHEMA regress_schema_1 +CREATE TABLE t4( + b INT, + a INT REFERENCES t5 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) +CREATE TABLE t5 (a INT, b INT, PRIMARY KEY (a)) +CREATE TABLE t6 (a INT, b INT, PRIMARY KEY (a)); + +DROP SCHEMA regress_schema_1 CASCADE; diff --git a/src/test/regress/expected/create_schema.out b/src/test/regress/expected/create_schema.out index a33cbd0c0d9..6df41f9a2f3 100644 --- a/src/test/regress/expected/create_schema.out +++ b/src/test/regress/expected/create_schema.out @@ -282,6 +282,73 @@ CREATE SCHEMA regress_schema_7 regress_schema_7 | regress_schema_7.sss | (5 rows) +CREATE SCHEMA regress_schema_8 + CREATE TABLE regress_schema_8.t2 ( + b int, + a int REFERENCES t1 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t3 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t1 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) + CREATE TABLE regress_schema_8.t1 (a int PRIMARY KEY) + CREATE TABLE t3 (a int PRIMARY KEY) + CREATE TABLE t4(b int, + a int REFERENCES t5 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) + CREATE TABLE t5 (a int, b int, PRIMARY KEY (a)) + CREATE TABLE t6 (a int, b int, PRIMARY KEY (a)); +\d regress_schema_8.t2 + Table "regress_schema_8.t2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + b | integer | | | + a | integer | | | +Foreign-key constraints: + "fk" FOREIGN KEY (a) REFERENCES regress_schema_8.t1(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + "t2_a_fkey" FOREIGN KEY (a) REFERENCES regress_schema_8.t1(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + "t2_a_fkey1" FOREIGN KEY (a) REFERENCES regress_schema_8.t3(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + +\d regress_schema_8.t4 + Table "regress_schema_8.t4" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + b | integer | | | + a | integer | | | +Foreign-key constraints: + "fk" FOREIGN KEY (a) REFERENCES regress_schema_8.t6(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + "t4_a_fkey" FOREIGN KEY (a) REFERENCES regress_schema_8.t5(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + "t4_a_fkey1" FOREIGN KEY (a) REFERENCES regress_schema_8.t6(a) DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + +CREATE SCHEMA regress_schema_9 + CREATE TABLE t2 (a int, b int, + CONSTRAINT fk FOREIGN KEY (a, b) REFERENCES t1 MATCH FULL NOT DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED, + CONSTRAINT fk1 FOREIGN KEY (a, b) REFERENCES t3 MATCH FULL DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED) + CREATE TABLE t1 (a int, b int, PRIMARY KEY (b, a)) + CREATE TABLE t3 (a int, b int, PRIMARY KEY (b, a)) + CREATE TABLE t4 (a int, b int, + CONSTRAINT fk FOREIGN KEY (b) REFERENCES t6 MATCH FULL NOT DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED, + CONSTRAINT fk1 FOREIGN KEY (a) REFERENCES t5 MATCH FULL DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED) + CREATE TABLE t5 (a int, b int, PRIMARY KEY (a)) + CREATE TABLE t6 (a int, b int, PRIMARY KEY (b)); +\d regress_schema_9.t2 + Table "regress_schema_9.t2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + a | integer | | | + b | integer | | | +Foreign-key constraints: + "fk" FOREIGN KEY (a, b) REFERENCES regress_schema_9.t1(b, a) MATCH FULL NOT ENFORCED + "fk1" FOREIGN KEY (a, b) REFERENCES regress_schema_9.t3(b, a) MATCH FULL DEFERRABLE NOT ENFORCED + +\d regress_schema_9.t4 + Table "regress_schema_9.t4" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + a | integer | | | + b | integer | | | +Foreign-key constraints: + "fk" FOREIGN KEY (b) REFERENCES regress_schema_9.t6(b) MATCH FULL NOT ENFORCED + "fk1" FOREIGN KEY (a) REFERENCES regress_schema_9.t5(a) MATCH FULL DEFERRABLE NOT ENFORCED + DROP SCHEMA regress_schema_2 CASCADE; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to type regress_schema_2.ss @@ -313,5 +380,21 @@ drop cascades to type regress_schema_7.ss drop cascades to type regress_schema_7.sss drop cascades to type regress_schema_7.rainbow drop cascades to table regress_schema_7.t +DROP SCHEMA regress_schema_8 CASCADE; +NOTICE: drop cascades to 6 other objects +DETAIL: drop cascades to table regress_schema_8.t2 +drop cascades to table regress_schema_8.t1 +drop cascades to table regress_schema_8.t3 +drop cascades to table regress_schema_8.t4 +drop cascades to table regress_schema_8.t5 +drop cascades to table regress_schema_8.t6 +DROP SCHEMA regress_schema_9 CASCADE; +NOTICE: drop cascades to 6 other objects +DETAIL: drop cascades to table regress_schema_9.t2 +drop cascades to table regress_schema_9.t1 +drop cascades to table regress_schema_9.t3 +drop cascades to table regress_schema_9.t4 +drop cascades to table regress_schema_9.t5 +drop cascades to table regress_schema_9.t6 -- Clean up DROP ROLE regress_create_schema_role; diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out index 4c32e1dcaf5..065f586310f 100644 --- a/src/test/regress/expected/event_trigger.out +++ b/src/test/regress/expected/event_trigger.out @@ -427,11 +427,11 @@ NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_ NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_c_seq NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.one_idx NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.two -NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.id_col_d_seq NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.id NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.id_col_d_seq NOTICE: END: command_tag=CREATE VIEW type=view identity=evttrig.one_view +NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two -- View with column additions CREATE OR REPLACE VIEW evttrig.one_view AS SELECT * FROM evttrig.two, evttrig.id; NOTICE: END: command_tag=CREATE VIEW type=view identity=evttrig.one_view diff --git a/src/test/regress/sql/create_schema.sql b/src/test/regress/sql/create_schema.sql index 75fd928eacb..547016f54cd 100644 --- a/src/test/regress/sql/create_schema.sql +++ b/src/test/regress/sql/create_schema.sql @@ -168,12 +168,48 @@ CREATE SCHEMA regress_schema_7 CREATE TABLE t(a floatrange, b ss, c rainbow); \dT regress_schema_7.* +CREATE SCHEMA regress_schema_8 + CREATE TABLE regress_schema_8.t2 ( + b int, + a int REFERENCES t1 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t3 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t1 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) + CREATE TABLE regress_schema_8.t1 (a int PRIMARY KEY) + CREATE TABLE t3 (a int PRIMARY KEY) + CREATE TABLE t4(b int, + a int REFERENCES t5 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED + REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED, + CONSTRAINT fk FOREIGN KEY (a) REFERENCES t6 DEFERRABLE INITIALLY DEFERRED NOT ENFORCED) + CREATE TABLE t5 (a int, b int, PRIMARY KEY (a)) + CREATE TABLE t6 (a int, b int, PRIMARY KEY (a)); + +\d regress_schema_8.t2 +\d regress_schema_8.t4 + +CREATE SCHEMA regress_schema_9 + CREATE TABLE t2 (a int, b int, + CONSTRAINT fk FOREIGN KEY (a, b) REFERENCES t1 MATCH FULL NOT DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED, + CONSTRAINT fk1 FOREIGN KEY (a, b) REFERENCES t3 MATCH FULL DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED) + CREATE TABLE t1 (a int, b int, PRIMARY KEY (b, a)) + CREATE TABLE t3 (a int, b int, PRIMARY KEY (b, a)) + CREATE TABLE t4 (a int, b int, + CONSTRAINT fk FOREIGN KEY (b) REFERENCES t6 MATCH FULL NOT DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED, + CONSTRAINT fk1 FOREIGN KEY (a) REFERENCES t5 MATCH FULL DEFERRABLE INITIALLY IMMEDIATE NOT ENFORCED) + CREATE TABLE t5 (a int, b int, PRIMARY KEY (a)) + CREATE TABLE t6 (a int, b int, PRIMARY KEY (b)); + +\d regress_schema_9.t2 +\d regress_schema_9.t4 + + DROP SCHEMA regress_schema_2 CASCADE; DROP SCHEMA regress_schema_3 CASCADE; DROP SCHEMA regress_schema_4 CASCADE; DROP SCHEMA regress_schema_5 CASCADE; DROP SCHEMA regress_schema_6 CASCADE; DROP SCHEMA regress_schema_7 CASCADE; +DROP SCHEMA regress_schema_8 CASCADE; +DROP SCHEMA regress_schema_9 CASCADE; -- Clean up DROP ROLE regress_create_schema_role; -- 2.34.1