Hi

2015-02-26 18:31 GMT+01:00 Tom Lane <t...@sss.pgh.pa.us>:

> At the behest of Salesforce, I've been looking into improving plpgsql's
> handling of variables of domain types, which is currently pretty awful.
> It's really slow, because any assignment to a domain variable goes through
> the slow double-I/O-conversion path in exec_cast_value, even if no actual
> work is needed.  And I noticed that the domain's constraints get looked up
> only once per function per session; for example this script gets
> unexpected results:
>
> create domain di as int;
>
> create function foo1(int) returns di as $$
> declare d di;
> begin
>   d := $1;
>   return d;
> end
> $$ language plpgsql immutable;
>
> select foo1(0); -- call once to set up cache
>
> alter domain di add constraint pos check (value > 0);
>
> select 0::di;   -- fails, as expected
>
> select foo1(0); -- should fail, does not
>
> \c -
>
> select foo1(0); -- now it fails
>
> The reason for this is that domain_in looks up the domain's constraints
> and caches them under the calling FmgrInfo struct.  That behavior was
> designed to ensure we'd do just one constraint-lookup per query, which
> I think is reasonable.  But plpgsql sets up an FmgrInfo in the variable's
> PLpgSQL_type record, which persists for the whole session unless the
> function's parse tree is flushed for some reason.  So the constraints
> only get looked up once.
>
> The rough sketch I have in mind for fixing this is:
>
> 1. Arrange to cache the constraints for domain types in typcache.c,
> so as to reduce the number of trips to the actual catalogs.  I think
> typcache.c will have to flush these cache items upon seeing any sinval
> change in pg_constraint, but that's still cheaper than searching
> pg_constraint for every query.
>
> 2. In plpgsql, explicitly model a domain type as being its base type
> plus some constraints --- that is, stop depending on domain_in() to
> enforce the constraints, and do it ourselves.  This would mean that
> the FmgrInfo in a PLpgSQL_type struct would reference the base type's
> input function rather than domain_in, so we'd not have to be afraid
> to cache that.  The constraints would be represented as a separate list,
> which we'd arrange to fetch from the typcache once per transaction.
> (I think checking for new constraints once per transaction is sufficient
> for reasonable situations, though I suppose that could be argued about.)
> The advantage of this approach is first that we could avoid an I/O
> conversion when the incoming value to be assigned matches the domain's
> base type, which is the typical case; and second that a domain without
> any CHECK constraints would become essentially free, which is also a
> common case.
>

I like this variant

There can be some good optimization with  scalar types: text, varchars,
numbers and reduce IO cast.



>
> 3. We could still have domains.c responsible for most of the details;
> the domain_check() API may be good enough as-is, though it seems to lack
> any simple way to force re-lookup of the domain constraints once per xact.
>
> Thoughts, better ideas?
>
> Given the lack of field complaints, I don't feel a need to try to
> back-patch a fix for this, but I do want to see it fixed for 9.5.
>

+1

Regards

Pavel


>
>                         regards, tom lane
>
>
> --
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers
>

Reply via email to