From: Tom Lane Date: Fri, 25 Jan 2019 22:09:45 +0000 (-0500) Subject: Split QTW_EXAMINE_RTES flag into QTW_EXAMINE_RTES_BEFORE/_AFTER. X-Git-Tag: REL_12_BETA1~867 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18c0da88a5d9da566c3bfac444366b73bd0b57da;p=postgresql Split QTW_EXAMINE_RTES flag into QTW_EXAMINE_RTES_BEFORE/_AFTER. This change allows callers of query_tree_walker() to choose whether to visit an RTE before or after visiting the contents of the RTE (i.e., prefix or postfix tree order). All existing users of QTW_EXAMINE_RTES want the QTW_EXAMINE_RTES_BEFORE behavior, but an upcoming patch will want QTW_EXAMINE_RTES_AFTER, and it seems like a potentially useful change on its own. Andreas Karlsson (extracted from CTE inlining patch) Discussion: https://postgr.es/m/8810.1542402910@sss.pgh.pa.us --- diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 19b65f681d..a806d51edc 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -2255,7 +2255,7 @@ expression_tree_walker(Node *node, * Some callers want to suppress visitation of certain items in the sub-Query, * typically because they need to process them specially, or don't actually * want to recurse into subqueries. This is supported by the flags argument, - * which is the bitwise OR of flag values to suppress visitation of + * which is the bitwise OR of flag values to add or suppress visitation of * indicated items. (More flag bits may be added as needed.) */ bool @@ -2314,8 +2314,12 @@ range_table_walker(List *rtable, { RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); - /* For historical reasons, visiting RTEs is not the default */ - if (flags & QTW_EXAMINE_RTES) + /* + * Walkers might need to examine the RTE node itself either before or + * after visiting its contents (or, conceivably, both). Note that if + * you specify neither flag, the walker won't visit the RTE at all. + */ + if (flags & QTW_EXAMINE_RTES_BEFORE) if (walker(rte, context)) return true; @@ -2355,6 +2359,10 @@ range_table_walker(List *rtable, if (walker(rte->securityQuals, context)) return true; + + if (flags & QTW_EXAMINE_RTES_AFTER) + if (walker(rte, context)) + return true; } return false; } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 5d363edab8..6bd3b2d1ac 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -340,7 +340,7 @@ flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte) (void) query_tree_walker(rte->subquery, flatten_rtes_walker, (void *) glob, - QTW_EXAMINE_RTES); + QTW_EXAMINE_RTES_BEFORE); } static bool @@ -363,7 +363,7 @@ flatten_rtes_walker(Node *node, PlannerGlobal *glob) return query_tree_walker((Query *) node, flatten_rtes_walker, (void *) glob, - QTW_EXAMINE_RTES); + QTW_EXAMINE_RTES_BEFORE); } return expression_tree_walker(node, flatten_rtes_walker, (void *) glob); diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index acbe669294..fd7a751c9a 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -761,7 +761,7 @@ IncrementVarSublevelsUp_walker(Node *node, result = query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, (void *) context, - QTW_EXAMINE_RTES); + QTW_EXAMINE_RTES_BEFORE); context->min_sublevels_up--; return result; } @@ -785,7 +785,7 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, query_or_expression_tree_walker(node, IncrementVarSublevelsUp_walker, (void *) &context, - QTW_EXAMINE_RTES); + QTW_EXAMINE_RTES_BEFORE); } /* @@ -804,7 +804,7 @@ IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up, range_table_walker(rtable, IncrementVarSublevelsUp_walker, (void *) &context, - QTW_EXAMINE_RTES); + QTW_EXAMINE_RTES_BEFORE); } diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h index 7739600db2..a9f76bbb33 100644 --- a/src/include/nodes/nodeFuncs.h +++ b/src/include/nodes/nodeFuncs.h @@ -22,8 +22,11 @@ #define QTW_IGNORE_RC_SUBQUERIES 0x03 /* both of above */ #define QTW_IGNORE_JOINALIASES 0x04 /* JOIN alias var lists */ #define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */ -#define QTW_EXAMINE_RTES 0x10 /* examine RTEs */ -#define QTW_DONT_COPY_QUERY 0x20 /* do not copy top Query */ +#define QTW_EXAMINE_RTES_BEFORE 0x10 /* examine RTE nodes before their + * contents */ +#define QTW_EXAMINE_RTES_AFTER 0x20 /* examine RTE nodes after their + * contents */ +#define QTW_DONT_COPY_QUERY 0x40 /* do not copy top Query */ /* callback function for check_functions_in_node */ typedef bool (*check_function_callback) (Oid func_id, void *context);