pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@lists.postgresql.org
Subject: resolve_generic_type() is over-complex and under-correct
Date: Sat, 14 Mar 2020 12:08:50 -0400
Message-ID: <6093.1584202130@sss.pgh.pa.us> (raw)

parse_coerce.c's resolve_generic_type() is written on the assumption
that it might be asked to infer any polymorphic type's concrete type
given any other polymorphic type's concrete type.  This is overkill,
because the only call sites look like

        anyelement_type = resolve_generic_type(ANYELEMENTOID,
                                               anyarray_type,
                                               ANYARRAYOID);

        subtype = resolve_generic_type(ANYELEMENTOID,
                                       anyrange_type,
                                       ANYRANGEOID);

        anyarray_type = resolve_generic_type(ANYARRAYOID,
                                             anyelement_type,
                                             ANYELEMENTOID);

(There are two occurrences of each of these in funcapi.c,
and nothing anywhere else.)

But that's a good thing, because resolve_generic_type() gets some
of the un-exercised cases wrong.  Notably, it appears to believe
that anyrange is the same type variable as anyelement: if asked
to resolve anyarray from anyrange, it will produce the array over
the concrete range type, where it should produce the array over
the range's subtype.

Rather than fix this up, I'm inclined to just nuke resolve_generic_type()
altogether, and replace the call sites with direct uses of the underlying
lookups such as get_array_type().  I think this is simpler to understand
as well as being significantly less code.

I also noticed that there's an asymmetry in funcapi.c's usage pattern:
it can resolve anyelement from either anyarray or anyrange, but it
can only resolve anyarray from anyelement not anyrange.  This results
in warts like so:

regression=# create function foo(x anyrange) returns anyarray language sql
as 'select array[lower(x),upper(x)]';
CREATE FUNCTION
regression=# select foo(int4range(6,9));
  foo  
-------
 {6,9}
(1 row)

-- so far so good, but let's try it with OUT parameters:

regression=# create function foo2(x anyrange, out lu anyarray, out ul anyarray)
language sql
as 'select array[lower(x),upper(x)], array[upper(x),lower(x)]';
CREATE FUNCTION
regression=# select * from foo2(int4range(6,9));
ERROR:  cache lookup failed for type 0

So that's a bug that needs fixing in any case.

			regards, tom lane





Message-ID: <6093.1584202130@sss.pgh.pa.us>
Permalink:  ../6093.1584202130@sss.pgh.pa.us/
Also on:    postgresql.org/message-id/6093.1584202130@sss.pgh.pa.us

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: tgl@sss.pgh.pa.us, pgsql-hackers@lists.postgresql.org
  Subject: Re: resolve_generic_type() is over-complex and under-correct
  In-Reply-To: <6093.1584202130@sss.pgh.pa.us>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox