diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execQual.c | 15 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 92 |
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); +} |