aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execQual.c15
-rw-r--r--src/backend/executor/nodeSubplan.c92
2 files changed, 104 insertions, 3 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 7761485d7c1..57b2df9c00e 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.231 2008/05/15 00:17:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.232 2008/08/22 00:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3957,6 +3957,19 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) sstate;
}
break;
+ case T_AlternativeSubPlan:
+ {
+ AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
+ AlternativeSubPlanState *asstate;
+
+ if (!parent)
+ elog(ERROR, "AlternativeSubPlan found with no parent plan");
+
+ asstate = ExecInitAlternativeSubPlan(asplan, parent);
+
+ state = (ExprState *) asstate;
+ }
+ break;
case T_FieldSelect:
{
FieldSelect *fselect = (FieldSelect *) node;
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 0c9ec82b01d..3ebb045f922 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.93 2008/05/12 00:00:49 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.94 2008/08/22 00:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,6 +29,14 @@
#include "utils/memutils.h"
+static Datum ExecSubPlan(SubPlanState *node,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone);
+static Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone);
static Datum ExecHashSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull);
@@ -45,7 +53,7 @@ static bool slotNoNulls(TupleTableSlot *slot);
* ExecSubPlan
* ----------------------------------------------------------------
*/
-Datum
+static Datum
ExecSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull,
@@ -1066,3 +1074,83 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
parent->chgParam = bms_add_member(parent->chgParam, paramid);
}
}
+
+
+/*
+ * ExecInitAlternativeSubPlan
+ *
+ * Initialize for execution of one of a set of alternative subplans.
+ */
+AlternativeSubPlanState *
+ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
+{
+ AlternativeSubPlanState *asstate = makeNode(AlternativeSubPlanState);
+ double num_calls;
+ SubPlan *subplan1;
+ SubPlan *subplan2;
+ Cost cost1;
+ Cost cost2;
+
+ asstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecAlternativeSubPlan;
+ asstate->xprstate.expr = (Expr *) asplan;
+
+ /*
+ * Initialize subplans. (Can we get away with only initializing the
+ * one we're going to use?)
+ */
+ asstate->subplans = (List *) ExecInitExpr((Expr *) asplan->subplans,
+ parent);
+
+ /*
+ * Select the one to be used. For this, we need an estimate of the
+ * number of executions of the subplan. We use the number of output
+ * rows expected from the parent plan node. This is a good estimate
+ * if we are in the parent's targetlist, and an underestimate (but
+ * probably not by more than a factor of 2) if we are in the qual.
+ */
+ num_calls = parent->plan->plan_rows;
+
+ /*
+ * The planner saved enough info so that we don't have to work very hard
+ * to estimate the total cost, given the number-of-calls estimate.
+ */
+ Assert(list_length(asplan->subplans) == 2);
+ subplan1 = (SubPlan *) linitial(asplan->subplans);
+ subplan2 = (SubPlan *) lsecond(asplan->subplans);
+
+ cost1 = subplan1->startup_cost + num_calls * subplan1->per_call_cost;
+ cost2 = subplan2->startup_cost + num_calls * subplan2->per_call_cost;
+
+ if (cost1 < cost2)
+ asstate->active = 0;
+ else
+ asstate->active = 1;
+
+ return asstate;
+}
+
+/*
+ * ExecAlternativeSubPlan
+ *
+ * Execute one of a set of alternative subplans.
+ *
+ * Note: in future we might consider changing to different subplans on the
+ * fly, in case the original rowcount estimate turns out to be way off.
+ */
+static Datum
+ExecAlternativeSubPlan(AlternativeSubPlanState *node,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone)
+{
+ /* Just pass control to the active subplan */
+ SubPlanState *activesp = (SubPlanState *) list_nth(node->subplans,
+ node->active);
+
+ Assert(IsA(activesp, SubPlanState));
+
+ return ExecSubPlan(activesp,
+ econtext,
+ isNull,
+ isDone);
+}