I'm using PG 14 and have an application using a custom range with a custom
domain subtype. My problem: PG does not do an implicit cast from the
domain's base type when used with range operators. Below is a script that
will demonstrate the problem (and below that, the output of running it with
psql).
domain subtype. My problem: PG does not do an implicit cast from the
domain's base type when used with range operators. Below is a script that
will demonstrate the problem (and below that, the output of running it with
psql).
What I'm looking for: the magic to add to my schema so I do not have to add
explicit casts throughout my application code when using the base type of a
domain as an operand to a range operator using a subtype of the domain. How
do we get implicit casts?
Thanks!
Daniel
Here's my script. Note it creates a schema to isolate what it generates.
Output of running it follows.
----------------------------------------------------------------------
\set ECHO all
\set VERBOSITY verbose
select version();
create schema _range_domain_cast;
set search_path to _range_domain_cast,public;
-- domain with underlying type of integer (what constraints we might
-- place on the integer values are not germane to the issue so they're
-- left out).
create domain zzzint integer;
-- a range on our domain
create type zzzrange as range (subtype = zzzint);
-- similar range, but on an integer
create type myintrange as range (subtype = integer);
-- these work
select myintrange(10, 20) @> 15; -- subtype is integer and this
just works
select zzzrange(10, 20) @> 15::zzzint; -- subtype is zzzint and this
works with the explicit cast
-- as does using integer where zzzint is expected
create table foo (
x zzzint
);
insert into foo select * from generate_series(1,3);
select * from foo;
-- But this fails! - without the explicit cast, PG doesn't do the
implicit cast
-- even though integer is the underlying type of the domain
select zzzrange(10, 20) @> 15;
----------------------------------------------------------------------
Here is the output when running it:
\set VERBOSITY verbose
select version();
version
--------------------------------------------------------------------------------------------------------------
PostgreSQL 14.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine
10.3.1_git20211027) 10.3.1 20211027, 64-bit
(1 row)
create schema _range_domain_cast;
CREATE SCHEMA
set search_path to _range_domain_cast,public;
SET
-- domain with underlying type of integer (what constraints we might
-- place on the integer values are not germane to the issue so they're
-- left out).
create domain zzzint integer;
CREATE DOMAIN
-- a range on our domain
create type zzzrange as range (subtype = zzzint);
CREATE TYPE
-- similar range, but on an integer
create type myintrange as range (subtype = integer);
CREATE TYPE
-- these work
select myintrange(10, 20) @> 15; -- subtype is integer and this
just works
?column?
----------
t
(1 row)
select zzzrange(10, 20) @> 15::zzzint; -- subtype is zzzint and this
works with the explicit cast
?column?
----------
t
(1 row)
-- as does using integer where zzzint is expected
create table foo (
x zzzint
);
CREATE TABLE
insert into foo select * from generate_series(1,3);
INSERT 0 3
select * from foo;
x
---
1
2
3
(3 rows)
-- But this fails! - without the explicit cast, PG doesn't do the
implicit cast
-- even though integer is the underlying type of the domain
select zzzrange(10, 20) @> 15;
ERROR: 42883: operator does not exist: zzzrange @> integer
LINE 1: select zzzrange(10, 20) @> 15;
^
HINT: No operator matches the given name and argument types. You might need
to add explicit type casts.
LOCATION: op_error, parse_oper.c:647
----------------------------------------------------------------------