Skip to content

Commit b59ca98

Browse files
committed
Allow CREATE TABLE (LIKE ...) from composite type
The only reason this didn't work before was that parserOpenTable() rejects composite types. So use relation_openrv() directly and manually do the errposition() setup that parserOpenTable() does.
1 parent d923125 commit b59ca98

File tree

4 files changed

+37
-17
lines changed

4 files changed

+37
-17
lines changed

doc/src/sgml/ref/create_table.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
370370
</para>
371371
<para>
372372
The <literal>LIKE</literal> clause can also be used to copy columns from
373-
views or foreign tables. Inapplicable options (e.g., <literal>INCLUDING
373+
views, foreign tables, or composite types. Inapplicable options (e.g., <literal>INCLUDING
374374
INDEXES</literal> from a view) are ignored.
375375
</para>
376376
</listitem>

src/backend/parser/parse_utilcmd.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -636,26 +636,42 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
636636
TupleConstr *constr;
637637
AclResult aclresult;
638638
char *comment;
639+
ParseCallbackState pcbstate;
639640

640-
relation = parserOpenTable(cxt->pstate, table_like_clause->relation,
641-
AccessShareLock);
641+
setup_parser_errposition_callback(&pcbstate, cxt->pstate, table_like_clause->relation->location);
642+
643+
relation = relation_openrv(table_like_clause->relation, AccessShareLock);
642644

643645
if (relation->rd_rel->relkind != RELKIND_RELATION
644646
&& relation->rd_rel->relkind != RELKIND_VIEW
645-
&& relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
647+
&& relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE
648+
&& relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
646649
ereport(ERROR,
647650
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
648-
errmsg("LIKE source relation \"%s\" is not a table, view, or foreign table",
651+
errmsg("\"%s\" is not a table, view, composite type, or foreign table",
649652
table_like_clause->relation->relname)));
650653

654+
cancel_parser_errposition_callback(&pcbstate);
655+
651656
/*
652-
* Check for SELECT privileges
657+
* Check for privileges
653658
*/
654-
aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
659+
if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
660+
{
661+
aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
662+
ACL_USAGE);
663+
if (aclresult != ACLCHECK_OK)
664+
aclcheck_error(aclresult, ACL_KIND_TYPE,
665+
RelationGetRelationName(relation));
666+
}
667+
else
668+
{
669+
aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
655670
ACL_SELECT);
656-
if (aclresult != ACLCHECK_OK)
657-
aclcheck_error(aclresult, ACL_KIND_CLASS,
658-
RelationGetRelationName(relation));
671+
if (aclresult != ACLCHECK_OK)
672+
aclcheck_error(aclresult, ACL_KIND_CLASS,
673+
RelationGetRelationName(relation));
674+
}
659675

660676
tupleDesc = RelationGetDescr(relation);
661677
constr = tupleDesc->constr;

src/test/regress/expected/create_table_like.out

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ CREATE TABLE inhx (xx text DEFAULT 'text');
88
*/
99
CREATE TABLE ctla (aa TEXT);
1010
CREATE TABLE ctlb (bb TEXT) INHERITS (ctla);
11+
CREATE TABLE foo (LIKE nonexistent);
12+
ERROR: relation "nonexistent" does not exist
13+
LINE 1: CREATE TABLE foo (LIKE nonexistent);
14+
^
1115
CREATE TABLE inhe (ee text, LIKE inhx) inherits (ctlb);
1216
INSERT INTO inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4');
1317
SELECT * FROM inhe; /* Columns aa, bb, xx value NULL, ee */
@@ -224,18 +228,16 @@ NOTICE: drop cascades to table inhe
224228
CREATE TABLE ctlt4 (a int, b text);
225229
CREATE SEQUENCE ctlseq1;
226230
CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail
227-
ERROR: LIKE source relation "ctlseq1" is not a table, view, or foreign table
231+
ERROR: "ctlseq1" is not a table, view, composite type, or foreign table
232+
LINE 1: CREATE TABLE ctlt10 (LIKE ctlseq1);
233+
^
228234
CREATE VIEW ctlv1 AS SELECT * FROM ctlt4;
229235
CREATE TABLE ctlt11 (LIKE ctlv1);
230236
CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING ALL);
231237
CREATE TYPE ctlty1 AS (a int, b text);
232-
CREATE TABLE ctlt12 (LIKE ctlty1); -- currently fails
233-
ERROR: "ctlty1" is a composite type
234-
LINE 1: CREATE TABLE ctlt12 (LIKE ctlty1);
235-
^
238+
CREATE TABLE ctlt12 (LIKE ctlty1);
236239
DROP SEQUENCE ctlseq1;
237240
DROP TYPE ctlty1;
238241
DROP VIEW ctlv1;
239242
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
240243
NOTICE: table "ctlt10" does not exist, skipping
241-
NOTICE: table "ctlt12" does not exist, skipping

src/test/regress/sql/create_table_like.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ CREATE TABLE inhx (xx text DEFAULT 'text');
1010
CREATE TABLE ctla (aa TEXT);
1111
CREATE TABLE ctlb (bb TEXT) INHERITS (ctla);
1212

13+
CREATE TABLE foo (LIKE nonexistent);
14+
1315
CREATE TABLE inhe (ee text, LIKE inhx) inherits (ctlb);
1416
INSERT INTO inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4');
1517
SELECT * FROM inhe; /* Columns aa, bb, xx value NULL, ee */
@@ -111,7 +113,7 @@ CREATE TABLE ctlt11 (LIKE ctlv1);
111113
CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING ALL);
112114

113115
CREATE TYPE ctlty1 AS (a int, b text);
114-
CREATE TABLE ctlt12 (LIKE ctlty1); -- currently fails
116+
CREATE TABLE ctlt12 (LIKE ctlty1);
115117

116118
DROP SEQUENCE ctlseq1;
117119
DROP TYPE ctlty1;

0 commit comments

Comments
 (0)