]> granicus.if.org Git - postgresql/commitdiff
Only allow typed tables to hang off composite types, not e.g. tables.
authorRobert Haas <rhaas@postgresql.org>
Mon, 18 Apr 2011 14:13:34 +0000 (10:13 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 18 Apr 2011 14:19:46 +0000 (10:19 -0400)
This also ensures that we take a relation lock on the composite type when
creating a typed table, which is necessary to prevent the composite type
and the typed table from getting out of step in the face of concurrent
DDL.

Noah Misch, with some changes.

src/backend/parser/parse_utilcmd.c
src/test/regress/expected/typed_table.out
src/test/regress/sql/typed_table.sql

index eba890bf88dbb6835ed80b37ef56ae5486e8534f..4f1bb34dae0a995aaf9524a55c67bb4ccebb6d21 100644 (file)
@@ -825,6 +825,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
        TupleDesc       tupdesc;
        int                     i;
        Oid                     ofTypeId;
+       bool            typeOk = false;
 
        AssertArg(ofTypename);
 
@@ -833,7 +834,21 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
        ofTypeId = HeapTupleGetOid(tuple);
        ofTypename->typeOid = ofTypeId;         /* cached for later */
 
-       if (typ->typtype != TYPTYPE_COMPOSITE)
+       if (typ->typtype == TYPTYPE_COMPOSITE)
+       {
+               Relation        typeRelation;
+
+               Assert(OidIsValid(typ->typrelid));
+               typeRelation = relation_open(typ->typrelid, AccessShareLock);
+               typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
+               /*
+                * Close the parent rel, but keep our AccessShareLock on it until xact
+                * commit.      That will prevent someone else from deleting or ALTERing
+                * the type before the typed table creation commits.
+                */
+               relation_close(typeRelation, NoLock);
+       }
+       if (!typeOk)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("type %s is not a composite type",
index 0874a64d55463c0c723613eee17a6a31ed8af309..1fe426d6e377d6c6d25256d9e3a7c1b5e8abfb15 100644 (file)
@@ -91,6 +91,8 @@ DETAIL:  drop cascades to table persons
 drop cascades to function get_all_persons()
 drop cascades to table persons2
 drop cascades to table persons3
+CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used
+ERROR:  type stuff is not a composite type
 DROP TABLE stuff;
 -- implicit casting
 CREATE TYPE person_type AS (id int, name text);
index b0d452c387ed0ec152493dd60ed727fe1df67a0b..25aaccb8bcdf219d32b68dbf41e8e648148808ca 100644 (file)
@@ -46,6 +46,8 @@ CREATE TABLE persons4 OF person_type (
 DROP TYPE person_type RESTRICT;
 DROP TYPE person_type CASCADE;
 
+CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used
+
 DROP TABLE stuff;