diff options
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
| -rw-r--r-- | src/backend/optimizer/util/clauses.c | 80 |
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; } |
