Allow CREATE TABLE (LIKE ...) from composite type
authorPeter Eisentraut
Sat, 3 Mar 2012 14:03:05 +0000 (16:03 +0200)
committerPeter Eisentraut
Sat, 3 Mar 2012 14:03:05 +0000 (16:03 +0200)
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.

doc/src/sgml/ref/create_table.sgml
src/backend/parser/parse_utilcmd.c
src/test/regress/expected/create_table_like.out
src/test/regress/sql/create_table_like.sql

index f55a0010de50f4687098a8aaff1888f1c8a470ef..bb9321421023884aa273e72f397abf19b5023a2f 100644 (file)
@@ -370,7 +370,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
      
      
       The LIKE clause can also be used to copy columns from
-      views or foreign tables.  Inapplicable options (e.g., INCLUDING
+      views, foreign tables, or composite types.  Inapplicable options (e.g., INCLUDING
       INDEXES from a view) are ignored.
      
     
index f1a108a9828abded3fda6b609028bf2d73de5328..43f5634d16c693cb8afd8bfcb9d14ea525b0be09 100644 (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;
index 40b6766892a14f09c2018b37e6176d68d992f55e..8bec55c3ca3f9351dba6ec281eaf723cbd5b7b40 100644 (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
index db66e48d45713c1af076a63940ae7154b9c1907a..2d017bc02b5b12f155e9147ef68eccb141394f96 100644 (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;