]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Support more object types within CREATE SCHEMA.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Apr 2026 19:16:21 +0000 (15:16 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Apr 2026 19:16:25 +0000 (15:16 -0400)
Having rejected the principle that we should know how to re-order
the sub-commands of CREATE SCHEMA, there is not really anything
except a little coding to stop us from supporting more object types.
This patch adds support for creating functions (including procedures
and aggregates), operators, types (including domains), collations,
and text search objects.

SQL:2021 specifies that we should allow functions, procedures,
types, domains, and collations, so this moves us a great deal
closer to full SQL compatibility of CREATE SCHEMA.  What remains
missing from their list are casts, transforms, roles, and some
object types we don't support yet (e.g. CREATE CHARACTER SET).
Supporting casts or transforms would be problematic because
they don't have names at all, let alone schema-qualified names,
so it'd be quite a stretch to say that they belong to a schema.
Roles likewise are not schema-qualified, plus they are global
to a cluster, making it even less reasonable to consider them
as belonging to a schema.  So I don't see us trying to complete
the list.

User-defined aggregates and operators are outside the spec's ken,
as are text search objects, so adding them does not do anything for
spec compatibility.  But they go along with these other object types,
plus it takes no additional code to support them since they are
represented as DefineStmts like some variants of CREATE TYPE.
It would indeed take some effort to reject them.

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

doc/src/sgml/ref/create_schema.sgml
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/bin/psql/tab-complete.in.c
src/fe_utils/psqlscan.l
src/test/modules/test_ddl_deparse/expected/create_schema.out
src/test/modules/test_ddl_deparse/sql/create_schema.sql
src/test/regress/expected/create_schema.out
src/test/regress/sql/create_schema.sql

index 96bc496e7777f18542721830794dfcdbd87f6743..4ecf82d6bcb7bc77f4a01774c5dc18d5bb79733b 100644 (file)
@@ -100,12 +100,27 @@ CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="parameter">role_sp
       <listitem>
        <para>
         An SQL statement defining an object to be created within the
-        schema. Currently, only <command>CREATE
-        TABLE</command>, <command>CREATE VIEW</command>, <command>CREATE
-        INDEX</command>, <command>CREATE SEQUENCE</command>, <command>CREATE
-        TRIGGER</command> and <command>GRANT</command> are accepted as clauses
+        schema. Currently, only
+        <command>CREATE AGGREGATE</command>,
+        <command>CREATE COLLATION</command>,
+        <command>CREATE DOMAIN</command>,
+        <command>CREATE FUNCTION</command>,
+        <command>CREATE INDEX</command>,
+        <command>CREATE OPERATOR</command>,
+        <command>CREATE PROCEDURE</command>,
+        <command>CREATE SEQUENCE</command>,
+        <command>CREATE TABLE</command>,
+        <command>CREATE TEXT SEARCH CONFIGURATION</command>,
+        <command>CREATE TEXT SEARCH DICTIONARY</command>,
+        <command>CREATE TEXT SEARCH PARSER</command>,
+        <command>CREATE TEXT SEARCH TEMPLATE</command>,
+        <command>CREATE TRIGGER</command>,
+        <command>CREATE TYPE</command>,
+        <command>CREATE VIEW</command>,
+        and <command>GRANT</command> are accepted as clauses
         within <command>CREATE SCHEMA</command>. Other kinds of objects may
-        be created in separate commands after the schema is created.
+        be created within the schema in separate commands after the schema
+        is created.
        </para>
       </listitem>
      </varlistentry>
index f4a08baa95aa6b564709a61236259b6559e6b2d3..2d1b19d1f53c4df2438d9ae4143cb45522ba68f5 100644 (file)
@@ -1679,8 +1679,11 @@ OptSchemaEltList:
 schema_stmt:
                        CreateStmt
                        | IndexStmt
+                       | CreateDomainStmt
+                       | CreateFunctionStmt
                        | CreateSeqStmt
                        | CreateTrigStmt
+                       | DefineStmt
                        | GrantStmt
                        | ViewStmt
                ;
index b0c3407b23d464d870b612955a63e29d04f9494c..e135c91a6adfc923567d68aaea3af9a37c04d505 100644 (file)
@@ -127,6 +127,8 @@ static void transformConstraintAttrs(ParseState *pstate,
 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
 static void checkSchemaNameRV(ParseState *pstate, const char *context_schema,
                                                          RangeVar *relation);
+static void checkSchemaNameList(const char *context_schema,
+                                                               List *qualified_name);
 static CreateStmt *transformCreateSchemaCreateTable(ParseState *pstate,
                                                                                                        CreateStmt *stmt,
                                                                                                        List **fk_elements);
@@ -4481,6 +4483,68 @@ transformCreateSchemaStmtElements(ParseState *pstate, List *schemaElts,
                                }
                                break;
 
+                       case T_CreateDomainStmt:
+                               {
+                                       CreateDomainStmt *elp = (CreateDomainStmt *) element;
+
+                                       checkSchemaNameList(schemaName, elp->domainname);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
+                       case T_CreateFunctionStmt:
+                               {
+                                       CreateFunctionStmt *elp = (CreateFunctionStmt *) element;
+
+                                       checkSchemaNameList(schemaName, elp->funcname);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
+                               /*
+                                * CREATE TYPE can produce a DefineStmt, but also
+                                * CreateEnumStmt, CreateRangeStmt, and CompositeTypeStmt.
+                                * Allowing DefineStmt also provides support for several other
+                                * commands: currently, CREATE AGGREGATE, CREATE COLLATION,
+                                * CREATE OPERATOR, and text search objects.
+                                */
+
+                       case T_DefineStmt:
+                               {
+                                       DefineStmt *elp = (DefineStmt *) element;
+
+                                       checkSchemaNameList(schemaName, elp->defnames);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
+                       case T_CreateEnumStmt:
+                               {
+                                       CreateEnumStmt *elp = (CreateEnumStmt *) element;
+
+                                       checkSchemaNameList(schemaName, elp->typeName);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
+                       case T_CreateRangeStmt:
+                               {
+                                       CreateRangeStmt *elp = (CreateRangeStmt *) element;
+
+                                       checkSchemaNameList(schemaName, elp->typeName);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
+                       case T_CompositeTypeStmt:
+                               {
+                                       CompositeTypeStmt *elp = (CompositeTypeStmt *) element;
+
+                                       checkSchemaNameRV(pstate, schemaName, elp->typevar);
+                                       elements = lappend(elements, element);
+                               }
+                               break;
+
                        case T_GrantStmt:
                                elements = lappend(elements, element);
                                break;
@@ -4528,6 +4592,30 @@ checkSchemaNameRV(ParseState *pstate, const char *context_schema,
        }
 }
 
+/*
+ * checkSchemaNameList
+ *             Check schema name in an element of a CREATE SCHEMA command,
+ *             where the element's name is given by a List
+ *
+ * Much as above, but we don't have to worry about TEMP.
+ * Sadly, this also means we don't have a parse location to report.
+ */
+static void
+checkSchemaNameList(const char *context_schema, List *qualified_name)
+{
+       char       *obj_schema;
+       char       *obj_name;
+
+       DeconstructQualifiedName(qualified_name, &obj_schema, &obj_name);
+       if (obj_schema != NULL &&
+               strcmp(context_schema, obj_schema) != 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
+                                errmsg("CREATE specifies a schema (%s) "
+                                               "different from the one being created (%s)",
+                                               obj_schema, context_schema)));
+}
+
 /*
  * transformCreateSchemaCreateTable
  *             Process one CreateStmt for transformCreateSchemaStmtElements.
index 1d941c11997bb2f15bf329388456b76b6639ee26..ed15c1b4f836cd7aa7fc779362d05314e423fda4 100644 (file)
@@ -2211,7 +2211,11 @@ match_previous_words(int pattern_id,
        {
                /* only some object types can be created as part of CREATE SCHEMA */
                if (HeadMatches("CREATE", "SCHEMA"))
-                       COMPLETE_WITH("TABLE", "VIEW", "INDEX", "SEQUENCE", "TRIGGER",
+                       COMPLETE_WITH("AGGREGATE", "COLLATION", "DOMAIN", "FUNCTION",
+                                                 "INDEX", "OPERATOR", "PROCEDURE", "SEQUENCE", "TABLE",
+                                                 "TEXT SEARCH CONFIGURATION", "TEXT SEARCH DICTIONARY",
+                                                 "TEXT SEARCH PARSER", "TEXT SEARCH TEMPLATE",
+                                                 "TRIGGER", "TYPE", "VIEW",
                        /* for INDEX and TABLE/SEQUENCE, respectively */
                                                  "UNIQUE", "UNLOGGED");
                else
@@ -3535,15 +3539,15 @@ match_previous_words(int pattern_id,
        else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
                COMPLETE_WITH("WAL_LOG", "FILE_COPY");
 
-       /* CREATE DOMAIN */
-       else if (Matches("CREATE", "DOMAIN", MatchAny))
+       /* CREATE DOMAIN --- is allowed inside CREATE SCHEMA, so use TailMatches */
+       else if (TailMatches("CREATE", "DOMAIN", MatchAny))
                COMPLETE_WITH("AS");
-       else if (Matches("CREATE", "DOMAIN", MatchAny, "AS"))
+       else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS"))
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
-       else if (Matches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
+       else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
                COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
                                          "NOT NULL", "NULL", "CHECK (");
-       else if (Matches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
+       else if (TailMatches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
 
        /* CREATE EXTENSION */
@@ -3907,10 +3911,10 @@ match_previous_words(int pattern_id,
        else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
                COMPLETE_WITH("LOCATION");
 
-/* CREATE TEXT SEARCH */
-       else if (Matches("CREATE", "TEXT", "SEARCH"))
+/* CREATE TEXT SEARCH --- is allowed inside CREATE SCHEMA, so use TailMatches */
+       else if (TailMatches("CREATE", "TEXT", "SEARCH"))
                COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
-       else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
+       else if (TailMatches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
                COMPLETE_WITH("(");
 
 /* CREATE TRANSFORM */
index 7e1f9b22c49cd553543b3b8f3bc4e8bd7b7ed5be..d29dda4d8e1e93432005506e523a7aad2a2e7e26 100644 (file)
@@ -928,19 +928,24 @@ other                     .
                                         * writing a full parser here, the following heuristic
                                         * should work.  First, we track whether the beginning of
                                         * the statement matches CREATE [OR REPLACE]
-                                        * {FUNCTION|PROCEDURE}
+                                        * {FUNCTION|PROCEDURE|SCHEMA}.  (Allowing this in
+                                        * CREATE SCHEMA, without tracking whether we're within a
+                                        * CREATE FUNCTION/PROCEDURE subcommand, is a bit shaky
+                                        * but should be okay with the present set of valid
+                                        * subcommands.)
                                         */
 
                                        if (cur_state->identifier_count == 0)
                                                memset(cur_state->identifiers, 0, sizeof(cur_state->identifiers));
 
-                                       if (pg_strcasecmp(yytext, "create") == 0 ||
-                                               pg_strcasecmp(yytext, "function") == 0 ||
-                                               pg_strcasecmp(yytext, "procedure") == 0 ||
-                                               pg_strcasecmp(yytext, "or") == 0 ||
-                                               pg_strcasecmp(yytext, "replace") == 0)
+                                       if (cur_state->identifier_count < sizeof(cur_state->identifiers))
                                        {
-                                               if (cur_state->identifier_count < sizeof(cur_state->identifiers))
+                                               if (pg_strcasecmp(yytext, "create") == 0 ||
+                                                       pg_strcasecmp(yytext, "function") == 0 ||
+                                                       pg_strcasecmp(yytext, "procedure") == 0 ||
+                                                       pg_strcasecmp(yytext, "or") == 0 ||
+                                                       pg_strcasecmp(yytext, "replace") == 0 ||
+                                                       pg_strcasecmp(yytext, "schema") == 0)
                                                        cur_state->identifiers[cur_state->identifier_count] = pg_tolower((unsigned char) yytext[0]);
                                        }
 
@@ -949,7 +954,8 @@ other                       .
                                        if (cur_state->identifiers[0] == 'c' &&
                                                (cur_state->identifiers[1] == 'f' || cur_state->identifiers[1] == 'p' ||
                                                 (cur_state->identifiers[1] == 'o' && cur_state->identifiers[2] == 'r' &&
-                                                 (cur_state->identifiers[3] == 'f' || cur_state->identifiers[3] == 'p'))) &&
+                                                 (cur_state->identifiers[3] == 'f' || cur_state->identifiers[3] == 'p')) ||
+                                                cur_state->identifiers[1] == 's') &&
                                                cur_state->paren_depth == 0)
                                        {
                                                if (pg_strcasecmp(yytext, "begin") == 0)
index 6ed85ef7446cbb8150323aad64ff82f5157445e1..a867786899bbb93f74a08ef7bf36c6a942f6b1b4 100644 (file)
@@ -13,10 +13,46 @@ CREATE SCHEMA IF NOT EXISTS baz;
 NOTICE:  schema "baz" already exists, skipping
 CREATE SCHEMA element_test
   CREATE TABLE foo (id int)
-  CREATE VIEW bar AS SELECT * FROM foo;
+  CREATE VIEW bar AS SELECT * FROM foo
+  CREATE COLLATION coll (LOCALE="C")
+  CREATE DOMAIN d1 AS INT
+  CREATE FUNCTION et_add(int4, int4) RETURNS int4 LANGUAGE sql
+    AS 'SELECT $1 + $2'
+  CREATE PROCEDURE et_proc(int4, int4)
+    BEGIN ATOMIC SELECT et_add($1,$2); END
+  CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
+  CREATE TYPE ss AS (a int)
+  CREATE TYPE sss
+  CREATE TYPE rainbow AS ENUM ('red', 'orange')
+  CREATE TEXT SEARCH PARSER et_ts_prs
+    (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end,
+     lextypes = prsd_lextype)
+;
 NOTICE:  DDL test: type simple, tag CREATE SCHEMA
 NOTICE:  DDL test: type simple, tag CREATE TABLE
 NOTICE:  DDL test: type simple, tag CREATE VIEW
+NOTICE:  DDL test: type simple, tag CREATE COLLATION
+NOTICE:  DDL test: type simple, tag CREATE DOMAIN
+NOTICE:  DDL test: type simple, tag CREATE FUNCTION
+NOTICE:  DDL test: type simple, tag CREATE PROCEDURE
+NOTICE:  DDL test: type simple, tag CREATE TYPE
+NOTICE:  DDL test: type simple, tag CREATE TYPE
+NOTICE:  DDL test: type simple, tag CREATE TYPE
+NOTICE:  DDL test: type simple, tag CREATE TYPE
+NOTICE:  DDL test: type simple, tag CREATE TEXT SEARCH PARSER
+DROP SCHEMA element_test CASCADE;
+NOTICE:  drop cascades to 11 other objects
+DETAIL:  drop cascades to table element_test.foo
+drop cascades to view element_test.bar
+drop cascades to collation element_test.coll
+drop cascades to type element_test.d1
+drop cascades to function element_test.et_add(integer,integer)
+drop cascades to function element_test.et_proc(integer,integer)
+drop cascades to type element_test.floatrange
+drop cascades to type element_test.ss
+drop cascades to type element_test.sss
+drop cascades to type element_test.rainbow
+drop cascades to text search parser element_test.et_ts_prs
 CREATE SCHEMA regress_schema_1
 CREATE TABLE t4(
     b INT,
index 145aef2a75afccf8cf2695997e247a762dc0daea..7ba641d06d67c9ca9612e72246dd8f2d9852bd54 100644 (file)
@@ -14,7 +14,23 @@ CREATE SCHEMA IF NOT EXISTS baz;
 
 CREATE SCHEMA element_test
   CREATE TABLE foo (id int)
-  CREATE VIEW bar AS SELECT * FROM foo;
+  CREATE VIEW bar AS SELECT * FROM foo
+  CREATE COLLATION coll (LOCALE="C")
+  CREATE DOMAIN d1 AS INT
+  CREATE FUNCTION et_add(int4, int4) RETURNS int4 LANGUAGE sql
+    AS 'SELECT $1 + $2'
+  CREATE PROCEDURE et_proc(int4, int4)
+    BEGIN ATOMIC SELECT et_add($1,$2); END
+  CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
+  CREATE TYPE ss AS (a int)
+  CREATE TYPE sss
+  CREATE TYPE rainbow AS ENUM ('red', 'orange')
+  CREATE TEXT SEARCH PARSER et_ts_prs
+    (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end,
+     lextypes = prsd_lextype)
+;
+
+DROP SCHEMA element_test CASCADE;
 
 CREATE SCHEMA regress_schema_1
 CREATE TABLE t4(
index b34b99889628a1e12a99df228642c44ea799cbd6..bfe211338abe8c1c8b6896ea39e5ee0c530bc6b7 100644 (file)
@@ -5,7 +5,7 @@
 CREATE ROLE regress_create_schema_role SUPERUSER;
 -- Cases where schema creation fails as objects are qualified with a schema
 -- that does not match with what's expected.
--- This checks all the object types that include schema qualifications.
+-- This checks most object types that include schema qualifications.
 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)
@@ -32,6 +32,10 @@ CREATE SCHEMA AUTHORIZATION regress_create_schema_role
 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...
                                                       ^
+CREATE SCHEMA AUTHORIZATION regress_create_schema_role
+  CREATE FUNCTION schema_not_existing.func(int) RETURNS int
+  AS 'SELECT $1' LANGUAGE sql;
+ERROR:  CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
 -- Again, with a role specification and no schema names.
 SET ROLE regress_create_schema_role;
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
@@ -177,5 +181,141 @@ drop cascades to table regress_schema_fk.t3
 drop cascades to table regress_schema_fk.t4
 drop cascades to table regress_schema_fk.t5
 drop cascades to table regress_schema_fk.t6
+-- Test miscellaneous object types within CREATE SCHEMA.
+CREATE SCHEMA regress_schema_misc
+  CREATE AGGREGATE cs_sum(int4)
+    (
+        SFUNC = int4_sum(int8, int4),
+        STYPE = int8,
+        INITCOND = '0'
+    )
+  CREATE COLLATION cs_builtin_c ( PROVIDER = builtin, LOCALE = "C" )
+  CREATE DOMAIN cs_positive AS integer CHECK (VALUE > 0)
+  CREATE FUNCTION cs_add(int4, int4) returns int4 language sql
+    as 'select $1 + $2'
+  CREATE OPERATOR + (function = cs_add, leftarg = int4, rightarg = int4)
+  CREATE PROCEDURE cs_proc(int4, int4)
+    BEGIN ATOMIC SELECT cs_add($1,$2); END
+  CREATE TEXT SEARCH CONFIGURATION cs_ts_conf (copy=english)
+  CREATE TEXT SEARCH DICTIONARY cs_ts_dict (template=simple)
+  CREATE TEXT SEARCH PARSER cs_ts_prs
+    (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end,
+     lextypes = prsd_lextype)
+  CREATE TEXT SEARCH TEMPLATE cs_ts_temp (lexize=dsimple_lexize)
+  CREATE TYPE regress_schema_misc.cs_enum AS ENUM ('red', 'orange')
+  CREATE TYPE cs_composite AS (a int, b float8)
+  CREATE TYPE cs_range AS RANGE (subtype = float8, subtype_diff = float8mi)
+  -- demonstrate creation of a base type with its I/O functions
+  CREATE TYPE cs_type
+  CREATE FUNCTION cs_type_in(cstring)
+    RETURNS cs_type LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT
+    AS 'int4in'
+  CREATE FUNCTION cs_type_out(cs_type)
+    RETURNS cstring LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT
+    AS 'int4out'
+  CREATE TYPE cs_type (
+    INPUT = cs_type_in,
+    OUTPUT = cs_type_out,
+    LIKE = int4
+  )
+  GRANT USAGE ON TYPE cs_type TO public
+;
+NOTICE:  return type cs_type is only a shell
+NOTICE:  argument type cs_type is only a shell
+LINE 29:   CREATE FUNCTION cs_type_out(cs_type)
+                                       ^
+\df regress_schema_misc.cs_add
+                              List of functions
+       Schema        |  Name  | Result data type | Argument data types | Type 
+---------------------+--------+------------------+---------------------+------
+ regress_schema_misc | cs_add | integer          | integer, integer    | func
+(1 row)
+
+\df regress_schema_misc.cs_proc
+                                List of functions
+       Schema        |  Name   | Result data type |  Argument data types   | Type 
+---------------------+---------+------------------+------------------------+------
+ regress_schema_misc | cs_proc |                  | IN integer, IN integer | proc
+(1 row)
+
+\da regress_schema_misc.cs_sum
+                             List of aggregate functions
+       Schema        |  Name  | Result data type | Argument data types | Description 
+---------------------+--------+------------------+---------------------+-------------
+ regress_schema_misc | cs_sum | bigint           | integer             | 
+(1 row)
+
+\do regress_schema_misc.+
+                                    List of operators
+       Schema        | Name | Left arg type | Right arg type | Result type | Description 
+---------------------+------+---------------+----------------+-------------+-------------
+ regress_schema_misc | +    | integer       | integer        | integer     | 
+(1 row)
+
+\dO regress_schema_misc.*
+                                          List of collations
+       Schema        |     Name     | Provider | Collate | Ctype | Locale | ICU Rules | Deterministic? 
+---------------------+--------------+----------+---------+-------+--------+-----------+----------------
+ regress_schema_misc | cs_builtin_c | builtin  |         |       | C      |           | yes
+(1 row)
+
+\dT regress_schema_misc.*
+                          List of data types
+       Schema        |               Name                | Description 
+---------------------+-----------------------------------+-------------
+ regress_schema_misc | regress_schema_misc.cs_composite  | 
+ regress_schema_misc | regress_schema_misc.cs_enum       | 
+ regress_schema_misc | regress_schema_misc.cs_multirange | 
+ regress_schema_misc | regress_schema_misc.cs_positive   | 
+ regress_schema_misc | regress_schema_misc.cs_range      | 
+ regress_schema_misc | regress_schema_misc.cs_type       | 
+(6 rows)
+
+\dF regress_schema_misc.*
+       List of text search configurations
+       Schema        |    Name    | Description 
+---------------------+------------+-------------
+ regress_schema_misc | cs_ts_conf | 
+(1 row)
+
+\dFd regress_schema_misc.*
+        List of text search dictionaries
+       Schema        |    Name    | Description 
+---------------------+------------+-------------
+ regress_schema_misc | cs_ts_dict | 
+(1 row)
+
+\dFp regress_schema_misc.*
+          List of text search parsers
+       Schema        |   Name    | Description 
+---------------------+-----------+-------------
+ regress_schema_misc | cs_ts_prs | 
+(1 row)
+
+\dFt regress_schema_misc.*
+         List of text search templates
+       Schema        |    Name    | Description 
+---------------------+------------+-------------
+ regress_schema_misc | cs_ts_temp | 
+(1 row)
+
+DROP SCHEMA regress_schema_misc CASCADE;
+NOTICE:  drop cascades to 16 other objects
+DETAIL:  drop cascades to function regress_schema_misc.cs_sum(integer)
+drop cascades to collation regress_schema_misc.cs_builtin_c
+drop cascades to type regress_schema_misc.cs_positive
+drop cascades to function regress_schema_misc.cs_add(integer,integer)
+drop cascades to operator regress_schema_misc.+(integer,integer)
+drop cascades to function regress_schema_misc.cs_proc(integer,integer)
+drop cascades to text search configuration regress_schema_misc.cs_ts_conf
+drop cascades to text search dictionary regress_schema_misc.cs_ts_dict
+drop cascades to text search parser regress_schema_misc.cs_ts_prs
+drop cascades to text search template regress_schema_misc.cs_ts_temp
+drop cascades to type regress_schema_misc.cs_enum
+drop cascades to type regress_schema_misc.cs_composite
+drop cascades to type regress_schema_misc.cs_range
+drop cascades to function regress_schema_misc.cs_type_out(regress_schema_misc.cs_type)
+drop cascades to type regress_schema_misc.cs_type
+drop cascades to function regress_schema_misc.cs_type_in(cstring)
 -- Clean up
 DROP ROLE regress_create_schema_role;
index 0f2accc59ec411666eb2b75c245855e3efa2a7ec..ebe05d5110ecfff713bcd21550bd64cd202b3da0 100644 (file)
@@ -8,7 +8,7 @@ CREATE ROLE regress_create_schema_role SUPERUSER;
 
 -- Cases where schema creation fails as objects are qualified with a schema
 -- that does not match with what's expected.
--- This checks all the object types that include schema qualifications.
+-- This checks most object types that include schema qualifications.
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE SEQUENCE schema_not_existing.seq;
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
@@ -20,6 +20,9 @@ CREATE SCHEMA AUTHORIZATION regress_create_schema_role
 CREATE SCHEMA AUTHORIZATION regress_create_schema_role
   CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
   EXECUTE FUNCTION schema_trig.no_func();
+CREATE SCHEMA AUTHORIZATION regress_create_schema_role
+  CREATE FUNCTION schema_not_existing.func(int) RETURNS int
+  AS 'SELECT $1' LANGUAGE sql;
 -- Again, with a role specification and no schema names.
 SET ROLE regress_create_schema_role;
 CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
@@ -98,5 +101,76 @@ CREATE SCHEMA regress_schema_fk
 
 DROP SCHEMA regress_schema_fk CASCADE;
 
+-- Test miscellaneous object types within CREATE SCHEMA.
+CREATE SCHEMA regress_schema_misc
+  CREATE AGGREGATE cs_sum(int4)
+    (
+        SFUNC = int4_sum(int8, int4),
+        STYPE = int8,
+        INITCOND = '0'
+    )
+
+  CREATE COLLATION cs_builtin_c ( PROVIDER = builtin, LOCALE = "C" )
+
+  CREATE DOMAIN cs_positive AS integer CHECK (VALUE > 0)
+
+  CREATE FUNCTION cs_add(int4, int4) returns int4 language sql
+    as 'select $1 + $2'
+
+  CREATE OPERATOR + (function = cs_add, leftarg = int4, rightarg = int4)
+
+  CREATE PROCEDURE cs_proc(int4, int4)
+    BEGIN ATOMIC SELECT cs_add($1,$2); END
+
+  CREATE TEXT SEARCH CONFIGURATION cs_ts_conf (copy=english)
+
+  CREATE TEXT SEARCH DICTIONARY cs_ts_dict (template=simple)
+
+  CREATE TEXT SEARCH PARSER cs_ts_prs
+    (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end,
+     lextypes = prsd_lextype)
+
+  CREATE TEXT SEARCH TEMPLATE cs_ts_temp (lexize=dsimple_lexize)
+
+  CREATE TYPE regress_schema_misc.cs_enum AS ENUM ('red', 'orange')
+
+  CREATE TYPE cs_composite AS (a int, b float8)
+
+  CREATE TYPE cs_range AS RANGE (subtype = float8, subtype_diff = float8mi)
+
+  -- demonstrate creation of a base type with its I/O functions
+
+  CREATE TYPE cs_type
+
+  CREATE FUNCTION cs_type_in(cstring)
+    RETURNS cs_type LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT
+    AS 'int4in'
+
+  CREATE FUNCTION cs_type_out(cs_type)
+    RETURNS cstring LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT
+    AS 'int4out'
+
+  CREATE TYPE cs_type (
+    INPUT = cs_type_in,
+    OUTPUT = cs_type_out,
+    LIKE = int4
+  )
+
+  GRANT USAGE ON TYPE cs_type TO public
+;
+
+\df regress_schema_misc.cs_add
+\df regress_schema_misc.cs_proc
+\da regress_schema_misc.cs_sum
+\do regress_schema_misc.+
+\dO regress_schema_misc.*
+\dT regress_schema_misc.*
+\dF regress_schema_misc.*
+\dFd regress_schema_misc.*
+\dFp regress_schema_misc.*
+\dFt regress_schema_misc.*
+
+DROP SCHEMA regress_schema_misc CASCADE;
+
 -- Clean up
 DROP ROLE regress_create_schema_role;