summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 71e727a7b4..48b125a774 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.219 2006/08/12 20:05:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.220 2006/09/06 20:40:47 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -1462,7 +1462,9 @@ eval_const_expressions(Node *node)
*
* Currently the extra steps that are taken in this mode are:
* 1. Substitute values for Params, where a bound Param value has been made
- * available by the caller of planner().
+ * available by the caller of planner(), even if the Param isn't marked
+ * constant. This effectively means that we plan using the first supplied
+ * value of the Param.
* 2. Fold stable, as well as immutable, functions to constants.
*--------------------
*/
@@ -1487,33 +1489,38 @@ eval_const_expressions_mutator(Node *node,
{
Param *param = (Param *) node;
- /* OK to try to substitute value? */
- if (context->estimate && param->paramkind == PARAM_EXTERN &&
- PlannerBoundParamList != NULL)
+ /* Look to see if we've been given a value for this Param */
+ if (param->paramkind == PARAM_EXTERN &&
+ PlannerBoundParamList != NULL &&
+ param->paramid > 0 &&
+ param->paramid <= PlannerBoundParamList->numParams)
{
- /* Look to see if we've been given a value for this Param */
- if (param->paramid > 0 &&
- param->paramid <= PlannerBoundParamList->numParams)
- {
- ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
+ ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
- if (OidIsValid(prm->ptype))
+ if (OidIsValid(prm->ptype))
+ {
+ /* OK to substitute parameter value? */
+ if (context->estimate || (prm->pflags & PARAM_FLAG_CONST))
{
/*
- * Found it, so return a Const representing the param
- * value. Note that we don't copy pass-by-ref datatypes,
- * so the Const will only be valid as long as the bound
- * parameter list exists. This is okay for intended uses
- * of estimate_expression_value().
+ * Return a Const representing the param value. Must copy
+ * pass-by-ref datatypes, since the Param might be in a
+ * memory context shorter-lived than our output plan
+ * should be.
*/
int16 typLen;
bool typByVal;
+ Datum pval;
Assert(prm->ptype == param->paramtype);
get_typlenbyval(param->paramtype, &typLen, &typByVal);
+ if (prm->isnull || typByVal)
+ pval = prm->value;
+ else
+ pval = datumCopy(prm->value, typByVal, typLen);
return (Node *) makeConst(param->paramtype,
(int) typLen,
- prm->value,
+ pval,
prm->isnull,
typByVal);
}
@@ -3016,10 +3023,9 @@ evaluate_expr(Expr *expr, Oid result_type)
* stage. In particular, it handles List nodes since a cnf-ified qual clause
* will have List structure at the top level, and it handles TargetEntry nodes
* so that a scan of a target list can be handled without additional code.
- * (But only the "expr" part of a TargetEntry is examined, unless the walker
- * chooses to process TargetEntry nodes specially.) Also, RangeTblRef,
- * FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
- * jointrees and setOperation trees can be processed without additional code.
+ * Also, RangeTblRef, FromExpr, JoinExpr, and SetOperationStmt nodes are
+ * handled, so that query jointrees and setOperation trees can be processed
+ * without additional code.
*
* expression_tree_walker will handle SubLink nodes by recursing normally
* into the "testexpr" subtree (which is an expression belonging to the outer
@@ -3364,6 +3370,38 @@ query_tree_walker(Query *query,
return true;
if (range_table_walker(query->rtable, walker, context, flags))
return true;
+ if (query->utilityStmt)
+ {
+ /*
+ * Certain utility commands contain general-purpose Querys embedded
+ * in them --- if this is one, invoke the walker on the sub-Query.
+ */
+ if (IsA(query->utilityStmt, CopyStmt))
+ {
+ if (walker(((CopyStmt *) query->utilityStmt)->query, context))
+ return true;
+ }
+ if (IsA(query->utilityStmt, DeclareCursorStmt))
+ {
+ if (walker(((DeclareCursorStmt *) query->utilityStmt)->query, context))
+ return true;
+ }
+ if (IsA(query->utilityStmt, ExplainStmt))
+ {
+ if (walker(((ExplainStmt *) query->utilityStmt)->query, context))
+ return true;
+ }
+ if (IsA(query->utilityStmt, PrepareStmt))
+ {
+ if (walker(((PrepareStmt *) query->utilityStmt)->query, context))
+ return true;
+ }
+ if (IsA(query->utilityStmt, ViewStmt))
+ {
+ if (walker(((ViewStmt *) query->utilityStmt)->query, context))
+ return true;
+ }
+ }
return false;
}