diff options
author | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-02-13 03:26:53 +0000 |
---|---|---|
committer | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-02-13 03:26:53 +0000 |
commit | 1a105cefbd4769a1ef857f94a71faed6cb76717b (patch) | |
tree | 2c9b0cf10965e5e1d31106451552aad0c7c7e18d /src/backend/executor/nodeSubplan.c | |
parent | 13637df458b1d5a4f773bd17d3b894d9ff27197b (diff) | |
download | postgresql-1a105cefbd4769a1ef857f94a71faed6cb76717b.tar.gz postgresql-1a105cefbd4769a1ef857f94a71faed6cb76717b.zip |
Support for subselects.
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.
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c new file mode 100644 index 00000000000..610f0a09643 --- /dev/null +++ b/src/backend/executor/nodeSubplan.c @@ -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)); + +} |