Add CREATE TRIGGER, CREATE INDEX, and CREATE SEQUENCE to the list of
authorNeil Conway <neilc@samurai.com>
Sun, 11 Jan 2004 04:58:17 +0000 (04:58 +0000)
committerNeil Conway <neilc@samurai.com>
Sun, 11 Jan 2004 04:58:17 +0000 (04:58 +0000)
expressions supported by CREATE SCHEMA.

Also added the beginning of some regression tests for CREATE SCHEMA;
plenty more work is needed here.

doc/src/sgml/ref/create_schema.sgml
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/test/regress/expected/namespace.out [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/namespace.sql [new file with mode: 0644]

index e348ff58797f38eb3c2d702b4c47cc6f1272f626..4c0f61ad95a5a0f5c776aaf33f88a1be5de3cb6a 100644 (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
 -->
 
@@ -84,11 +84,13 @@ CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">username</replaceable
       <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.
+        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 bc70cca429a4371c1b7a96ee5d0c9e7e982823e5..33f32c1b377fb6e3321aff44f22d484147f5dbc1 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * 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" */
        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 */
@@ -3152,13 +3155,28 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
        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).
+ * 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
@@ -3168,7 +3186,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
  * 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
+ * Note: Called from commands/schemacmds.c
  */
 List *
 analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
@@ -3180,9 +3198,12 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
        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;
@@ -3198,23 +3219,24 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
 
                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;
 
-                                       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)));
+                                       setSchemaName(cxt.schemaname, &elp->relation->schemaname);
 
                                        /*
                                         * XXX todo: deal with constraints
                                         */
-
                                        cxt.tables = lappend(cxt.tables, element);
                                }
                                break;
@@ -3223,23 +3245,33 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
                                {
                                        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)));
+                                       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;
@@ -3251,8 +3283,11 @@ analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
        }
 
        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 535da4f2b50523a955403203e7bc06ff12de10cd..6057071653737b7604c853cef4b6c6b8168d9f1e 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * 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
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -815,6 +815,9 @@ OptSchemaEltList:
  */
 schema_stmt:
                        CreateStmt
+                       | IndexStmt
+                       | CreateSeqStmt
+                       | CreateTrigStmt
                        | GrantStmt
                        | ViewStmt
                ;
diff --git a/src/test/regress/expected/namespace.out b/src/test/regress/expected/namespace.out
new file mode 100644 (file)
index 0000000..60e3a82
--- /dev/null
@@ -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)
+
index a2e34d0f2ab53ec2afd36ee97c821f627b1c37e3..43a7bcff9aca61840c0fede33983764cd0c83afc 100644 (file)
@@ -60,7 +60,7 @@ ignore: random
 # ----------
 # 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: misc
index 5f3a7bba9a5227d46ab99b9019a32c5acbbc96cd..61ac9eff335e90d327c3e84609acb5936eabbd5f 100644 (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.
 test: boolean
 test: char
@@ -73,6 +73,7 @@ test: arrays
 test: btree_index
 test: hash_index
 test: update
+test: namespace
 test: privileges
 test: misc
 test: select_views
diff --git a/src/test/regress/sql/namespace.sql b/src/test/regress/sql/namespace.sql
new file mode 100644 (file)
index 0000000..919f72a
--- /dev/null
@@ -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');