This patch adds a few additional commands to the list of expressions
accepted by CREATE SCHEMA: CREATE INDEX, CREATE SEQUENCE, and CREATE
TRIGGER are now supported. The latter two are required by SQL 200x,
while the first is merely useful.
Unless anyone objects, I intend to apply this patch by the end of the
week (I might add a few more commands to the set of allowed
expressions first).
-Neil
Index: doc/src/sgml/ref/create_schema.sgml
===================================================================
RCS file: /var/lib/cvs/pgsql-server/doc/src/sgml/ref/create_schema.sgml,v
retrieving revision 1.9
diff -c -r1.9 create_schema.sgml
*** doc/src/sgml/ref/create_schema.sgml 29 Nov 2003 19:51:38 -0000 1.9
--- doc/src/sgml/ref/create_schema.sgml 5 Jan 2004 21:14:36 -0000
***************
*** 84,94 ****
<term><replaceable class="parameter">schema_element</replaceable></term>
<listitem>
<para>
! An SQL statement defining an object to be created within the schema.
! Currently, only <command>CREATE TABLE</>, <command>CREATE VIEW</>,
! and <command>GRANT</> are accepted as clauses within
! <command>CREATE SCHEMA</>. Other kinds of objects may be created
! in separate commands after the schema is created.
</para>
</listitem>
</varlistentry>
--- 84,96 ----
<term><replaceable class="parameter">schema_element</replaceable></term>
<listitem>
<para>
! An SQL statement defining an object to be created within the
! schema. Currently, only <command>CREATE
! TABLE</>, <command>CREATE VIEW</>, <command>CREATE
! INDEX</>, <command>CREATE SEQUENCE</>, <command>CREATE
! TRIGGER</> and <command>GRANT</> are accepted as clauses
! within <command>CREATE SCHEMA</>. Other kinds of objects may
! be created in separate commands after the schema is created.
</para>
</listitem>
</varlistentry>
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/parser/analyze.c,v
retrieving revision 1.292
diff -c -r1.292 analyze.c
*** src/backend/parser/analyze.c 29 Nov 2003 19:51:51 -0000 1.292
--- src/backend/parser/analyze.c 5 Jan 2004 21:15:42 -0000
***************
*** 53,60 ****
--- 53,63 ----
const char *stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */
char *schemaname; /* name of schema */
char *authid; /* owner 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 */
List *fwconstraints; /* Forward referencing FOREIGN KEY
* constraints */
***************
*** 3126,3138 ****
ReleaseSysCache(ctype);
}
/*
* analyzeCreateSchemaStmt -
* analyzes the "create schema" statement
*
* Split the schema element list 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).
*
* SQL92 also allows constraints to make forward references, so thumb through
* the table columns and move forward references to a posterior alter-table
--- 3129,3156 ----
ReleaseSysCache(ctype);
}
+ static void
+ setSchemaName(char *context_schema, char **stmt_schema_name)
+ {
+ if (*stmt_schema_name == NULL)
+ *stmt_schema_name = context_schema;
+ else if (strcmp(context_schema, *stmt_schema_name) != 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)));
+ }
+
/*
* analyzeCreateSchemaStmt -
* analyzes the "create schema" statement
*
* Split the schema element list 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.
*
* SQL92 also allows constraints to make forward references, so thumb through
* the table columns and move forward references to a posterior alter-table
***************
*** 3142,3148 ****
* but we can't analyze the later commands until we've executed the earlier
* ones, because of possible inter-object references.
*
! * Note: Called from commands/command.c
*/
List *
analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
--- 3160,3166 ----
* but we can't analyze the later commands until we've executed the earlier
* ones, because of possible inter-object references.
*
! * Note: Called from commands/schemacmds.c
*/
List *
analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
***************
*** 3154,3162 ****
--- 3172,3183 ----
cxt.stmtType = "CREATE SCHEMA";
cxt.schemaname = stmt->schemaname;
cxt.authid = stmt->authid;
+ cxt.sequences = NIL;
cxt.tables = NIL;
cxt.views = NIL;
+ cxt.indexes = NIL;
cxt.grants = NIL;
+ cxt.triggers = NIL;
cxt.fwconstraints = NIL;
cxt.alters = NIL;
cxt.blist = NIL;
***************
*** 3172,3194 ****
switch (nodeTag(element))
{
case T_CreateStmt:
{
CreateStmt *elp = (CreateStmt *) element;
! if (elp->relation->schemaname == NULL)
! elp->relation->schemaname = cxt.schemaname;
! else if (strcmp(cxt.schemaname, elp->relation->schemaname) != 0)
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
! errmsg("CREATE specifies a schema (%s)"
! " different from the one being created (%s)",
! elp->relation->schemaname, cxt.schemaname)));
/*
* XXX todo: deal with constraints
*/
-
cxt.tables = lappend(cxt.tables, element);
}
break;
--- 3193,3216 ----
switch (nodeTag(element))
{
+ case T_CreateSeqStmt:
+ {
+ CreateSeqStmt *elp = (CreateSeqStmt *) element;
+
+ setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
+ cxt.sequences = lappend(cxt.sequences, element);
+ }
+ break;
+
case T_CreateStmt:
{
CreateStmt *elp = (CreateStmt *) element;
! setSchemaName(cxt.schemaname, &elp->relation->schemaname);
/*
* XXX todo: deal with constraints
*/
cxt.tables = lappend(cxt.tables, element);
}
break;
***************
*** 3197,3219 ****
{
ViewStmt *elp = (ViewStmt *) element;
! if (elp->view->schemaname == NULL)
! elp->view->schemaname = cxt.schemaname;
! else if (strcmp(cxt.schemaname, elp->view->schemaname) != 0)
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
! errmsg("CREATE specifies a schema (%s)"
! " different from the one being created (%s)",
! elp->view->schemaname, cxt.schemaname)));
/*
* XXX todo: deal with references between views
*/
-
cxt.views = lappend(cxt.views, element);
}
break;
case T_GrantStmt:
cxt.grants = lappend(cxt.grants, element);
break;
--- 3219,3251 ----
{
ViewStmt *elp = (ViewStmt *) element;
! setSchemaName(cxt.schemaname, &elp->view->schemaname);
/*
* XXX todo: deal with references between views
*/
cxt.views = lappend(cxt.views, element);
}
break;
+ case T_IndexStmt:
+ {
+ IndexStmt *elp = (IndexStmt *) element;
+
+ setSchemaName(cxt.schemaname, &elp->relation->schemaname);
+ cxt.indexes = lappend(cxt.indexes, element);
+ }
+ break;
+
+ case T_CreateTrigStmt:
+ {
+ CreateTrigStmt *elp = (CreateTrigStmt *) element;
+
+ setSchemaName(cxt.schemaname, &elp->relation->schemaname);
+ cxt.triggers = lappend(cxt.triggers, element);
+ }
+ break;
+
case T_GrantStmt:
cxt.grants = lappend(cxt.grants, element);
break;
***************
*** 3225,3232 ****
--- 3257,3267 ----
}
result = NIL;
+ result = nconc(result, cxt.sequences);
result = nconc(result, cxt.tables);
result = nconc(result, cxt.views);
+ result = nconc(result, cxt.indexes);
+ result = nconc(result, cxt.triggers);
result = nconc(result, cxt.grants);
return result;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/parser/gram.y,v
retrieving revision 2.441
diff -c -r2.441 gram.y
*** src/backend/parser/gram.y 1 Dec 2003 22:07:58 -0000 2.441
--- src/backend/parser/gram.y 5 Jan 2004 21:14:36 -0000
***************
*** 811,816 ****
--- 811,819 ----
*/
schema_stmt:
CreateStmt
+ | IndexStmt
+ | CreateSeqStmt
+ | CreateTrigStmt
| GrantStmt
| ViewStmt
;
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match