aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2011-04-18 10:13:34 -0400
committerRobert Haas <rhaas@postgresql.org>2011-04-18 10:19:46 -0400
commit04db0fdbfa9382730bb65f94bca2cd8063a3456a (patch)
treefa66be340f38b1cd5507732828e59aef0744a293 /src
parentb7b86924c6da46c774e1ab5d524a6bc4f72627ab (diff)
downloadpostgresql-04db0fdbfa9382730bb65f94bca2cd8063a3456a.tar.gz
postgresql-04db0fdbfa9382730bb65f94bca2cd8063a3456a.zip
Only allow typed tables to hang off composite types, not e.g. tables.
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_utilcmd.c17
-rw-r--r--src/test/regress/expected/typed_table.out2
-rw-r--r--src/test/regress/sql/typed_table.sql2
3 files changed, 20 insertions, 1 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index eba890bf88d..4f1bb34dae0 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -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",
diff --git a/src/test/regress/expected/typed_table.out b/src/test/regress/expected/typed_table.out
index 0874a64d554..1fe426d6e37 100644
--- a/src/test/regress/expected/typed_table.out
+++ b/src/test/regress/expected/typed_table.out
@@ -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);
diff --git a/src/test/regress/sql/typed_table.sql b/src/test/regress/sql/typed_table.sql
index b0d452c387e..25aaccb8bcd 100644
--- a/src/test/regress/sql/typed_table.sql
+++ b/src/test/regress/sql/typed_table.sql
@@ -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;