diff options
Diffstat (limited to 'src/backend/optimizer/util')
| -rw-r--r-- | src/backend/optimizer/util/clauses.c | 66 | 
1 files changed, 66 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 10843fb3800..943162fb89f 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -641,6 +641,11 @@ contain_subplans_walker(Node *node, void *context)   * mistakenly think that something like "WHERE random() < 0.5" can be treated   * as a constant qualification.   * + * This will give the right answer only for clauses that have been put + * through expression preprocessing.  Callers outside the planner typically + * should use contain_mutable_functions_after_planning() instead, for the + * reasons given there. + *   * We will recursively look into Query nodes (i.e., SubLink sub-selects)   * but not into SubPlans.  See comments for contain_volatile_functions().   */ @@ -700,6 +705,34 @@ contain_mutable_functions_walker(Node *node, void *context)  								  context);  } +/* + * contain_mutable_functions_after_planning + *	  Test whether given expression contains mutable functions. + * + * This is a wrapper for contain_mutable_functions() that is safe to use from + * outside the planner.  The difference is that it first runs the expression + * through expression_planner().  There are two key reasons why we need that: + * + * First, function default arguments will get inserted, which may affect + * volatility (consider "default now()"). + * + * Second, inline-able functions will get inlined, which may allow us to + * conclude that the function is really less volatile than it's marked. + * As an example, polymorphic functions must be marked with the most volatile + * behavior that they have for any input type, but once we inline the + * function we may be able to conclude that it's not so volatile for the + * particular input type we're dealing with. + */ +bool +contain_mutable_functions_after_planning(Expr *expr) +{ +	/* We assume here that expression_planner() won't scribble on its input */ +	expr = expression_planner(expr); + +	/* Now we can search for non-immutable functions */ +	return contain_mutable_functions((Node *) expr); +} +  /*****************************************************************************   *		Check clauses for volatile functions @@ -713,6 +746,11 @@ contain_mutable_functions_walker(Node *node, void *context)   * volatile function) is found. This test prevents, for example,   * invalid conversions of volatile expressions into indexscan quals.   * + * This will give the right answer only for clauses that have been put + * through expression preprocessing.  Callers outside the planner typically + * should use contain_volatile_functions_after_planning() instead, for the + * reasons given there. + *   * We will recursively look into Query nodes (i.e., SubLink sub-selects)   * but not into SubPlans.  This is a bit odd, but intentional.  If we are   * looking at a SubLink, we are probably deciding whether a query tree @@ -770,6 +808,34 @@ contain_volatile_functions_walker(Node *node, void *context)  }  /* + * contain_volatile_functions_after_planning + *	  Test whether given expression contains volatile functions. + * + * This is a wrapper for contain_volatile_functions() that is safe to use from + * outside the planner.  The difference is that it first runs the expression + * through expression_planner().  There are two key reasons why we need that: + * + * First, function default arguments will get inserted, which may affect + * volatility (consider "default random()"). + * + * Second, inline-able functions will get inlined, which may allow us to + * conclude that the function is really less volatile than it's marked. + * As an example, polymorphic functions must be marked with the most volatile + * behavior that they have for any input type, but once we inline the + * function we may be able to conclude that it's not so volatile for the + * particular input type we're dealing with. + */ +bool +contain_volatile_functions_after_planning(Expr *expr) +{ +	/* We assume here that expression_planner() won't scribble on its input */ +	expr = expression_planner(expr); + +	/* Now we can search for volatile functions */ +	return contain_volatile_functions((Node *) expr); +} + +/*   * Special purpose version of contain_volatile_functions() for use in COPY:   * ignore nextval(), but treat all other functions normally.   */  | 
