Skip to content

Commit a839fac

Browse files
jianhe-funCommitfest Bot
authored andcommitted
CREATE SCHEMA CREATE TYPE
SQL standard allow type to be specified with CREATE SCHEMA statement. This patch adds support in PostgreSQL for that. For example: CREATE SCHEMA schema_name CREATE TYPE ss; The type will be created within the to be created schema. The type name can be schema-qualified or database-qualified, however it's not allowed to let type create within a different schema. TODO: tab complete for CREATE SCHEMA ... CREATE TYPE seems tricky Discussion: https://postgr.es/m/CALdSSPh4jUSDsWu3K58hjO60wnTRR0DuO4CKRcwa8EVuOSfXxg@mail.gmail.com
1 parent 277f1eb commit a839fac

File tree

8 files changed

+202
-7
lines changed

8 files changed

+202
-7
lines changed

doc/src/sgml/ref/create_schema.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="parameter">role_sp
104104
<command>CREATE DOMAIN</command>, <command>CREATE TABLE</command>,
105105
<command>CREATE VIEW</command>, <command>CREATE
106106
INDEX</command>, <command>CREATE SEQUENCE</command>, <command>CREATE
107-
TRIGGER</command> and <command>GRANT</command> are accepted as clauses
107+
TRIGGER</command>, <command>CREATE TYPE</command> and
108+
<command>GRANT</command> are accepted as clauses
108109
within <command>CREATE SCHEMA</command>. Other kinds of objects may
109110
be created in separate commands after the schema is created.
110111
</para>

