mirror of https://github.com/postgres/postgres
ExecReScan for nodeAgg, nodeHash, nodeHashjoin, nodeNestloop and nodeResult. Fixed ExecReScan for nodeMaterial. Get rid of #ifdef INDEXSCAN_PATCH. Get rid of ExecMarkPos and ExecRestrPos in nodeNestloop.pull/50/head
parent
13637df458
commit
1a105cefbd
@ -0,0 +1,280 @@ |
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* |
||||||
|
* nodeSubplan.c-- |
||||||
|
* routines to support subselects |
||||||
|
* |
||||||
|
*------------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* INTERFACE ROUTINES |
||||||
|
* ExecSubPlan - process a subselect |
||||||
|
* ExecInitSubPlan - initialize a subselect |
||||||
|
* ExecEndSubPlan - shut down a subselect |
||||||
|
*/ |
||||||
|
#include "postgres.h" |
||||||
|
|
||||||
|
#include "access/heapam.h" |
||||||
|
#include "tcop/pquery.h" |
||||||
|
#include "executor/executor.h" |
||||||
|
#include "executor/execdebug.h" |
||||||
|
#include "executor/nodeSubplan.h" |
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* ExecSubPlan(node) |
||||||
|
* |
||||||
|
* ---------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext) |
||||||
|
{ |
||||||
|
Plan *plan = node->plan; |
||||||
|
SubLink *sublink = node->sublink; |
||||||
|
TupleTableSlot *slot; |
||||||
|
List *lst; |
||||||
|
bool result = false; |
||||||
|
bool found = false; |
||||||
|
|
||||||
|
if ( node->setParam != NULL ) |
||||||
|
elog (ERROR, "ExecSubPlan: can't set parent params from subquery"); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Set Params of this plan from parent plan correlation Vars |
||||||
|
*/ |
||||||
|
if ( node->parParam != NULL ) |
||||||
|
{ |
||||||
|
foreach (lst, node->parParam) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); |
||||||
|
|
||||||
|
prm->value = ExecEvalExpr ((Node*) lfirst(pvar),
|
||||||
|
econtext,
|
||||||
|
&(prm->isnull), NULL); |
||||||
|
pvar = lnext (pvar); |
||||||
|
} |
||||||
|
plan->chgParam = nconc (plan->chgParam, listCopy(node->parParam)); |
||||||
|
} |
||||||
|
|
||||||
|
ExecReScan (plan, (ExprContext*) NULL, plan); |
||||||
|
|
||||||
|
for (slot = ExecProcNode (plan, plan);
|
||||||
|
!TupIsNull(slot);
|
||||||
|
slot = ExecProcNode (plan, plan)) |
||||||
|
{ |
||||||
|
HeapTuple tup = slot->val; |
||||||
|
TupleDesc tdesc = slot->ttc_tupleDescriptor; |
||||||
|
int i = 1; |
||||||
|
|
||||||
|
if ( sublink->subLinkType == EXPR_SUBLINK && found ) |
||||||
|
{ |
||||||
|
elog (ERROR, "ExecSubPlan: more than one tuple returned by expression subselect"); |
||||||
|
return ((Datum) false); |
||||||
|
} |
||||||
|
|
||||||
|
if ( sublink->subLinkType == EXISTS_SUBLINK ) |
||||||
|
return ((Datum) true); |
||||||
|
|
||||||
|
found = true; |
||||||
|
|
||||||
|
foreach (lst, sublink->oper) |
||||||
|
{ |
||||||
|
Expr *expr = (Expr*) lfirst(lst); |
||||||
|
Const *con = lsecond(expr->args); |
||||||
|
bool isnull; |
||||||
|
|
||||||
|
con->constvalue = heap_getattr (tup, i, tdesc, &(con->constisnull)); |
||||||
|
result = (bool) ExecEvalExpr ((Node*) expr, econtext, &isnull, (bool*) NULL); |
||||||
|
if ( isnull ) |
||||||
|
result = false; |
||||||
|
if ( (!result && !(sublink->useor)) || (result && sublink->useor) ) |
||||||
|
break; |
||||||
|
i++; |
||||||
|
} |
||||||
|
|
||||||
|
if ( (!result && sublink->subLinkType == ALL_SUBLINK) || |
||||||
|
(result && sublink->subLinkType == ANY_SUBLINK) ) |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return ((Datum) result); |
||||||
|
} |
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* ExecInitSubPlan |
||||||
|
* |
||||||
|
* ---------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
bool |
||||||
|
ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) |
||||||
|
{ |
||||||
|
EState *sp_estate = CreateExecutorState (); |
||||||
|
|
||||||
|
sp_estate->es_range_table = node->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(node->plan) + 10); |
||||||
|
pfree (sp_estate->es_refcount); |
||||||
|
sp_estate->es_refcount = estate->es_refcount; |
||||||
|
|
||||||
|
if ( !ExecInitNode (node->plan, sp_estate, NULL) ) |
||||||
|
return (false); |
||||||
|
|
||||||
|
node->shutdown = true; |
||||||
|
|
||||||
|
/*
|
||||||
|
* If this plan is un-correlated or undirect correlated one and
|
||||||
|
* want to set params for parent plan then prepare parameters. |
||||||
|
*/ |
||||||
|
if ( node->setParam != NULL ) |
||||||
|
{ |
||||||
|
List *lst; |
||||||
|
|
||||||
|
foreach (lst, node->setParam) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); |
||||||
|
|
||||||
|
prm->execPlan = node; |
||||||
|
} |
||||||
|
/*
|
||||||
|
* Note that in the case of un-correlated subqueries we don't care |
||||||
|
* about setting parent->chgParam here: indices take care about it, |
||||||
|
* for others - it doesn't matter... |
||||||
|
*/ |
||||||
|
} |
||||||
|
|
||||||
|
return (true); |
||||||
|
} |
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* ExecSetParamPlan |
||||||
|
* |
||||||
|
* Executes plan of node and sets parameters. |
||||||
|
* ---------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
void |
||||||
|
ExecSetParamPlan (SubPlan *node) |
||||||
|
{ |
||||||
|
Plan *plan = node->plan; |
||||||
|
SubLink *sublink = node->sublink; |
||||||
|
TupleTableSlot *slot; |
||||||
|
List *lst; |
||||||
|
bool found = false; |
||||||
|
|
||||||
|
if ( sublink->subLinkType == ANY_SUBLINK || |
||||||
|
sublink->subLinkType == ALL_SUBLINK ) |
||||||
|
elog (ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported"); |
||||||
|
|
||||||
|
if ( plan->chgParam != NULL ) |
||||||
|
ExecReScan (plan, (ExprContext*) NULL, plan); |
||||||
|
|
||||||
|
for (slot = ExecProcNode (plan, plan);
|
||||||
|
!TupIsNull(slot);
|
||||||
|
slot = ExecProcNode (plan, plan)) |
||||||
|
{ |
||||||
|
HeapTuple tup = slot->val; |
||||||
|
TupleDesc tdesc = slot->ttc_tupleDescriptor; |
||||||
|
int i = 1; |
||||||
|
|
||||||
|
if ( sublink->subLinkType == EXPR_SUBLINK && found ) |
||||||
|
{ |
||||||
|
elog (ERROR, "ExecSetParamPlan: more than one tuple returned by expression subselect"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
found = true; |
||||||
|
|
||||||
|
if ( sublink->subLinkType == EXISTS_SUBLINK ) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); |
||||||
|
|
||||||
|
prm->execPlan = NULL; |
||||||
|
prm->value = (Datum) true; |
||||||
|
prm->isnull = false; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
foreach (lst, node->setParam) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); |
||||||
|
|
||||||
|
prm->execPlan = NULL; |
||||||
|
prm->value = heap_getattr (tup, i, tdesc, &(prm->isnull)); |
||||||
|
i++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ( !found ) |
||||||
|
{ |
||||||
|
if ( sublink->subLinkType == EXISTS_SUBLINK ) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); |
||||||
|
|
||||||
|
prm->execPlan = NULL; |
||||||
|
prm->value = (Datum) false; |
||||||
|
prm->isnull = false; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
foreach (lst, node->setParam) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); |
||||||
|
|
||||||
|
prm->execPlan = NULL; |
||||||
|
prm->value = (Datum) NULL; |
||||||
|
prm->isnull = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ( plan->extParam == NULL ) /* un-correlated ... */ |
||||||
|
{ |
||||||
|
ExecEndNode (plan, plan); |
||||||
|
node->shutdown = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* ExecEndSubPlan |
||||||
|
* ---------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
void |
||||||
|
ExecEndSubPlan(SubPlan *node) |
||||||
|
{ |
||||||
|
|
||||||
|
if ( node->shutdown ) |
||||||
|
{ |
||||||
|
ExecEndNode (node->plan, node->plan); |
||||||
|
node->shutdown = false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void
|
||||||
|
ExecReScanSetParamPlan (SubPlan *node, Plan *parent) |
||||||
|
{ |
||||||
|
Plan *plan = node->plan; |
||||||
|
List *lst; |
||||||
|
|
||||||
|
if ( node->parParam != NULL ) |
||||||
|
elog (ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet"); |
||||||
|
if ( node->setParam == NULL ) |
||||||
|
elog (ERROR, "ExecReScanSetParamPlan: setParam list is NULL"); |
||||||
|
if ( plan->extParam == NULL ) |
||||||
|
elog (ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't actual re-scan: ExecSetParamPlan does re-scan if
|
||||||
|
* node->plan->chgParam is not NULL... |
||||||
|
ExecReScan (plan, NULL, plan); |
||||||
|
*/ |
||||||
|
|
||||||
|
foreach (lst, node->setParam) |
||||||
|
{ |
||||||
|
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); |
||||||
|
|
||||||
|
prm->execPlan = node; |
||||||
|
} |
||||||
|
|
||||||
|
parent->chgParam = nconc (parent->chgParam, listCopy(node->setParam)); |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue