create-table-like-composite-type.patch
text/x-patch
Filename: create-table-like-composite-type.patch
Type: text/x-patch
Part: 0
Message:
Re: Misleading CREATE TABLE error
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/create_table.sgml | 1 | 1 |
| src/backend/parser/parse_utilcmd.c | 25 | 9 |
| src/test/regress/expected/create_table_like.out | 8 | 6 |
| src/test/regress/sql/create_table_like.sql | 3 | 1 |
diff --git i/doc/src/sgml/ref/create_table.sgml w/doc/src/sgml/ref/create_table.sgml
index f55a001..bb93214 100644
--- i/doc/src/sgml/ref/create_table.sgml
+++ w/doc/src/sgml/ref/create_table.sgml
@@ -370,7 +370,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
</para>
<para>
The <literal>LIKE</literal> clause can also be used to copy columns from
- views or foreign tables. Inapplicable options (e.g., <literal>INCLUDING
+ views, foreign tables, or composite types. Inapplicable options (e.g., <literal>INCLUDING
INDEXES</literal> from a view) are ignored.
</para>
</listitem>
diff --git i/src/backend/parser/parse_utilcmd.c w/src/backend/parser/parse_utilcmd.c
index f1a108a..43f5634 100644
--- i/src/backend/parser/parse_utilcmd.c
+++ w/src/backend/parser/parse_utilcmd.c
@@ -636,26 +636,42 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
TupleConstr *constr;
AclResult aclresult;
char *comment;
+ ParseCallbackState pcbstate;
- relation = parserOpenTable(cxt->pstate, table_like_clause->relation,
- AccessShareLock);
+ setup_parser_errposition_callback(&pcbstate, cxt->pstate, table_like_clause->relation->location);
+
+ relation = relation_openrv(table_like_clause->relation, AccessShareLock);
if (relation->rd_rel->relkind != RELKIND_RELATION
&& relation->rd_rel->relkind != RELKIND_VIEW
- && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE
+ && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("LIKE source relation \"%s\" is not a table, view, or foreign table",
+ errmsg("\"%s\" is not a table, view, composite type, or foreign table",
table_like_clause->relation->relname)));
+ cancel_parser_errposition_callback(&pcbstate);
+
/*
- * Check for SELECT privileges
+ * Check for privileges
*/
- aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
+ if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
+ ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_TYPE,
+ RelationGetRelationName(relation));
+ }
+ else
+ {
+ aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
ACL_SELECT);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_CLASS,
- RelationGetRelationName(relation));
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_CLASS,
+ RelationGetRelationName(relation));
+ }
tupleDesc = RelationGetDescr(relation);
constr = tupleDesc->constr;
diff --git i/src/test/regress/expected/create_table_like.out w/src/test/regress/expected/create_table_like.out
index 40b6766..8bec55c 100644
--- i/src/test/regress/expected/create_table_like.out
+++ w/src/test/regress/expected/create_table_like.out
@@ -8,6 +8,10 @@ CREATE TABLE inhx (xx text DEFAULT 'text');
*/
CREATE TABLE ctla (aa TEXT);
CREATE TABLE ctlb (bb TEXT) INHERITS (ctla);
+CREATE TABLE foo (LIKE nonexistent);
+ERROR: relation "nonexistent" does not exist
+LINE 1: CREATE TABLE foo (LIKE nonexistent);
+ ^
CREATE TABLE inhe (ee text, LIKE inhx) inherits (ctlb);
INSERT INTO inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4');
SELECT * FROM inhe; /* Columns aa, bb, xx value NULL, ee */
@@ -224,18 +228,16 @@ NOTICE: drop cascades to table inhe
CREATE TABLE ctlt4 (a int, b text);
CREATE SEQUENCE ctlseq1;
CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail
-ERROR: LIKE source relation "ctlseq1" is not a table, view, or foreign table
+ERROR: "ctlseq1" is not a table, view, composite type, or foreign table
+LINE 1: CREATE TABLE ctlt10 (LIKE ctlseq1);
+ ^
CREATE VIEW ctlv1 AS SELECT * FROM ctlt4;
CREATE TABLE ctlt11 (LIKE ctlv1);
CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING ALL);
CREATE TYPE ctlty1 AS (a int, b text);
-CREATE TABLE ctlt12 (LIKE ctlty1); -- currently fails
-ERROR: "ctlty1" is a composite type
-LINE 1: CREATE TABLE ctlt12 (LIKE ctlty1);
- ^
+CREATE TABLE ctlt12 (LIKE ctlty1);
DROP SEQUENCE ctlseq1;
DROP TYPE ctlty1;
DROP VIEW ctlv1;
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
NOTICE: table "ctlt10" does not exist, skipping
-NOTICE: table "ctlt12" does not exist, skipping
diff --git i/src/test/regress/sql/create_table_like.sql w/src/test/regress/sql/create_table_like.sql
index db66e48..2d017bc 100644
--- i/src/test/regress/sql/create_table_like.sql
+++ w/src/test/regress/sql/create_table_like.sql
@@ -10,6 +10,8 @@ CREATE TABLE inhx (xx text DEFAULT 'text');
CREATE TABLE ctla (aa TEXT);
CREATE TABLE ctlb (bb TEXT) INHERITS (ctla);
+CREATE TABLE foo (LIKE nonexistent);
+
CREATE TABLE inhe (ee text, LIKE inhx) inherits (ctlb);
INSERT INTO inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4');
SELECT * FROM inhe; /* Columns aa, bb, xx value NULL, ee */
@@ -111,7 +113,7 @@ CREATE TABLE ctlt11 (LIKE ctlv1);
CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING ALL);
CREATE TYPE ctlty1 AS (a int, b text);
-CREATE TABLE ctlt12 (LIKE ctlty1); -- currently fails
+CREATE TABLE ctlt12 (LIKE ctlty1);
DROP SEQUENCE ctlseq1;
DROP TYPE ctlty1;