Re: Domains versus arrays versus typmods

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org, Richard Huxton <dev(at)archonet(dot)com>
Subject: Re: Domains versus arrays versus typmods
Date: 2010-10-21 16:46:39
Message-ID: 25892.1287679599@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Robert Haas <robertmhaas(at)gmail(dot)com> writes:
> On Wed, Oct 20, 2010 at 10:03 AM, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:
>> My point is that anyplace that is relying on the surface typelem,
>> without drilling down to see what the base type is, is wrong.
>> So yeah, those lookups are (will be) necessary.

> OK. In that case, +1 from me.

I've come across another interesting definitional issue, which is what
properties should domains have with respect to matching to polymorphic
arguments. Currently, the polymorphic matching functions take domains
at face value (ie, without noticing their relationships to their base
types), with one exception: because they use get_element_type() to
decide if a type matches ANYARRAY, domains over arrays will be
considered to match ANYARRAY. This leads to some weird inconsistencies
and at least one genuine bug. Observe (this is with 9.0.x HEAD):

regression=# create domain myi as int;
CREATE DOMAIN
regression=# select array[1,2] || 3;
?column?
----------
{1,2,3}
(1 row)

regression=# select array[1,2] || 3::myi;
ERROR: operator does not exist: integer[] || myi

In this case, one might expect myi to be automatically downcast to int
so that it could be matched up with the int array, but that's not
happening. However:

regression=# create domain myia as int[];
CREATE DOMAIN
regression=# select array[1,2]::myia || 3;
?column?
----------
{1,2,3}
(1 row)

So we will downcast myia to int[], or at least one might assume that's
what's happening. But actually it's worse than that: the result of this
operation is thought to be myia not int[], because myia itself is taken
as matching ANYARRAY, and the operator result is the same ANYARRAY type.
Thus, this case goes off the rails completely:

regression=# create domain myia2 as int[] check(array_length(value,1) = 2);
CREATE DOMAIN
regression=# select array[1,2]::myia2;
array
-------
{1,2}
(1 row)

regression=# select array[1,2,3]::myia2;
ERROR: value for domain myia2 violates check constraint "myia2_check"
regression=# select array[1,2]::myia2 || 3;
?column?
----------
{1,2,3}
(1 row)

The result of the || is considered to be myia2, as can be seen for
example this way:

regression=# create view vvv as select array[1,2]::myia2 || 3 as x;
CREATE VIEW
regression=# \d vvv
View "public.vvv"
Column | Type | Modifiers
--------+-------+-----------
x | myia2 |

So we have a value that's claimed to belong to the domain, but it
doesn't meet the domain's constraints.

What I am intending to do about this in the short run is to leave the
anyarray-ness tests in the polymorphic-compatibility-checking functions
as-is. That will mean (with the change in typelem for domains) that a
domain over array doesn't match ANYARRAY unless you explicitly downcast
it. I argue that this is consistent with the current behavior of not
auto-downcasting domains to match the element type of an array. We
could go back and change it later, but if we do, we should try to make
both cases provide auto-downcast-when-needed behavior. I have not dug
into just what code changes would be needed for that. Auto-downcast
wouldn't be exactly compatible with the current behavior anyway, since
it would result in a different claimed type for the operator result.

Comments?

regards, tom lane

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeff Davis 2010-10-21 16:47:49 Re: Serializable snapshot isolation patch
Previous Message Robert Haas 2010-10-21 16:42:13 Re: Extensions, this time with a patch