diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/heap.c | 38 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 3 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 8 | ||||
-rw-r--r-- | src/include/catalog/heap.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/alter_table.out | 12 | ||||
-rw-r--r-- | src/test/regress/sql/alter_table.sql | 9 |
6 files changed, 67 insertions, 4 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a090981e5c4..d74700f716f 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -422,6 +422,7 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, { CheckAttributeType(NameStr(tupdesc->attrs[i]->attname), tupdesc->attrs[i]->atttypid, + NIL, /* assume we're creating a new rowtype */ allow_system_table_mods); } } @@ -430,15 +431,24 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, * CheckAttributeType * * Verify that the proposed datatype of an attribute is legal. - * This is needed because there are types (and pseudo-types) + * This is needed mainly because there are types (and pseudo-types) * in the catalogs that we do not support as elements of real tuples. + * We also check some other properties required of a table column. + * + * If the attribute is being proposed for addition to an existing table or + * composite type, pass a one-element list of the rowtype OID as + * containing_rowtypes. When checking a to-be-created rowtype, it's + * sufficient to pass NIL, because there could not be any recursive reference + * to a not-yet-existing rowtype. * -------------------------------- */ void CheckAttributeType(const char *attname, Oid atttypid, + List *containing_rowtypes, bool allow_system_table_mods) { char att_typtype = get_typtype(atttypid); + Oid att_typelem; if (atttypid == UNKNOWNOID) { @@ -476,6 +486,20 @@ CheckAttributeType(const char *attname, Oid atttypid, TupleDesc tupdesc; int i; + /* + * Check for self-containment. Eventually we might be able to allow + * this (just return without complaint, if so) but it's not clear how + * many other places would require anti-recursion defenses before it + * would be safe to allow tables to contain their own rowtype. + */ + if (list_member_oid(containing_rowtypes, atttypid)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("composite type %s cannot be made a member of itself", + format_type_be(atttypid)))); + + containing_rowtypes = lcons_oid(atttypid, containing_rowtypes); + relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock); tupdesc = RelationGetDescr(relation); @@ -487,10 +511,22 @@ CheckAttributeType(const char *attname, Oid atttypid, if (attr->attisdropped) continue; CheckAttributeType(NameStr(attr->attname), attr->atttypid, + containing_rowtypes, allow_system_table_mods); } relation_close(relation, AccessShareLock); + + containing_rowtypes = list_delete_first(containing_rowtypes); + } + else if (OidIsValid((att_typelem = get_element_type(atttypid)))) + { + /* + * Must recurse into array types, too, in case they are composite. + */ + CheckAttributeType(attname, att_typelem, + containing_rowtypes, + allow_system_table_mods); } } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 54cf280d57f..caa985a791f 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -258,7 +258,8 @@ ConstructTupleDescriptor(Relation heapRelation, * whether a table column is of a safe type (which is why we * needn't check for the non-expression case). */ - CheckAttributeType(NameStr(to->attname), to->atttypid, false); + CheckAttributeType(NameStr(to->attname), to->atttypid, + NIL, false); } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 6a1804b6fec..64141c03408 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3729,7 +3729,9 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, typeOid = HeapTupleGetOid(typeTuple); /* make sure datatype is legal for a column */ - CheckAttributeType(colDef->colname, typeOid, false); + CheckAttributeType(colDef->colname, typeOid, + list_make1_oid(rel->rd_rel->reltype), + false); /* construct new attribute's pg_attribute entry */ attribute.attrelid = myrelid; @@ -5858,7 +5860,9 @@ ATPrepAlterColumnType(List **wqueue, targettype = typenameTypeId(NULL, typeName, &targettypmod); /* make sure datatype is legal for a column */ - CheckAttributeType(colName, targettype, false); + CheckAttributeType(colName, targettype, + list_make1_oid(rel->rd_rel->reltype), + false); /* * Set up an expression to transform the old data value to the new type. diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 557c311bc22..6a91ddb4fc3 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -115,6 +115,7 @@ extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, bool allow_system_table_mods); extern void CheckAttributeType(const char *attname, Oid atttypid, + List *containing_rowtypes, bool allow_system_table_mods); #endif /* HEAP_H */ diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 40a907d869e..a460371a112 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -1476,6 +1476,18 @@ select * from another; (3 rows) drop table another; +-- disallow recursive containment of row types +create temp table recur1 (f1 int); +alter table recur1 add column f2 recur1; -- fails +ERROR: composite type recur1 cannot be made a member of itself +alter table recur1 add column f2 recur1[]; -- fails +ERROR: composite type recur1 cannot be made a member of itself +create temp table recur2 (f1 int, f2 recur1); +alter table recur1 add column f2 recur2; -- fails +ERROR: composite type recur1 cannot be made a member of itself +alter table recur1 add column f2 int; +alter table recur1 alter column f2 type recur2; -- fails +ERROR: composite type recur1 cannot be made a member of itself -- -- alter function -- diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 2b01238e282..8f472cff1e5 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -1092,6 +1092,15 @@ select * from another; drop table another; +-- disallow recursive containment of row types +create temp table recur1 (f1 int); +alter table recur1 add column f2 recur1; -- fails +alter table recur1 add column f2 recur1[]; -- fails +create temp table recur2 (f1 int, f2 recur1); +alter table recur1 add column f2 recur2; -- fails +alter table recur1 add column f2 int; +alter table recur1 alter column f2 type recur2; -- fails + -- -- alter function -- |