From 6609c3ad984bde125ff6ec4e3e056a5b23f68210 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 23 Dec 2019 12:08:24 -0500 Subject: [PATCH] Prevent a rowtype from being included in itself via a range. We probably should have thought of this case when ranges were added, but we didn't. (It's not the fault of commit eb51af71f, because ranges didn't exist then.) It's an old bug, so back-patch to all supported branches. Discussion: https://postgr.es/m/7782.1577051475@sss.pgh.pa.us --- src/backend/catalog/heap.c | 9 +++++++++ src/test/regress/expected/rangetypes.out | 19 +++++++++++++++++++ src/test/regress/sql/rangetypes.sql | 16 ++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 5cb87c105a6..910e73f7eab 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -563,6 +563,15 @@ CheckAttributeType(const char *attname, containing_rowtypes = list_delete_first(containing_rowtypes); } + else if (att_typtype == TYPTYPE_RANGE) + { + /* + * If it's a range, recurse to check its subtype. + */ + CheckAttributeType(attname, get_range_subtype(atttypid), attcollation, + containing_rowtypes, + allow_system_table_mods); + } else if (OidIsValid((att_typelem = get_element_type(atttypid)))) { /* diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index 130604b37d0..1e3e8b038a5 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -1361,6 +1361,25 @@ select array[1,3] <@ arrayrange(array[1,2], array[2,1]); t (1 row) +-- +-- Ranges of composites +-- +create type two_ints as (a int, b int); +create type two_ints_range as range (subtype = two_ints); +select *, row_to_json(upper(t)) as u from + (values (two_ints_range(row(1,2), row(3,4))), + (two_ints_range(row(5,6), row(7,8)))) v(t); + t | u +-------------------+--------------- + ["(1,2)","(3,4)") | {"a":3,"b":4} + ["(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_range; +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 -- -- Check behavior when subtype lacks a hash function -- diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index 0793a8235a1..b8030e5aca7 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -451,6 +451,22 @@ select arrayrange(ARRAY[2,1], ARRAY[1,2]); -- fail select array[1,1] <@ arrayrange(array[1,2], array[2,1]); select array[1,3] <@ arrayrange(array[1,2], array[2,1]); +-- +-- Ranges of composites +-- + +create type two_ints as (a int, b int); +create type two_ints_range as range (subtype = two_ints); + +select *, row_to_json(upper(t)) as u from + (values (two_ints_range(row(1,2), row(3,4))), + (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_range; + +drop type two_ints cascade; + -- -- Check behavior when subtype lacks a hash function -- -- 2.39.5