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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers