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

Reply via email to