summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/subselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r--src/backend/optimizer/plan/subselect.c93
1 files changed, 55 insertions, 38 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index d19e9d298c0..27db5c0433f 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.121 2007/02/22 22:00:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.122 2007/02/27 01:11:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -241,9 +241,10 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
{
Query *subquery = (Query *) (slink->subselect);
double tuple_fraction;
- SubPlan *node;
+ SubPlan *splan;
Plan *plan;
PlannerInfo *subroot;
+ bool isInitPlan;
Bitmapset *tmpset;
int paramid;
Node *result;
@@ -295,17 +296,17 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
/*
* Initialize the SubPlan node. Note plan_id isn't set yet.
*/
- node = makeNode(SubPlan);
- node->subLinkType = slink->subLinkType;
- node->testexpr = NULL;
- node->paramIds = NIL;
- node->firstColType = get_first_col_type(plan);
- node->useHashTable = false;
+ splan = makeNode(SubPlan);
+ splan->subLinkType = slink->subLinkType;
+ splan->testexpr = NULL;
+ splan->paramIds = NIL;
+ splan->firstColType = get_first_col_type(plan);
+ splan->useHashTable = false;
/* At top level of a qual, can treat UNKNOWN the same as FALSE */
- node->unknownEqFalse = isTopQual;
- node->setParam = NIL;
- node->parParam = NIL;
- node->args = NIL;
+ splan->unknownEqFalse = isTopQual;
+ splan->setParam = NIL;
+ splan->parParam = NIL;
+ splan->args = NIL;
/*
* Make parParam list of params that current query level will pass to this
@@ -317,7 +318,7 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
if (pitem->abslevel == root->query_level)
- node->parParam = lappend_int(node->parParam, paramid);
+ splan->parParam = lappend_int(splan->parParam, paramid);
}
bms_free(tmpset);
@@ -329,16 +330,16 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
* PARAM_EXEC Params instead of the PARAM_SUBLINK Params emitted by the
* parser.
*/
- if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
+ if (splan->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
{
Param *prm;
prm = generate_new_param(root, BOOLOID, -1);
- node->setParam = list_make1_int(prm->paramid);
- root->init_plans = lappend(root->init_plans, node);
+ splan->setParam = list_make1_int(prm->paramid);
+ isInitPlan = true;
result = (Node *) prm;
}
- else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
+ else if (splan->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
{
TargetEntry *te = linitial(plan->targetlist);
Param *prm;
@@ -347,11 +348,11 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
prm = generate_new_param(root,
exprType((Node *) te->expr),
exprTypmod((Node *) te->expr));
- node->setParam = list_make1_int(prm->paramid);
- root->init_plans = lappend(root->init_plans, node);
+ splan->setParam = list_make1_int(prm->paramid);
+ isInitPlan = true;
result = (Node *) prm;
}
- else if (node->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
+ else if (splan->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
{
TargetEntry *te = linitial(plan->targetlist);
Oid arraytype;
@@ -365,19 +366,19 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
prm = generate_new_param(root,
arraytype,
exprTypmod((Node *) te->expr));
- node->setParam = list_make1_int(prm->paramid);
- root->init_plans = lappend(root->init_plans, node);
+ splan->setParam = list_make1_int(prm->paramid);
+ isInitPlan = true;
result = (Node *) prm;
}
- else if (node->parParam == NIL && slink->subLinkType == ROWCOMPARE_SUBLINK)
+ else if (splan->parParam == NIL && slink->subLinkType == ROWCOMPARE_SUBLINK)
{
/* Adjust the Params */
result = convert_testexpr(root,
testexpr,
0,
- &node->paramIds);
- node->setParam = list_copy(node->paramIds);
- root->init_plans = lappend(root->init_plans, node);
+ &splan->paramIds);
+ splan->setParam = list_copy(splan->paramIds);
+ isInitPlan = true;
/*
* The executable expression is returned to become part of the outer
@@ -390,10 +391,10 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
ListCell *l;
/* Adjust the Params */
- node->testexpr = convert_testexpr(root,
- testexpr,
- 0,
- &node->paramIds);
+ splan->testexpr = convert_testexpr(root,
+ testexpr,
+ 0,
+ &splan->paramIds);
/*
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
@@ -402,8 +403,8 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
* tuple. But if it's an IN (= ANY) test, we might be able to use a
* hashtable to avoid comparing all the tuples.
*/
- if (subplan_is_hashable(slink, node, plan))
- node->useHashTable = true;
+ if (subplan_is_hashable(slink, splan, plan))
+ splan->useHashTable = true;
/*
* Otherwise, we have the option to tack a MATERIAL node onto the top
@@ -413,7 +414,7 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
* correlated subplans, we add MATERIAL unless the subplan's top plan
* node would materialize its output anyway.
*/
- else if (node->parParam == NIL)
+ else if (splan->parParam == NIL)
{
bool use_material;
@@ -433,10 +434,10 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
}
/*
- * Make node->args from parParam.
+ * Make splan->args from parParam.
*/
args = NIL;
- foreach(l, node->parParam)
+ foreach(l, splan->parParam)
{
PlannerParamItem *pitem = list_nth(root->glob->paramlist,
lfirst_int(l));
@@ -448,9 +449,10 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
*/
args = lappend(args, copyObject(pitem->item));
}
- node->args = args;
+ splan->args = args;
- result = (Node *) node;
+ result = (Node *) splan;
+ isInitPlan = false;
}
/*
@@ -460,7 +462,22 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
plan);
root->glob->subrtables = lappend(root->glob->subrtables,
subroot->parse->rtable);
- node->plan_id = list_length(root->glob->subplans);
+ splan->plan_id = list_length(root->glob->subplans);
+
+ if (isInitPlan)
+ root->init_plans = lappend(root->init_plans, splan);
+
+ /*
+ * A parameterless subplan (not initplan) should be prepared to handle
+ * REWIND efficiently. If it has direct parameters then there's no point
+ * since it'll be reset on each scan anyway; and if it's an initplan
+ * then there's no point since it won't get re-run without parameter
+ * changes anyway. The input of a hashed subplan doesn't need REWIND
+ * either.
+ */
+ if (splan->parParam == NIL && !isInitPlan && !splan->useHashTable)
+ root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
+ splan->plan_id);
return result;
}