mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
Make pg_get_expr() more bulletproof.
Since this function is defined to accept pg_node_tree values, it could get applied to any nodetree that can appear in a cataloged pg_node_tree column. Some such cases can't be supported --- for example, its API doesn't allow providing referents for more than one relation --- but we should try to throw a user-facing error rather than an internal error when encountering such a case. In support of this, extend expression_tree_walker/mutator to be sure they'll work on any such node tree (which basically means adding support for relpartbound node types). That allows us to run pull_varnos and check for the case of multiple relations before we start processing the tree. The alternative of changing the low-level error thrown for an out-of-range varno isn't appealing, because that could mask actual bugs in other usages of ruleutils. Per report from Justin Pryzby. This is basically cosmetic, so no back-patch. Discussion: https://postgr.es/m/20211219205422.GT17618@telsasoft.com
This commit is contained in:
@@ -88,6 +88,9 @@ static Relids alias_relid_set(Query *query, Relids relids);
|
||||
* Create a set of all the distinct varnos present in a parsetree.
|
||||
* Only varnos that reference level-zero rtable entries are considered.
|
||||
*
|
||||
* "root" can be passed as NULL if it is not necessary to process
|
||||
* PlaceHolderVars.
|
||||
*
|
||||
* NOTE: this is used on not-yet-planned expressions. It may therefore find
|
||||
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
|
||||
* references to the desired rtable level! But when we find a completed
|
||||
@@ -168,9 +171,13 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
||||
/*
|
||||
* If a PlaceHolderVar is not of the target query level, ignore it,
|
||||
* instead recursing into its expression to see if it contains any
|
||||
* vars that are of the target level.
|
||||
* vars that are of the target level. We'll also do that when the
|
||||
* caller doesn't pass a "root" pointer. (We probably shouldn't see
|
||||
* PlaceHolderVars at all in such cases, but if we do, this is a
|
||||
* reasonable behavior.)
|
||||
*/
|
||||
if (phv->phlevelsup == context->sublevels_up)
|
||||
if (phv->phlevelsup == context->sublevels_up &&
|
||||
context->root != NULL)
|
||||
{
|
||||
/*
|
||||
* Ideally, the PHV's contribution to context->varnos is its
|
||||
|
Reference in New Issue
Block a user