On Tue, Dec 23, 2025 at 11:25 AM Paul A Jungwirth
<[email protected]> wrote:
>
> > diff --git a/src/backend/utils/cache/typcache.c
> > b/src/backend/utils/cache/typcache.c
> > index 6a347698edf..e27ca1466f2 100644
> > --- a/src/backend/utils/cache/typcache.c
> > +++ b/src/backend/utils/cache/typcache.c
> > @@ -944,6 +944,8 @@ lookup_type_cache(Oid type_id, int flags)
> > typentry->domainBaseTypmod = -1;
> > typentry->domainBaseType =
> > getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
> > + typentry->domainBaseTyptype =
> > + get_typtype(typentry->domainBaseType);
> > }
> > if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
> > (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
>
> Is there any performance concern about adding this lookup?
> From what I can tell we don't use TYPECACHE_DOMAIN_BASE_INFO very
> often, so it is probably okay.
> We can get here in the executor from ExecEvalWholeRowVar, but that
> seems acceptable to me.
>
>
hi.
To make WITHOUT OVERLAPS work with domains, ExecWithoutOverlapsNotEmpty requires
the base type’s typtype. I do not see a viable alternative approach.
We can cache the base type's typtype in TypeCacheEntry->domainBaseTyptype.
```
if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
typentry->domainBaseType == InvalidOid &&
typentry->typtype == TYPTYPE_DOMAIN)
{
typentry->domainBaseTypmod = -1;
typentry->domainBaseType =
getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
typentry->domainBaseTyptype =
get_typtype(typentry->domainBaseType);
}
```
We look up the domain base type’s typtype only once. On subsequent
lookup_type_cache call, typentry->domainBaseType already is a valid OID, so the
IF branch above will not be reached.
so. I don't see any performance issues here.
>
> Also testing a range over a domain (in WITHOUT OVERLAPS position) would be
> good.
>
I do not think we need extensive foreign key–related tests, because
check_exclusion_or_unique_constraint is only invoked for data changes on the
primary key side. So, I kept only a single foreign key–related test.
The attached patch should address all of your comments.
I think you will like attached regress tests.
--
jian
https://www.enterprisedb.com/
From 041198f2fb6674060675980e4bfca6ff16074f13 Mon Sep 17 00:00:00 2001
From: jian he <[email protected]>
Date: Mon, 29 Dec 2025 15:15:23 +0800
Subject: [PATCH v3 1/1] Add support for domain types in WITHOUT OVERLAPS
This commit allows domain types to work with the WITHOUT OVERLAPS constraint.
Domains over range types and domains over multirange types are both supported.
User-defined range types whose subtype is a domain are also supported.
commitfest: https://commitfest.postgresql.org/patch/6281
discussion: https://postgr.es/m/CACJufxGoAmN_0iJ=hjtg0vgposoyy-vyyfe+-q0awxrq2_p...@mail.gmail.com
---
src/backend/executor/execIndexing.c | 10 +-
src/backend/parser/parse_utilcmd.c | 2 +
src/backend/utils/cache/typcache.c | 2 +
src/include/utils/typcache.h | 5 +-
.../regress/expected/without_overlaps.out | 128 +++++++++++++++++-
src/test/regress/sql/without_overlaps.sql | 104 +++++++++++++-
6 files changed, 243 insertions(+), 8 deletions(-)
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index 0b3a31f1703..67eddcac0f3 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -752,13 +752,19 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
if (!isnull[indnkeyatts - 1])
{
+ char typtype;
TupleDesc tupdesc = RelationGetDescr(heap);
Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
- TypeCacheEntry *typcache = lookup_type_cache(att->atttypid, 0);
+ TypeCacheEntry *typcache = lookup_type_cache(att->atttypid, TYPECACHE_DOMAIN_BASE_INFO);
+
+ if (OidIsValid(typcache->domainBaseType))
+ typtype = typcache->domainBaseTyptype;
+ else
+ typtype = typcache->typtype;
ExecWithoutOverlapsNotEmpty(heap, att->attname,
values[indnkeyatts - 1],
- typcache->typtype, att->atttypid);
+ typtype, att->atttypid);
}
}
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 2b7b084f216..33360ba0761 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -2795,6 +2795,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
if (!OidIsValid(typid) && column)
typid = typenameTypeId(NULL, column->typeName);
+ typid = getBaseType(typid);
+
if (!OidIsValid(typid) || !(type_is_range(typid) || type_is_multirange(typid)))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 0c17d99d021..839d1e3ebcf 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -944,6 +944,8 @@ lookup_type_cache(Oid type_id, int flags)
typentry->domainBaseTypmod = -1;
typentry->domainBaseType =
getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
+ typentry->domainBaseTyptype =
+ get_typtype(typentry->domainBaseType);
}
if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
(typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h
index 1cb30f1818c..2ad7528c195 100644
--- a/src/include/utils/typcache.h
+++ b/src/include/utils/typcache.h
@@ -109,11 +109,12 @@ typedef struct TypeCacheEntry
struct TypeCacheEntry *rngtype; /* multirange's range underlying type */
/*
- * Domain's base type and typmod if it's a domain type. Zeroes if not
- * domain, or if information hasn't been requested.
+ * Domain's base type, typmod, and typtype if it's a domain type.
+ * Zeroes if not domain, or if information hasn't been requested.
*/
Oid domainBaseType;
int32 domainBaseTypmod;
+ char domainBaseTyptype;
/*
* Domain constraint data if it's a domain type. NULL if not domain, or
diff --git a/src/test/regress/expected/without_overlaps.out b/src/test/regress/expected/without_overlaps.out
index f3144bdc39c..4853302cae5 100644
--- a/src/test/regress/expected/without_overlaps.out
+++ b/src/test/regress/expected/without_overlaps.out
@@ -162,7 +162,129 @@ CREATE TABLE temporal_rng3 (
);
ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_pk;
DROP TABLE temporal_rng3;
-DROP TYPE textrange2;
+--
+-- tests for range over domain, multirange over a domain, custom range type over
+-- domain, custom multi range type over domain.
+--
+CREATE DOMAIN int4_d as integer check (value <> 10);
+CREATE TYPE int4_d_range as range (subtype = int4_d);
+CREATE DOMAIN int4multirange_d as int4multirange check (value <> '{[10,11)}');
+CREATE DOMAIN int4range_d AS int4range CHECK (VALUE <> '[10,11)');
+CREATE DOMAIN textrange2_d AS textrange2 CHECK (VALUE <> '[c,d)');
+CREATE DOMAIN textrange2_dd AS textrange2_d;
+CREATE DOMAIN textmultirange2_d AS textmultirange2 CHECK (VALUE <> '{[c,d)}');
+-- It is a range type rather than a domain type; however, the range type’s
+-- subtype is a domain type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at int4_d_range,
+ CONSTRAINT temporal_rng4_pk PRIMARY KEY(id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[10,11)'); --error
+ERROR: value for domain int4_d violates check constraint "int4_d_check"
+LINE 1: INSERT INTO temporal_rng4 VALUES ('[1,2)', '[10,11)');
+ ^
+INSERT INTO temporal_rng4 VALUES ('[10,11)', '[1,2)'); --error
+ERROR: value for domain int4range_d violates check constraint "int4range_d_check"
+INSERT INTO temporal_rng4 VALUES ('[1,11)', '[9,10)'); --error
+ERROR: value for domain int4_d violates check constraint "int4_d_check"
+LINE 1: INSERT INTO temporal_rng4 VALUES ('[1,11)', '[9,10)');
+ ^
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[1,13)'), ('[1,2)', '[2,5)'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_rng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), [2,5)) conflicts with existing key (id, valid_at)=([1,2), [1,13)).
+DROP TABLE temporal_rng4;
+--The domain is a range type, and its base type is a built-in range type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at int4range_d,
+ CONSTRAINT temporal_rng4_pk UNIQUE (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[10,11)'); --error
+ERROR: value for domain int4range_d violates check constraint "int4range_d_check"
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[3,13)'), ('[1,2)', '[2,13)'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_rng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), [2,13)) conflicts with existing key (id, valid_at)=([1,2), [3,13)).
+DROP TABLE temporal_rng4;
+--The domain is a range type, and its base type is a user-defined range type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at textrange2_dd,
+ CONSTRAINT temporal_rng4_pk UNIQUE (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', NULL), (NULL, '[1,2)');
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[c,d)'); --error
+ERROR: value for domain textrange2_dd violates check constraint "textrange2_d_check"
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[a,d)');
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[b,c)'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_rng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), [b,c)) conflicts with existing key (id, valid_at)=([1,2), [a,d)).
+INSERT INTO temporal_rng4 VALUES ('[10,11)', NULL); --error
+ERROR: value for domain int4range_d violates check constraint "int4range_d_check"
+INSERT INTO temporal_rng4 VALUES ('[2,3)', '[B,C)'), ('[2,3)', '[A,C)'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_rng4_pk"
+DETAIL: Key (id, valid_at)=([2,3), [A,C)) conflicts with existing key (id, valid_at)=([2,3), [B,C)).
+-- It is a multirange type rather than a domain type; however, the multirange
+-- type’s subtype is a domain type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at int4_d_multirange,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[10,11)}'); --error
+ERROR: value for domain int4_d violates check constraint "int4_d_check"
+LINE 1: INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[10,11)}');
+ ^
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[3,13)}'), ('[1,2)', '{[2,13)}'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_mltrng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), {[2,13)}) conflicts with existing key (id, valid_at)=([1,2), {[3,13)}).
+DROP TABLE temporal_mltrng4;
+--The domain is a multirange type, and its base type is a built-in multirange
+--type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at int4multirange_d,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[10,11)}'); --error
+ERROR: value for domain int4multirange_d violates check constraint "int4multirange_d_check"
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[3,13)}'), ('[1,2)', '{[2,13)}'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_mltrng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), {[2,13)}) conflicts with existing key (id, valid_at)=([1,2), {[3,13)}).
+DROP TABLE temporal_mltrng4;
+--The domain is a multirange type, and its base type is a user-defined
+--multirange type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at textmultirange2_d,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[c,d)}'); --error
+ERROR: value for domain textmultirange2_d violates check constraint "textmultirange2_d_check"
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[a,g)}');
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[b,c)}'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_mltrng4_pk"
+DETAIL: Key (id, valid_at)=([1,2), {[b,c)}) conflicts with existing key (id, valid_at)=([1,2), {[a,g)}).
+INSERT INTO temporal_mltrng4 VALUES ('[2,3)', '{[B,C)}'), ('[2,3)', '{[A,C)}'); --error
+ERROR: conflicting key value violates exclusion constraint "temporal_mltrng4_pk"
+DETAIL: Key (id, valid_at)=([2,3), {[A,C)}) conflicts with existing key (id, valid_at)=([2,3), {[B,C)}).
+----now test foreign key
+CREATE TABLE temporal_mltrngfk (
+ parent_id int4range_d,
+ id int4range,
+ valid_at textmultirange2_d);
+ALTER TABLE temporal_mltrngfk
+ ADD CONSTRAINT temporal_mltrngfk_fk
+ FOREIGN KEY (parent_id, PERIOD valid_at)
+ REFERENCES temporal_mltrng4;
+INSERT INTO temporal_mltrngfk VALUES ('[1,2)', '[2,3)', '{[d,e)}');
+UPDATE temporal_mltrng4 SET valid_at = '{[c,d)}'; --error
+ERROR: value for domain textmultirange2_d violates check constraint "textmultirange2_d_check"
+UPDATE temporal_mltrng4 SET valid_at = '{[a,h)}';
+UPDATE temporal_mltrng4 SET valid_at = '{[f,g)}'; --error
+ERROR: update or delete on table "temporal_mltrng4" violates foreign key constraint "temporal_mltrngfk_fk" on table "temporal_mltrngfk"
+DETAIL: Key (id, valid_at)=([1,2), {[a,h)}) is still referenced from table "temporal_mltrngfk".
+DROP TABLE temporal_mltrng4, temporal_mltrngfk, temporal_rng4;
-- PK with one column plus a multirange:
CREATE TABLE temporal_mltrng (
id int4range,
@@ -301,7 +423,6 @@ SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'te
DROP TABLE temporal_rng3;
-- UNIQUE with a custom range type:
-CREATE TYPE textrange2 AS range (subtype=text, collation="C");
CREATE TABLE temporal_rng3 (
id int4range,
valid_at textrange2,
@@ -309,6 +430,9 @@ CREATE TABLE temporal_rng3 (
);
ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq;
DROP TABLE temporal_rng3;
+DROP TYPE int4_d_range;
+DROP DOMAIN int4range_d, textrange2_dd, textrange2_d,
+ textmultirange2_d, int4multirange_d, int4_d;
DROP TYPE textrange2;
--
-- test ALTER TABLE ADD CONSTRAINT
diff --git a/src/test/regress/sql/without_overlaps.sql b/src/test/regress/sql/without_overlaps.sql
index 4aaca242bbe..55b89b08622 100644
--- a/src/test/regress/sql/without_overlaps.sql
+++ b/src/test/regress/sql/without_overlaps.sql
@@ -100,7 +100,105 @@ CREATE TABLE temporal_rng3 (
);
ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_pk;
DROP TABLE temporal_rng3;
-DROP TYPE textrange2;
+
+--
+-- tests for range over domain, multirange over a domain, custom range type over
+-- domain, custom multi range type over domain.
+--
+CREATE DOMAIN int4_d as integer check (value <> 10);
+CREATE TYPE int4_d_range as range (subtype = int4_d);
+CREATE DOMAIN int4multirange_d as int4multirange check (value <> '{[10,11)}');
+CREATE DOMAIN int4range_d AS int4range CHECK (VALUE <> '[10,11)');
+CREATE DOMAIN textrange2_d AS textrange2 CHECK (VALUE <> '[c,d)');
+CREATE DOMAIN textrange2_dd AS textrange2_d;
+CREATE DOMAIN textmultirange2_d AS textmultirange2 CHECK (VALUE <> '{[c,d)}');
+
+-- It is a range type rather than a domain type; however, the range type’s
+-- subtype is a domain type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at int4_d_range,
+ CONSTRAINT temporal_rng4_pk PRIMARY KEY(id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[10,11)'); --error
+INSERT INTO temporal_rng4 VALUES ('[10,11)', '[1,2)'); --error
+INSERT INTO temporal_rng4 VALUES ('[1,11)', '[9,10)'); --error
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[1,13)'), ('[1,2)', '[2,5)'); --error
+DROP TABLE temporal_rng4;
+
+--The domain is a range type, and its base type is a built-in range type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at int4range_d,
+ CONSTRAINT temporal_rng4_pk UNIQUE (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[10,11)'); --error
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[3,13)'), ('[1,2)', '[2,13)'); --error
+DROP TABLE temporal_rng4;
+
+--The domain is a range type, and its base type is a user-defined range type.
+CREATE TABLE temporal_rng4 (
+ id int4range_d,
+ valid_at textrange2_dd,
+ CONSTRAINT temporal_rng4_pk UNIQUE (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_rng4 VALUES ('[1,2)', NULL), (NULL, '[1,2)');
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[c,d)'); --error
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[a,d)');
+INSERT INTO temporal_rng4 VALUES ('[1,2)', '[b,c)'); --error
+INSERT INTO temporal_rng4 VALUES ('[10,11)', NULL); --error
+INSERT INTO temporal_rng4 VALUES ('[2,3)', '[B,C)'), ('[2,3)', '[A,C)'); --error
+
+-- It is a multirange type rather than a domain type; however, the multirange
+-- type’s subtype is a domain type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at int4_d_multirange,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[10,11)}'); --error
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[3,13)}'), ('[1,2)', '{[2,13)}'); --error
+DROP TABLE temporal_mltrng4;
+
+--The domain is a multirange type, and its base type is a built-in multirange
+--type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at int4multirange_d,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[10,11)}'); --error
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[3,13)}'), ('[1,2)', '{[2,13)}'); --error
+DROP TABLE temporal_mltrng4;
+
+--The domain is a multirange type, and its base type is a user-defined
+--multirange type.
+CREATE TABLE temporal_mltrng4 (
+ id int4range_d,
+ valid_at textmultirange2_d,
+ CONSTRAINT temporal_mltrng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)
+);
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[c,d)}'); --error
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[a,g)}');
+INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[b,c)}'); --error
+INSERT INTO temporal_mltrng4 VALUES ('[2,3)', '{[B,C)}'), ('[2,3)', '{[A,C)}'); --error
+
+----now test foreign key
+CREATE TABLE temporal_mltrngfk (
+ parent_id int4range_d,
+ id int4range,
+ valid_at textmultirange2_d);
+ALTER TABLE temporal_mltrngfk
+ ADD CONSTRAINT temporal_mltrngfk_fk
+ FOREIGN KEY (parent_id, PERIOD valid_at)
+ REFERENCES temporal_mltrng4;
+
+INSERT INTO temporal_mltrngfk VALUES ('[1,2)', '[2,3)', '{[d,e)}');
+UPDATE temporal_mltrng4 SET valid_at = '{[c,d)}'; --error
+UPDATE temporal_mltrng4 SET valid_at = '{[a,h)}';
+UPDATE temporal_mltrng4 SET valid_at = '{[f,g)}'; --error
+
+DROP TABLE temporal_mltrng4, temporal_mltrngfk, temporal_rng4;
-- PK with one column plus a multirange:
CREATE TABLE temporal_mltrng (
@@ -170,7 +268,6 @@ SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'te
DROP TABLE temporal_rng3;
-- UNIQUE with a custom range type:
-CREATE TYPE textrange2 AS range (subtype=text, collation="C");
CREATE TABLE temporal_rng3 (
id int4range,
valid_at textrange2,
@@ -178,6 +275,9 @@ CREATE TABLE temporal_rng3 (
);
ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq;
DROP TABLE temporal_rng3;
+DROP TYPE int4_d_range;
+DROP DOMAIN int4range_d, textrange2_dd, textrange2_d,
+ textmultirange2_d, int4multirange_d, int4_d;
DROP TYPE textrange2;
--
--
2.34.1