• Tom Lane's avatar
    Change representation of statement lists, and add statement location info. · ab1f0c82
    Tom Lane authored
    This patch makes several changes that improve the consistency of
    representation of lists of statements.  It's always been the case
    that the output of parse analysis is a list of Query nodes, whatever
    the types of the individual statements in the list.  This patch brings
    similar consistency to the outputs of raw parsing and planning steps:
    
    * The output of raw parsing is now always a list of RawStmt nodes;
    the statement-type-dependent nodes are one level down from that.
    
    * The output of pg_plan_queries() is now always a list of PlannedStmt
    nodes, even for utility statements.  In the case of a utility statement,
    "planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
    the utility node.  This list representation is now used in Portal and
    CachedPlan plan lists, replacing the former convention of intermixing
    PlannedStmts with bare utility-statement nodes.
    
    Now, every list of statements has a consistent head-node type depending
    on how far along it is in processing.  This allows changing many places
    that formerly used generic "Node *" pointers to use a more specific
    pointer type, thus reducing the number of IsA() tests and casts needed,
    as well as improving code clarity.
    
    Also, the post-parse-analysis representation of DECLARE CURSOR is changed
    so that it looks more like EXPLAIN, PREPARE, etc.  That is, the contained
    SELECT remains a child of the DeclareCursorStmt rather than getting flipped
    around to be the other way.  It's now true for both Query and PlannedStmt
    that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
    That allows simplifying a lot of places that were testing both fields.
    (I think some of those were just defensive programming, but in many places,
    it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
    
    Because PlannedStmt carries a canSetTag field, we're also able to get rid
    of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
    statement; specifically, the assumption that a utility is canSetTag if and
    only if it's the only one in its list.  While I see no near-term need for
    relaxing that restriction, it's nice to get rid of the ad-hocery.
    
    The API of ProcessUtility() is changed so that what it's passed is the
    wrapper PlannedStmt not just the bare utility statement.  This will affect
    all users of ProcessUtility_hook, but the changes are pretty trivial; see
    the affected contrib modules for examples of the minimum change needed.
    (Most compilers should give pointer-type-mismatch warnings for uncorrected
    code.)
    
    There's also a change in the API of ExplainOneQuery_hook, to pass through
    cursorOptions instead of expecting hook functions to know what to pick.
    This is needed because of the DECLARE CURSOR changes, but really should
    have been done in 9.6; it's unlikely that any extant hook functions
    know about using CURSOR_OPT_PARALLEL_OK.
    
    Finally, teach gram.y to save statement boundary locations in RawStmt
    nodes, and pass those through to Query and PlannedStmt nodes.  This allows
    more intelligent handling of cases where a source query string contains
    multiple statements.  This patch doesn't actually do anything with the
    information, but a follow-on patch will.  (Passing this information through
    cleanly is the true motivation for these changes; while I think this is all
    good cleanup, it's unlikely we'd have bothered without this end goal.)
    
    catversion bump because addition of location fields to struct Query
    affects stored rules.
    
    This patch is by me, but it owes a good deal to Fabien Coelho who did
    a lot of preliminary work on the problem, and also reviewed the patch.
    
    Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
    ab1f0c82
pquery.c 45 KB