aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-09-06 20:40:48 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-09-06 20:40:48 +0000
commit5983a1aaa9137367c834e0ff84cd8d4d48b326b2 (patch)
tree3425eaf290ad8ee4d565551d45e60df514f67e55 /src/backend/optimizer/util/clauses.c
parent389870b256bc65f088a7f9a4ea4a88c01242c551 (diff)
downloadpostgresql-5983a1aaa9137367c834e0ff84cd8d4d48b326b2.tar.gz
postgresql-5983a1aaa9137367c834e0ff84cd8d4d48b326b2.zip
Change processing of extended-Query mode so that an unnamed statement
that has parameters is always planned afresh for each Bind command, treating the parameter values as constants in the planner. This removes the performance penalty formerly often paid for using out-of-line parameters --- with this definition, the planner can do constant folding, LIKE optimization, etc. After a suggestion by Andrew@supernews.
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 71e727a7b4c..48b125a774c 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;
}