Re: Domains versus polymorphic functions, redux - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Domains versus polymorphic functions, redux
Date
Msg-id 11259.1306257119@sss.pgh.pa.us
Whole thread Raw
In response to Re: Domains versus polymorphic functions, redux  ("David E. Wheeler" <david@kineticode.com>)
Responses Re: Domains versus polymorphic functions, redux  ("David E. Wheeler" <david@kineticode.com>)
List pgsql-hackers
"David E. Wheeler" <david@kineticode.com> writes:
> On May 24, 2011, at 9:12 AM, Tom Lane wrote:
>> An alternative rule we could use in place of #2 is just "smash domains
>> to base types always, when they're matched to ANYELEMENT".  That would
>> be simpler and more in keeping with #1, but it might change the behavior
>> in cases where the historical behavior is reasonable (unlike the cases
>> discussed in my message referenced above...)  I find this simpler rule
>> tempting from an implementor's standpoint, but am unsure if there'll be
>> complaints.

> I'm not sure where the historical behavior manifests, but this
> certainly seems like it might be the most consistent implementation,
> as well. Which option is least likely to violate the principal of
> surprise?

Well, the basic issue here is what happens when a function like
create function noop(anyelement) returns anyelement ...

is applied to a domain argument.  Currently, the result is thought to be
of the domain type, whereas if we smash to base unconditionally, the
result will be thought to be of the domain's base type.  You can make an
argument for either behavior, but I think the argument for the current
behavior hinges on the assumption that such a function isn't "doing
anything" to the argument value, only passing it through as-is.

I should probably also point out the previous discussion of this area
from a couple weeks ago, notably here:
http://archives.postgresql.org/pgsql-hackers/2011-05/msg00640.php
The example I gave there seems relevant:
create function negate(anyelement) returns anyelement as$$ select - $1 $$ language sql;
create domain pos as int check (value > 0);
select negate(42::pos);

This example function isn't quite silly --- it will work on any datatype
having a unary '-' operator, and you could imagine someone wanting to do
something roughly like this in more realistic cases.  But if you want to
assume that the function returns pos when handed pos, you'd better be
prepared to insert a CastToDomain node to recheck the domain constraint.
Right now the SQL-function code doesn't support such cases:

regression=# select negate(42::pos);
ERROR:  return type mismatch in function declared to return pos
DETAIL:  Actual return type is integer.
CONTEXT:  SQL function "negate" during inlining

If we smashed to base type then this issue would go away.

On the other hand it feels like we'd be taking yet another step away
from allowing domains to be usefully used in function declarations.
I can't put my finger on any concrete consequence of that sort, since
what we're talking about here is ANYELEMENT/ANYARRAY functions not
functions declared to take domains --- but it sure seems like this
would put domains even further away from the status of first-class
citizenship in the type system.
        regards, tom lane


pgsql-hackers by date:

Previous
From: Noah Misch
Date:
Subject: Re: Domains versus polymorphic functions, redux
Next
From: Tom Lane
Date:
Subject: Re: Domains versus polymorphic functions, redux