Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQrld-001Sfg-2n for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Dec 2025 18:39:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vQrlc-00FPr2-1V for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Dec 2025 18:39:56 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQrlb-00FPqu-31 for pgsql-hackers@lists.postgresql.org; Wed, 03 Dec 2025 18:39:56 +0000 Received: from mail-oi1-x231.google.com ([2607:f8b0:4864:20::231]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vQrla-002xwz-0G for pgsql-hackers@postgresql.org; Wed, 03 Dec 2025 18:39:55 +0000 Received: by mail-oi1-x231.google.com with SMTP id 5614622812f47-450c6f5ff81so71970b6e.0 for ; Wed, 03 Dec 2025 10:39:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=illuminatedcomputing-com.20230601.gappssmtp.com; s=20230601; t=1764787192; x=1765391992; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=McOXEDlJMCLOb3X6kcZyZq0qB2f0w34amHuL3Z5rZRw=; b=g4ReH0dwKJSr1Yqrj4e4jn5KMQCKgt1gj/I5kvqd+gj1do2abNStXPBOEY1PSNqzh3 9k98FGVMsvVcKN3VnX+dsHoUn3wDd/TsWsWNDSEWb3Ab06DO8yQYD/cVgmYY4KMArJZT DDIxUQW/nH7ydgTe3Bgor6pU4nCJ3KgqblDLr3n5W/EmZ3os5y4e9P+a4aTK0njdr/q+ krdM5atfX7pdv9Haxlt/6QDrZ0/G5duvM2B43mrPTBT3D7a8R8bxrcHTqY9zQdQ/Sj8T 4cdMdE+jeQ0LhZcLP6lR6Sj72TE+q59H7FO4jE23aF9y6sm2l33AJcTe41G7UjLX/ub3 dVbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764787192; x=1765391992; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=McOXEDlJMCLOb3X6kcZyZq0qB2f0w34amHuL3Z5rZRw=; b=iDfTCiyO2WH9RAqEMsQsDhcmKpR6NNVc/d2WzHpyUTLLBjR4uWq/s5sneV9H7op7QA +YNS0l7aCecEb0+G69yTFKFWso2n3xhQGnF8503qY58Sphax216thkWWJ9UHmzb8ZvYc jR8Z27Am13WeDyoshGYZ4rhcf7q6Aq9aGCn51r7aQMfc+6zEq2cos5PgK/TK3WEVWpAB IdexmUXo9vKp9rw2hmiNKDho0HXtEyRNXwYSy3U56HEg5oh/3m0Sy0JeOFA8thJkSlBv b1csZXnTyK00VxPQQSwiePqE6c5IogZh+fxQwsOsrhK39VnMrPpz5QiZ2O3FJHCgw4rV SCdA== X-Gm-Message-State: AOJu0Yzw94dyCAIehRtr7Fy2lymn1JdOvxiGk/cybwlCozT2Bzw0o3k9 AxzjnNEcyLVQTpbTf7a9G/36OFPfz3FEn0sxiDKxwri3Ud48yULziZiV+7c/nBrO3NChc9uHlQ1 0s0uI95OrKZcPdD1s6br0Yk3ps2fblpoAQORo/Ko1tA== X-Gm-Gg: ASbGncuBfObPHWp+YFY7KzylZLXD1S8kypgjdjXa9vs2+azNNv4lpSxMA1c0QfV7fBG fb5xtiJXhr1KTjSIlsRrww4DOTw3om50KizgYqA2ixiuybA2boI1c/X5r54O7lMA946ldr0QWMJ lxXCIME6eKHupZe4dO/Dahc3CWk7S+BE5UsEzgEIvoPTu7T8vlVCTwqo8QUpYluUFzgLa9vzu1b 1X4aK5wS02A2q2FMGomQGSxQGjd6ycYf0nuQmyVjEfbrdfTb6U3UIPNfmIrLd0RvsuT X-Google-Smtp-Source: AGHT+IGSDSYROq9eVY7+ufwUpZtGzOCQyy2agrBMv/4N0+8r9a/BYWQv/+vegkANAwPIF7QbdTMYAvBAyivGH5UBPgQ= X-Received: by 2002:a05:6808:1405:b0:44f:9fd0:8a5b with SMTP id 5614622812f47-45378f76c7fmr290637b6e.26.1764787191681; Wed, 03 Dec 2025 10:39:51 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Paul A Jungwirth Date: Wed, 3 Dec 2025 10:39:40 -0800 X-Gm-Features: AWmQ_bl9swsJ8_hyeU8JbarqehEx0LDrSz32lGom-TwA7tOhZ_0rJCA9RyEDujA Message-ID: Subject: Re: domain for WITHOUT OVERLAPS To: jian he Cc: PostgreSQL-development Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Dec 2, 2025 at 11:39=E2=80=AFPM jian he wrote: > > While working on domain IS JSON, I found out that > WITHOUT OVERLAPS does not support for domain too. > but it does support user-defined range types (via CREATE TYPE). > > after looking around: > check_exclusion_or_unique_constraint->ExecWithoutOverlapsNotEmpty > ExecWithoutOverlapsNotEmpty typtype should be domain's basetype's typtype > otherwise it will fallback to: > elog(ERROR, "WITHOUT OVERLAPS column \"%s\" is not a range > or multirange", > NameStr(attname)); > > That means we need to cheaply get the domain basetype's > pg_type.typtype in lookup_type_cache. > so I added a new char field: TypeCacheEntry.domainBaseTyptype. Thanks for the bug report and fix! Have you created a commitfest entry for this? I didn't find one. +CREATE DOMAIN d_textrange1 AS int4range CHECK (VALUE <> '[10,10]'); +CREATE DOMAIN d_textrange2 AS textrange2 CHECK (VALUE <> '[c,c]'); +CREATE DOMAIN d_textrange2c AS d_textrange2; The first domain should be called d_int4range or d_int4range1, right? Also let's name them like int4range_d so that we can use int4_d_range for a range over a domain. Please use closed/open notation to match the rest of the ranges in the file: '[10,11)' and '[c,d)'. I think there are these cases to consider: - WITHOUT OVERLAPS on a rangetype whose subtype has a domain - WITHOUT OVERLAPS on a rangetype with a domain on itself - WITHOUT OVERLAPS on a multirangetype whose subtype has a domain - WITHOUT OVERLAPS on a multirangetype whose rangetype has a domain - WITHOUT OVERLAPS on a multirangetype with a domain on itself For instance we could set things up like so: -- range+multirange over a domain: create domain int4_d as integer check (value <> 10); create type int4_d_range as range (subtype =3D int4_d); -- domain on a range: create domain int4range_d as int4range check (value <> '[10,11)'); -- domain on a multirange: create domain int4multirange_d as int4multirange check (value <> '{[10,11)}= '); Then we have this: ``` [v19devel:5432][426675] postgres=3D# select oid, typname, typtype, typbasetype, typtypmod from pg_type where oid >=3D 20000 order by oid ; oid | typname | typtype | typbasetype | typtypmod -------+--------------------+---------+-------------+----------- 24595 | _int4_d | b | 0 | -1 24596 | int4_d | d | 23 | -1 24598 | _int4_d_range | b | 0 | -1 24599 | int4_d_multirange | m | 0 | -1 24600 | _int4_d_multirange | b | 0 | -1 24601 | int4_d_range | r | 0 | -1 24608 | _int4range_d | b | 0 | -1 24609 | int4range_d | d | 3904 | -1 24611 | _int4multirange_d | b | 0 | -1 24612 | int4multirange_d | d | 4451 | -1 ``` Note that creating a domain on a range does not create a corresponding multirange. Maybe that is a bug. It means we can't test the 4th case above. It looks like domains on the subtype work, but not directly on a range or multirange: ``` [v19devel:5432][426675] postgres=3D# create table t1 (id int4range, valid_at int4_d_range, primary key (id, valid_at without overlaps)); CREATE TABLE [v19devel:5432][426675] postgres=3D# create table t2 (id int4range, valid_at int4range_d, primary key (id, valid_at without overlaps)); ERROR: column "valid_at" in WITHOUT OVERLAPS is not a range or multirange = type LINE 1: ...ate table t2 (id int4range, valid_at int4range_d, primary ke... ^ [v19devel:5432][426675] postgres=3D# create table t3 (id int4range, valid_at int4_d_multirange, primary key (id, valid_at without overlaps)); CREATE TABLE [v19devel:5432][426675] postgres=3D# create table t4 (id int4range, valid_at int4_multirange_d, primary key (id, valid_at without overlaps)); ERROR: type "int4_multirange_d" does not exist LINE 1: create table t4 (id int4range, valid_at int4_multirange_d, p... ``` It would be good to have tests for all of those. For instance: ``` -- domain on a multirange: CREATE DOMAIN textmultirange2_d AS textmultirange2 CHECK (VALUE <> '{[c,d)}= '); CREATE TABLE temporal_mltrng4 ( id d_int4range1, valid_at textmultirange2_d, CONSTRAINT temporal_rng4_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) ); INSERT INTO temporal_mltrng4 VALUES ('[1,2)', '{[c,d)}'); --domain constraint violation 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,2]', '{[A,C)}'); --error CREATE TABLE temporal_mltrngfk (parent_id d_int4range1, 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)}'); TABLE temporal_mltrng4; TABLE temporal_mltrngfk; UPDATE temporal_mltrng4 SET valid_at =3D '{[c,d)}'; --error UPDATE temporal_mltrng4 SET valid_at =3D '{[a,h)}'; UPDATE temporal_mltrng4 SET valid_at =3D '{[f,g)}'; --error DROP TABLE temporal_mltrng4, temporal_mltrngfk; ``` When I try that, it looks like your patch fixes multiranges too. Yours, --=20 Paul ~{:-) pj@illuminatedcomputing.com