]> granicus.if.org Git - postgresql/commitdiff
Allow CREATE TABLE (LIKE ...) from composite type
authorPeter Eisentraut <peter_e@gmx.net>
Sat, 3 Mar 2012 14:03:05 +0000 (16:03 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
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
      </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>
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;