@@ -95,18 +95,6 @@ typedef struct
9595 bool ofType ; /* true if statement contains OF typename */
9696} CreateStmtContext ;
9797
98- /* State shared by transformCreateSchemaStmtElements and its subroutines */
99- typedef struct
100- {
101- const char * schemaname ; /* name of schema */
102- List * sequences ; /* CREATE SEQUENCE items */
103- List * tables ; /* CREATE TABLE items */
104- List * views ; /* CREATE VIEW items */
105- List * indexes ; /* CREATE INDEX items */
106- List * triggers ; /* CREATE TRIGGER items */
107- List * grants ; /* GRANT items */
108- } CreateSchemaStmtContext ;
109-
11098
11199static void transformColumnDefinition (CreateStmtContext * cxt ,
112100 ColumnDef * column );
@@ -133,7 +121,8 @@ static void transformCheckConstraints(CreateStmtContext *cxt,
133121static void transformConstraintAttrs (CreateStmtContext * cxt ,
134122 List * constraintList );
135123static void transformColumnType (CreateStmtContext * cxt , ColumnDef * column );
136- static void setSchemaName (const char * context_schema , char * * stmt_schema_name );
124+ static void checkSchemaName (ParseState * pstate , const char * context_schema ,
125+ RangeVar * relation );
137126static void transformPartitionCmd (CreateStmtContext * cxt , PartitionCmd * cmd );
138127static List * transformPartitionRangeBounds (ParseState * pstate , List * blist ,
139128 Relation parent );
@@ -4075,109 +4064,85 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
40754064 * transformCreateSchemaStmtElements -
40764065 * analyzes the elements of a CREATE SCHEMA statement
40774066 *
4078- * Split the schema element list from a CREATE SCHEMA statement into
4079- * individual commands and place them in the result list in an order
4080- * such that there are no forward references (e.g. GRANT to a table
4081- * created later in the list). Note that the logic we use for determining
4082- * forward references is presently quite incomplete.
4067+ * This is now somewhat vestigial: its only real responsibility is to complain
4068+ * if any of the elements are trying to create objects outside the new schema.
4069+ * We used to try to re-order the commands in a way that would work even if
4070+ * the user-written order would not, but that's too hard (perhaps impossible)
4071+ * to do correctly with not-yet-parse-analyzed commands. Now we'll just
4072+ * execute the elements in the order given.
40834073 *
40844074 * "schemaName" is the name of the schema that will be used for the creation
4085- * of the objects listed, that may be compiled from the schema name defined
4075+ * of the objects listed. It may be obtained from the schema name defined
40864076 * in the statement or a role specification.
40874077 *
4088- * SQL also allows constraints to make forward references, so thumb through
4089- * the table columns and move forward references to a posterior alter-table
4090- * command.
4091- *
40924078 * The result is a list of parse nodes that still need to be analyzed ---
40934079 * but we can't analyze the later commands until we've executed the earlier
40944080 * ones, because of possible inter-object references.
4095- *
4096- * Note: this breaks the rules a little bit by modifying schema-name fields
4097- * within passed-in structs. However, the transformation would be the same
4098- * if done over, so it should be all right to scribble on the input to this
4099- * extent.
41004081 */
41014082List *
4102- transformCreateSchemaStmtElements (List * schemaElts , const char * schemaName )
4083+ transformCreateSchemaStmtElements (ParseState * pstate , List * schemaElts ,
4084+ const char * schemaName )
41034085{
4104- CreateSchemaStmtContext cxt ;
4105- List * result ;
4106- ListCell * elements ;
4107-
4108- cxt .schemaname = schemaName ;
4109- cxt .sequences = NIL ;
4110- cxt .tables = NIL ;
4111- cxt .views = NIL ;
4112- cxt .indexes = NIL ;
4113- cxt .triggers = NIL ;
4114- cxt .grants = NIL ;
4086+ List * elements = NIL ;
4087+ ListCell * lc ;
41154088
41164089 /*
4117- * Run through each schema element in the schema element list. Separate
4118- * statements by type , and do preliminary analysis .
4090+ * Run through each schema element in the schema element list. Check
4091+ * target schema names , and collect the list of actions to be done .
41194092 */
4120- foreach (elements , schemaElts )
4093+ foreach (lc , schemaElts )
41214094 {
4122- Node * element = lfirst (elements );
4095+ Node * element = lfirst (lc );
41234096
41244097 switch (nodeTag (element ))
41254098 {
41264099 case T_CreateSeqStmt :
41274100 {
41284101 CreateSeqStmt * elp = (CreateSeqStmt * ) element ;
41294102
4130- setSchemaName ( cxt . schemaname , & elp -> sequence -> schemaname );
4131- cxt . sequences = lappend (cxt . sequences , element );
4103+ checkSchemaName ( pstate , schemaName , elp -> sequence );
4104+ elements = lappend (elements , element );
41324105 }
41334106 break ;
41344107
41354108 case T_CreateStmt :
41364109 {
41374110 CreateStmt * elp = (CreateStmt * ) element ;
41384111
4139- setSchemaName (cxt .schemaname , & elp -> relation -> schemaname );
4140-
4141- /*
4142- * XXX todo: deal with constraints
4143- */
4144- cxt .tables = lappend (cxt .tables , element );
4112+ checkSchemaName (pstate , schemaName , elp -> relation );
4113+ elements = lappend (elements , element );
41454114 }
41464115 break ;
41474116
41484117 case T_ViewStmt :
41494118 {
41504119 ViewStmt * elp = (ViewStmt * ) element ;
41514120
4152- setSchemaName (cxt .schemaname , & elp -> view -> schemaname );
4153-
4154- /*
4155- * XXX todo: deal with references between views
4156- */
4157- cxt .views = lappend (cxt .views , element );
4121+ checkSchemaName (pstate , schemaName , elp -> view );
4122+ elements = lappend (elements , element );
41584123 }
41594124 break ;
41604125
41614126 case T_IndexStmt :
41624127 {
41634128 IndexStmt * elp = (IndexStmt * ) element ;
41644129
4165- setSchemaName ( cxt . schemaname , & elp -> relation -> schemaname );
4166- cxt . indexes = lappend (cxt . indexes , element );
4130+ checkSchemaName ( pstate , schemaName , elp -> relation );
4131+ elements = lappend (elements , element );
41674132 }
41684133 break ;
41694134
41704135 case T_CreateTrigStmt :
41714136 {
41724137 CreateTrigStmt * elp = (CreateTrigStmt * ) element ;
41734138
4174- setSchemaName ( cxt . schemaname , & elp -> relation -> schemaname );
4175- cxt . triggers = lappend (cxt . triggers , element );
4139+ checkSchemaName ( pstate , schemaName , elp -> relation );
4140+ elements = lappend (elements , element );
41764141 }
41774142 break ;
41784143
41794144 case T_GrantStmt :
4180- cxt . grants = lappend (cxt . grants , element );
4145+ elements = lappend (elements , element );
41814146 break ;
41824147
41834148 default :
@@ -4186,32 +4151,40 @@ transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
41864151 }
41874152 }
41884153
4189- result = NIL ;
4190- result = list_concat (result , cxt .sequences );
4191- result = list_concat (result , cxt .tables );
4192- result = list_concat (result , cxt .views );
4193- result = list_concat (result , cxt .indexes );
4194- result = list_concat (result , cxt .triggers );
4195- result = list_concat (result , cxt .grants );
4196-
4197- return result ;
4154+ return elements ;
41984155}
41994156
42004157/*
4201- * setSchemaName
4202- * Set or check schema name in an element of a CREATE SCHEMA command
4158+ * checkSchemaName
4159+ * Check schema name in an element of a CREATE SCHEMA command
4160+ *
4161+ * It's okay if the command doesn't specify a target schema name, because
4162+ * CreateSchemaCommand will set up the default creation schema to be the
4163+ * new schema. But if a target schema name is given, it had better match.
4164+ * We also have to check that the command doesn't say CREATE TEMP, since
4165+ * that would likewise put the object into the wrong schema.
42034166 */
42044167static void
4205- setSchemaName (const char * context_schema , char * * stmt_schema_name )
4168+ checkSchemaName (ParseState * pstate , const char * context_schema ,
4169+ RangeVar * relation )
42064170{
4207- if (* stmt_schema_name == NULL )
4208- * stmt_schema_name = unconstify (char * , context_schema );
4209- else if (strcmp (context_schema , * stmt_schema_name ) != 0 )
4171+ if (relation -> schemaname != NULL &&
4172+ strcmp (context_schema , relation -> schemaname ) != 0 )
42104173 ereport (ERROR ,
4211- ( errcode (ERRCODE_INVALID_SCHEMA_DEFINITION ),
4212- errmsg ("CREATE specifies a schema (%s) "
4174+ errcode (ERRCODE_INVALID_SCHEMA_DEFINITION ),
4175+ errmsg ("CREATE specifies a schema (%s) "
42134176 "different from the one being created (%s)" ,
4214- * stmt_schema_name , context_schema )));
4177+ relation -> schemaname , context_schema ),
4178+ parser_errposition (pstate , relation -> location ));
4179+
4180+ if (relation -> relpersistence == RELPERSISTENCE_TEMP )
4181+ {
4182+ /* spell this error the same as in RangeVarAdjustRelationPersistence */
4183+ ereport (ERROR ,
4184+ errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
4185+ errmsg ("cannot create temporary relation in non-temporary schema" ),
4186+ parser_errposition (pstate , relation -> location ));
4187+ }
42154188}
42164189
42174190/*
0 commit comments