Re: proposal: new polymorphic types - commontype and commontypearray - Mailing list pgsql-hackers

From Pavel Stehule
Subject Re: proposal: new polymorphic types - commontype and commontypearray
Date
Msg-id CAFj8pRDs2=ptAOLbQs_sRsL07jqdOK01e4FZC8FH+amcotWNCA@mail.gmail.com
Whole thread Raw
In response to Re: proposal: new polymorphic types - commontype and commontypearray  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: proposal: new polymorphic types - commontype and commontypearray  (Pavel Stehule <pavel.stehule@gmail.com>)
List pgsql-hackers


so 26. 1. 2019 v 1:20 odesílatel Tom Lane <tgl@sss.pgh.pa.us> napsal:
Pavel Stehule <pavel.stehule@gmail.com> writes:
> Four years ago I proposed implicit casting to common type of arguments with
> anyelement type.
> https://www.postgresql.org/message-id/CAFj8pRCZVo_xoW0cfxt%3DmmgjXKBgr3Gm1VMGL_zx9wDRHmm6Cw%40mail.gmail.com
> My proposal was rejected, because it introduce compatibility issues.

Yup.

> Now I have a solution that doesn't break anything. With two new polymorphic
> types: commontype and commontypearray we can write functions like coalesce,
> greatest, ..

I think this is a good idea at its core, but I don't like the specifics
too much.

I agree with the basic idea of introducing a second, independent set of
polymorphic-type variables.  Way back when we first discussed polymorphic
types, we thought maybe we should invent anyelement2 and anyarray2, and
perhaps even more pairs, to allow polymorphic functions to deal with two
or more base types.  We didn't do that for lack of convincing examples of
the need for it, but I expected some would emerge; I'm rather astonished
that we've gotten by for so many years without adding a second set.
So where I think we should go with this is to solve that need while
we're at it.

I still expect we can have a more polymorphic types like any***(N)

There are important questions

1. Has a sense to have more distinct polymorphic types with same be behave? - I see a benefit of this possibility - we can introduce anyelement2 .. AN2 and we can have a function

  fx(AN,AN, AN2,AN2) .. that means P2 and P4 should to have a same types like P1 and P3.

2. What are a strategy of choosing real type for polymorphic types? - now only equivalence is supported, but I can see more possibilities

  * common type - I did it
  * first win - often used in Oracle

The common type strategy is more important, because it is typical for some "pseudo" functions like coalesce, least, greatest, .. in Postgres - and extension's developers can design functions more compatible with core functionality.

first win can be interesting for me (like Orafce creator and maintainer). It can increase level of similarity implemented functions there, and reduce work when queries are ported to Postgres. But this is important for smaller group of PostgreSQL users.
 

However, this proposal doesn't do so, because it omits "commonrange".
I'm prepared to believe that we don't need "commonenum"; that would
presumably have the semantics of "resolve the common type and then
it must be an enum".  And that seems pretty useless, because there
are no type resolution rules that would let us choose one enum out of
a set.  (I suppose somebody might create implicit casts between some
enum types, but it doesn't seem very likely.)  I also suspect that
we could get away without "commonnonarray".  Anynonarray is really
just a hack that we invented to avoid ambiguity around the ||
operator, and an equivalent need would likely not come up for this
second set of types.  (I could be wrong though; I'm not sure right
now whether array_agg's use of anynonarray rather than anyelement
is essential or just randomness.)  But neither of those arguments
apply to commonrange; in fact it's highly likely that somebody would
want to have "myfunc(commontype, commontype) returns commonrange"
as a customized range constructor that can deal with slightly
different input types.

I implemented just minimal set of new polymorphic types, just for demonstration of my idea. Better coverage of other variants (where it has a sense) is not a problem. Now, mostly I am searching a design where can be a some agreement.
 

My second problem with this proposal is that it simply ignores
the naming precedent of the existing polymorphic types.  We have
a convention that polymorphic types are named "any-something",
and I do not think we should just toss that overboard.  Moreover,
if we do end up needing "commonnonarray" or "commonenum", those
names are ugly, typo-prone, and unreasonably long.

We could do worse than to call these types anyelement2, anyarray2,
anyrange2 and just document that their resolution rule depends
on finding a common type rather than identical base types.
I suppose that's not too pretty --- it reminds one of Oracle finally
getting varchar semantics right with varchar2 :-(.  Another idea
is anyelementc, anyarrayc, anyrangec ("c" for "common") but that's
not pretty either.  Anyway I think the names need to be any-something.

I am open to any ideas. I don't like anyelement2, anyarray2 because

a) it is not verbose - and really different behave should not be signed by number
b) I can imagine very well more anyelementX types.

I don't think so length is too important factor (but I fully agree - shorter is better here). The polymorphic types are not too common.

I though about your proposed anyelementc, but the "c" is not much visible. Can we use snake notation?

commontype, commottype_array, commontype_nonarray ..
common_type, common_type_array, ...

I am not fully happy with "commontype", but I didn't find better




I haven't particularly studied the patch code, but I will note that
this sort of change seems pretty dumb:

@@ -953,7 +953,7 @@ make_scalar_array_op(ParseState *pstate, List *opname,
         * enforce_generic_type_consistency may or may not have replaced a
         * polymorphic type with a real one.
         */
-       if (IsPolymorphicType(declared_arg_types[1]))
+       if (IsPolymorphicTypeAny(declared_arg_types[1]))
        {
                /* assume the actual array type is OK */
                res_atypeId = atypeId;

Why would we want to reject the new poly types here?  Or just about
anyplace else that tests IsPolymorphicType?  The argument-type resolution
functions themselves need to distinguish the two groups of types,
at least for some purposes, but it's very hard to believe anyplace
else should do so.

Just I use original behave everywhere where I had not a stronger idea to use new polymorphic types there.

Regards

Pavel

                        regards, tom lane

pgsql-hackers by date:

Previous
From: Michael Meskes
Date:
Subject: Re: Thread-unsafe coding in ecpg
Next
From: Michael Paquier
Date:
Subject: Re: using expression syntax for partition bounds