mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Clean up plantree representation of SubPlan-s --- SubLink does not appear
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.
This commit is contained in:
@ -5,7 +5,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -589,8 +589,8 @@ explain_outNode(StringInfo str,
|
|||||||
appendStringInfo(str, " InitPlan\n");
|
appendStringInfo(str, " InitPlan\n");
|
||||||
foreach(lst, planstate->initPlan)
|
foreach(lst, planstate->initPlan)
|
||||||
{
|
{
|
||||||
SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
|
SubPlanState *sps = (SubPlanState *) lfirst(lst);
|
||||||
SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
|
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
|
||||||
|
|
||||||
es->rtable = sp->rtable;
|
es->rtable = sp->rtable;
|
||||||
for (i = 0; i < indent; i++)
|
for (i = 0; i < indent; i++)
|
||||||
@ -687,8 +687,8 @@ explain_outNode(StringInfo str,
|
|||||||
appendStringInfo(str, " SubPlan\n");
|
appendStringInfo(str, " SubPlan\n");
|
||||||
foreach(lst, planstate->subPlan)
|
foreach(lst, planstate->subPlan)
|
||||||
{
|
{
|
||||||
SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
|
SubPlanState *sps = (SubPlanState *) lfirst(lst);
|
||||||
SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
|
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
|
||||||
|
|
||||||
es->rtable = sp->rtable;
|
es->rtable = sp->rtable;
|
||||||
for (i = 0; i < indent; i++)
|
for (i = 0; i < indent; i++)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -61,7 +61,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
|
|||||||
|
|
||||||
foreach(lst, node->initPlan)
|
foreach(lst, node->initPlan)
|
||||||
{
|
{
|
||||||
SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
|
SubPlanState *sstate = (SubPlanState *) lfirst(lst);
|
||||||
PlanState *splan = sstate->planstate;
|
PlanState *splan = sstate->planstate;
|
||||||
|
|
||||||
if (splan->plan->extParam != NIL) /* don't care about child
|
if (splan->plan->extParam != NIL) /* don't care about child
|
||||||
@ -72,7 +72,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
|
|||||||
}
|
}
|
||||||
foreach(lst, node->subPlan)
|
foreach(lst, node->subPlan)
|
||||||
{
|
{
|
||||||
SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
|
SubPlanState *sstate = (SubPlanState *) lfirst(lst);
|
||||||
PlanState *splan = sstate->planstate;
|
PlanState *splan = sstate->planstate;
|
||||||
|
|
||||||
if (splan->plan->extParam != NIL)
|
if (splan->plan->extParam != NIL)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -228,10 +228,10 @@ ExecInitNode(Plan *node, EState *estate)
|
|||||||
subps = NIL;
|
subps = NIL;
|
||||||
foreach(subp, node->initPlan)
|
foreach(subp, node->initPlan)
|
||||||
{
|
{
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
|
SubPlan *subplan = (SubPlan *) lfirst(subp);
|
||||||
SubPlanExprState *sstate;
|
SubPlanState *sstate;
|
||||||
|
|
||||||
Assert(IsA(subplan, SubPlanExpr));
|
Assert(IsA(subplan, SubPlan));
|
||||||
sstate = ExecInitExprInitPlan(subplan, result);
|
sstate = ExecInitExprInitPlan(subplan, result);
|
||||||
ExecInitSubPlan(sstate, estate);
|
ExecInitSubPlan(sstate, estate);
|
||||||
subps = lappend(subps, sstate);
|
subps = lappend(subps, sstate);
|
||||||
@ -247,9 +247,9 @@ ExecInitNode(Plan *node, EState *estate)
|
|||||||
subps = NIL;
|
subps = NIL;
|
||||||
foreach(subp, result->subPlan)
|
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);
|
ExecInitSubPlan(sstate, estate);
|
||||||
subps = lappend(subps, sstate);
|
subps = lappend(subps, sstate);
|
||||||
}
|
}
|
||||||
@ -500,9 +500,9 @@ ExecEndNode(PlanState *node)
|
|||||||
|
|
||||||
/* Clean up initPlans and subPlans */
|
/* Clean up initPlans and subPlans */
|
||||||
foreach(subp, node->initPlan)
|
foreach(subp, node->initPlan)
|
||||||
ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
|
ExecEndSubPlan((SubPlanState *) lfirst(subp));
|
||||||
foreach(subp, node->subPlan)
|
foreach(subp, node->subPlan)
|
||||||
ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
|
ExecEndSubPlan((SubPlanState *) lfirst(subp));
|
||||||
|
|
||||||
if (node->chgParam != NIL)
|
if (node->chgParam != NIL)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1794,8 +1794,8 @@ ExecEvalExpr(ExprState *expression,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
retDatum = ExecSubPlan((SubPlanExprState *) expression,
|
retDatum = ExecSubPlan((SubPlanState *) expression,
|
||||||
econtext,
|
econtext,
|
||||||
isNull);
|
isNull);
|
||||||
break;
|
break;
|
||||||
@ -1883,7 +1883,7 @@ ExecEvalExprSwitchContext(ExprState *expression,
|
|||||||
* executions of the expression are needed. Typically the context will be
|
* executions of the expression are needed. Typically the context will be
|
||||||
* the same as the per-query context of the associated ExprContext.
|
* 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
|
* of such nodes held by the parent PlanState. Otherwise, we do very little
|
||||||
* initialization here other than building the state-node tree. Any nontrivial
|
* initialization here other than building the state-node tree. Any nontrivial
|
||||||
* work associated with initializing runtime info for a node should happen
|
* work associated with initializing runtime info for a node should happen
|
||||||
@ -2003,31 +2003,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
|||||||
state = (ExprState *) bstate;
|
state = (ExprState *) bstate;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
{
|
{
|
||||||
/* Keep this in sync with ExecInitExprInitPlan, below */
|
/* Keep this in sync with ExecInitExprInitPlan, below */
|
||||||
SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
|
SubPlan *subplan = (SubPlan *) node;
|
||||||
SubLink *sublink = subplanexpr->sublink;
|
SubPlanState *sstate = makeNode(SubPlanState);
|
||||||
SubPlanExprState *sstate = makeNode(SubPlanExprState);
|
|
||||||
|
|
||||||
Assert(IsA(sublink, SubLink));
|
|
||||||
if (!parent)
|
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. The subplans will be initialized later.
|
||||||
*/
|
*/
|
||||||
parent->subPlan = lcons(sstate, parent->subPlan);
|
parent->subPlan = lcons(sstate, parent->subPlan);
|
||||||
sstate->planstate = NULL;
|
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 *)
|
sstate->oper = (List *)
|
||||||
ExecInitExpr((Expr *) sublink->oper, parent);
|
ExecInitExpr((Expr *) subplan->oper, parent);
|
||||||
|
sstate->args = (List *)
|
||||||
|
ExecInitExpr((Expr *) subplan->args, parent);
|
||||||
|
|
||||||
state = (ExprState *) sstate;
|
state = (ExprState *) sstate;
|
||||||
}
|
}
|
||||||
@ -2145,26 +2140,20 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
|||||||
* subplan expr, except we do NOT want to add the node to the parent's
|
* subplan expr, except we do NOT want to add the node to the parent's
|
||||||
* subplan list.
|
* subplan list.
|
||||||
*/
|
*/
|
||||||
SubPlanExprState *
|
SubPlanState *
|
||||||
ExecInitExprInitPlan(SubPlanExpr *node, PlanState *parent)
|
ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
|
||||||
{
|
{
|
||||||
SubLink *sublink = node->sublink;
|
SubPlanState *sstate = makeNode(SubPlanState);
|
||||||
SubPlanExprState *sstate = makeNode(SubPlanExprState);
|
|
||||||
|
|
||||||
Assert(IsA(sublink, SubLink));
|
|
||||||
if (!parent)
|
if (!parent)
|
||||||
elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
|
elog(ERROR, "ExecInitExpr: SubPlan not expected here");
|
||||||
|
|
||||||
/* The subplan's state will be initialized later */
|
/* The subplan's state will be initialized later */
|
||||||
sstate->planstate = NULL;
|
sstate->planstate = NULL;
|
||||||
|
|
||||||
|
sstate->oper = (List *) ExecInitExpr((Expr *) node->oper, parent);
|
||||||
sstate->args = (List *) ExecInitExpr((Expr *) node->args, 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;
|
sstate->xprstate.expr = (Expr *) node;
|
||||||
|
|
||||||
return sstate;
|
return sstate;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -30,15 +30,14 @@
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
ExecSubPlan(SubPlanExprState *node,
|
ExecSubPlan(SubPlanState *node,
|
||||||
ExprContext *econtext,
|
ExprContext *econtext,
|
||||||
bool *isNull)
|
bool *isNull)
|
||||||
{
|
{
|
||||||
|
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
|
||||||
PlanState *planstate = node->planstate;
|
PlanState *planstate = node->planstate;
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
|
SubLinkType subLinkType = subplan->subLinkType;
|
||||||
SubLink *sublink = subplan->sublink;
|
bool useor = subplan->useor;
|
||||||
SubLinkType subLinkType = sublink->subLinkType;
|
|
||||||
bool useor = sublink->useor;
|
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
Datum result;
|
Datum result;
|
||||||
@ -292,56 +291,56 @@ ExecSubPlan(SubPlanExprState *node,
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
EState *sp_estate;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do access checking on the rangetable entries in the subquery.
|
* Do access checking on the rangetable entries in the subquery.
|
||||||
* Here, we assume the subquery is a SELECT.
|
* Here, we assume the subquery is a SELECT.
|
||||||
*/
|
*/
|
||||||
ExecCheckRTPerms(expr->rtable, CMD_SELECT);
|
ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize state
|
* initialize state
|
||||||
*/
|
*/
|
||||||
sstate->needShutdown = false;
|
node->needShutdown = false;
|
||||||
sstate->curTuple = NULL;
|
node->curTuple = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create an EState for the subplan
|
* create an EState for the subplan
|
||||||
*/
|
*/
|
||||||
sp_estate = CreateExecutorState();
|
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_list_info = estate->es_param_list_info;
|
||||||
sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
|
sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
|
||||||
sp_estate->es_tupleTable =
|
sp_estate->es_tupleTable =
|
||||||
ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10);
|
ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
|
||||||
sp_estate->es_snapshot = estate->es_snapshot;
|
sp_estate->es_snapshot = estate->es_snapshot;
|
||||||
sp_estate->es_instrument = estate->es_instrument;
|
sp_estate->es_instrument = estate->es_instrument;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start up the subplan
|
* 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
|
* If this plan is un-correlated or undirect correlated one and want
|
||||||
* to set params for parent plan then prepare parameters.
|
* to set params for parent plan then prepare parameters.
|
||||||
*/
|
*/
|
||||||
if (expr->setParam != NIL)
|
if (subplan->setParam != NIL)
|
||||||
{
|
{
|
||||||
List *lst;
|
List *lst;
|
||||||
|
|
||||||
foreach(lst, expr->setParam)
|
foreach(lst, subplan->setParam)
|
||||||
{
|
{
|
||||||
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
|
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
|
||||||
|
|
||||||
prm->execPlan = sstate;
|
prm->execPlan = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -366,11 +365,11 @@ ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
|
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
|
||||||
{
|
{
|
||||||
|
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
|
||||||
PlanState *planstate = node->planstate;
|
PlanState *planstate = node->planstate;
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
|
SubLinkType subLinkType = subplan->subLinkType;
|
||||||
SubLinkType subLinkType = subplan->sublink->subLinkType;
|
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
List *lst;
|
List *lst;
|
||||||
@ -473,7 +472,7 @@ ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecEndSubPlan(SubPlanExprState *node)
|
ExecEndSubPlan(SubPlanState *node)
|
||||||
{
|
{
|
||||||
if (node->needShutdown)
|
if (node->needShutdown)
|
||||||
{
|
{
|
||||||
@ -488,10 +487,10 @@ ExecEndSubPlan(SubPlanExprState *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent)
|
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
|
||||||
{
|
{
|
||||||
PlanState *planstate = node->planstate;
|
PlanState *planstate = node->planstate;
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
|
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
|
||||||
EState *estate = parent->state;
|
EState *estate = parent->state;
|
||||||
List *lst;
|
List *lst;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -818,21 +818,22 @@ _copySubLink(SubLink *from)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _copySubPlanExpr
|
* _copySubPlan
|
||||||
*/
|
*/
|
||||||
static SubPlanExpr *
|
static SubPlan *
|
||||||
_copySubPlanExpr(SubPlanExpr *from)
|
_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_NODE_FIELD(plan);
|
||||||
COPY_SCALAR_FIELD(plan_id);
|
COPY_SCALAR_FIELD(plan_id);
|
||||||
COPY_NODE_FIELD(rtable);
|
COPY_NODE_FIELD(rtable);
|
||||||
COPY_INTLIST_FIELD(setParam);
|
COPY_INTLIST_FIELD(setParam);
|
||||||
COPY_INTLIST_FIELD(parParam);
|
COPY_INTLIST_FIELD(parParam);
|
||||||
COPY_NODE_FIELD(args);
|
COPY_NODE_FIELD(args);
|
||||||
COPY_NODE_FIELD(sublink);
|
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
@ -2431,8 +2432,8 @@ copyObject(void *from)
|
|||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
retval = _copySubLink(from);
|
retval = _copySubLink(from);
|
||||||
break;
|
break;
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
retval = _copySubPlanExpr(from);
|
retval = _copySubPlan(from);
|
||||||
break;
|
break;
|
||||||
case T_FieldSelect:
|
case T_FieldSelect:
|
||||||
retval = _copyFieldSelect(from);
|
retval = _copyFieldSelect(from);
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -296,16 +296,17 @@ _equalSubLink(SubLink *a, SubLink *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 */
|
/* should compare plans, but have to settle for comparing plan IDs */
|
||||||
COMPARE_SCALAR_FIELD(plan_id);
|
COMPARE_SCALAR_FIELD(plan_id);
|
||||||
COMPARE_NODE_FIELD(rtable);
|
COMPARE_NODE_FIELD(rtable);
|
||||||
COMPARE_INTLIST_FIELD(setParam);
|
COMPARE_INTLIST_FIELD(setParam);
|
||||||
COMPARE_INTLIST_FIELD(parParam);
|
COMPARE_INTLIST_FIELD(parParam);
|
||||||
COMPARE_NODE_FIELD(args);
|
COMPARE_NODE_FIELD(args);
|
||||||
COMPARE_NODE_FIELD(sublink);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1561,8 +1562,8 @@ equal(void *a, void *b)
|
|||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
retval = _equalSubLink(a, b);
|
retval = _equalSubLink(a, b);
|
||||||
break;
|
break;
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
retval = _equalSubPlanExpr(a, b);
|
retval = _equalSubPlan(a, b);
|
||||||
break;
|
break;
|
||||||
case T_FieldSelect:
|
case T_FieldSelect:
|
||||||
retval = _equalFieldSelect(a, b);
|
retval = _equalFieldSelect(a, b);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Every node type that can appear in stored rules' parsetrees *must*
|
* Every node type that can appear in stored rules' parsetrees *must*
|
||||||
@ -665,18 +665,19 @@ _outSubLink(StringInfo str, SubLink *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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_NODE_FIELD(plan);
|
||||||
WRITE_INT_FIELD(plan_id);
|
WRITE_INT_FIELD(plan_id);
|
||||||
WRITE_NODE_FIELD(rtable);
|
WRITE_NODE_FIELD(rtable);
|
||||||
WRITE_INTLIST_FIELD(setParam);
|
WRITE_INTLIST_FIELD(setParam);
|
||||||
WRITE_INTLIST_FIELD(parParam);
|
WRITE_INTLIST_FIELD(parParam);
|
||||||
WRITE_NODE_FIELD(args);
|
WRITE_NODE_FIELD(args);
|
||||||
WRITE_NODE_FIELD(sublink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1498,8 +1499,8 @@ _outNode(StringInfo str, void *obj)
|
|||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
_outSubLink(str, obj);
|
_outSubLink(str, obj);
|
||||||
break;
|
break;
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
_outSubPlanExpr(str, obj);
|
_outSubPlan(str, obj);
|
||||||
break;
|
break;
|
||||||
case T_FieldSelect:
|
case T_FieldSelect:
|
||||||
_outFieldSelect(str, obj);
|
_outFieldSelect(str, obj);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Path and Plan nodes do not have any readfuncs support, because we
|
* Path and Plan nodes do not have any readfuncs support, because we
|
||||||
@ -540,7 +540,7 @@ _readSubLink(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _readSubPlanExpr is not needed since it doesn't appear in stored rules.
|
* _readSubPlan is not needed since it doesn't appear in stored rules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1234,7 +1234,7 @@ cost_qual_eval_walker(Node *node, Cost *total)
|
|||||||
IsA(node, OpExpr) ||
|
IsA(node, OpExpr) ||
|
||||||
IsA(node, DistinctExpr))
|
IsA(node, DistinctExpr))
|
||||||
*total += cpu_operator_cost;
|
*total += cpu_operator_cost;
|
||||||
else if (IsA(node, SubPlanExpr))
|
else if (IsA(node, SubPlan))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* A subplan node in an expression indicates that the
|
* A subplan node in an expression indicates that the
|
||||||
@ -1246,18 +1246,18 @@ cost_qual_eval_walker(Node *node, Cost *total)
|
|||||||
* NOTE: this logic should agree with the estimates used by
|
* NOTE: this logic should agree with the estimates used by
|
||||||
* make_subplan() in plan/subselect.c.
|
* make_subplan() in plan/subselect.c.
|
||||||
*/
|
*/
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) node;
|
SubPlan *subplan = (SubPlan *) node;
|
||||||
Plan *plan = subplan->plan;
|
Plan *plan = subplan->plan;
|
||||||
Cost subcost;
|
Cost subcost;
|
||||||
|
|
||||||
if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
|
if (subplan->subLinkType == EXISTS_SUBLINK)
|
||||||
{
|
{
|
||||||
/* we only need to fetch 1 tuple */
|
/* we only need to fetch 1 tuple */
|
||||||
subcost = plan->startup_cost +
|
subcost = plan->startup_cost +
|
||||||
(plan->total_cost - plan->startup_cost) / plan->plan_rows;
|
(plan->total_cost - plan->startup_cost) / plan->plan_rows;
|
||||||
}
|
}
|
||||||
else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
|
else if (subplan->subLinkType == ALL_SUBLINK ||
|
||||||
subplan->sublink->subLinkType == ANY_SUBLINK)
|
subplan->subLinkType == ANY_SUBLINK)
|
||||||
{
|
{
|
||||||
/* assume we need 50% of the tuples */
|
/* assume we need 50% of the tuples */
|
||||||
subcost = plan->startup_cost +
|
subcost = plan->startup_cost +
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -91,7 +91,7 @@ planner(Query *parse)
|
|||||||
* purpose is communication across multiple sub-Queries.
|
* purpose is communication across multiple sub-Queries.
|
||||||
*
|
*
|
||||||
* Note we do NOT save and restore PlannerPlanId: it exists to assign
|
* 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
|
* the life of a backend. Also, PlannerInitPlan is saved/restored in
|
||||||
* subquery_planner, not here.
|
* subquery_planner, not here.
|
||||||
*/
|
*/
|
||||||
@ -278,7 +278,7 @@ subquery_planner(Query *parse, double tuple_fraction)
|
|||||||
/* Must add the initPlans' extParams to the topmost node's, too */
|
/* Must add the initPlans' extParams to the topmost node's, too */
|
||||||
foreach(lst, plan->initPlan)
|
foreach(lst, plan->initPlan)
|
||||||
{
|
{
|
||||||
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
|
SubPlan *subplan = (SubPlan *) lfirst(lst);
|
||||||
|
|
||||||
plan->extParam = set_unioni(plan->extParam,
|
plan->extParam = set_unioni(plan->extParam,
|
||||||
subplan->plan->extParam);
|
subplan->plan->extParam);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -219,7 +219,7 @@ set_plan_references(Plan *plan, List *rtable)
|
|||||||
* subplan references in this plan's tlist and quals. If we did the
|
* subplan references in this plan's tlist and quals. If we did the
|
||||||
* reference-adjustments bottom-up, then we would fail to match this
|
* reference-adjustments bottom-up, then we would fail to match this
|
||||||
* plan's var nodes against the already-modified nodes of the
|
* 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.
|
* nodes; else we'd need two passes over the expression trees.
|
||||||
*/
|
*/
|
||||||
set_plan_references(plan->lefttree, rtable);
|
set_plan_references(plan->lefttree, rtable);
|
||||||
@ -227,9 +227,9 @@ set_plan_references(Plan *plan, List *rtable)
|
|||||||
|
|
||||||
foreach(pl, plan->initPlan)
|
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_plan_references(sp->plan, sp->rtable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,9 +259,9 @@ fix_expr_references_walker(Node *node, void *context)
|
|||||||
set_opfuncid((OpExpr *) node);
|
set_opfuncid((OpExpr *) node);
|
||||||
else if (IsA(node, DistinctExpr))
|
else if (IsA(node, DistinctExpr))
|
||||||
set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
|
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);
|
set_plan_references(sp->plan, sp->rtable);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,8 +53,17 @@ int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static void convert_sublink_opers(SubLink *slink, List *targetlist,
|
typedef struct finalize_primnode_results
|
||||||
List **setParams);
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -144,29 +153,27 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 *
|
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);
|
Query *subquery = (Query *) (slink->subselect);
|
||||||
Oid result_type = exprType((Node *) slink);
|
|
||||||
double tuple_fraction;
|
double tuple_fraction;
|
||||||
Plan *plan;
|
Plan *plan;
|
||||||
List *lst;
|
List *lst;
|
||||||
Node *result;
|
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
|
* Copy the source Query node. This is a quick and dirty kluge to
|
||||||
* resolve the fact that the parser can generate trees with multiple
|
* resolve the fact that the parser can generate trees with multiple
|
||||||
@ -210,14 +217,19 @@ make_subplan(SubLink *slink)
|
|||||||
node->plan = plan = subquery_planner(subquery, tuple_fraction);
|
node->plan = plan = subquery_planner(subquery, tuple_fraction);
|
||||||
|
|
||||||
node->plan_id = PlannerPlanId++; /* Assign unique ID to this
|
node->plan_id = PlannerPlanId++; /* Assign unique ID to this
|
||||||
* SubPlanExpr */
|
* SubPlan */
|
||||||
|
|
||||||
node->rtable = subquery->rtable;
|
node->rtable = subquery->rtable;
|
||||||
node->sublink = slink;
|
|
||||||
|
|
||||||
node->typeOid = result_type;
|
/*
|
||||||
|
* Fill in other fields of the SubPlan node.
|
||||||
slink->subselect = NULL; /* cool ?! see error check above! */
|
*/
|
||||||
|
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
|
* Make parParam list of params that current query level will pass to
|
||||||
@ -262,17 +274,23 @@ make_subplan(SubLink *slink)
|
|||||||
}
|
}
|
||||||
else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
|
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);
|
PlannerInitPlan = lappend(PlannerInitPlan, node);
|
||||||
if (length(slink->oper) > 1)
|
if (length(oper) > 1)
|
||||||
result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
|
result = (Node *) (node->useor ? make_orclause(oper) :
|
||||||
make_andclause(slink->oper));
|
make_andclause(oper));
|
||||||
else
|
else
|
||||||
result = (Node *) lfirst(slink->oper);
|
result = (Node *) lfirst(oper);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List *args = NIL;
|
List *args;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
|
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
|
||||||
@ -347,12 +365,16 @@ make_subplan(SubLink *slink)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix the SubLink's oper list */
|
/* Convert the SubLink's oper list into executable form */
|
||||||
convert_sublink_opers(slink, plan->targetlist, NULL);
|
node->oper = convert_sublink_opers(slink->oper,
|
||||||
|
lefthand,
|
||||||
|
plan->targetlist,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make node->args from parParam.
|
* Make node->args from parParam.
|
||||||
*/
|
*/
|
||||||
|
args = NIL;
|
||||||
foreach(lst, node->parParam)
|
foreach(lst, node->parParam)
|
||||||
{
|
{
|
||||||
Var *var = nth(lfirsti(lst), PlannerParamVar);
|
Var *var = nth(lfirsti(lst), PlannerParamVar);
|
||||||
@ -379,27 +401,26 @@ make_subplan(SubLink *slink)
|
|||||||
* convert_sublink_opers: convert a SubLink's oper list from the
|
* convert_sublink_opers: convert a SubLink's oper list from the
|
||||||
* parser/rewriter format into the executor's format.
|
* parser/rewriter format into the executor's format.
|
||||||
*
|
*
|
||||||
* The oper list is initially just a list of OpExpr nodes. We replace it
|
* The oper list is initially a list of OpExpr nodes with NIL args. We
|
||||||
* with a list of actually executable expressions, in which the specified
|
* convert it to a list of actually executable expressions, in which the
|
||||||
* operators are applied to corresponding elements of the lefthand list
|
* specified operators are applied to corresponding elements of the
|
||||||
* and Params representing the results of the subplan. lefthand is then
|
* lefthand list and Params representing the results of the subplan.
|
||||||
* set to NIL.
|
|
||||||
*
|
*
|
||||||
* If setParams is not NULL, the paramids of the Params created are added
|
* If setParams is not NULL, the paramids of the Params created are added
|
||||||
* to the *setParams list.
|
* to the *setParams list.
|
||||||
*/
|
*/
|
||||||
static void
|
static List *
|
||||||
convert_sublink_opers(SubLink *slink, List *targetlist,
|
convert_sublink_opers(List *operlist, List *lefthand,
|
||||||
List **setParams)
|
List *targetlist, List **setParams)
|
||||||
{
|
{
|
||||||
List *newoper = NIL;
|
List *newoper = NIL;
|
||||||
List *leftlist = slink->lefthand;
|
List *leftlist = lefthand;
|
||||||
List *lst;
|
List *lst;
|
||||||
|
|
||||||
foreach(lst, slink->oper)
|
foreach(lst, operlist)
|
||||||
{
|
{
|
||||||
OpExpr *oper = (OpExpr *) lfirst(lst);
|
OpExpr *oper = (OpExpr *) lfirst(lst);
|
||||||
Node *lefthand = lfirst(leftlist);
|
Node *leftop = lfirst(leftlist);
|
||||||
TargetEntry *te = lfirst(targetlist);
|
TargetEntry *te = lfirst(targetlist);
|
||||||
Param *prm;
|
Param *prm;
|
||||||
Operator tup;
|
Operator tup;
|
||||||
@ -430,7 +451,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
|
|||||||
* Note: we use make_operand in case runtime type conversion
|
* Note: we use make_operand in case runtime type conversion
|
||||||
* function calls must be inserted for this operator!
|
* 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);
|
right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
|
||||||
newoper = lappend(newoper,
|
newoper = lappend(newoper,
|
||||||
make_opclause(oper->opno,
|
make_opclause(oper->opno,
|
||||||
@ -445,65 +466,12 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
|
|||||||
targetlist = lnext(targetlist);
|
targetlist = lnext(targetlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
slink->oper = newoper;
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace correlation vars (uplevel vars) with Params.
|
* Replace correlation vars (uplevel vars) with Params.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static Node *replace_correlation_vars_mutator(Node *node, void *context);
|
|
||||||
|
|
||||||
Node *
|
Node *
|
||||||
SS_replace_correlation_vars(Node *expr)
|
SS_replace_correlation_vars(Node *expr)
|
||||||
{
|
{
|
||||||
@ -529,9 +497,6 @@ replace_correlation_vars_mutator(Node *node, void *context)
|
|||||||
/*
|
/*
|
||||||
* Expand SubLinks to SubPlans in the given expression.
|
* Expand SubLinks to SubPlans in the given expression.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static Node *process_sublinks_mutator(Node *node, void *context);
|
|
||||||
|
|
||||||
Node *
|
Node *
|
||||||
SS_process_sublinks(Node *expr)
|
SS_process_sublinks(Node *expr)
|
||||||
{
|
{
|
||||||
@ -547,20 +512,21 @@ process_sublinks_mutator(Node *node, void *context)
|
|||||||
if (IsA(node, SubLink))
|
if (IsA(node, SubLink))
|
||||||
{
|
{
|
||||||
SubLink *sublink = (SubLink *) node;
|
SubLink *sublink = (SubLink *) node;
|
||||||
|
List *lefthand;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, scan the lefthand-side expressions, if any. This is a
|
* First, recursively process the lefthand-side expressions, if any.
|
||||||
* tad klugy since we modify the input SubLink node, but that
|
|
||||||
* should be OK (make_subplan does it too!)
|
|
||||||
*/
|
*/
|
||||||
sublink->lefthand = (List *)
|
lefthand = (List *)
|
||||||
process_sublinks_mutator((Node *) sublink->lefthand, context);
|
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
|
* (since this is the very routine that creates 'em to begin with). So
|
||||||
* the code in expression_tree_mutator() that might do inappropriate
|
* the code in expression_tree_mutator() that might do inappropriate
|
||||||
* things with SubPlans or SubLinks will not be exercised.
|
* things with SubPlans or SubLinks will not be exercised.
|
||||||
@ -572,6 +538,12 @@ process_sublinks_mutator(Node *node, void *context)
|
|||||||
context);
|
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 *
|
List *
|
||||||
SS_finalize_plan(Plan *plan, List *rtable)
|
SS_finalize_plan(Plan *plan, List *rtable)
|
||||||
{
|
{
|
||||||
@ -721,3 +693,46 @@ SS_finalize_plan(Plan *plan, List *rtable)
|
|||||||
|
|
||||||
return results.paramids;
|
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);
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -872,13 +872,13 @@ adjust_inherited_attrs_mutator(Node *node,
|
|||||||
*/
|
*/
|
||||||
if (is_subplan(node))
|
if (is_subplan(node))
|
||||||
{
|
{
|
||||||
SubPlanExpr *subplan;
|
SubPlan *subplan;
|
||||||
|
|
||||||
/* Copy the node and process subplan args */
|
/* Copy the node and process subplan args */
|
||||||
node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
|
node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
|
||||||
(void *) context);
|
(void *) context);
|
||||||
/* Make sure we have separate copies of subplan and its rtable */
|
/* Make sure we have separate copies of subplan and its rtable */
|
||||||
subplan = (SubPlanExpr *) node;
|
subplan = (SubPlan *) node;
|
||||||
subplan->plan = copyObject(subplan->plan);
|
subplan->plan = copyObject(subplan->plan);
|
||||||
subplan->rtable = copyObject(subplan->rtable);
|
subplan->rtable = copyObject(subplan->rtable);
|
||||||
return node;
|
return node;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -486,7 +486,7 @@ expression_returns_set_walker(Node *node, void *context)
|
|||||||
return false;
|
return false;
|
||||||
if (IsA(node, SubLink))
|
if (IsA(node, SubLink))
|
||||||
return false;
|
return false;
|
||||||
if (IsA(node, SubPlanExpr))
|
if (IsA(node, SubPlan))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return expression_tree_walker(node, expression_returns_set_walker,
|
return expression_tree_walker(node, expression_returns_set_walker,
|
||||||
@ -519,7 +519,7 @@ contain_subplans_walker(Node *node, void *context)
|
|||||||
{
|
{
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (IsA(node, SubPlanExpr) ||
|
if (IsA(node, SubPlan) ||
|
||||||
IsA(node, SubLink))
|
IsA(node, SubLink))
|
||||||
return true; /* abort the tree traversal and return
|
return true; /* abort the tree traversal and return
|
||||||
* true */
|
* true */
|
||||||
@ -530,7 +530,7 @@ contain_subplans_walker(Node *node, void *context)
|
|||||||
* pull_subplans
|
* pull_subplans
|
||||||
* Recursively pulls all subplans from an expression tree.
|
* 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.
|
* are not copied, only referenced.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
@ -656,7 +656,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
|
|||||||
*/
|
*/
|
||||||
List *t;
|
List *t;
|
||||||
|
|
||||||
foreach(t, ((SubPlanExpr *) node)->args)
|
foreach(t, ((SubPlan *) node)->args)
|
||||||
{
|
{
|
||||||
Node *thisarg = lfirst(t);
|
Node *thisarg = lfirst(t);
|
||||||
Var *var;
|
Var *var;
|
||||||
@ -1483,14 +1483,14 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
|
|||||||
break;
|
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.
|
* with it.
|
||||||
*
|
*
|
||||||
* XXX should we elog() here instead? Probably this routine
|
* 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;
|
return node;
|
||||||
}
|
}
|
||||||
@ -2089,17 +2089,17 @@ substitute_actual_parameters_mutator(Node *node,
|
|||||||
* FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
|
* FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
|
||||||
* jointrees and setOperation trees can be processed without additional code.
|
* jointrees and setOperation trees can be processed without additional code.
|
||||||
*
|
*
|
||||||
* expression_tree_walker will handle SubLink and SubPlanExpr nodes by
|
* expression_tree_walker will handle SubLink nodes by recursing normally into
|
||||||
* recursing normally into the "lefthand" arguments (which are expressions
|
* the "lefthand" arguments (which are expressions belonging to the outer
|
||||||
* belonging to the outer plan). It will also call the walker on the
|
* plan). It will also call the walker on the sub-Query node; however, when
|
||||||
* sub-Query node; however, when expression_tree_walker itself is called on a
|
* expression_tree_walker itself is called on a Query node, it does nothing
|
||||||
* Query node, it does nothing and returns "false". The net effect is that
|
* and returns "false". The net effect is that unless the walker does
|
||||||
* unless the walker does something special at a Query node, sub-selects will
|
* something special at a Query node, sub-selects will not be visited during
|
||||||
* not be visited during an expression tree walk. This is exactly the behavior
|
* an expression tree walk. This is exactly the behavior wanted in many cases
|
||||||
* wanted in many cases --- and for those walkers that do want to recurse into
|
* --- and for those walkers that do want to recurse into sub-selects, special
|
||||||
* sub-selects, special behavior is typically needed anyway at the entry to a
|
* behavior is typically needed anyway at the entry to a sub-select (such as
|
||||||
* sub-select (such as incrementing a depth counter). A walker that wants to
|
* incrementing a depth counter). A walker that wants to examine sub-selects
|
||||||
* examine sub-selects should include code along the lines of:
|
* should include code along the lines of:
|
||||||
*
|
*
|
||||||
* if (IsA(node, Query))
|
* if (IsA(node, Query))
|
||||||
* {
|
* {
|
||||||
@ -2113,10 +2113,12 @@ substitute_actual_parameters_mutator(Node *node,
|
|||||||
* query_tree_walker is a convenience routine (see below) that calls the
|
* query_tree_walker is a convenience routine (see below) that calls the
|
||||||
* walker on all the expression subtrees of the given Query node.
|
* walker on all the expression subtrees of the given Query node.
|
||||||
*
|
*
|
||||||
* NOTE: currently, because make_subplan() clears the subselect link in
|
* expression_tree_walker will handle SubPlan nodes by recursing normally
|
||||||
* a SubLink node, it is not actually possible to recurse into subselects
|
* into the "oper" and "args" lists (which are expressions belonging to the
|
||||||
* of an already-planned expression tree. This is OK for current uses,
|
* outer plan). It will not touch the completed subplan, however. Since
|
||||||
* but ought to be cleaned up when we redesign querytree processing.
|
* 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.
|
||||||
*--------------------
|
*--------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2207,24 +2209,13 @@ expression_tree_walker(Node *node,
|
|||||||
SubLink *sublink = (SubLink *) node;
|
SubLink *sublink = (SubLink *) node;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the SubLink has already been processed by
|
* We only recurse into the lefthand list (the incomplete
|
||||||
* subselect.c, it will have lefthand=NIL, and we need to
|
* OpExpr nodes in the oper list are deemed uninteresting,
|
||||||
* scan the oper list. Otherwise we only need to look at
|
* perhaps even confusing).
|
||||||
* the lefthand list (the incomplete OpExpr nodes in the
|
|
||||||
* oper list are deemed uninteresting, perhaps even
|
|
||||||
* confusing).
|
|
||||||
*/
|
*/
|
||||||
if (sublink->lefthand)
|
if (expression_tree_walker((Node *) sublink->lefthand,
|
||||||
{
|
walker, context))
|
||||||
if (walker((Node *) sublink->lefthand, context))
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (walker((Node *) sublink->oper, context))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Also invoke the walker on the sublink's Query node, so
|
* Also invoke the walker on the sublink's Query node, so
|
||||||
* it can recurse into the sub-query if it wants to.
|
* it can recurse into the sub-query if it wants to.
|
||||||
@ -2232,15 +2223,16 @@ expression_tree_walker(Node *node,
|
|||||||
return walker(sublink->subselect, context);
|
return walker(sublink->subselect, context);
|
||||||
}
|
}
|
||||||
break;
|
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 */
|
/* recurse into the oper list, but not into the Plan */
|
||||||
if (walker((Node *) expr->sublink, context))
|
if (expression_tree_walker((Node *) subplan->oper,
|
||||||
|
walker, context))
|
||||||
return true;
|
return true;
|
||||||
/* also examine args list */
|
/* also examine args list */
|
||||||
if (expression_tree_walker((Node *) expr->args,
|
if (expression_tree_walker((Node *) subplan->args,
|
||||||
walker, context))
|
walker, context))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2442,18 +2434,17 @@ query_tree_walker(Query *query,
|
|||||||
* expression_tree_mutator include all those normally found in target lists
|
* expression_tree_mutator include all those normally found in target lists
|
||||||
* and qualifier clauses during the planning stage.
|
* and qualifier clauses during the planning stage.
|
||||||
*
|
*
|
||||||
* expression_tree_mutator will handle a SubPlanExpr node by recursing into
|
* expression_tree_mutator will handle a SubPlan node by recursing into
|
||||||
* the args and sublink->oper lists (which belong to the outer plan), but it
|
* 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
|
* 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
|
* 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.
|
* and doing the right thing.
|
||||||
*
|
*
|
||||||
* Bare SubLink nodes (without a SubPlanExpr) are handled by recursing into
|
* SubLink nodes are handled by recursing into the "lefthand" argument list
|
||||||
* the "lefthand" argument list only. (A bare SubLink should be seen only if
|
* only. (A SubLink will be seen only if the tree has not yet been
|
||||||
* the tree has not yet been processed by subselect.c.) Again, this can be
|
* processed by subselect.c.) Again, this can be overridden by the mutator,
|
||||||
* overridden by the mutator, but it seems to be the most useful default
|
* but it seems to be the most useful default behavior.
|
||||||
* behavior.
|
|
||||||
*--------------------
|
*--------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2560,9 +2551,8 @@ expression_tree_mutator(Node *node,
|
|||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* A "bare" SubLink (note we will not come here if we
|
* We transform the lefthand side, but not the oper list nor
|
||||||
* found a SubPlanExpr node above it). Transform the
|
* the subquery.
|
||||||
* lefthand side, but not the oper list nor the subquery.
|
|
||||||
*/
|
*/
|
||||||
SubLink *sublink = (SubLink *) node;
|
SubLink *sublink = (SubLink *) node;
|
||||||
SubLink *newnode;
|
SubLink *newnode;
|
||||||
@ -2572,20 +2562,17 @@ expression_tree_mutator(Node *node,
|
|||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
{
|
{
|
||||||
SubPlanExpr *expr = (SubPlanExpr *) node;
|
SubPlan *subplan = (SubPlan *) node;
|
||||||
SubLink *oldsublink = expr->sublink;
|
SubPlan *newnode;
|
||||||
SubPlanExpr *newnode;
|
|
||||||
|
|
||||||
FLATCOPY(newnode, expr, SubPlanExpr);
|
FLATCOPY(newnode, subplan, SubPlan);
|
||||||
/* flat-copy the SubLink node */
|
|
||||||
CHECKFLATCOPY(newnode->sublink, oldsublink, SubLink);
|
|
||||||
/* transform args list (params to be passed to subplan) */
|
/* transform args list (params to be passed to subplan) */
|
||||||
MUTATE(newnode->args, expr->args, List *);
|
MUTATE(newnode->args, subplan->args, List *);
|
||||||
/* transform sublink's oper list as well */
|
/* transform oper list as well */
|
||||||
MUTATE(newnode->sublink->oper, oldsublink->oper, List *);
|
MUTATE(newnode->oper, subplan->oper, List *);
|
||||||
/* but not the subplan itself, which is referenced as-is */
|
/* but not the sub-Plan itself, which is referenced as-is */
|
||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -65,7 +65,7 @@ static Node *flatten_join_alias_vars_mutator(Node *node,
|
|||||||
* NOTE: this is used on not-yet-planned expressions. It may therefore find
|
* 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
|
* 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
|
* 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 *
|
List *
|
||||||
pull_varnos(Node *node)
|
pull_varnos(Node *node)
|
||||||
@ -111,9 +111,9 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
|||||||
* executed by the outer query. But short-circuit recursion into
|
* executed by the outer query. But short-circuit recursion into
|
||||||
* the subquery itself, which would be a waste of effort.
|
* 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))
|
context))
|
||||||
return true;
|
return true;
|
||||||
if (pull_varnos_walker((Node *) subplan->args,
|
if (pull_varnos_walker((Node *) subplan->args,
|
||||||
@ -146,7 +146,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
|||||||
* NOTE: this is used on not-yet-planned expressions. It may therefore find
|
* 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
|
* 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
|
* 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
|
bool
|
||||||
contain_var_reference(Node *node, int varno, int varattno, int levelsup)
|
contain_var_reference(Node *node, int varno, int varattno, int levelsup)
|
||||||
@ -194,9 +194,9 @@ contain_var_reference_walker(Node *node,
|
|||||||
* executed by the outer query. But short-circuit recursion into
|
* executed by the outer query. But short-circuit recursion into
|
||||||
* the subquery itself, which would be a waste of effort.
|
* 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))
|
context))
|
||||||
return true;
|
return true;
|
||||||
if (contain_var_reference_walker((Node *) subplan->args,
|
if (contain_var_reference_walker((Node *) subplan->args,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -2099,7 +2099,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||||||
get_sublink_expr((SubLink *) node, context);
|
get_sublink_expr((SubLink *) node, context);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_SubPlanExpr:
|
case T_SubPlan:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We cannot see an already-planned subplan in
|
* We cannot see an already-planned subplan in
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -92,8 +92,7 @@ extern Datum ExecEvalExpr(ExprState *expression, ExprContext *econtext,
|
|||||||
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
|
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
|
||||||
bool *isNull, ExprDoneCond *isDone);
|
bool *isNull, ExprDoneCond *isDone);
|
||||||
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
|
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
|
||||||
extern SubPlanExprState *ExecInitExprInitPlan(SubPlanExpr *node,
|
extern SubPlanState *ExecInitExprInitPlan(SubPlan *node, PlanState *parent);
|
||||||
PlanState *parent);
|
|
||||||
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
|
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
|
||||||
extern int ExecTargetListLength(List *targetlist);
|
extern int ExecTargetListLength(List *targetlist);
|
||||||
extern int ExecCleanTargetListLength(List *targetlist);
|
extern int ExecCleanTargetListLength(List *targetlist);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
#include "nodes/execnodes.h"
|
#include "nodes/execnodes.h"
|
||||||
|
|
||||||
extern void ExecInitSubPlan(SubPlanExprState *sstate, EState *estate);
|
extern void ExecInitSubPlan(SubPlanState *node, EState *estate);
|
||||||
extern Datum ExecSubPlan(SubPlanExprState *node,
|
extern Datum ExecSubPlan(SubPlanState *node,
|
||||||
ExprContext *econtext,
|
ExprContext *econtext,
|
||||||
bool *isNull);
|
bool *isNull);
|
||||||
extern void ExecEndSubPlan(SubPlanExprState *node);
|
extern void ExecEndSubPlan(SubPlanState *node);
|
||||||
extern void ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent);
|
extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
|
||||||
|
|
||||||
extern void ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext);
|
extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
|
||||||
|
|
||||||
#endif /* NODESUBPLAN_H */
|
#endif /* NODESUBPLAN_H */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -451,21 +451,18 @@ typedef struct BoolExprState
|
|||||||
} BoolExprState;
|
} BoolExprState;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* SubPlanExprState node
|
* SubPlanState 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.
|
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
typedef struct SubPlanExprState
|
typedef struct SubPlanState
|
||||||
{
|
{
|
||||||
ExprState xprstate;
|
ExprState xprstate;
|
||||||
struct PlanState *planstate; /* subselect plan's state tree */
|
struct PlanState *planstate; /* subselect plan's state tree */
|
||||||
bool needShutdown; /* TRUE = need to shutdown subplan */
|
bool needShutdown; /* TRUE = need to shutdown subplan */
|
||||||
HeapTuple curTuple; /* copy of most recent tuple from subplan */
|
HeapTuple curTuple; /* copy of most recent tuple from subplan */
|
||||||
List *args; /* states of argument expression(s) */
|
|
||||||
List *oper; /* states for executable combining exprs */
|
List *oper; /* states for executable combining exprs */
|
||||||
} SubPlanExprState;
|
List *args; /* states of argument expression(s) */
|
||||||
|
} SubPlanState;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* CaseExprState node
|
* CaseExprState node
|
||||||
@ -538,9 +535,9 @@ typedef struct PlanState
|
|||||||
List *qual; /* implicitly-ANDed qual conditions */
|
List *qual; /* implicitly-ANDed qual conditions */
|
||||||
struct PlanState *lefttree; /* input plan tree(s) */
|
struct PlanState *lefttree; /* input plan tree(s) */
|
||||||
struct PlanState *righttree;
|
struct PlanState *righttree;
|
||||||
List *initPlan; /* Init SubPlanExprState nodes (un-correlated
|
List *initPlan; /* Init SubPlanState nodes (un-correlated
|
||||||
* expr subselects) */
|
* expr subselects) */
|
||||||
List *subPlan; /* SubPlanExprState nodes in my expressions */
|
List *subPlan; /* SubPlanState nodes in my expressions */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* State for management of parameter-change-driven rescanning
|
* State for management of parameter-change-driven rescanning
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -107,7 +107,7 @@ typedef enum NodeTag
|
|||||||
T_DistinctExpr,
|
T_DistinctExpr,
|
||||||
T_BoolExpr,
|
T_BoolExpr,
|
||||||
T_SubLink,
|
T_SubLink,
|
||||||
T_SubPlanExpr,
|
T_SubPlan,
|
||||||
T_FieldSelect,
|
T_FieldSelect,
|
||||||
T_RelabelType,
|
T_RelabelType,
|
||||||
T_CaseExpr,
|
T_CaseExpr,
|
||||||
@ -133,7 +133,7 @@ typedef enum NodeTag
|
|||||||
T_ArrayRefExprState,
|
T_ArrayRefExprState,
|
||||||
T_FuncExprState,
|
T_FuncExprState,
|
||||||
T_BoolExprState,
|
T_BoolExprState,
|
||||||
T_SubPlanExprState,
|
T_SubPlanState,
|
||||||
T_CaseExprState,
|
T_CaseExprState,
|
||||||
T_CaseWhenState,
|
T_CaseWhenState,
|
||||||
T_ConstraintTestState,
|
T_ConstraintTestState,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -88,7 +88,7 @@ typedef ParamListInfoData *ParamListInfo;
|
|||||||
* array of ParamExecData records, which is referenced through
|
* array of ParamExecData records, which is referenced through
|
||||||
* es_param_exec_vals or ecxt_param_exec_vals.
|
* 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
|
* 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
|
* lazy evaluation of InitPlans: they aren't executed until/unless a
|
||||||
* result value is needed.) Otherwise the value is assumed to be valid
|
* result value is needed.) Otherwise the value is assumed to be valid
|
||||||
@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo;
|
|||||||
|
|
||||||
typedef struct ParamExecData
|
typedef struct ParamExecData
|
||||||
{
|
{
|
||||||
void *execPlan; /* should be "SubPlanExprState *" */
|
void *execPlan; /* should be "SubPlanState *" */
|
||||||
Datum value;
|
Datum value;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
} ParamExecData;
|
} ParamExecData;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -378,32 +378,21 @@ typedef struct BoolExpr
|
|||||||
* using AND and OR semantics respectively.
|
* using AND and OR semantics respectively.
|
||||||
*
|
*
|
||||||
* SubLink is classed as an Expr node, but it is not actually executable;
|
* 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.
|
* planning.
|
||||||
*
|
*
|
||||||
* NOTE: lefthand and oper have varying meanings depending on where you look
|
* NOTE: in the raw output of gram.y, lefthand contains a list of (raw)
|
||||||
* in the parse/plan pipeline:
|
* expressions, and oper contains a single A_Expr (not a list!) containing
|
||||||
* 1. gram.y delivers a list of the (untransformed) lefthand expressions in
|
* the string name of the operator, but no arguments. Also, subselect is
|
||||||
* lefthand, and sets oper to a single A_Expr (not a list!) containing
|
* a raw parsetree. During parse analysis, the parser transforms the
|
||||||
* the string name of the operator, but no arguments.
|
* lefthand expression list using normal expression transformation rules.
|
||||||
* 2. The parser's expression transformation transforms lefthand normally,
|
* It replaces oper with a list of OpExpr nodes, one per lefthand expression.
|
||||||
* and replaces oper with a list of OpExpr nodes, one per lefthand
|
* These nodes represent the parser's resolution of exactly which operator
|
||||||
* expression. These nodes represent the parser's resolution of exactly
|
* to apply to each pair of lefthand and targetlist expressions. However,
|
||||||
* which operator to apply to each pair of lefthand and targetlist
|
* we have not constructed complete Expr trees for these operations yet:
|
||||||
* expressions. However, we have not constructed complete Expr trees for
|
* the args fields of the OpExpr nodes are NIL. And subselect is transformed
|
||||||
* these operations yet: the args fields of the OpExpr nodes are NIL.
|
* to a Query. This is the representation seen in saved rules and in the
|
||||||
* This is the representation seen in saved rules and in the rewriter.
|
* 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.
|
|
||||||
*
|
*
|
||||||
* In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
|
* In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
|
||||||
* always NIL. useor is not significant either for these sublink types.
|
* always NIL. useor is not significant either for these sublink types.
|
||||||
@ -423,37 +412,58 @@ typedef struct SubLink
|
|||||||
* "OR" not "AND" */
|
* "OR" not "AND" */
|
||||||
List *lefthand; /* list of outer-query expressions on the
|
List *lefthand; /* list of outer-query expressions on the
|
||||||
* left */
|
* left */
|
||||||
List *oper; /* list of OpExpr nodes for combining
|
List *oper; /* list of arg-less OpExpr nodes for
|
||||||
* operators, or final list of executable
|
* combining operators */
|
||||||
* expressions */
|
|
||||||
Node *subselect; /* subselect as Query* or parsetree */
|
Node *subselect; /* subselect as Query* or parsetree */
|
||||||
} SubLink;
|
} SubLink;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SubPlanExpr - executable expression node for a subplan (sub-SELECT)
|
* SubPlan - executable expression node for a subplan (sub-SELECT)
|
||||||
*
|
*
|
||||||
* The planner replaces SubLink nodes in expression trees with SubPlanExpr
|
* The planner replaces SubLink nodes in expression trees with SubPlan
|
||||||
* nodes after it has finished planning the subquery. See notes above.
|
* 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 SubPlanExpr
|
typedef struct SubPlan
|
||||||
{
|
{
|
||||||
Expr xpr;
|
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 */
|
struct Plan *plan; /* subselect plan itself */
|
||||||
int plan_id; /* dummy thing because of we haven't equal
|
int plan_id; /* dummy thing because of we haven't equal
|
||||||
* funcs for plan nodes... actually, we
|
* funcs for plan nodes... actually, we
|
||||||
* could put *plan itself somewhere else
|
* could put *plan itself somewhere else
|
||||||
* (TopPlan node ?)... */
|
* (TopPlan node ?)... */
|
||||||
List *rtable; /* range table for subselect */
|
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) */
|
/* setParam and parParam are lists of integers (param IDs) */
|
||||||
List *setParam; /* non-correlated EXPR & EXISTS subqueries
|
List *setParam; /* non-correlated EXPR & EXISTS subqueries
|
||||||
* have to set some Params for paren Plan */
|
* have to set some Params for paren Plan */
|
||||||
List *parParam; /* indices of input Params from parent plan */
|
List *parParam; /* indices of input Params from parent plan */
|
||||||
List *args; /* exprs to pass as parParam values */
|
List *args; /* exprs to pass as parParam values */
|
||||||
SubLink *sublink; /* SubLink node from parser; holds info
|
} SubPlan;
|
||||||
* about what to do with subselect's
|
|
||||||
* results */
|
|
||||||
} SubPlanExpr;
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* FieldSelect
|
* FieldSelect
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr))
|
#define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr))
|
||||||
#define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr))
|
#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,
|
extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
|
||||||
|
Reference in New Issue
Block a user