Add CREATE TRIGGER, CREATE INDEX, and CREATE SEQUENCE to the list of

expressions supported by CREATE SCHEMA.

Also added the beginning of some regression tests for CREATE SCHEMA;
plenty more work is needed here.
This commit is contained in:
Neil Conway 2004-01-11 04:58:17 +00:00
parent 4cdf51e646
commit e97b8f2da9
7 changed files with 155 additions and 31 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.9 2003/11/29 19:51:38 pgsql Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.10 2004/01/11 04:58:17 neilc Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -84,11 +84,13 @@ CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">username</replaceable
<term><replaceable class="parameter">schema_element</replaceable></term> <term><replaceable class="parameter">schema_element</replaceable></term>
<listitem> <listitem>
<para> <para>
An SQL statement defining an object to be created within the schema. An SQL statement defining an object to be created within the
Currently, only <command>CREATE TABLE</>, <command>CREATE VIEW</>, schema. Currently, only <command>CREATE
and <command>GRANT</> are accepted as clauses within TABLE</>, <command>CREATE VIEW</>, <command>CREATE
<command>CREATE SCHEMA</>. Other kinds of objects may be created INDEX</>, <command>CREATE SEQUENCE</>, <command>CREATE
in separate commands after the schema is created. 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> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.294 2004/01/10 23:28:45 neilc Exp $ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.295 2004/01/11 04:58:17 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -54,8 +54,11 @@ typedef struct
const char *stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */ const char *stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */
char *schemaname; /* name of schema */ char *schemaname; /* name of schema */
char *authid; /* owner of schema */ char *authid; /* owner of schema */
List *sequences; /* CREATE SEQUENCE items */
List *tables; /* CREATE TABLE items */ List *tables; /* CREATE TABLE items */
List *views; /* CREATE VIEW items */ List *views; /* CREATE VIEW items */
List *indexes; /* CREATE INDEX items */
List *triggers; /* CREATE TRIGGER items */
List *grants; /* GRANT items */ List *grants; /* GRANT items */
List *fwconstraints; /* Forward referencing FOREIGN KEY List *fwconstraints; /* Forward referencing FOREIGN KEY
* constraints */ * constraints */
@ -3152,13 +3155,28 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
ReleaseSysCache(ctype); 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 - * analyzeCreateSchemaStmt -
* analyzes the "create schema" statement * analyzes the "create schema" statement
* *
* Split the schema element list into individual commands and place * Split the schema element list into individual commands and place
* them in the result list in an order such that there are no * them in the result list in an order such that there are no forward
* forward references (e.g. GRANT to a table created later in the list). * 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 * SQL92 also allows constraints to make forward references, so thumb through
* the table columns and move forward references to a posterior alter-table * the table columns and move forward references to a posterior alter-table
@ -3168,7 +3186,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
* but we can't analyze the later commands until we've executed the earlier * but we can't analyze the later commands until we've executed the earlier
* ones, because of possible inter-object references. * ones, because of possible inter-object references.
* *
* Note: Called from commands/command.c * Note: Called from commands/schemacmds.c
*/ */
List * List *
analyzeCreateSchemaStmt(CreateSchemaStmt *stmt) analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
@ -3180,9 +3198,12 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
cxt.stmtType = "CREATE SCHEMA"; cxt.stmtType = "CREATE SCHEMA";
cxt.schemaname = stmt->schemaname; cxt.schemaname = stmt->schemaname;
cxt.authid = stmt->authid; cxt.authid = stmt->authid;
cxt.sequences = NIL;
cxt.tables = NIL; cxt.tables = NIL;
cxt.views = NIL; cxt.views = NIL;
cxt.indexes = NIL;
cxt.grants = NIL; cxt.grants = NIL;
cxt.triggers = NIL;
cxt.fwconstraints = NIL; cxt.fwconstraints = NIL;
cxt.alters = NIL; cxt.alters = NIL;
cxt.blist = NIL; cxt.blist = NIL;
@ -3198,23 +3219,24 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
switch (nodeTag(element)) 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: case T_CreateStmt:
{ {
CreateStmt *elp = (CreateStmt *) element; CreateStmt *elp = (CreateStmt *) element;
if (elp->relation->schemaname == NULL) setSchemaName(cxt.schemaname, &elp->relation->schemaname);
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 * XXX todo: deal with constraints
*/ */
cxt.tables = lappend(cxt.tables, element); cxt.tables = lappend(cxt.tables, element);
} }
break; break;
@ -3223,23 +3245,33 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
{ {
ViewStmt *elp = (ViewStmt *) element; ViewStmt *elp = (ViewStmt *) element;
if (elp->view->schemaname == NULL) setSchemaName(cxt.schemaname, &elp->view->schemaname);
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 * XXX todo: deal with references between views
*/ */
cxt.views = lappend(cxt.views, element); cxt.views = lappend(cxt.views, element);
} }
break; 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: case T_GrantStmt:
cxt.grants = lappend(cxt.grants, element); cxt.grants = lappend(cxt.grants, element);
break; break;
@ -3251,8 +3283,11 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
} }
result = NIL; result = NIL;
result = nconc(result, cxt.sequences);
result = nconc(result, cxt.tables); result = nconc(result, cxt.tables);
result = nconc(result, cxt.views); result = nconc(result, cxt.views);
result = nconc(result, cxt.indexes);
result = nconc(result, cxt.triggers);
result = nconc(result, cxt.grants); result = nconc(result, cxt.grants);
return result; return result;

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.445 2004/01/10 23:28:45 neilc Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.446 2004/01/11 04:58:17 neilc Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -815,6 +815,9 @@ OptSchemaEltList:
*/ */
schema_stmt: schema_stmt:
CreateStmt CreateStmt
| IndexStmt
| CreateSeqStmt
| CreateTrigStmt
| GrantStmt | GrantStmt
| ViewStmt | ViewStmt
; ;