src/backend/parser/parse_utilcmd.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4177,7 +4177,7 @@ transformCreateSchemaStmtElements(ParseState *pstate, List *schemaElts,
41774177
char *collName;
41784178
DefineStmt *stmt = (DefineStmt *) element;
41794179

4180-
if (stmt->kind != OBJECT_COLLATION)
4180+
if (stmt->kind != OBJECT_COLLATION && stmt->kind != OBJECT_TYPE)
41814181
ereport(ERROR,
41824182
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
41834183
errmsg("CREATE SCHEMA ... CREATE %s currently not supported",
@@ -4195,12 +4195,48 @@ transformCreateSchemaStmtElements(ParseState *pstate, List *schemaElts,
41954195
elements = lappend(elements, element);
41964196
}
41974197
break;
4198+
41984199
case T_CompositeTypeStmt:
4200+
{
4201+
CompositeTypeStmt *stmt = (CompositeTypeStmt *) element;
4202+
4203+
checkSchemaName(pstate, schemaName, stmt->typevar);
4204+
elements = lappend(elements, element);
4205+
}
4206+
break;
4207+
41994208
case T_CreateEnumStmt:
4209+
{
4210+
char *schema = NULL;
4211+
char *typname;
4212+
CreateEnumStmt *stmt = (CreateEnumStmt *) element;
4213+
DeconstructQualifiedName(stmt->typeName, &schema, &typname);
4214+
if (schema && strcmp(schema, schemaName) != 0)
4215+
ereport(ERROR,
4216+
errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
4217+
errmsg("CREATE specifies a schema (%s) "
4218+
"different from the one being created (%s)",
4219+
schemaName, schema));
4220+
4221+
elements = lappend(elements, element);
4222+
}
4223+
break;
4224+
42004225
case T_CreateRangeStmt:
4201-
ereport(ERROR,
4202-
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4203-
errmsg("CREATE SCHEMA ... CREATE TYPE currently not supported"));
4226+
{
4227+
char *schema = NULL;
4228+
char *typname;
4229+
CreateRangeStmt *stmt = (CreateRangeStmt *) element;
4230+
DeconstructQualifiedName(stmt->typeName, &schema, &typname);
4231+
if (schema && strcmp(schema, schemaName) != 0)
4232+
ereport(ERROR,
4233+
errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
4234+
errmsg("CREATE specifies a schema (%s) "
4235+
"different from the one being created (%s)",
4236+
schemaName, schema));
4237+
4238+
elements = lappend(elements, element);
4239+
}
42044240
break;
42054241
default:
42064242
elog(ERROR, "unrecognized node type: %d",

src/test/modules/test_ddl_deparse/expected/create_schema.out

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ CREATE SCHEMA element_test
1515
CREATE TABLE foo (id int)
1616
CREATE VIEW bar AS SELECT * FROM foo
1717
CREATE DOMAIN d1 AS INT
18-
CREATE COLLATION coll (LOCALE="C");
18+
CREATE COLLATION coll (LOCALE="C")
19+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
20+
CREATE TYPE ss AS (a int)
21+
CREATE TYPE sss
22+
CREATE TYPE rainbow AS ENUM ('red', 'orange');
1923
NOTICE: DDL test: type simple, tag CREATE SCHEMA
2024
NOTICE: DDL test: type simple, tag CREATE TABLE
2125
NOTICE: DDL test: type simple, tag CREATE VIEW
2226
NOTICE: DDL test: type simple, tag CREATE DOMAIN
2327
NOTICE: DDL test: type simple, tag CREATE COLLATION
28+
NOTICE: DDL test: type simple, tag CREATE TYPE
29+
NOTICE: DDL test: type simple, tag CREATE TYPE
30+
NOTICE: DDL test: type simple, tag CREATE TYPE
31+
NOTICE: DDL test: type simple, tag CREATE TYPE

src/test/modules/test_ddl_deparse/sql/create_schema.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ CREATE SCHEMA element_test
1616
CREATE TABLE foo (id int)
1717
CREATE VIEW bar AS SELECT * FROM foo
1818
CREATE DOMAIN d1 AS INT
19-
CREATE COLLATION coll (LOCALE="C");
19+
CREATE COLLATION coll (LOCALE="C")
20+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
21+
CREATE TYPE ss AS (a int)
22+
CREATE TYPE sss
23+
CREATE TYPE rainbow AS ENUM ('red', 'orange');

src/test/regress/expected/create_schema.out

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,76 @@ CREATE SCHEMA regress_schema_5 AUTHORIZATION CURRENT_ROLE
212212
regress_schema_5 | coll | libc | C | C | | | yes
213213
(1 row)
214214

215+
-----CREATE SCHEMA CREATE TYPE
216+
--fail. cannot CREATE TYPE to other schema
217+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.ss AS (a int);
218+
ERROR: CREATE specifies a schema (public) different from the one being created (regress_schema_6)
219+
LINE 1: CREATE SCHEMA regress_schema_6 CREATE TYPE public.ss AS (a i...
220+
^
221+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.ss;
222+
ERROR: CREATE specifies a schema (regress_schema_6) different from the one being created (public)
223+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.rainbow AS ENUM ('red', 'orange');
224+
ERROR: CREATE specifies a schema (regress_schema_6) different from the one being created (public)
225+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
226+
ERROR: CREATE specifies a schema (regress_schema_6) different from the one being created (public)
227+
--fail. improper qualified name
228+
CREATE SCHEMA regress_schema_6 AUTHORIZATION CURRENT_ROLE
229+
CREATE TYPE postgres.public.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
230+
ERROR: cross-database references are not implemented: postgres.public.floatrange
231+
--all the following 4 should error, because we execute subcommands in order
232+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE TYPE ss;
233+
ERROR: type "ss" does not exist
234+
LINE 1: CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE...
235+
^
236+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE TYPE ss AS (a int);
237+
ERROR: type "ss" does not exist
238+
LINE 1: CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE...
239+
^
240+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a rainbow) CREATE TYPE rainbow AS ENUM ('red', 'orange');
241+
ERROR: type "rainbow" does not exist
242+
LINE 1: CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a rainbow) C...
243+
^
244+
CREATE SCHEMA regress_schema_6
245+
CREATE TABLE tts(a floatrange)
246+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
247+
ERROR: type "floatrange" does not exist
248+
LINE 2: CREATE TABLE tts(a floatrange)
249+
^
250+
--ok
251+
CREATE SCHEMA regress_schema_6
252+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
253+
CREATE TYPE ss AS (a int)
254+
CREATE TYPE sss
255+
CREATE TYPE rainbow AS ENUM ('red', 'orange');
256+
\dT regress_schema_6.*
257+
List of data types
258+
Schema | Name | Description
259+
------------------+----------------------------------+-------------
260+
regress_schema_6 | regress_schema_6.floatmultirange |
261+
regress_schema_6 | regress_schema_6.floatrange |
262+
regress_schema_6 | regress_schema_6.rainbow |
263+
regress_schema_6 | regress_schema_6.ss |
264+
regress_schema_6 | regress_schema_6.sss |
265+
(5 rows)
266+
267+
--schema qualified, ok
268+
CREATE SCHEMA regress_schema_7
269+
CREATE TYPE regress_schema_7.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
270+
CREATE TYPE regress_schema_7.ss AS (a int)
271+
CREATE TYPE regress_schema_7.sss
272+
CREATE TYPE regress_schema_7.rainbow AS ENUM ('red', 'orange')
273+
CREATE TABLE t(a floatrange, b ss, c rainbow);
274+
\dT regress_schema_7.*
275+
List of data types
276+
Schema | Name | Description
277+
------------------+----------------------------------+-------------
278+
regress_schema_7 | regress_schema_7.floatmultirange |
279+
regress_schema_7 | regress_schema_7.floatrange |
280+
regress_schema_7 | regress_schema_7.rainbow |
281+
regress_schema_7 | regress_schema_7.ss |
282+
regress_schema_7 | regress_schema_7.sss |
283+
(5 rows)
284+
215285
DROP SCHEMA regress_schema_2 CASCADE;
216286
NOTICE: drop cascades to 2 other objects
217287
DETAIL: drop cascades to type regress_schema_2.ss
@@ -230,5 +300,18 @@ DROP SCHEMA regress_schema_5 CASCADE;
230300
NOTICE: drop cascades to 2 other objects
231301
DETAIL: drop cascades to collation regress_schema_5.coll
232302
drop cascades to table regress_schema_5.t
303+
DROP SCHEMA regress_schema_6 CASCADE;
304+
NOTICE: drop cascades to 4 other objects
305+
DETAIL: drop cascades to type regress_schema_6.floatrange
306+
drop cascades to type regress_schema_6.ss
307+
drop cascades to type regress_schema_6.sss
308+
drop cascades to type regress_schema_6.rainbow
309+
DROP SCHEMA regress_schema_7 CASCADE;
310+
NOTICE: drop cascades to 5 other objects
311+
DETAIL: drop cascades to type regress_schema_7.floatrange
312+
drop cascades to type regress_schema_7.ss
313+
drop cascades to type regress_schema_7.sss
314+
drop cascades to type regress_schema_7.rainbow
315+
drop cascades to table regress_schema_7.t
233316
-- Clean up
234317
DROP ROLE regress_create_schema_role;

src/test/regress/expected/create_type.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ CREATE FUNCTION int44out(city_budget)
3535
NOTICE: argument type city_budget is only a shell
3636
LINE 1: CREATE FUNCTION int44out(city_budget)
3737
^
38+
----- CREATE SCHEMA CREATE TYPE test
39+
--error. cannot CREATE TYPE to other schema
40+
CREATE SCHEMA regress_schema_1
41+
CREATE TYPE public.widget (
42+
internallength = 24,
43+
input = widget_in,
44+
output = widget_out,
45+
typmod_in = numerictypmodin,
46+
typmod_out = numerictypmodout,
47+
alignment = double
48+
);
49+
ERROR: CREATE specifies a schema (regress_schema_1) different from the one being created (public)
3850
CREATE TYPE widget (
3951
internallength = 24,
4052
input = widget_in,

src/test/regress/sql/create_schema.sql

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,49 @@ CREATE SCHEMA regress_schema_5 AUTHORIZATION CURRENT_ROLE
128128
CREATE TABLE t(a TEXT COLLATE coll);
129129
\dO regress_schema_5.*
130130

131+
132+
-----CREATE SCHEMA CREATE TYPE
133+
--fail. cannot CREATE TYPE to other schema
134+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.ss AS (a int);
135+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.ss;
136+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.rainbow AS ENUM ('red', 'orange');
137+
CREATE SCHEMA regress_schema_6 CREATE TYPE public.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
138+
139+
--fail. improper qualified name
140+
CREATE SCHEMA regress_schema_6 AUTHORIZATION CURRENT_ROLE
141+
CREATE TYPE postgres.public.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
142+
143+
--all the following 4 should error, because we execute subcommands in order
144+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE TYPE ss;
145+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a ss) CREATE TYPE ss AS (a int);
146+
CREATE SCHEMA regress_schema_6 CREATE TABLE tts(a rainbow) CREATE TYPE rainbow AS ENUM ('red', 'orange');
147+
CREATE SCHEMA regress_schema_6
148+
CREATE TABLE tts(a floatrange)
149+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi);
150+
151+
--ok
152+
CREATE SCHEMA regress_schema_6
153+
CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
154+
CREATE TYPE ss AS (a int)
155+
CREATE TYPE sss
156+
CREATE TYPE rainbow AS ENUM ('red', 'orange');
157+
\dT regress_schema_6.*
158+
159+
--schema qualified, ok
160+
CREATE SCHEMA regress_schema_7
161+
CREATE TYPE regress_schema_7.floatrange AS RANGE (subtype = float8, subtype_diff = float8mi)
162+
CREATE TYPE regress_schema_7.ss AS (a int)
163+
CREATE TYPE regress_schema_7.sss
164+
CREATE TYPE regress_schema_7.rainbow AS ENUM ('red', 'orange')
165+
CREATE TABLE t(a floatrange, b ss, c rainbow);
166+
\dT regress_schema_7.*
167+
131168
DROP SCHEMA regress_schema_2 CASCADE;
132169
DROP SCHEMA regress_schema_3 CASCADE;
133170
DROP SCHEMA regress_schema_4 CASCADE;
134171
DROP SCHEMA regress_schema_5 CASCADE;
172+
DROP SCHEMA regress_schema_6 CASCADE;
173+
DROP SCHEMA regress_schema_7 CASCADE;
135174

136175
-- Clean up
137176
DROP ROLE regress_create_schema_role;

src/test/regress/sql/create_type.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ CREATE FUNCTION int44out(city_budget)
3232
AS :'regresslib'
3333
LANGUAGE C STRICT IMMUTABLE;
3434

35+
----- CREATE SCHEMA CREATE TYPE test
36+
--error. cannot CREATE TYPE to other schema
37+
CREATE SCHEMA regress_schema_1
38+
CREATE TYPE public.widget (
39+
internallength = 24,
40+
input = widget_in,
41+
output = widget_out,
42+
typmod_in = numerictypmodin,
43+
typmod_out = numerictypmodout,
44+
alignment = double
45+
);
46+
3547
CREATE TYPE widget (
3648
internallength = 24,
3749
input = widget_in,

0 commit comments

Comments
 (0)