• Tom Lane's avatar
    Drop no-op CoerceToDomain nodes from expressions at planning time. · 04fe805a
    Tom Lane authored
    If a domain has no constraints, then CoerceToDomain doesn't really do
    anything and can be simplified to a RelabelType.  This not only
    eliminates cycles at execution, but allows the planner to optimize better
    (for instance, match the coerced expression to an index on the underlying
    column).  However, we do have to support invalidating the plan later if
    a constraint gets added to the domain.  That's comparable to the case of
    a change to a SQL function that had been inlined into a plan, so all the
    necessary logic already exists for plans depending on functions.  We
    need only duplicate or share that logic for domains.
    
    ALTER DOMAIN ADD/DROP CONSTRAINT need to be taught to send out sinval
    messages for the domain's pg_type entry, since those operations don't
    update that row.  (ALTER DOMAIN SET/DROP NOT NULL do update that row,
    so no code change is needed for them.)
    
    Testing this revealed what's really a pre-existing bug in plpgsql:
    it caches the SQL-expression-tree expansion of type coercions and
    had no provision for invalidating entries in that cache.  Up to now
    that was only a problem if such an expression had inlined a SQL
    function that got changed, which is unlikely though not impossible.
    But failing to track changes of domain constraints breaks an existing
    regression test case and would likely cause practical problems too.
    
    We could fix that locally in plpgsql, but what seems like a better
    idea is to build some generic infrastructure in plancache.c to store
    standalone expressions and track invalidation events for them.
    (It's tempting to wonder whether plpgsql's "simple expression" stuff
    could use this code with lower overhead than its current use of the
    heavyweight plancache APIs.  But I've left that idea for later.)
    
    Other stuff fixed in passing:
    
    * Allow estimate_expression_value() to drop CoerceToDomain
    unconditionally, effectively assuming that the coercion will succeed.
    This will improve planner selectivity estimates for cases involving
    estimatable expressions that are coerced to domains.  We could have
    done this independently of everything else here, but there wasn't
    previously any need for eval_const_expressions_mutator to know about
    CoerceToDomain at all.
    
    * Use a dlist for plancache.c's list of cached plans, rather than a
    manually threaded singly-linked list.  That eliminates a potential
    performance problem in DropCachedPlan.
    
    * Fix a couple of inconsistencies in typecmds.c about whether
    operations on domains drop RowExclusiveLock on pg_type.  Our common
    practice is that DDL operations do drop catalog locks, so standardize
    on that choice.
    
    Discussion: https://postgr.es/m/19958.1544122124@sss.pgh.pa.us
    04fe805a
planmain.h 4.31 KB