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