From 06e304524d5c19223697a78ffaa8c7610bc6a365 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 23 Apr 2026 21:28:11 +0300 Subject: [PATCH] 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 Discussion: https://www.postgresql.org/message-id/93ce56cd-02a6-4db1-8224-c8999372facc@iki.fi Backpatch-through: 14 --- src/backend/catalog/heap.c | 10 ++++++++++ src/test/regress/expected/multirangetypes.out | 3 +++ src/test/regress/sql/multirangetypes.sql | 3 +++ 3 files changed, 16 insertions(+) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index e67ffc37b7d..5811bcd074c 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -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)))) { /* diff --git a/src/test/regress/expected/multirangetypes.out b/src/test/regress/expected/multirangetypes.out index a0cb8754928..4290998912f 100644 --- a/src/test/regress/expected/multirangetypes.out +++ b/src/test/regress/expected/multirangetypes.out @@ -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 -- diff --git a/src/test/regress/sql/multirangetypes.sql b/src/test/regress/sql/multirangetypes.sql index fefb4b4d422..cd3b940fd31 100644 --- a/src/test/regress/sql/multirangetypes.sql +++ b/src/test/regress/sql/multirangetypes.sql @@ -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; --