Re: Domains versus arrays versus typmods - Mailing list pgsql-hackers

From Robert Haas
Subject Re: Domains versus arrays versus typmods
Date
Msg-id AANLkTimsV7jU5i0YVD=vhJZiy=aQYKwDaiXxiwo5=DOu@mail.gmail.com
Whole thread Raw
In response to Domains versus arrays versus typmods  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Domains versus arrays versus typmods
Re: Domains versus arrays versus typmods
List pgsql-hackers
On Tue, Oct 19, 2010 at 6:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> In bug #5717, Richard Huxton complains that a domain declared like
>        CREATE DOMAIN mynums numeric(4,2)[1];
> doesn't work properly, ie, the typmod isn't enforced in places where
> it reasonably ought to be.  I dug into this a bit, and found that there
> are more worms in this can than I first expected.
>
> In the first place, plpgsql seems a few bricks shy of a load, in that
> its code to handle assignment to an array element doesn't appear to
> be considering arrays with typmod at all: it just passes typmod -1 to
> exec_simple_cast_value() in the PLPGSQL_DTYPE_ARRAYELEM case in
> exec_assign_value().  Nonetheless, if you try a case like
>
>        declare
>          x numeric(4,2)[1];
>        begin
>          x[1] := $1;
>
> you'll find the typmod *is* enforced.  It turns out that the reason that
> it works is that after constructing the modified array value,
> exec_assign_value() calls itself recursively to do the actual assignment
> to the array variable --- and that call sees that the array variable has
> a typmod, so it applies the cast *at the array level*, ie it
> disassembles the array, re-coerces each element, and builds a new array.
> So it's horridly inefficient but it works.
>
> That could and should be improved, but it seems to be just a matter
> of local changes in pl_exec.c, and it's only an efficiency hack anyway.
> The big problem is that none of this happens when the variable is
> declared as a domain, and I believe that that is a significantly more
> wide-ranging issue.
>
> The real issue as I see it is that it's possible to subscript an array
> without realizing that the array's type is really a domain that
> incorporates a typmod specification.  This happens because of a hack
> we did to simplify implementation of domains over arrays: we expose the
> array element type as typelem of the domain as well.  For example, given
> Richard's declaration we have
>
> regression=# select typname,oid,typelem,typbasetype,typtypmod from pg_type where typname = 'mynums';
>  typname |  oid  | typelem | typbasetype | typtypmod
> ---------+-------+---------+-------------+-----------
>  mynums  | 92960 |    1700 |        1231 |    262150
> (1 row)
>
> If we were to wrap another domain around that, we'd have
>
> regression=# create domain mynums2 as mynums;
> CREATE DOMAIN
> regression=# select typname,oid,typelem,typbasetype,typtypmod from pg_type where typname = 'mynums2';
>  typname |  oid  | typelem | typbasetype | typtypmod
> ---------+-------+---------+-------------+-----------
>  mynums2 | 92976 |    1700 |       92960 |        -1
> (1 row)
>
> and at this point it's completely unobvious from inspection of the
> pg_type entry that any typmod needs to be applied when subscripting.
>
> So I'm suspicious that there are a boatload of bugs related to this kind
> of domain declaration, not just the one case in plpgsql.
>
> I think that what we ought to do about it is to stop exposing typelem
> in domains' pg_type rows.  If you want to subscript a domain value, you
> should have to drill down to its base type with getBaseTypeAndTypmod,
> which would also give you the correct typmod to apply.  If we set
> typelem to zero in domain pg_type rows, it shouldn't take too long to
> find any places that are missing this consideration --- the breakage
> will be obvious rather than subtle.

I fear that this is going to degrade the performance of common cases
as a way of debugging rare cases.

> This catalog definitional change obviously shouldn't be back-patched,
> but possibly the ensuing code changes could be, since the typelem change
> is just to expose where things are wrong and wouldn't be a prerequisite
> for corrected code to behave correctly.  Or we could decide that this is
> a corner case we're not going to try to fix in back branches.  It's been
> wrong since day 0, so there's certainly an argument that it's not
> important enough to risk back-patching.
>
> Comments?

It might be reasonable to back-patch whatever we decide on into 9.0,
because it is so new, but I would be reluctant to go back further
unless we have some evidence that it's bothering people.  It seems to
me that this can could have a lot of worms in it, and I fear that
there could be several rounds of fixes, which I would rather not
inflict on users of supposedly-stable branches.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


pgsql-hackers by date:

Previous
From: Hsien-Wen Chu
Date:
Subject: PostgreSQL and HugePage
Next
From: Robert Haas
Date:
Subject: Re: WIP: extensible enums