aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-06-11 01:09:22 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-06-11 01:09:22 +0000
commit7643bed58ecc87eedf7da1ed1938e85ed770d2f8 (patch)
tree0d97a4c6cb2d02ba9f9d9b5b5d4e1a6d9cbd538e /src/backend/optimizer/plan/planner.c
parent5fe8c7d6e50e3a310498f333e4f5130659c931fb (diff)
downloadpostgresql-7643bed58ecc87eedf7da1ed1938e85ed770d2f8.tar.gz
postgresql-7643bed58ecc87eedf7da1ed1938e85ed770d2f8.zip
When using extended-query protocol, postpone planning of unnamed statements
until Bind is received, so that actual parameter values are visible to the planner. Make use of the parameter values for estimation purposes (but don't fold them into the actual plan). This buys back most of the potential loss of plan quality that ensues from using out-of-line parameters instead of putting literal values right into the query text. This patch creates a notion of constant-folding expressions 'for estimation purposes only', in which case we can be more aggressive than the normal eval_const_expressions() logic can be. Right now the only difference in behavior is inserting bound values for Params, but it will be interesting to look at other possibilities. One that we've seen come up repeatedly is reducing now() and related functions to current values, so that queries like ... WHERE timestampcol > now() - '1 day' have some chance of being planned effectively. Oliver Jowett, with some kibitzing from Tom Lane.
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 064981b5af0..2fc82556c32 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.171 2004/05/30 23:40:29 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.172 2004/06/11 01:08:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -43,6 +43,9 @@
#include "utils/syscache.h"
+ParamListInfo PlannerBoundParamList = NULL; /* current boundParams */
+
+
/* Expression kind codes for preprocess_expression */
#define EXPRKIND_QUAL 0
#define EXPRKIND_TARGET 1
@@ -71,20 +74,24 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
*
*****************************************************************************/
Plan *
-planner(Query *parse, bool isCursor, int cursorOptions)
+planner(Query *parse, bool isCursor, int cursorOptions,
+ ParamListInfo boundParams)
{
double tuple_fraction;
Plan *result_plan;
Index save_PlannerQueryLevel;
List *save_PlannerParamList;
+ ParamListInfo save_PlannerBoundParamList;
/*
* The planner can be called recursively (an example is when
* eval_const_expressions tries to pre-evaluate an SQL function). So,
* these global state variables must be saved and restored.
*
- * These vars cannot be moved into the Query structure since their whole
- * purpose is communication across multiple sub-Queries.
+ * Query level and the param list cannot be moved into the Query structure
+ * since their whole purpose is communication across multiple sub-Queries.
+ * Also, boundParams is explicitly info from outside the Query, and so
+ * is likewise better handled as a global variable.
*
* Note we do NOT save and restore PlannerPlanId: it exists to assign
* unique IDs to SubPlan nodes, and we want those IDs to be unique for
@@ -93,10 +100,12 @@ planner(Query *parse, bool isCursor, int cursorOptions)
*/
save_PlannerQueryLevel = PlannerQueryLevel;
save_PlannerParamList = PlannerParamList;
+ save_PlannerBoundParamList = PlannerBoundParamList;
/* Initialize state for handling outer-level references and params */
PlannerQueryLevel = 0; /* will be 1 in top-level subquery_planner */
PlannerParamList = NIL;
+ PlannerBoundParamList = boundParams;
/* Determine what fraction of the plan is likely to be scanned */
if (isCursor)
@@ -139,6 +148,7 @@ planner(Query *parse, bool isCursor, int cursorOptions)
/* restore state for outer planner, if any */
PlannerQueryLevel = save_PlannerQueryLevel;
PlannerParamList = save_PlannerParamList;
+ PlannerBoundParamList = save_PlannerBoundParamList;
return result_plan;
}