On tis, 2011-11-29 at 06:33 +0200, Peter Eisentraut wrote: > > > I'm not trying to inherit a relation, I'm trying to base a table on > > > it. As it happens, "cows" is a foreign table, which *is* a table, > > > just not a regular table. It might be useful to add support to clone > > > foreign tables into regular tables, the use-case being that you may > > > wish to import all the data locally into a table of the same > > > structure. But the gripe here is the suggestion that the relation > > > would have been inherited, which would actually be achieved using > > > INHERITS. > > > > Interesting. I agree that there's no obvious reason why that > > shouldn't be allowed to work. Could be useful with views, too. > > I recently came across a situation where LIKE with a composite type > might have been useful. > This was the last piece of the puzzle that was missing in this area, for which I have now developed a fix. The problem was that parserOpenTable() rejected composite types. But the only thing that was really adding over using relation_open() directly was nicer error pointers. So I removed a few levels of indirection there, and integrated the error pointer support directly into transformTableLikeClause(). This also has the advantage that the "... is not a table, view, or ..." message now has error pointer support.
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;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers