]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Don't try to re-order the subcommands of CREATE SCHEMA.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Apr 2026 18:42:55 +0000 (14:42 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Apr 2026 19:16:25 +0000 (15:16 -0400)
transformCreateSchemaStmtElements has always believed that it is
supposed to re-order the subcommands of CREATE SCHEMA into a safe
execution order.  However, it is nowhere near being capable of doing
that correctly.  Nor is there reason to think that it ever will be,
or that that is a well-defined requirement.  (The SQL standard does
say that it should be possible to do foreign-key forward references
within CREATE SCHEMA, but it's not clear that the text requires
anything more than that.)  Moreover, the problem will get worse as
we add more subcommand types.  Let's just drop the whole idea and
execute the commands in the order given, which seems like a much
less astonishment-prone definition anyway.  The foreign-key issue
will be handled in a follow-up patch.

This will result in a release-note-worthy incompatibility,
which is that forward references like
CREATE SCHEMA myschema
    CREATE VIEW myview AS SELECT * FROM mytable
    CREATE TABLE mytable (...);
used to work and no longer will.  Considering how many closely
related variants never worked, this isn't much of a loss.

Along the way, pass down a ParseState so that we can provide an
error cursor for "wrong schema name" and related errors, and fix
transformCreateSchemaStmtElements so that it doesn't scribble
on the parsetree passed to it.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Jian He <jian.universality@gmail.com>
Discussion: https://postgr.es/m/1075425.1732993688@sss.pgh.pa.us

14 files changed:
doc/src/sgml/ref/create_schema.sgml
src/backend/commands/extension.c
src/backend/commands/schemacmds.c
src/backend/parser/parse_utilcmd.c
src/backend/tcop/utility.c
src/include/commands/schemacmds.h
src/include/parser/parse_utilcmd.h
src/test/regress/expected/create_schema.out
src/test/regress/expected/create_view.out
src/test/regress/expected/event_trigger.out
src/test/regress/expected/namespace.out
src/test/regress/sql/create_schema.sql
src/test/regress/sql/namespace.sql
src/tools/pgindent/typedefs.list

index ed69298ccc6ce7a880dc3b5a26be4169ff7f8825..9e6f0e243396b081771eced5159b5b011050e156 100644 (file)
@@ -131,6 +131,11 @@ CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="parameter">role_sp
    <literal>CREATE</literal> privilege for the current database.
    (Of course, superusers bypass this check.)
   </para>
+
+  <para>
+   The <replaceable class="parameter">schema_element</replaceable>
+   subcommands, if any, are executed in the order they are written.
+  </para>
  </refsect1>
 
  <refsect1>
@@ -193,12 +198,12 @@ CREATE VIEW hollywood.winners AS
   </para>
 
   <para>
-   The SQL standard specifies that the subcommands in <command>CREATE
-   SCHEMA</command> can appear in any order.  The present
-   <productname>PostgreSQL</productname> implementation does not
-   handle all cases of forward references in subcommands; it might
-   sometimes be necessary to reorder the subcommands in order to avoid
-   forward references.
+   Some other SQL implementations attempt to allow more kinds of forward
+   references to objects defined in
+   later <replaceable class="parameter">schema_element</replaceable>
+   subcommands than just foreign key constraints.  This is difficult or
+   impossible to do correctly in general, and it is not clear that the SQL
+   standard requires any such behavior except for foreign keys.
   </para>
 
   <para>
