diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml index 96bc496e777..4ecf82d6bcb 100644 --- a/doc/src/sgml/ref/create_schema.sgml +++ b/doc/src/sgml/ref/create_schema.sgml @@ -100,12 +100,27 @@ CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_sp An SQL statement defining an object to be created within the - schema. Currently, only CREATE - TABLE, CREATE VIEW, CREATE - INDEX, CREATE SEQUENCE, CREATE - TRIGGER and GRANT are accepted as clauses + schema. Currently, only + CREATE AGGREGATE, + CREATE COLLATION, + CREATE DOMAIN, + CREATE FUNCTION, + CREATE INDEX, + CREATE OPERATOR, + CREATE PROCEDURE, + CREATE SEQUENCE, + CREATE TABLE, + CREATE TEXT SEARCH CONFIGURATION, + CREATE TEXT SEARCH DICTIONARY, + CREATE TEXT SEARCH PARSER, + CREATE TEXT SEARCH TEMPLATE, + CREATE TRIGGER, + CREATE TYPE, + CREATE VIEW, + and GRANT are accepted as clauses within CREATE SCHEMA. 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. diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f4a08baa95a..2d1b19d1f53 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -1679,8 +1679,11 @@ OptSchemaEltList: schema_stmt: CreateStmt | IndexStmt + | CreateDomainStmt + | CreateFunctionStmt | CreateSeqStmt | CreateTrigStmt + | DefineStmt | GrantStmt | ViewStmt ; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index b0c3407b23d..e135c91a6ad 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -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. diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 1d941c11997..ed15c1b4f83 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -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 */ diff --git a/src/fe_utils/psqlscan.l b/src/fe_utils/psqlscan.l index 7e1f9b22c49..d29dda4d8e1 100644 --- a/src/fe_utils/psqlscan.l +++ b/src/fe_utils/psqlscan.l @@ -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) diff --git a/src/test/modules/test_ddl_deparse/expected/create_schema.out b/src/test/modules/test_ddl_deparse/expected/create_schema.out index 6ed85ef7446..a867786899b 100644 --- a/src/test/modules/test_ddl_deparse/expected/create_schema.out +++ b/src/test/modules/test_ddl_deparse/expected/create_schema.out @@ -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, diff --git a/src/test/modules/test_ddl_deparse/sql/create_schema.sql b/src/test/modules/test_ddl_deparse/sql/create_schema.sql index 145aef2a75a..7ba641d06d6 100644 --- a/src/test/modules/test_ddl_deparse/sql/create_schema.sql +++ b/src/test/modules/test_ddl_deparse/sql/create_schema.sql @@ -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( diff --git a/src/test/regress/expected/create_schema.out b/src/test/regress/expected/create_schema.out index b34b9988962..bfe211338ab 100644 --- a/src/test/regress/expected/create_schema.out +++ b/src/test/regress/expected/create_schema.out @@ -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; diff --git a/src/test/regress/sql/create_schema.sql b/src/test/regress/sql/create_schema.sql index 0f2accc59ec..ebe05d5110e 100644 --- a/src/test/regress/sql/create_schema.sql +++ b/src/test/regress/sql/create_schema.sql @@ -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;