in the planned representation of a subplan at all any more, only SubPlan.
This means subselect.c doesn't scribble on its input anymore, which seems
like a good thing; and there are no longer three different possible
interpretations of a SubLink. Simplify node naming and improve comments
in primnodes.h. No change to stored rules, though.
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.97 2002/12/13 19:45:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.98 2002/12/14 00:17:50 tgl Exp $
*
*/
appendStringInfo(str, " InitPlan\n");
foreach(lst, planstate->initPlan)
{
- SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
- SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
+ SubPlanState *sps = (SubPlanState *) lfirst(lst);
+ SubPlan *sp = (SubPlan *) sps->xprstate.expr;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++)
appendStringInfo(str, " SubPlan\n");
foreach(lst, planstate->subPlan)
{
- SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
- SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
+ SubPlanState *sps = (SubPlanState *) lfirst(lst);
+ SubPlan *sp = (SubPlan *) sps->xprstate.expr;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++)
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.67 2002/12/13 19:45:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.68 2002/12/14 00:17:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
foreach(lst, node->initPlan)
{
- SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
+ SubPlanState *sstate = (SubPlanState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL) /* don't care about child
}
foreach(lst, node->subPlan)
{
- SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
+ SubPlanState *sstate = (SubPlanState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.33 2002/12/13 19:45:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.34 2002/12/14 00:17:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
subps = NIL;
foreach(subp, node->initPlan)
{
- SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
- SubPlanExprState *sstate;
+ SubPlan *subplan = (SubPlan *) lfirst(subp);
+ SubPlanState *sstate;
- Assert(IsA(subplan, SubPlanExpr));
+ Assert(IsA(subplan, SubPlan));
sstate = ExecInitExprInitPlan(subplan, result);
ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
subps = NIL;
foreach(subp, result->subPlan)
{
- SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp);
+ SubPlanState *sstate = (SubPlanState *) lfirst(subp);
- Assert(IsA(sstate, SubPlanExprState));
+ Assert(IsA(sstate, SubPlanState));
ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
}
/* Clean up initPlans and subPlans */
foreach(subp, node->initPlan)
- ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
+ ExecEndSubPlan((SubPlanState *) lfirst(subp));
foreach(subp, node->subPlan)
- ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
+ ExecEndSubPlan((SubPlanState *) lfirst(subp));
if (node->chgParam != NIL)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.119 2002/12/13 19:45:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.120 2002/12/14 00:17:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
break;
}
- case T_SubPlanExpr:
- retDatum = ExecSubPlan((SubPlanExprState *) expression,
+ case T_SubPlan:
+ retDatum = ExecSubPlan((SubPlanState *) expression,
econtext,
isNull);
break;
* executions of the expression are needed. Typically the context will be
* the same as the per-query context of the associated ExprContext.
*
- * Any Aggref and SubplanExpr nodes found in the tree are added to the lists
+ * Any Aggref and SubPlan nodes found in the tree are added to the lists
* of such nodes held by the parent PlanState. Otherwise, we do very little
* initialization here other than building the state-node tree. Any nontrivial
* work associated with initializing runtime info for a node should happen
state = (ExprState *) bstate;
}
break;
- case T_SubPlanExpr:
+ case T_SubPlan:
{
/* Keep this in sync with ExecInitExprInitPlan, below */
- SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
- SubLink *sublink = subplanexpr->sublink;
- SubPlanExprState *sstate = makeNode(SubPlanExprState);
+ SubPlan *subplan = (SubPlan *) node;
+ SubPlanState *sstate = makeNode(SubPlanState);
- Assert(IsA(sublink, SubLink));
if (!parent)
- elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+ elog(ERROR, "ExecInitExpr: SubPlan not expected here");
/*
- * Here we just add the SubPlanExprState nodes to
+ * Here we just add the SubPlanState nodes to
* parent->subPlan. The subplans will be initialized later.
*/
parent->subPlan = lcons(sstate, parent->subPlan);
sstate->planstate = NULL;
- sstate->args = (List *)
- ExecInitExpr((Expr *) subplanexpr->args, parent);
-
- if (sublink->lefthand)
- elog(ERROR, "ExecInitExpr: sublink has not been transformed");
sstate->oper = (List *)
- ExecInitExpr((Expr *) sublink->oper, parent);
+ ExecInitExpr((Expr *) subplan->oper, parent);
+ sstate->args = (List *)
+ ExecInitExpr((Expr *) subplan->args, parent);
state = (ExprState *) sstate;
}
* subplan expr, except we do NOT want to add the node to the parent's
* subplan list.
*/
-SubPlanExprState *
-ExecInitExprInitPlan(SubPlanExpr *node, PlanState *parent)
+SubPlanState *
+ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
{
- SubLink *sublink = node->sublink;
- SubPlanExprState *sstate = makeNode(SubPlanExprState);
+ SubPlanState *sstate = makeNode(SubPlanState);
- Assert(IsA(sublink, SubLink));
if (!parent)
- elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+ elog(ERROR, "ExecInitExpr: SubPlan not expected here");
/* The subplan's state will be initialized later */
sstate->planstate = NULL;
+ sstate->oper = (List *) ExecInitExpr((Expr *) node->oper, parent);
sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);
- if (sublink->lefthand)
- elog(ERROR, "ExecInitExpr: sublink has not been transformed");
-
- sstate->oper = (List *) ExecInitExpr((Expr *) sublink->oper, parent);
-
sstate->xprstate.expr = (Expr *) node;
return sstate;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.37 2002/12/13 19:45:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.38 2002/12/14 00:17:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ----------------------------------------------------------------
*/
Datum
-ExecSubPlan(SubPlanExprState *node,
+ExecSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull)
{
+ SubPlan *subplan = (SubPlan *) node->xprstate.expr;
PlanState *planstate = node->planstate;
- SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
- SubLink *sublink = subplan->sublink;
- SubLinkType subLinkType = sublink->subLinkType;
- bool useor = sublink->useor;
+ SubLinkType subLinkType = subplan->subLinkType;
+ bool useor = subplan->useor;
MemoryContext oldcontext;
TupleTableSlot *slot;
Datum result;
* ----------------------------------------------------------------
*/
void
-ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
+ExecInitSubPlan(SubPlanState *node, EState *estate)
{
- SubPlanExpr *expr = (SubPlanExpr *) sstate->xprstate.expr;
+ SubPlan *subplan = (SubPlan *) node->xprstate.expr;
EState *sp_estate;
/*
* Do access checking on the rangetable entries in the subquery.
* Here, we assume the subquery is a SELECT.
*/
- ExecCheckRTPerms(expr->rtable, CMD_SELECT);
+ ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
/*
* initialize state
*/
- sstate->needShutdown = false;
- sstate->curTuple = NULL;
+ node->needShutdown = false;
+ node->curTuple = NULL;
/*
* create an EState for the subplan
*/
sp_estate = CreateExecutorState();
- sp_estate->es_range_table = expr->rtable;
+ sp_estate->es_range_table = subplan->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info;
sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
sp_estate->es_tupleTable =
- ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10);
+ ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
sp_estate->es_snapshot = estate->es_snapshot;
sp_estate->es_instrument = estate->es_instrument;
/*
* Start up the subplan
*/
- sstate->planstate = ExecInitNode(expr->plan, sp_estate);
+ node->planstate = ExecInitNode(subplan->plan, sp_estate);
- sstate->needShutdown = true; /* now we need to shutdown the subplan */
+ node->needShutdown = true; /* now we need to shutdown the subplan */
/*
* If this plan is un-correlated or undirect correlated one and want
* to set params for parent plan then prepare parameters.
*/
- if (expr->setParam != NIL)
+ if (subplan->setParam != NIL)
{
List *lst;
- foreach(lst, expr->setParam)
+ foreach(lst, subplan->setParam)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
- prm->execPlan = sstate;
+ prm->execPlan = node;
}
/*
* ----------------------------------------------------------------
*/
void
-ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
+ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
+ SubPlan *subplan = (SubPlan *) node->xprstate.expr;
PlanState *planstate = node->planstate;
- SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
- SubLinkType subLinkType = subplan->sublink->subLinkType;
+ SubLinkType subLinkType = subplan->subLinkType;
MemoryContext oldcontext;
TupleTableSlot *slot;
List *lst;
* ----------------------------------------------------------------
*/
void
-ExecEndSubPlan(SubPlanExprState *node)
+ExecEndSubPlan(SubPlanState *node)
{
if (node->needShutdown)
{
}
void
-ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent)
+ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{
PlanState *planstate = node->planstate;
- SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
+ SubPlan *subplan = (SubPlan *) node->xprstate.expr;
EState *estate = parent->state;
List *lst;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.232 2002/12/13 19:45:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.233 2002/12/14 00:17:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
/*
- * _copySubPlanExpr
+ * _copySubPlan
*/
-static SubPlanExpr *
-_copySubPlanExpr(SubPlanExpr *from)
+static SubPlan *
+_copySubPlan(SubPlan *from)
{
- SubPlanExpr *newnode = makeNode(SubPlanExpr);
+ SubPlan *newnode = makeNode(SubPlan);
- COPY_SCALAR_FIELD(typeOid);
+ COPY_SCALAR_FIELD(subLinkType);
+ COPY_SCALAR_FIELD(useor);
+ COPY_NODE_FIELD(oper);
COPY_NODE_FIELD(plan);
COPY_SCALAR_FIELD(plan_id);
COPY_NODE_FIELD(rtable);
COPY_INTLIST_FIELD(setParam);
COPY_INTLIST_FIELD(parParam);
COPY_NODE_FIELD(args);
- COPY_NODE_FIELD(sublink);
return newnode;
}
case T_SubLink:
retval = _copySubLink(from);
break;
- case T_SubPlanExpr:
- retval = _copySubPlanExpr(from);
+ case T_SubPlan:
+ retval = _copySubPlan(from);
break;
case T_FieldSelect:
retval = _copyFieldSelect(from);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.176 2002/12/12 20:35:12 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.177 2002/12/14 00:17:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
static bool
-_equalSubPlanExpr(SubPlanExpr *a, SubPlanExpr *b)
+_equalSubPlan(SubPlan *a, SubPlan *b)
{
- COMPARE_SCALAR_FIELD(typeOid);
+ COMPARE_SCALAR_FIELD(subLinkType);
+ COMPARE_SCALAR_FIELD(useor);
+ COMPARE_NODE_FIELD(oper);
/* should compare plans, but have to settle for comparing plan IDs */
COMPARE_SCALAR_FIELD(plan_id);
COMPARE_NODE_FIELD(rtable);
COMPARE_INTLIST_FIELD(setParam);
COMPARE_INTLIST_FIELD(parParam);
COMPARE_NODE_FIELD(args);
- COMPARE_NODE_FIELD(sublink);
return true;
}
case T_SubLink:
retval = _equalSubLink(a, b);
break;
- case T_SubPlanExpr:
- retval = _equalSubPlanExpr(a, b);
+ case T_SubPlan:
+ retval = _equalSubPlan(a, b);
break;
case T_FieldSelect:
retval = _equalFieldSelect(a, b);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.189 2002/12/13 19:45:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.190 2002/12/14 00:17:52 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
}
static void
-_outSubPlanExpr(StringInfo str, SubPlanExpr *node)
+_outSubPlan(StringInfo str, SubPlan *node)
{
- WRITE_NODE_TYPE("SUBPLANEXPR");
+ WRITE_NODE_TYPE("SUBPLAN");
- WRITE_OID_FIELD(typeOid);
+ WRITE_ENUM_FIELD(subLinkType, SubLinkType);
+ WRITE_BOOL_FIELD(useor);
+ WRITE_NODE_FIELD(oper);
WRITE_NODE_FIELD(plan);
WRITE_INT_FIELD(plan_id);
WRITE_NODE_FIELD(rtable);
WRITE_INTLIST_FIELD(setParam);
WRITE_INTLIST_FIELD(parParam);
WRITE_NODE_FIELD(args);
- WRITE_NODE_FIELD(sublink);
}
static void
case T_SubLink:
_outSubLink(str, obj);
break;
- case T_SubPlanExpr:
- _outSubPlanExpr(str, obj);
+ case T_SubPlan:
+ _outSubPlan(str, obj);
break;
case T_FieldSelect:
_outFieldSelect(str, obj);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.143 2002/12/13 19:45:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.144 2002/12/14 00:17:54 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
}
/*
- * _readSubPlanExpr is not needed since it doesn't appear in stored rules.
+ * _readSubPlan is not needed since it doesn't appear in stored rules.
*/
/*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.95 2002/12/13 17:29:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.96 2002/12/14 00:17:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
IsA(node, OpExpr) ||
IsA(node, DistinctExpr))
*total += cpu_operator_cost;
- else if (IsA(node, SubPlanExpr))
+ else if (IsA(node, SubPlan))
{
/*
* A subplan node in an expression indicates that the
* NOTE: this logic should agree with the estimates used by
* make_subplan() in plan/subselect.c.
*/
- SubPlanExpr *subplan = (SubPlanExpr *) node;
+ SubPlan *subplan = (SubPlan *) node;
Plan *plan = subplan->plan;
Cost subcost;
- if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
+ if (subplan->subLinkType == EXISTS_SUBLINK)
{
/* we only need to fetch 1 tuple */
subcost = plan->startup_cost +
(plan->total_cost - plan->startup_cost) / plan->plan_rows;
}
- else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
- subplan->sublink->subLinkType == ANY_SUBLINK)
+ else if (subplan->subLinkType == ALL_SUBLINK ||
+ subplan->subLinkType == ANY_SUBLINK)
{
/* assume we need 50% of the tuples */
subcost = plan->startup_cost +
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.134 2002/12/12 15:49:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.135 2002/12/14 00:17:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* purpose is communication across multiple sub-Queries.
*
* Note we do NOT save and restore PlannerPlanId: it exists to assign
- * unique IDs to SubPlanExpr nodes, and we want those IDs to be unique for
+ * unique IDs to SubPlan nodes, and we want those IDs to be unique for
* the life of a backend. Also, PlannerInitPlan is saved/restored in
* subquery_planner, not here.
*/
/* Must add the initPlans' extParams to the topmost node's, too */
foreach(lst, plan->initPlan)
{
- SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
+ SubPlan *subplan = (SubPlan *) lfirst(lst);
plan->extParam = set_unioni(plan->extParam,
subplan->plan->extParam);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.85 2002/12/12 15:49:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.86 2002/12/14 00:17:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* subplan references in this plan's tlist and quals. If we did the
* reference-adjustments bottom-up, then we would fail to match this
* plan's var nodes against the already-modified nodes of the
- * children. Fortunately, that consideration doesn't apply to SubPlanExpr
+ * children. Fortunately, that consideration doesn't apply to SubPlan
* nodes; else we'd need two passes over the expression trees.
*/
set_plan_references(plan->lefttree, rtable);
foreach(pl, plan->initPlan)
{
- SubPlanExpr *sp = (SubPlanExpr *) lfirst(pl);
+ SubPlan *sp = (SubPlan *) lfirst(pl);
- Assert(IsA(sp, SubPlanExpr));
+ Assert(IsA(sp, SubPlan));
set_plan_references(sp->plan, sp->rtable);
}
}
set_opfuncid((OpExpr *) node);
else if (IsA(node, DistinctExpr))
set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
- else if (IsA(node, SubPlanExpr))
+ else if (IsA(node, SubPlan))
{
- SubPlanExpr *sp = (SubPlanExpr *) node;
+ SubPlan *sp = (SubPlan *) node;
set_plan_references(sp->plan, sp->rtable);
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.60 2002/12/12 15:49:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.61 2002/12/14 00:17:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
-static void convert_sublink_opers(SubLink *slink, List *targetlist,
- List **setParams);
+typedef struct finalize_primnode_results
+{
+ List *paramids; /* List of PARAM_EXEC paramids found */
+} finalize_primnode_results;
+
+
+static List *convert_sublink_opers(List *operlist, List *lefthand,
+ List *targetlist, List **setParams);
+static Node *replace_correlation_vars_mutator(Node *node, void *context);
+static Node *process_sublinks_mutator(Node *node, void *context);
+static bool finalize_primnode(Node *node, finalize_primnode_results *results);
/*
}
/*
- * Convert a bare SubLink (as created by the parser) into a SubPlanExpr.
+ * Convert a bare SubLink (as created by the parser) into a SubPlan.
+ *
+ * We are given the raw SubLink and the already-processed lefthand argument
+ * list (use this instead of the SubLink's own field).
+ *
+ * The result is whatever we need to substitute in place of the SubLink
+ * node in the executable expression. This will be either the SubPlan
+ * node (if we have to do the subplan as a subplan), or a Param node
+ * representing the result of an InitPlan, or possibly an AND or OR tree
+ * containing InitPlan Param nodes.
*/
static Node *
-make_subplan(SubLink *slink)
+make_subplan(SubLink *slink, List *lefthand)
{
- SubPlanExpr *node = makeNode(SubPlanExpr);
+ SubPlan *node = makeNode(SubPlan);
Query *subquery = (Query *) (slink->subselect);
- Oid result_type = exprType((Node *) slink);
double tuple_fraction;
Plan *plan;
List *lst;
Node *result;
- /*
- * Check to see if this node was already processed; if so we have
- * trouble. We check to see if the linked-to Query appears to have
- * been planned already, too.
- */
- if (subquery == NULL)
- elog(ERROR, "make_subplan: invalid expression structure (SubLink already processed?)");
- if (subquery->base_rel_list != NIL)
- elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)");
-
/*
* Copy the source Query node. This is a quick and dirty kluge to
* resolve the fact that the parser can generate trees with multiple
node->plan = plan = subquery_planner(subquery, tuple_fraction);
node->plan_id = PlannerPlanId++; /* Assign unique ID to this
- * SubPlanExpr */
+ * SubPlan */
node->rtable = subquery->rtable;
- node->sublink = slink;
-
- node->typeOid = result_type;
- slink->subselect = NULL; /* cool ?! see error check above! */
+ /*
+ * Fill in other fields of the SubPlan node.
+ */
+ node->subLinkType = slink->subLinkType;
+ node->useor = slink->useor;
+ node->oper = NIL;
+ node->setParam = NIL;
+ node->parParam = NIL;
+ node->args = NIL;
/*
* Make parParam list of params that current query level will pass to
}
else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
{
- convert_sublink_opers(slink, plan->targetlist, &node->setParam);
+ List *oper;
+
+ /* Convert the oper list, but don't put it into the SubPlan node */
+ oper = convert_sublink_opers(slink->oper,
+ lefthand,
+ plan->targetlist,
+ &node->setParam);
PlannerInitPlan = lappend(PlannerInitPlan, node);
- if (length(slink->oper) > 1)
- result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
- make_andclause(slink->oper));
+ if (length(oper) > 1)
+ result = (Node *) (node->useor ? make_orclause(oper) :
+ make_andclause(oper));
else
- result = (Node *) lfirst(slink->oper);
+ result = (Node *) lfirst(oper);
}
else
{
- List *args = NIL;
+ List *args;
/*
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
}
}
- /* Fix the SubLink's oper list */
- convert_sublink_opers(slink, plan->targetlist, NULL);
+ /* Convert the SubLink's oper list into executable form */
+ node->oper = convert_sublink_opers(slink->oper,
+ lefthand,
+ plan->targetlist,
+ NULL);
/*
* Make node->args from parParam.
*/
+ args = NIL;
foreach(lst, node->parParam)
{
Var *var = nth(lfirsti(lst), PlannerParamVar);
* convert_sublink_opers: convert a SubLink's oper list from the
* parser/rewriter format into the executor's format.
*
- * The oper list is initially just a list of OpExpr nodes. We replace it
- * with a list of actually executable expressions, in which the specified
- * operators are applied to corresponding elements of the lefthand list
- * and Params representing the results of the subplan. lefthand is then
- * set to NIL.
+ * The oper list is initially a list of OpExpr nodes with NIL args. We
+ * convert it to a list of actually executable expressions, in which the
+ * specified operators are applied to corresponding elements of the
+ * lefthand list and Params representing the results of the subplan.
*
* If setParams is not NULL, the paramids of the Params created are added
* to the *setParams list.
*/
-static void
-convert_sublink_opers(SubLink *slink, List *targetlist,
- List **setParams)
+static List *
+convert_sublink_opers(List *operlist, List *lefthand,
+ List *targetlist, List **setParams)
{
List *newoper = NIL;
- List *leftlist = slink->lefthand;
+ List *leftlist = lefthand;
List *lst;
- foreach(lst, slink->oper)
+ foreach(lst, operlist)
{
OpExpr *oper = (OpExpr *) lfirst(lst);
- Node *lefthand = lfirst(leftlist);
+ Node *leftop = lfirst(leftlist);
TargetEntry *te = lfirst(targetlist);
Param *prm;
Operator tup;
* Note: we use make_operand in case runtime type conversion
* function calls must be inserted for this operator!
*/
- left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
+ left = make_operand(leftop, exprType(leftop), opform->oprleft);
right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
newoper = lappend(newoper,
make_opclause(oper->opno,
targetlist = lnext(targetlist);
}
- slink->oper = newoper;
- slink->lefthand = NIL;
-}
-
-/*
- * finalize_primnode: build lists of params appearing
- * in the given expression tree. NOTE: items are added to list passed in,
- * so caller must initialize list to NIL before first call!
- */
-
-typedef struct finalize_primnode_results
-{
- List *paramids; /* List of PARAM_EXEC paramids found */
-} finalize_primnode_results;
-
-static bool
-finalize_primnode(Node *node, finalize_primnode_results *results)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Param))
- {
- if (((Param *) node)->paramkind == PARAM_EXEC)
- {
- int paramid = (int) ((Param *) node)->paramid;
-
- if (!intMember(paramid, results->paramids))
- results->paramids = lconsi(paramid, results->paramids);
- }
- return false; /* no more to do here */
- }
- if (is_subplan(node))
- {
- SubPlanExpr *subplan = (SubPlanExpr *) node;
- List *lst;
-
- /* Check extParam list for params to add to paramids */
- foreach(lst, subplan->plan->extParam)
- {
- int paramid = lfirsti(lst);
- Var *var = nth(paramid, PlannerParamVar);
-
- /* note varlevelsup is absolute level number */
- if (var->varlevelsup < PlannerQueryLevel &&
- !intMember(paramid, results->paramids))
- results->paramids = lconsi(paramid, results->paramids);
- }
- /* fall through to recurse into subplan args */
- }
- return expression_tree_walker(node, finalize_primnode,
- (void *) results);
+ return newoper;
}
/*
* Replace correlation vars (uplevel vars) with Params.
*/
-
-static Node *replace_correlation_vars_mutator(Node *node, void *context);
-
Node *
SS_replace_correlation_vars(Node *expr)
{
/*
* Expand SubLinks to SubPlans in the given expression.
*/
-
-static Node *process_sublinks_mutator(Node *node, void *context);
-
Node *
SS_process_sublinks(Node *expr)
{
if (IsA(node, SubLink))
{
SubLink *sublink = (SubLink *) node;
+ List *lefthand;
/*
- * First, scan the lefthand-side expressions, if any. This is a
- * tad klugy since we modify the input SubLink node, but that
- * should be OK (make_subplan does it too!)
+ * First, recursively process the lefthand-side expressions, if any.
*/
- sublink->lefthand = (List *)
+ lefthand = (List *)
process_sublinks_mutator((Node *) sublink->lefthand, context);
- /* Now build the SubPlanExpr node and make the expr to return */
- return make_subplan(sublink);
+ /*
+ * Now build the SubPlan node and make the expr to return.
+ */
+ return make_subplan(sublink, lefthand);
}
/*
- * Note that we will never see a SubPlanExpr expression in the input
+ * Note that we will never see a SubPlan expression in the input
* (since this is the very routine that creates 'em to begin with). So
* the code in expression_tree_mutator() that might do inappropriate
* things with SubPlans or SubLinks will not be exercised.
context);
}
+/*
+ * SS_finalize_plan - do final sublink processing for a completed Plan.
+ *
+ * This recursively computes and sets the extParam and locParam lists
+ * for every Plan node in the given tree.
+ */
List *
SS_finalize_plan(Plan *plan, List *rtable)
{
return results.paramids;
}
+
+/*
+ * finalize_primnode: build lists of params appearing
+ * in the given expression tree. NOTE: items are added to list passed in,
+ * so caller must initialize list to NIL before first call!
+ */
+static bool
+finalize_primnode(Node *node, finalize_primnode_results *results)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Param))
+ {
+ if (((Param *) node)->paramkind == PARAM_EXEC)
+ {
+ int paramid = (int) ((Param *) node)->paramid;
+
+ if (!intMember(paramid, results->paramids))
+ results->paramids = lconsi(paramid, results->paramids);
+ }
+ return false; /* no more to do here */
+ }
+ if (is_subplan(node))
+ {
+ SubPlan *subplan = (SubPlan *) node;
+ List *lst;
+
+ /* Check extParam list for params to add to paramids */
+ foreach(lst, subplan->plan->extParam)
+ {
+ int paramid = lfirsti(lst);
+ Var *var = nth(paramid, PlannerParamVar);
+
+ /* note varlevelsup is absolute level number */
+ if (var->varlevelsup < PlannerQueryLevel &&
+ !intMember(paramid, results->paramids))
+ results->paramids = lconsi(paramid, results->paramids);
+ }
+ /* fall through to recurse into subplan args */
+ }
+ return expression_tree_walker(node, finalize_primnode,
+ (void *) results);
+}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.82 2002/12/12 15:49:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.83 2002/12/14 00:17:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
if (is_subplan(node))
{
- SubPlanExpr *subplan;
+ SubPlan *subplan;
/* Copy the node and process subplan args */
node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
(void *) context);
/* Make sure we have separate copies of subplan and its rtable */
- subplan = (SubPlanExpr *) node;
+ subplan = (SubPlan *) node;
subplan->plan = copyObject(subplan->plan);
subplan->rtable = copyObject(subplan->rtable);
return node;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.118 2002/12/13 19:45:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.119 2002/12/14 00:17:59 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
return false;
if (IsA(node, SubLink))
return false;
- if (IsA(node, SubPlanExpr))
+ if (IsA(node, SubPlan))
return false;
return expression_tree_walker(node, expression_returns_set_walker,
{
if (node == NULL)
return false;
- if (IsA(node, SubPlanExpr) ||
+ if (IsA(node, SubPlan) ||
IsA(node, SubLink))
return true; /* abort the tree traversal and return
* true */
* pull_subplans
* Recursively pulls all subplans from an expression tree.
*
- * Returns list of SubPlanExpr nodes found. Note the nodes themselves
+ * Returns list of SubPlan nodes found. Note the nodes themselves
* are not copied, only referenced.
*/
List *
*/
List *t;
- foreach(t, ((SubPlanExpr *) node)->args)
+ foreach(t, ((SubPlan *) node)->args)
{
Node *thisarg = lfirst(t);
Var *var;
break;
}
}
- if (IsA(node, SubPlanExpr))
+ if (IsA(node, SubPlan))
{
/*
- * Return a SubPlanExpr unchanged --- too late to do anything
+ * Return a SubPlan unchanged --- too late to do anything
* with it.
*
* XXX should we elog() here instead? Probably this routine
- * should never be invoked after SubPlanExpr creation.
+ * should never be invoked after SubPlan creation.
*/
return node;
}
* 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 and SubPlanExpr nodes by
- * recursing normally into the "lefthand" arguments (which are expressions
- * belonging to the outer plan). It will also call the walker on the
- * sub-Query node; however, when expression_tree_walker itself is called on a
- * Query node, it does nothing and returns "false". The net effect is that
- * unless the walker does something special at a Query node, sub-selects will
- * not be visited during an expression tree walk. This is exactly the behavior
- * wanted in many cases --- and for those walkers that do want to recurse into
- * sub-selects, special behavior is typically needed anyway at the entry to a
- * sub-select (such as incrementing a depth counter). A walker that wants to
- * examine sub-selects should include code along the lines of:
+ * expression_tree_walker will handle SubLink nodes by recursing normally into
+ * the "lefthand" arguments (which are expressions belonging to the outer
+ * plan). It will also call the walker on the sub-Query node; however, when
+ * expression_tree_walker itself is called on a Query node, it does nothing
+ * and returns "false". The net effect is that unless the walker does
+ * something special at a Query node, sub-selects will not be visited during
+ * an expression tree walk. This is exactly the behavior wanted in many cases
+ * --- and for those walkers that do want to recurse into sub-selects, special
+ * behavior is typically needed anyway at the entry to a sub-select (such as
+ * incrementing a depth counter). A walker that wants to examine sub-selects
+ * should include code along the lines of:
*
* if (IsA(node, Query))
* {
* query_tree_walker is a convenience routine (see below) that calls the
* walker on all the expression subtrees of the given Query node.
*
- * NOTE: currently, because make_subplan() clears the subselect link in
- * a SubLink node, it is not actually possible to recurse into subselects
- * of an already-planned expression tree. This is OK for current uses,
- * but ought to be cleaned up when we redesign querytree processing.
+ * expression_tree_walker will handle SubPlan nodes by recursing normally
+ * into the "oper" and "args" lists (which are expressions belonging to the
+ * outer plan). It will not touch the completed subplan, however. Since
+ * there is no link to the original Query, it is not possible to recurse into
+ * subselects of an already-planned expression tree. This is OK for current
+ * uses, but may need to be revisited in future.
*--------------------
*/
SubLink *sublink = (SubLink *) node;
/*
- * If the SubLink has already been processed by
- * subselect.c, it will have lefthand=NIL, and we need to
- * scan the oper list. Otherwise we only need to look at
- * the lefthand list (the incomplete OpExpr nodes in the
- * oper list are deemed uninteresting, perhaps even
- * confusing).
+ * We only recurse into the lefthand list (the incomplete
+ * OpExpr nodes in the oper list are deemed uninteresting,
+ * perhaps even confusing).
*/
- if (sublink->lefthand)
- {
- if (walker((Node *) sublink->lefthand, context))
- return true;
- }
- else
- {
- if (walker((Node *) sublink->oper, context))
- return true;
- }
-
+ if (expression_tree_walker((Node *) sublink->lefthand,
+ walker, context))
+ return true;
/*
* Also invoke the walker on the sublink's Query node, so
* it can recurse into the sub-query if it wants to.
return walker(sublink->subselect, context);
}
break;
- case T_SubPlanExpr:
+ case T_SubPlan:
{
- SubPlanExpr *expr = (SubPlanExpr *) node;
+ SubPlan *subplan = (SubPlan *) node;
- /* recurse to the SubLink node, but not into the Plan */
- if (walker((Node *) expr->sublink, context))
+ /* recurse into the oper list, but not into the Plan */
+ if (expression_tree_walker((Node *) subplan->oper,
+ walker, context))
return true;
/* also examine args list */
- if (expression_tree_walker((Node *) expr->args,
+ if (expression_tree_walker((Node *) subplan->args,
walker, context))
return true;
}
* expression_tree_mutator include all those normally found in target lists
* and qualifier clauses during the planning stage.
*
- * expression_tree_mutator will handle a SubPlanExpr node by recursing into
- * the args and sublink->oper lists (which belong to the outer plan), but it
+ * expression_tree_mutator will handle a SubPlan node by recursing into
+ * the "oper" and "args" lists (which belong to the outer plan), but it
* will simply copy the link to the inner plan, since that's typically what
* expression tree mutators want. A mutator that wants to modify the subplan
- * can force appropriate behavior by recognizing subplan expression nodes
+ * can force appropriate behavior by recognizing SubPlan expression nodes
* and doing the right thing.
*
- * Bare SubLink nodes (without a SubPlanExpr) are handled by recursing into
- * the "lefthand" argument list only. (A bare SubLink should be seen only if
- * the tree has not yet been processed by subselect.c.) Again, this can be
- * overridden by the mutator, but it seems to be the most useful default
- * behavior.
+ * SubLink nodes are handled by recursing into the "lefthand" argument list
+ * only. (A SubLink will be seen only if the tree has not yet been
+ * processed by subselect.c.) Again, this can be overridden by the mutator,
+ * but it seems to be the most useful default behavior.
*--------------------
*/
case T_SubLink:
{
/*
- * A "bare" SubLink (note we will not come here if we
- * found a SubPlanExpr node above it). Transform the
- * lefthand side, but not the oper list nor the subquery.
+ * We transform the lefthand side, but not the oper list nor
+ * the subquery.
*/
SubLink *sublink = (SubLink *) node;
SubLink *newnode;
return (Node *) newnode;
}
break;
- case T_SubPlanExpr:
+ case T_SubPlan:
{
- SubPlanExpr *expr = (SubPlanExpr *) node;
- SubLink *oldsublink = expr->sublink;
- SubPlanExpr *newnode;
+ SubPlan *subplan = (SubPlan *) node;
+ SubPlan *newnode;
- FLATCOPY(newnode, expr, SubPlanExpr);
- /* flat-copy the SubLink node */
- CHECKFLATCOPY(newnode->sublink, oldsublink, SubLink);
+ FLATCOPY(newnode, subplan, SubPlan);
/* transform args list (params to be passed to subplan) */
- MUTATE(newnode->args, expr->args, List *);
- /* transform sublink's oper list as well */
- MUTATE(newnode->sublink->oper, oldsublink->oper, List *);
- /* but not the subplan itself, which is referenced as-is */
+ MUTATE(newnode->args, subplan->args, List *);
+ /* transform oper list as well */
+ MUTATE(newnode->oper, subplan->oper, List *);
+ /* but not the sub-Plan itself, which is referenced as-is */
return (Node *) newnode;
}
break;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.41 2002/12/12 15:49:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.42 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
* references to the desired rtable level! But when we find a completed
- * SubPlanExpr, we only need to look at the parameters passed to the subplan.
+ * SubPlan, we only need to look at the parameters passed to the subplan.
*/
List *
pull_varnos(Node *node)
* executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort.
*/
- SubPlanExpr *subplan = (SubPlanExpr *) node;
+ SubPlan *subplan = (SubPlan *) node;
- if (pull_varnos_walker((Node *) subplan->sublink->oper,
+ if (pull_varnos_walker((Node *) subplan->oper,
context))
return true;
if (pull_varnos_walker((Node *) subplan->args,
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
* references to the desired rtable entry! But when we find a completed
- * SubPlanExpr, we only need to look at the parameters passed to the subplan.
+ * SubPlan, we only need to look at the parameters passed to the subplan.
*/
bool
contain_var_reference(Node *node, int varno, int varattno, int levelsup)
* executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort.
*/
- SubPlanExpr *subplan = (SubPlanExpr *) node;
+ SubPlan *subplan = (SubPlan *) node;
- if (contain_var_reference_walker((Node *) subplan->sublink->oper,
+ if (contain_var_reference_walker((Node *) subplan->oper,
context))
return true;
if (contain_var_reference_walker((Node *) subplan->args,
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.128 2002/12/12 15:49:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.129 2002/12/14 00:17:59 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
get_sublink_expr((SubLink *) node, context);
break;
- case T_SubPlanExpr:
+ case T_SubPlan:
{
/*
* We cannot see an already-planned subplan in
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: executor.h,v 1.82 2002/12/13 19:45:56 tgl Exp $
+ * $Id: executor.h,v 1.83 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
-extern SubPlanExprState *ExecInitExprInitPlan(SubPlanExpr *node,
- PlanState *parent);
+extern SubPlanState *ExecInitExprInitPlan(SubPlan *node, PlanState *parent);
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
extern int ExecTargetListLength(List *targetlist);
extern int ExecCleanTargetListLength(List *targetlist);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodeSubplan.h,v 1.14 2002/12/13 19:45:56 tgl Exp $
+ * $Id: nodeSubplan.h,v 1.15 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "nodes/execnodes.h"
-extern void ExecInitSubPlan(SubPlanExprState *sstate, EState *estate);
-extern Datum ExecSubPlan(SubPlanExprState *node,
+extern void ExecInitSubPlan(SubPlanState *node, EState *estate);
+extern Datum ExecSubPlan(SubPlanState *node,
ExprContext *econtext,
bool *isNull);
-extern void ExecEndSubPlan(SubPlanExprState *node);
-extern void ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent);
+extern void ExecEndSubPlan(SubPlanState *node);
+extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
-extern void ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext);
+extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
#endif /* NODESUBPLAN_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: execnodes.h,v 1.84 2002/12/13 19:45:57 tgl Exp $
+ * $Id: execnodes.h,v 1.85 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
} BoolExprState;
/* ----------------
- * SubPlanExprState node
- *
- * Note: there is no separate ExprState node for the SubLink. All it would
- * need is the oper field, which we can just as easily put here.
+ * SubPlanState node
* ----------------
*/
-typedef struct SubPlanExprState
+typedef struct SubPlanState
{
ExprState xprstate;
struct PlanState *planstate; /* subselect plan's state tree */
bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
- List *args; /* states of argument expression(s) */
List *oper; /* states for executable combining exprs */
-} SubPlanExprState;
+ List *args; /* states of argument expression(s) */
+} SubPlanState;
/* ----------------
* CaseExprState node
List *qual; /* implicitly-ANDed qual conditions */
struct PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree;
- List *initPlan; /* Init SubPlanExprState nodes (un-correlated
+ List *initPlan; /* Init SubPlanState nodes (un-correlated
* expr subselects) */
- List *subPlan; /* SubPlanExprState nodes in my expressions */
+ List *subPlan; /* SubPlanState nodes in my expressions */
/*
* State for management of parameter-change-driven rescanning
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.132 2002/12/13 19:46:00 tgl Exp $
+ * $Id: nodes.h,v 1.133 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
T_DistinctExpr,
T_BoolExpr,
T_SubLink,
- T_SubPlanExpr,
+ T_SubPlan,
T_FieldSelect,
T_RelabelType,
T_CaseExpr,
T_ArrayRefExprState,
T_FuncExprState,
T_BoolExprState,
- T_SubPlanExprState,
+ T_SubPlanState,
T_CaseExprState,
T_CaseWhenState,
T_ConstraintTestState,
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: params.h,v 1.20 2002/12/13 19:46:00 tgl Exp $
+ * $Id: params.h,v 1.21 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* array of ParamExecData records, which is referenced through
* es_param_exec_vals or ecxt_param_exec_vals.
*
- * If execPlan is not NULL, it points to a SubPlanExprState node that needs
+ * If execPlan is not NULL, it points to a SubPlanState node that needs
* to be executed to produce the value. (This is done so that we can have
* lazy evaluation of InitPlans: they aren't executed until/unless a
* result value is needed.) Otherwise the value is assumed to be valid
typedef struct ParamExecData
{
- void *execPlan; /* should be "SubPlanExprState *" */
+ void *execPlan; /* should be "SubPlanState *" */
Datum value;
bool isnull;
} ParamExecData;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: primnodes.h,v 1.74 2002/12/13 19:46:00 tgl Exp $
+ * $Id: primnodes.h,v 1.75 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* using AND and OR semantics respectively.
*
* SubLink is classed as an Expr node, but it is not actually executable;
- * it must be replaced in the expression tree by a SubPlanExpr node during
+ * it must be replaced in the expression tree by a SubPlan node during
* planning.
*
- * NOTE: lefthand and oper have varying meanings depending on where you look
- * in the parse/plan pipeline:
- * 1. gram.y delivers a list of the (untransformed) lefthand expressions in
- * lefthand, and sets oper to a single A_Expr (not a list!) containing
- * the string name of the operator, but no arguments.
- * 2. The parser's expression transformation transforms lefthand normally,
- * and replaces oper with a list of OpExpr nodes, one per lefthand
- * expression. These nodes represent the parser's resolution of exactly
- * which operator to apply to each pair of lefthand and targetlist
- * expressions. However, we have not constructed complete Expr trees for
- * these operations yet: the args fields of the OpExpr nodes are NIL.
- * This is the representation seen in saved rules and in the rewriter.
- * 3. Finally, the planner converts the oper list to a list of normal OpExpr
- * nodes representing the application of the operator(s) to the lefthand
- * expressions and values from the inner targetlist. The inner
- * targetlist items are represented by placeholder Param nodes.
- * The lefthand field is set to NIL, since its expressions are now in
- * the Expr list. This representation is passed to the executor.
- *
- * Planner routines that might see either representation 2 or 3 can tell
- * the difference by checking whether lefthand is NIL or not. Also,
- * representation 2 appears in a "bare" SubLink, while representation 3 is
- * found in SubLinks that are children of SubPlanExpr nodes.
+ * NOTE: in the raw output of gram.y, lefthand contains a list of (raw)
+ * expressions, and oper contains a single A_Expr (not a list!) containing
+ * the string name of the operator, but no arguments. Also, subselect is
+ * a raw parsetree. During parse analysis, the parser transforms the
+ * lefthand expression list using normal expression transformation rules.
+ * It replaces oper with a list of OpExpr nodes, one per lefthand expression.
+ * These nodes represent the parser's resolution of exactly which operator
+ * to apply to each pair of lefthand and targetlist expressions. However,
+ * we have not constructed complete Expr trees for these operations yet:
+ * the args fields of the OpExpr nodes are NIL. And subselect is transformed
+ * to a Query. This is the representation seen in saved rules and in the
+ * rewriter.
*
* In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
* always NIL. useor is not significant either for these sublink types.
* "OR" not "AND" */
List *lefthand; /* list of outer-query expressions on the
* left */
- List *oper; /* list of OpExpr nodes for combining
- * operators, or final list of executable
- * expressions */
+ List *oper; /* list of arg-less OpExpr nodes for
+ * combining operators */
Node *subselect; /* subselect as Query* or parsetree */
} SubLink;
/*
- * SubPlanExpr - executable expression node for a subplan (sub-SELECT)
- *
- * The planner replaces SubLink nodes in expression trees with SubPlanExpr
- * nodes after it has finished planning the subquery. See notes above.
- */
-typedef struct SubPlanExpr
+ * SubPlan - executable expression node for a subplan (sub-SELECT)
+ *
+ * The planner replaces SubLink nodes in expression trees with SubPlan
+ * nodes after it has finished planning the subquery. SubPlan contains
+ * a sub-plantree and rtable instead of a sub-Query. Its "oper" field
+ * corresponds to the original SubLink's oper list, but has been expanded
+ * into valid executable expressions representing the application of the
+ * combining operator(s) to the lefthand expressions and values from the
+ * inner targetlist. The original lefthand expressions now appear as
+ * left-hand arguments of the OpExpr nodes, while the inner targetlist items
+ * are represented by PARAM_EXEC Param nodes. (Note: if the sub-select
+ * becomes an InitPlan rather than a SubPlan, the rebuilt oper list is
+ * part of the outer plan tree and so is not stored in the oper field.)
+ *
+ * The planner also derives lists of the values that need to be passed into
+ * and out of the subplan. Input values are represented as a list "args" of
+ * expressions to be evaluated in the outer-query context (currently these
+ * args are always just Vars, but in principle they could be any expression).
+ * The values are assigned to the global PARAM_EXEC params indexed by parParam
+ * (the parParam and args lists must have the same length). setParam is a
+ * list of the PARAM_EXEC params that are computed by the sub-select, if it
+ * is an initPlan.
+ */
+typedef struct SubPlan
{
Expr xpr;
- Oid typeOid; /* PG_TYPE OID of the expression result */
+ /* Fields copied from original SubLink: */
+ SubLinkType subLinkType; /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
+ bool useor; /* TRUE to combine column results with
+ * "OR" not "AND" */
+ List *oper; /* list of executable expressions for
+ * combining operators (with arguments) */
+ /* The subselect, transformed to a Plan: */
struct Plan *plan; /* subselect plan itself */
int plan_id; /* dummy thing because of we haven't equal
* funcs for plan nodes... actually, we
* could put *plan itself somewhere else
* (TopPlan node ?)... */
List *rtable; /* range table for subselect */
+ /* Information for passing params into and out of the subselect: */
/* setParam and parParam are lists of integers (param IDs) */
List *setParam; /* non-correlated EXPR & EXISTS subqueries
* have to set some Params for paren Plan */
List *parParam; /* indices of input Params from parent plan */
List *args; /* exprs to pass as parParam values */
- SubLink *sublink; /* SubLink node from parser; holds info
- * about what to do with subselect's
- * results */
-} SubPlanExpr;
+} SubPlan;
/* ----------------
* FieldSelect
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: clauses.h,v 1.57 2002/12/12 15:49:41 tgl Exp $
+ * $Id: clauses.h,v 1.58 2002/12/14 00:17:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr))
#define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr))
-#define is_subplan(clause) ((clause) != NULL && IsA(clause, SubPlanExpr))
+#define is_subplan(clause) ((clause) != NULL && IsA(clause, SubPlan))
extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,