index b98801d08f220cda65e38f532e1b61ec93a68e37..a330b5fd6cec561cf90eaa482eda10bcf4a64000 100644 (file)
@@ -1952,14 +1952,17 @@ CreateExtensionInternal(char *extensionName,
 
                if (!OidIsValid(schemaOid))
                {
+                       ParseState *pstate = make_parsestate(NULL);
                        CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
 
+                       pstate->p_sourcetext = "(generated CREATE SCHEMA command)";
+
                        csstmt->schemaname = schemaName;
                        csstmt->authrole = NULL;        /* will be created by current user */
                        csstmt->schemaElts = NIL;
                        csstmt->if_not_exists = false;
-                       CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
-                                                               -1, -1);
+
+                       CreateSchemaCommand(pstate, csstmt, -1, -1);
 
                        /*
                         * CreateSchemaCommand includes CommandCounterIncrement, so new
index 4c51e920626a214296743fdb723b140450270e69..bfaa4743cd8ca34491e5a87bfda83f300cc994d7 100644 (file)
@@ -49,7 +49,7 @@ static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerI
  * a subquery.
  */
 Oid
-CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
+CreateSchemaCommand(ParseState *pstate, CreateSchemaStmt *stmt,
                                        int stmt_location, int stmt_len)
 {
        const char *schemaName = stmt->schemaname;
@@ -189,12 +189,12 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
 
        /*
         * Examine the list of commands embedded in the CREATE SCHEMA command, and
-        * reorganize them into a sequentially executable order with no forward
-        * references.  Note that the result is still a list of raw parsetrees ---
-        * we cannot, in general, run parse analysis on one statement until we
-        * have actually executed the prior ones.
+        * do preliminary transformations.  Note that the result is still a list
+        * of raw parsetrees --- we cannot, in general, run parse analysis on one
+        * statement until we have actually executed the prior ones.
         */
-       parsetree_list = transformCreateSchemaStmtElements(stmt->schemaElts,
+       parsetree_list = transformCreateSchemaStmtElements(pstate,
+                                                                                                          stmt->schemaElts,
                                                                                                           schemaName);
 
        /*
@@ -219,7 +219,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
 
                /* do this step */
                ProcessUtility(wrapper,
-                                          queryString,
+                                          pstate->p_sourcetext,
                                           false,
                                           PROCESS_UTILITY_SUBCOMMAND,
                                           NULL,
index 9a918e14aa705a1b98e3c70413fa0f61c719ea77..151d97312732eaabb5d01c2ea8021ea85d9e3b44 100644 (file)
@@ -99,18 +99,6 @@ typedef struct
        bool            ofType;                 /* true if statement contains OF typename */
 } CreateStmtContext;
 
-/* State shared by transformCreateSchemaStmtElements and its subroutines */
-typedef struct
-{
-       const char *schemaname;         /* name of schema */
-       List       *sequences;          /* CREATE SEQUENCE items */
-       List       *tables;                     /* CREATE TABLE items */
-       List       *views;                      /* CREATE VIEW items */
-       List       *indexes;            /* CREATE INDEX items */
-       List       *triggers;           /* CREATE TRIGGER items */
-       List       *grants;                     /* GRANT items */
-} CreateSchemaStmtContext;
-
 
 static void transformColumnDefinition(CreateStmtContext *cxt,
                                                                          ColumnDef *column);
@@ -137,7 +125,8 @@ static void transformCheckConstraints(CreateStmtContext *cxt,
 static void transformConstraintAttrs(CreateStmtContext *cxt,
                                                                         List *constraintList);
 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
-static void setSchemaName(const char *context_schema, char **stmt_schema_name);
+static void checkSchemaNameRV(ParseState *pstate, const char *context_schema,
+                                                         RangeVar *relation);
 static void transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound);
 static List *transformPartitionRangeBounds(ParseState *pstate, List *blist,
                                                                                   Relation parent);
@@ -4395,51 +4384,35 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
  * transformCreateSchemaStmtElements -
  *       analyzes the elements of a CREATE SCHEMA statement
  *
- * Split the schema element list from a CREATE SCHEMA statement into
- * individual commands and place them in the result list in an order
- * such that there are no forward references (e.g. GRANT to a table
- * created later in the list). Note that the logic we use for determining
- * forward references is presently quite incomplete.
+ * This is now somewhat vestigial: its only real responsibility is to complain
+ * if any of the elements are trying to create objects outside the new schema.
+ * We used to try to re-order the commands in a way that would work even if
+ * the user-written order would not, but that's too hard (perhaps impossible)
+ * to do correctly with not-yet-parse-analyzed commands.  Now we'll just
+ * execute the elements in the order given.
  *
  * "schemaName" is the name of the schema that will be used for the creation
- * of the objects listed, that may be compiled from the schema name defined
+ * of the objects listed.  It may be obtained from the schema name defined
  * in the statement or a role specification.
  *
- * SQL also allows constraints to make forward references, so thumb through
- * the table columns and move forward references to a posterior alter-table
- * command.
- *
  * The result is a list of parse nodes that still need to be analyzed ---
  * but we can't analyze the later commands until we've executed the earlier
  * ones, because of possible inter-object references.
- *
- * Note: this breaks the rules a little bit by modifying schema-name fields
- * within passed-in structs.  However, the transformation would be the same
- * if done over, so it should be all right to scribble on the input to this
- * extent.
  */
 List *
-transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
+transformCreateSchemaStmtElements(ParseState *pstate, List *schemaElts,
+                                                                 const char *schemaName)
 {
-       CreateSchemaStmtContext cxt;
-       List       *result;
-       ListCell   *elements;
-
-       cxt.schemaname = schemaName;
-       cxt.sequences = NIL;
-       cxt.tables = NIL;
-       cxt.views = NIL;
-       cxt.indexes = NIL;
-       cxt.triggers = NIL;
-       cxt.grants = NIL;
+       List       *elements = NIL;
+       ListCell   *lc;
 
        /*
-        * Run through each schema element in the schema element list. Separate
-        * statements by type, and do preliminary analysis.
+        * Run through each schema element in the schema element list.  Check
+        * target schema names, and collect the list of actions to be done.
         */
-       foreach(elements, schemaElts)
+       foreach(lc, schemaElts)
        {
-               Node       *element = lfirst(elements);
+               Node       *element = lfirst(lc);
 
                switch (nodeTag(element))
                {
@@ -4447,8 +4420,8 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                                {
                                        CreateSeqStmt *elp = (CreateSeqStmt *) element;
 
-                                       setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
-                                       cxt.sequences = lappend(cxt.sequences, element);
+                                       checkSchemaNameRV(pstate, schemaName, elp->sequence);
+                                       elements = lappend(elements, element);
                                }
                                break;
 
@@ -4456,12 +4429,8 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                                {
                                        CreateStmt *elp = (CreateStmt *) element;
 
-                                       setSchemaName(cxt.schemaname, &elp->relation->schemaname);
-
-                                       /*
-                                        * XXX todo: deal with constraints
-                                        */
-                                       cxt.tables = lappend(cxt.tables, element);
+                                       checkSchemaNameRV(pstate, schemaName, elp->relation);
+                                       elements = lappend(elements, element);
                                }
                                break;
 
@@ -4469,12 +4438,8 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                                {
                                        ViewStmt   *elp = (ViewStmt *) element;
 
-                                       setSchemaName(cxt.schemaname, &elp->view->schemaname);
-
-                                       /*
-                                        * XXX todo: deal with references between views
-                                        */
-                                       cxt.views = lappend(cxt.views, element);
+                                       checkSchemaNameRV(pstate, schemaName, elp->view);
+                                       elements = lappend(elements, element);
                                }
                                break;
 
@@ -4482,8 +4447,8 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                                {
                                        IndexStmt  *elp = (IndexStmt *) element;
 
-                                       setSchemaName(cxt.schemaname, &elp->relation->schemaname);
-                                       cxt.indexes = lappend(cxt.indexes, element);
+                                       checkSchemaNameRV(pstate, schemaName, elp->relation);
+                                       elements = lappend(elements, element);
                                }
                                break;
 
@@ -4491,13 +4456,13 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                                {
                                        CreateTrigStmt *elp = (CreateTrigStmt *) element;
 
-                                       setSchemaName(cxt.schemaname, &elp->relation->schemaname);
-                                       cxt.triggers = lappend(cxt.triggers, element);
+                                       checkSchemaNameRV(pstate, schemaName, elp->relation);
+                                       elements = lappend(elements, element);
                                }
                                break;
 
                        case T_GrantStmt:
-                               cxt.grants = lappend(cxt.grants, element);
+                               elements = lappend(elements, element);
                                break;
 
                        default:
@@ -4506,32 +4471,41 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
                }
        }
 
-       result = NIL;
-       result = list_concat(result, cxt.sequences);
-       result = list_concat(result, cxt.tables);
-       result = list_concat(result, cxt.views);
-       result = list_concat(result, cxt.indexes);
-       result = list_concat(result, cxt.triggers);
-       result = list_concat(result, cxt.grants);
-
-       return result;
+       return elements;
 }
 
 /*
- * setSchemaName
- *             Set or check schema name in an element of a CREATE SCHEMA command
+ * checkSchemaNameRV
+ *             Check schema name in an element of a CREATE SCHEMA command,
+ *             where the element's name is given by a RangeVar
+ *
+ * It's okay if the command doesn't specify a target schema name, because
+ * CreateSchemaCommand will set up the default creation schema to be the
+ * new schema.  But if a target schema name is given, it had better match.
+ * We also have to check that the command doesn't say CREATE TEMP, since
+ * that would likewise put the object into the wrong schema.
  */
 static void
-setSchemaName(const char *context_schema, char **stmt_schema_name)
+checkSchemaNameRV(ParseState *pstate, const char *context_schema,
+                                 RangeVar *relation)
 {
-       if (*stmt_schema_name == NULL)
-               *stmt_schema_name = unconstify(char *, context_schema);
-       else if (strcmp(context_schema, *stmt_schema_name) != 0)
+       if (relation->schemaname != NULL &&
+               strcmp(context_schema, relation->schemaname) != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
                                 errmsg("CREATE specifies a schema (%s) "
                                                "different from the one being created (%s)",
-                                               *stmt_schema_name, context_schema)));
+                                               relation->schemaname, context_schema),
+                                parser_errposition(pstate, relation->location)));
+
+       if (relation->relpersistence == RELPERSISTENCE_TEMP)
+       {
+               /* spell this error the same as in RangeVarAdjustRelationPersistence */
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+                                errmsg("cannot create temporary relation in non-temporary schema"),
+                                parser_errposition(pstate, relation->location)));
+       }
 }
 
 /*
index 5f8c766c4be2134fe47017c0ff2b5ca294161ca0..1d34c19913ee68a84449337c5a979859b6b2d2e1 100644 (file)
@@ -1122,8 +1122,8 @@ ProcessUtilitySlow(ParseState *pstate,
                                 * relation and attribute manipulation
                                 */
                        case T_CreateSchemaStmt:
