• Tom Lane's avatar
    Make plpgsql use its DTYPE_REC code paths for composite-type variables. · 4b93f579
    Tom Lane authored
    Formerly, DTYPE_REC was used only for variables declared as "record";
    variables of named composite types used DTYPE_ROW, which is faster for
    some purposes but much less flexible.  In particular, the ROW code paths
    are entirely incapable of dealing with DDL-caused changes to the number
    or data types of the columns of a row variable, once a particular plpgsql
    function has been parsed for the first time in a session.  And, since the
    stored representation of a ROW isn't a tuple, there wasn't any easy way
    to deal with variables of domain-over-composite types, since the domain
    constraint checking code would expect the value to be checked to be a
    tuple.  A lesser, but still real, annoyance is that ROW format cannot
    represent a true NULL composite value, only a row of per-field NULL
    values, which is not exactly the same thing.
    
    Hence, switch to using DTYPE_REC for all composite-typed variables,
    whether "record", named composite type, or domain over named composite
    type.  DTYPE_ROW remains but is used only for its native purpose, to
    represent a fixed-at-compile-time list of variables, for instance the
    targets of an INTO clause.
    
    To accomplish this without taking significant performance losses, introduce
    infrastructure that allows storing composite-type variables as "expanded
    objects", similar to the "expanded array" infrastructure introduced in
    commit 1dc5ebc9.  A composite variable's value is thereby kept (most of
    the time) in the form of separate Datums, so that field accesses and
    updates are not much more expensive than they were in the ROW format.
    This holds the line, more or less, on performance of variables of named
    composite types in field-access-intensive microbenchmarks, and makes
    variables declared "record" perform much better than before in similar
    tests.  In addition, the logic involved with enforcing composite-domain
    constraints against updates of individual fields is in the expanded
    record infrastructure not plpgsql proper, so that it might be reusable
    for other purposes.
    
    In further support of this, introduce a typcache feature for assigning a
    unique-within-process identifier to each distinct tuple descriptor of
    interest; in particular, DDL alterations on composite types result in a new
    identifier for that type.  This allows very cheap detection of the need to
    refresh tupdesc-dependent data.  This improves on the "tupDescSeqNo" idea
    I had in commit 687f096e: that assigned identifying sequence numbers to
    successive versions of individual composite types, but the numbers were not
    unique across different types, nor was there support for assigning numbers
    to registered record types.
    
    In passing, allow plpgsql functions to accept as well as return type
    "record".  There was no good reason for the old restriction, and it
    was out of step with most of the other PLs.
    
    Tom Lane, reviewed by Pavel Stehule
    
    Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
    4b93f579
plpgsql.sql 116 KB