View File

@ -0,0 +1,52 @@
--
-- Regression tests for schemas (namespaces)
--
CREATE SCHEMA test_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
);
NOTICE: CREATE TABLE will create implicit sequence "abc_a_seq" for "serial" column "abc.a"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "abc_b_key" for table "abc"
-- verify that the objects were created
SELECT COUNT(*) FROM pg_class WHERE relnamespace =
(SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');
count
-------
5
(1 row)
INSERT INTO test_schema_1.abc DEFAULT VALUES;
INSERT INTO test_schema_1.abc DEFAULT VALUES;
INSERT INTO test_schema_1.abc DEFAULT VALUES;
SELECT * FROM test_schema_1.abc;
a | b
---+---
1 |
2 |
3 |
(3 rows)
SELECT * FROM test_schema_1.abc_view;
a | b
---+---
2 |
3 |
4 |
(3 rows)
DROP SCHEMA test_schema_1 CASCADE;
NOTICE: drop cascades to view test_schema_1.abc_view
NOTICE: drop cascades to rule _RETURN on view test_schema_1.abc_view
NOTICE: drop cascades to table test_schema_1.abc
-- verify that the objects were dropped
SELECT COUNT(*) FROM pg_class WHERE relnamespace =
(SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');
count
-------
0
(1 row)

View File

@ -60,7 +60,7 @@ ignore: random
# ---------- # ----------
# The fourth group of parallel test # The fourth group of parallel test
# ---------- # ----------
test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update namespace
test: privileges test: privileges
test: misc test: misc

View File

@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.23 2003/11/29 19:52:14 pgsql Exp $ # $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.24 2004/01/11 04:58:17 neilc Exp $
# This should probably be in an order similar to parallel_schedule. # This should probably be in an order similar to parallel_schedule.
test: boolean test: boolean
test: char test: char
@ -73,6 +73,7 @@ test: arrays
test: btree_index test: btree_index
test: hash_index test: hash_index
test: update test: update
test: namespace
test: privileges test: privileges
test: misc test: misc
test: select_views test: select_views

View File

@ -0,0 +1,31 @@
--
-- Regression tests for schemas (namespaces)
--
CREATE SCHEMA test_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
);
-- verify that the objects were created
SELECT COUNT(*) FROM pg_class WHERE relnamespace =
(SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');
INSERT INTO test_schema_1.abc DEFAULT VALUES;
INSERT INTO test_schema_1.abc DEFAULT VALUES;
INSERT INTO test_schema_1.abc DEFAULT VALUES;
SELECT * FROM test_schema_1.abc;
SELECT * FROM test_schema_1.abc_view;
DROP SCHEMA test_schema_1 CASCADE;
-- verify that the objects were dropped
SELECT COUNT(*) FROM pg_class WHERE relnamespace =
(SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');