-                               CreateSchemaCommand((CreateSchemaStmt *) parsetree,
-                                                                       queryString,
+                               CreateSchemaCommand(pstate,
+                                                                       (CreateSchemaStmt *) parsetree,
                                                                        pstmt->stmt_location,
                                                                        pstmt->stmt_len);
 
index d100e4691b3b67dd3b347a9418d87f73ce4d3446..b4348436dd38b0ddd19eb4bcc5ccb7f5ab4411c3 100644 (file)
 #define SCHEMACMDS_H
 
 #include "catalog/objectaddress.h"
-#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
 
-extern Oid     CreateSchemaCommand(CreateSchemaStmt *stmt,
-                                                               const char *queryString,
+extern Oid     CreateSchemaCommand(ParseState *pstate,
+                                                               CreateSchemaStmt *stmt,
                                                                int stmt_location, int stmt_len);
-
 extern ObjectAddress RenameSchema(const char *oldname, const char *newname);
 extern ObjectAddress AlterSchemaOwner(const char *name, Oid newOwnerId);
 extern void AlterSchemaOwner_oid(Oid schemaoid, Oid newOwnerId);
index 53f282f77ec172461404b5f52854607537ca290b..34c98e5122f4bb78d591e43fb887e41ce38957c9 100644 (file)
@@ -30,7 +30,8 @@ extern CreateStatsStmt *transformStatsStmt(Oid relid, CreateStatsStmt *stmt,
                                                                                   const char *queryString);
 extern void transformRuleStmt(RuleStmt *stmt, const char *queryString,
                                                          List **actions, Node **whereClause);
-extern List *transformCreateSchemaStmtElements(List *schemaElts,
+extern List *transformCreateSchemaStmtElements(ParseState *pstate,
+                                                                                          List *schemaElts,
                                                                                           const char *schemaName);
 extern PartitionBoundSpec *transformPartitionBound(ParseState *pstate, Relation parent,
                                                                                                   PartitionBoundSpec *spec);
index 93302a07efc36b32fba9c7f61c3c20676fd67f3e..4ab947a60a8ac52d4e8174ef3542a0ede3cdf13f 100644 (file)
@@ -9,55 +9,92 @@ CREATE ROLE regress_create_schema_role SUPERUSER;
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE SEQUENCE schema_not_existing.seq;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE SEQUENCE schema_not_existing.seq;
+                          ^
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE TABLE schema_not_existing.tab (id int);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE TABLE schema_not_existing.tab (id int);
+                       ^
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE VIEW schema_not_existing.view AS SELECT 1;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE VIEW schema_not_existing.view AS SELECT 1;
+                      ^
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE INDEX ON schema_not_existing.tab (id);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE INDEX ON schema_not_existing.tab (id);
+                          ^
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
   EXECUTE FUNCTION schema_trig.no_func();
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_exi...
+                                                      ^
 -- Again, with a role specification and no schema names.
 SET ROLE regress_create_schema_role;
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
   CREATE SEQUENCE schema_not_existing.seq;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE SEQUENCE schema_not_existing.seq;
+                          ^
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
   CREATE TABLE schema_not_existing.tab (id int);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE TABLE schema_not_existing.tab (id int);
+                       ^
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
   CREATE VIEW schema_not_existing.view AS SELECT 1;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE VIEW schema_not_existing.view AS SELECT 1;
+                      ^
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
   CREATE INDEX ON schema_not_existing.tab (id);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE INDEX ON schema_not_existing.tab (id);
+                          ^
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
   EXECUTE FUNCTION schema_trig.no_func();
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
+LINE 2:   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_exi...
+                                                      ^
 -- Again, with a schema name and a role specification.
 CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   CREATE SEQUENCE schema_not_existing.seq;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
+LINE 2:   CREATE SEQUENCE schema_not_existing.seq;
+                          ^
 CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   CREATE TABLE schema_not_existing.tab (id int);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
+LINE 2:   CREATE TABLE schema_not_existing.tab (id int);
+                       ^
 CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   CREATE VIEW schema_not_existing.view AS SELECT 1;
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
+LINE 2:   CREATE VIEW schema_not_existing.view AS SELECT 1;
+                      ^
 CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   CREATE INDEX ON schema_not_existing.tab (id);
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
+LINE 2:   CREATE INDEX ON schema_not_existing.tab (id);
+                          ^
 CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
   EXECUTE FUNCTION schema_trig.no_func();
 ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
+LINE 2:   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_exi...
+                                                      ^
 RESET ROLE;
+-- Forward references no longer work in general.
+CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
+  CREATE VIEW abcd_view AS SELECT a FROM abcd
+  CREATE TABLE abcd (a int);
+ERROR:  relation "abcd" does not exist
+LINE 2:   CREATE VIEW abcd_view AS SELECT a FROM abcd
+                                                 ^
 -- Cases where the schema creation succeeds.
 -- The schema created matches the role name.
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
index bc4f79938b360de47420ccd08cb3024a4b8c4b44..63cf4b4371d00ca0b77219bd27bb6bda735d9bcf 100644 (file)
@@ -128,6 +128,8 @@ ERROR:  cannot create temporary relation in non-temporary schema
 CREATE SCHEMA test_view_schema
     CREATE TEMP VIEW testview AS SELECT 1;
 ERROR:  cannot create temporary relation in non-temporary schema
+LINE 2:     CREATE TEMP VIEW testview AS SELECT 1;
+                             ^
 -- joins: if any of the join relations are temporary, the view
 -- should also be temporary
 -- should be non-temp
index f897b079e67e98d7430fa46f4bb24afb0c45e8f6..4c32e1dcaf5f6d32f59611785ef6ec4fe175588c 100644 (file)
@@ -425,13 +425,13 @@ NOTICE:  END: command_tag=CREATE TABLE type=table identity=evttrig.one
 NOTICE:  END: command_tag=CREATE INDEX type=index identity=evttrig.one_pkey
 NOTICE:  END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_a_seq
 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=CREATE INDEX type=index identity=evttrig.one_idx
 -- 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
index dbbda72d3951af6f67e4c7d7c355e7e934d9d1d5..2e582e783c261598feb7f01f0009cf18f2901a0b 100644 (file)
@@ -10,13 +10,14 @@ SELECT pg_catalog.set_config('search_path', ' ', false);
 (1 row)
 
 CREATE SCHEMA test_ns_schema_1
-       CREATE UNIQUE INDEX abc_a_idx ON abc (a)
-       CREATE VIEW abc_view AS
-              SELECT a+1 AS a, b+1 AS b FROM abc
        CREATE TABLE abc (
               a serial,
               b int UNIQUE
-       );
+       )
+       CREATE UNIQUE INDEX abc_a_idx ON abc (a)
+       CREATE VIEW abc_view AS
+              SELECT a+1 AS a, b+1 AS b FROM abc
+;
 -- verify that the correct search_path restored on abort
 SET search_path to public;
 BEGIN;
index 1b7064247a1c6697cf4d871530c4320051f46913..62651342114db930d465932d3acacbbb83b64c74 100644 (file)
@@ -47,6 +47,11 @@ CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
   EXECUTE FUNCTION schema_trig.no_func();
 RESET ROLE;
 
+-- Forward references no longer work in general.
+CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
+  CREATE VIEW abcd_view AS SELECT a FROM abcd
+  CREATE TABLE abcd (a int);
+
 -- Cases where the schema creation succeeds.
 -- The schema created matches the role name.
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
index 306cdc2d8c6a1cd3d4d7d83686a9046caab730cf..a75d4f580d3a64008f4af69116dc69950ea18cd0 100644 (file)
@@ -7,15 +7,16 @@
 SELECT pg_catalog.set_config('search_path', ' ', false);
 
 CREATE SCHEMA test_ns_schema_1
+       CREATE TABLE abc (
+              a serial,
+              b int UNIQUE
+       )
+
        CREATE UNIQUE INDEX abc_a_idx ON abc (a)
 
        CREATE VIEW abc_view AS
               SELECT a+1 AS a, b+1 AS b FROM abc
-
-       CREATE TABLE abc (
-              a serial,
-              b int UNIQUE
-       );
+;
 
 -- verify that the correct search_path restored on abort
 SET search_path to public;
index 4f8cc27d5b88ba61904fd7185375821277f078ab..e2d8dbdb03b00fe1b05a24b2e21b5ecfcc1e672c 100644 (file)
@@ -585,7 +585,6 @@ CreateRangeStmt
 CreateReplicationSlotCmd
 CreateRoleStmt
 CreateSchemaStmt
-CreateSchemaStmtContext
 CreateSeqStmt
 CreateStatsStmt
 CreateStmt