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.
This commit is contained in:
Peter Eisentraut 2012-03-03 16:03:05 +02:00
parent d923125b77
commit b59ca98209
4 changed files with 37 additions and 17 deletions

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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;