Don't allow composite type to be member of itself via multirange

CheckAttributeType() checks that a composite type is not made a member
of itself with ALTER TABLE ADD COLUMN or ALTER TYPE ADD ATTRIBUTE,
even indirectly via a domain, array, another composite type or a range
type. But it missed checking for multiranges. That was a simple
oversight when multiranges were added.

Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://www.postgresql.org/message-id/93ce56cd-02a6-4db1-8224-c8999372facc@iki.fi
Backpatch-through: 14
This commit is contained in:
Heikki Linnakangas 2026-04-23 21:28:11 +03:00
parent e1e60f148a
commit 06e304524d
3 changed files with 16 additions and 0 deletions

View file

@ -647,6 +647,16 @@ CheckAttributeType(const char *attname,
containing_rowtypes,
flags);
}
else if (att_typtype == TYPTYPE_MULTIRANGE)
{
/*
* If it's a multirange, recurse to check its plain range type.
*/
CheckAttributeType(attname, get_multirange_range(atttypid),
InvalidOid, /* range types are not collatable */
containing_rowtypes,
flags);
}
else if (OidIsValid((att_typelem = get_element_type(atttypid))))
{
/*

View file

@ -3267,6 +3267,9 @@ select *, row_to_json(upper(t)) as u from
{["(5,6)","(7,8)")} | {"a":7,"b":8}
(2 rows)
-- this must be rejected to avoid self-inclusion issues:
alter type two_ints add attribute c two_ints_multirange;
ERROR: composite type two_ints cannot be made a member of itself
drop type two_ints cascade;
NOTICE: drop cascades to type two_ints_range
--

View file

@ -794,6 +794,9 @@ select *, row_to_json(upper(t)) as u from
(values (two_ints_multirange(two_ints_range(row(1,2), row(3,4)))),
(two_ints_multirange(two_ints_range(row(5,6), row(7,8))))) v(t);
-- this must be rejected to avoid self-inclusion issues:
alter type two_ints add attribute c two_ints_multirange;
drop type two_ints cascade;
--