PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeSubplan.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeSubplan.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

SubPlanStateExecInitSubPlan (SubPlan *subplan, PlanState *parent)
 
AlternativeSubPlanStateExecInitAlternativeSubPlan (AlternativeSubPlan *asplan, PlanState *parent)
 
void ExecReScanSetParamPlan (SubPlanState *node, PlanState *parent)
 
void ExecSetParamPlan (SubPlanState *node, ExprContext *econtext)
 

Function Documentation

AlternativeSubPlanState* ExecInitAlternativeSubPlan ( AlternativeSubPlan asplan,
PlanState parent 
)

Definition at line 1157 of file nodeSubplan.c.

References AlternativeSubPlanState::active, Assert, ExprState::evalfunc, ExecAlternativeSubPlan(), ExecInitExpr(), ExprState::expr, linitial, list_length(), lsecond, makeNode, SubPlan::per_call_cost, PlanState::plan, Plan::plan_rows, SubPlan::startup_cost, AlternativeSubPlan::subplans, AlternativeSubPlanState::subplans, and AlternativeSubPlanState::xprstate.

Referenced by ExecInitExpr().

1158 {
1160  double num_calls;
1161  SubPlan *subplan1;
1162  SubPlan *subplan2;
1163  Cost cost1;
1164  Cost cost2;
1165 
1167  asstate->xprstate.expr = (Expr *) asplan;
1168 
1169  /*
1170  * Initialize subplans. (Can we get away with only initializing the one
1171  * we're going to use?)
1172  */
1173  asstate->subplans = (List *) ExecInitExpr((Expr *) asplan->subplans,
1174  parent);
1175 
1176  /*
1177  * Select the one to be used. For this, we need an estimate of the number
1178  * of executions of the subplan. We use the number of output rows
1179  * expected from the parent plan node. This is a good estimate if we are
1180  * in the parent's targetlist, and an underestimate (but probably not by
1181  * more than a factor of 2) if we are in the qual.
1182  */
1183  num_calls = parent->plan->plan_rows;
1184 
1185  /*
1186  * The planner saved enough info so that we don't have to work very hard
1187  * to estimate the total cost, given the number-of-calls estimate.
1188  */
1189  Assert(list_length(asplan->subplans) == 2);
1190  subplan1 = (SubPlan *) linitial(asplan->subplans);
1191  subplan2 = (SubPlan *) lsecond(asplan->subplans);
1192 
1193  cost1 = subplan1->startup_cost + num_calls * subplan1->per_call_cost;
1194  cost2 = subplan2->startup_cost + num_calls * subplan2->per_call_cost;
1195 
1196  if (cost1 < cost2)
1197  asstate->active = 0;
1198  else
1199  asstate->active = 1;
1200 
1201  return asstate;
1202 }
double plan_rows
Definition: plannodes.h:117
#define lsecond(l)
Definition: pg_list.h:114
Datum(* ExprStateEvalFunc)(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execnodes.h:591
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
#define linitial(l)
Definition: pg_list.h:110
Expr * expr
Definition: execnodes.h:598
ExprStateEvalFunc evalfunc
Definition: execnodes.h:599
Plan * plan
Definition: execnodes.h:1047
Cost per_call_cost
Definition: primnodes.h:689
#define makeNode(_type_)
Definition: nodes.h:557
#define Assert(condition)
Definition: c.h:671
static Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:1213
static int list_length(const List *l)
Definition: pg_list.h:89
Cost startup_cost
Definition: primnodes.h:688
Definition: pg_list.h:45
double Cost
Definition: nodes.h:633
SubPlanState* ExecInitSubPlan ( SubPlan subplan,
PlanState parent 
)

Definition at line 692 of file nodeSubplan.c.

References ALLOCSET_DEFAULT_SIZES, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), and_clause(), GenericExprState::arg, SubPlan::args, FuncExprState::args, SubPlanState::args, Assert, castNode, CreateExprContext(), CTE_SUBLINK, SubPlanState::cur_eq_funcs, SubPlanState::curArray, CurrentMemoryContext, SubPlanState::curTuple, elog, ERROR, EState::es_param_exec_vals, EState::es_subplanstates, ExprState::evalfunc, ExecBuildProjectionInfo(), ExecInitExpr(), ExecInitExtraTupleSlot(), ParamExecData::execPlan, ExecSetSlotDescriptor(), ExecSubPlan(), ExecTypeFromTL(), ExprState::expr, fmgr_info(), fmgr_info_set_expr, get_compatible_hash_operators(), get_op_hash_functions(), get_opcode(), SubPlanState::hashnulls, SubPlanState::hashtable, SubPlanState::hashtablecxt, SubPlanState::hashtempcxt, i, SubPlanState::innerecontext, IsA, SubPlanState::keyColIdx, lappend(), lfirst, lfirst_int, SubPlanState::lhs_hash_funcs, linitial, list_length(), list_make1, list_nth(), lsecond, makeNode, makeTargetEntry(), NIL, nodeTag, NULL, OpExpr::opfuncid, OpExpr::opno, palloc(), SubPlan::paramIds, SubPlanState::parent, SubPlan::plan_id, SubPlanState::planstate, PointerGetDatum, SubPlanState::projLeft, SubPlanState::projRight, SubPlan::setParam, PlanState::state, SubPlan::subLinkType, SubPlanState::tab_eq_funcs, SubPlanState::tab_hash_funcs, SubPlan::testexpr, SubPlanState::testexpr, SubPlan::useHashTable, GenericExprState::xprstate, FuncExprState::xprstate, and SubPlanState::xprstate.

Referenced by ExecInitExpr(), and ExecInitNode().

693 {
695  EState *estate = parent->state;
696 
698  sstate->xprstate.expr = (Expr *) subplan;
699 
700  /* Link the SubPlanState to already-initialized subplan */
701  sstate->planstate = (PlanState *) list_nth(estate->es_subplanstates,
702  subplan->plan_id - 1);
703 
704  /* ... and to its parent's state */
705  sstate->parent = parent;
706 
707  /* Initialize subexpressions */
708  sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent);
709  sstate->args = (List *) ExecInitExpr((Expr *) subplan->args, parent);
710 
711  /*
712  * initialize my state
713  */
714  sstate->curTuple = NULL;
715  sstate->curArray = PointerGetDatum(NULL);
716  sstate->projLeft = NULL;
717  sstate->projRight = NULL;
718  sstate->hashtable = NULL;
719  sstate->hashnulls = NULL;
720  sstate->hashtablecxt = NULL;
721  sstate->hashtempcxt = NULL;
722  sstate->innerecontext = NULL;
723  sstate->keyColIdx = NULL;
724  sstate->tab_hash_funcs = NULL;
725  sstate->tab_eq_funcs = NULL;
726  sstate->lhs_hash_funcs = NULL;
727  sstate->cur_eq_funcs = NULL;
728 
729  /*
730  * If this is an initplan or MULTIEXPR subplan, it has output parameters
731  * that the parent plan will use, so mark those parameters as needing
732  * evaluation. We don't actually run the subplan until we first need one
733  * of its outputs.
734  *
735  * A CTE subplan's output parameter is never to be evaluated in the normal
736  * way, so skip this in that case.
737  *
738  * Note that we don't set parent->chgParam here: the parent plan hasn't
739  * been run yet, so no need to force it to re-run.
740  */
741  if (subplan->setParam != NIL && subplan->subLinkType != CTE_SUBLINK)
742  {
743  ListCell *lst;
744 
745  foreach(lst, subplan->setParam)
746  {
747  int paramid = lfirst_int(lst);
748  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
749 
750  prm->execPlan = sstate;
751  }
752  }
753 
754  /*
755  * If we are going to hash the subquery output, initialize relevant stuff.
756  * (We don't create the hashtable until needed, though.)
757  */
758  if (subplan->useHashTable)
759  {
760  int ncols,
761  i;
762  TupleDesc tupDesc;
763  TupleTableSlot *slot;
764  List *oplist,
765  *lefttlist,
766  *righttlist,
767  *leftptlist,
768  *rightptlist;
769  ListCell *l;
770 
771  /* We need a memory context to hold the hash table(s) */
772  sstate->hashtablecxt =
774  "Subplan HashTable Context",
776  /* and a small one for the hash tables to use as temp storage */
777  sstate->hashtempcxt =
779  "Subplan HashTable Temp Context",
781  /* and a short-lived exprcontext for function evaluation */
782  sstate->innerecontext = CreateExprContext(estate);
783  /* Silly little array of column numbers 1..n */
784  ncols = list_length(subplan->paramIds);
785  sstate->keyColIdx = (AttrNumber *) palloc(ncols * sizeof(AttrNumber));
786  for (i = 0; i < ncols; i++)
787  sstate->keyColIdx[i] = i + 1;
788 
789  /*
790  * We use ExecProject to evaluate the lefthand and righthand
791  * expression lists and form tuples. (You might think that we could
792  * use the sub-select's output tuples directly, but that is not the
793  * case if we had to insert any run-time coercions of the sub-select's
794  * output datatypes; anyway this avoids storing any resjunk columns
795  * that might be in the sub-select's output.) Run through the
796  * combining expressions to build tlists for the lefthand and
797  * righthand sides. We need both the ExprState list (for ExecProject)
798  * and the underlying parse Exprs (for ExecTypeFromTL).
799  *
800  * We also extract the combining operators themselves to initialize
801  * the equality and hashing functions for the hash tables.
802  */
803  if (IsA(sstate->testexpr->expr, OpExpr))
804  {
805  /* single combining operator */
806  oplist = list_make1(sstate->testexpr);
807  }
808  else if (and_clause((Node *) sstate->testexpr->expr))
809  {
810  /* multiple combining operators */
811  oplist = castNode(BoolExprState, sstate->testexpr)->args;
812  }
813  else
814  {
815  /* shouldn't see anything else in a hashable subplan */
816  elog(ERROR, "unrecognized testexpr type: %d",
817  (int) nodeTag(sstate->testexpr->expr));
818  oplist = NIL; /* keep compiler quiet */
819  }
820  Assert(list_length(oplist) == ncols);
821 
822  lefttlist = righttlist = NIL;
823  leftptlist = rightptlist = NIL;
824  sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
825  sstate->tab_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
826  sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
827  sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
828  i = 1;
829  foreach(l, oplist)
830  {
832  OpExpr *opexpr = castNode(OpExpr, fstate->xprstate.expr);
833  ExprState *exstate;
834  Expr *expr;
835  TargetEntry *tle;
836  GenericExprState *tlestate;
837  Oid rhs_eq_oper;
838  Oid left_hashfn;
839  Oid right_hashfn;
840 
841  Assert(list_length(fstate->args) == 2);
842 
843  /* Process lefthand argument */
844  exstate = (ExprState *) linitial(fstate->args);
845  expr = exstate->expr;
846  tle = makeTargetEntry(expr,
847  i,
848  NULL,
849  false);
850  tlestate = makeNode(GenericExprState);
851  tlestate->xprstate.expr = (Expr *) tle;
852  tlestate->xprstate.evalfunc = NULL;
853  tlestate->arg = exstate;
854  lefttlist = lappend(lefttlist, tlestate);
855  leftptlist = lappend(leftptlist, tle);
856 
857  /* Process righthand argument */
858  exstate = (ExprState *) lsecond(fstate->args);
859  expr = exstate->expr;
860  tle = makeTargetEntry(expr,
861  i,
862  NULL,
863  false);
864  tlestate = makeNode(GenericExprState);
865  tlestate->xprstate.expr = (Expr *) tle;
866  tlestate->xprstate.evalfunc = NULL;
867  tlestate->arg = exstate;
868  righttlist = lappend(righttlist, tlestate);
869  rightptlist = lappend(rightptlist, tle);
870 
871  /* Lookup the equality function (potentially cross-type) */
872  fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
873  fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]);
874 
875  /* Look up the equality function for the RHS type */
876  if (!get_compatible_hash_operators(opexpr->opno,
877  NULL, &rhs_eq_oper))
878  elog(ERROR, "could not find compatible hash operator for operator %u",
879  opexpr->opno);
880  fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]);
881 
882  /* Lookup the associated hash functions */
883  if (!get_op_hash_functions(opexpr->opno,
884  &left_hashfn, &right_hashfn))
885  elog(ERROR, "could not find hash function for hash operator %u",
886  opexpr->opno);
887  fmgr_info(left_hashfn, &sstate->lhs_hash_funcs[i - 1]);
888  fmgr_info(right_hashfn, &sstate->tab_hash_funcs[i - 1]);
889 
890  i++;
891  }
892 
893  /*
894  * Construct tupdescs, slots and projection nodes for left and right
895  * sides. The lefthand expressions will be evaluated in the parent
896  * plan node's exprcontext, which we don't have access to here.
897  * Fortunately we can just pass NULL for now and fill it in later
898  * (hack alert!). The righthand expressions will be evaluated in our
899  * own innerecontext.
900  */
901  tupDesc = ExecTypeFromTL(leftptlist, false);
902  slot = ExecInitExtraTupleSlot(estate);
903  ExecSetSlotDescriptor(slot, tupDesc);
904  sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
905  NULL,
906  slot,
907  NULL);
908 
909  tupDesc = ExecTypeFromTL(rightptlist, false);
910  slot = ExecInitExtraTupleSlot(estate);
911  ExecSetSlotDescriptor(slot, tupDesc);
912  sstate->projRight = ExecBuildProjectionInfo(righttlist,
913  sstate->innerecontext,
914  slot,
915  NULL);
916  }
917 
918  return sstate;
919 }
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:53
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition: lsyscache.c:407
void * execPlan
Definition: params.h:99
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
ProjectionInfo * projLeft
Definition: execnodes.h:793
HeapTuple curTuple
Definition: execnodes.h:790
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:507
TupleHashTable hashtable
Definition: execnodes.h:795
ExprState xprstate
Definition: execnodes.h:611
int plan_id
Definition: primnodes.h:666
ExprContext * innerecontext
Definition: execnodes.h:801
ExprState xprstate
Definition: execnodes.h:785
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
#define PointerGetDatum(X)
Definition: postgres.h:564
List * args
Definition: execnodes.h:697
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:161
SubLinkType subLinkType
Definition: primnodes.h:661
Definition: nodes.h:509
List * paramIds
Definition: primnodes.h:664
ExprState * testexpr
Definition: execnodes.h:788
EState * state
Definition: execnodes.h:1049
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:114
Datum(* ExprStateEvalFunc)(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execnodes.h:591
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:803
#define list_make1(x1)
Definition: pg_list.h:133
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
ParamExecData * es_param_exec_vals
Definition: execnodes.h:394
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:786
Expr * expr
Definition: execnodes.h:598
List * args
Definition: execnodes.h:789
#define lfirst_int(lc)
Definition: pg_list.h:107
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:151
AttrNumber * keyColIdx
Definition: execnodes.h:802
bool and_clause(Node *clause)
Definition: clauses.c:313
void * list_nth(const List *list, int n)
Definition: list.c:410
ExprStateEvalFunc evalfunc
Definition: execnodes.h:599
static Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:68
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:96
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, TupleDesc inputDesc)
Definition: execUtils.c:482
struct PlanState * parent
Definition: execnodes.h:787
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
List * lappend(List *list, void *datum)
Definition: list.c:128
ExprState * arg
Definition: execnodes.h:612
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
Datum curArray
Definition: execnodes.h:791
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Oid opfuncid
Definition: primnodes.h:474
Node * testexpr
Definition: primnodes.h:663
MemoryContext hashtempcxt
Definition: execnodes.h:800
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
MemoryContext hashtablecxt
Definition: execnodes.h:799
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
FmgrInfo * tab_eq_funcs
Definition: execnodes.h:804
List * setParam
Definition: primnodes.h:683
static int list_length(const List *l)
Definition: pg_list.h:89
List * es_subplanstates
Definition: execnodes.h:412
ExprState xprstate
Definition: execnodes.h:696
FmgrInfo * lhs_hash_funcs
Definition: execnodes.h:805
#define nodeTag(nodeptr)
Definition: nodes.h:514
FmgrInfo * cur_eq_funcs
Definition: execnodes.h:806
void * palloc(Size size)
Definition: mcxt.c:891
int i
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:208
bool useHashTable
Definition: primnodes.h:675
ProjectionInfo * projRight
Definition: execnodes.h:794
Oid opno
Definition: primnodes.h:473
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
TupleHashTable hashnulls
Definition: execnodes.h:796
List * args
Definition: primnodes.h:686
void ExecReScanSetParamPlan ( SubPlanState node,
PlanState parent 
)

Definition at line 1111 of file nodeSubplan.c.

References bms_add_member(), bms_is_empty(), PlanState::chgParam, CTE_SUBLINK, elog, ERROR, ParamExecData::execPlan, ExprState::expr, Plan::extParam, lfirst_int, NIL, SubPlan::parParam, PlanState::plan, SubPlanState::planstate, SubPlan::setParam, PlanState::state, SubPlan::subLinkType, and SubPlanState::xprstate.

Referenced by ExecReScan().

1112 {
1113  PlanState *planstate = node->planstate;
1114  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
1115  EState *estate = parent->state;
1116  ListCell *l;
1117 
1118  /* sanity checks */
1119  if (subplan->parParam != NIL)
1120  elog(ERROR, "direct correlated subquery unsupported as initplan");
1121  if (subplan->setParam == NIL)
1122  elog(ERROR, "setParam list of initplan is empty");
1123  if (bms_is_empty(planstate->plan->extParam))
1124  elog(ERROR, "extParam set of initplan is empty");
1125 
1126  /*
1127  * Don't actually re-scan: it'll happen inside ExecSetParamPlan if needed.
1128  */
1129 
1130  /*
1131  * Mark this subplan's output parameters as needing recalculation.
1132  *
1133  * CTE subplans are never executed via parameter recalculation; instead
1134  * they get run when called by nodeCtescan.c. So don't mark the output
1135  * parameter of a CTE subplan as dirty, but do set the chgParam bit for it
1136  * so that dependent plan nodes will get told to rescan.
1137  */
1138  foreach(l, subplan->setParam)
1139  {
1140  int paramid = lfirst_int(l);
1141  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
1142 
1143  if (subplan->subLinkType != CTE_SUBLINK)
1144  prm->execPlan = node;
1145 
1146  parent->chgParam = bms_add_member(parent->chgParam, paramid);
1147  }
1148 }
#define NIL
Definition: pg_list.h:69
void * execPlan
Definition: params.h:99
ExprState xprstate
Definition: execnodes.h:785
SubLinkType subLinkType
Definition: primnodes.h:661
EState * state
Definition: execnodes.h:1049
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:786
Expr * expr
Definition: execnodes.h:598
#define lfirst_int(lc)
Definition: pg_list.h:107
Bitmapset * chgParam
Definition: execnodes.h:1072
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:633
Plan * plan
Definition: execnodes.h:1047
List * setParam
Definition: primnodes.h:683
Bitmapset * extParam
Definition: plannodes.h:147
List * parParam
Definition: primnodes.h:685
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
#define elog
Definition: elog.h:219
void ExecSetParamPlan ( SubPlanState node,
ExprContext econtext 
)

Definition at line 935 of file nodeSubplan.c.

References accumArrayResultAny(), ALL_SUBLINK, ANY_SUBLINK, SubPlanState::args, ARRAY_SUBLINK, Assert, tupleDesc::attrs, bms_add_member(), BoolGetDatum, CTE_SUBLINK, SubPlanState::curArray, CurrentMemoryContext, SubPlanState::curTuple, DatumGetPointer, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errmsg(), ERROR, ExecCopySlotTuple(), ExecEvalExprSwitchContext(), ParamExecData::execPlan, ExecProcNode(), EXISTS_SUBLINK, ExprState::expr, EXPR_SUBLINK, SubPlan::firstColType, forboth, heap_freetuple(), heap_getattr, i, initArrayResultAny(), ParamExecData::isnull, lfirst, lfirst_int, linitial_int, list_length(), makeArrayResultAny(), MemoryContextSwitchTo(), MULTIEXPR_SUBLINK, NIL, NULL, SubPlan::parParam, pfree(), SubPlanState::planstate, PointerGetDatum, ROWCOMPARE_SUBLINK, SubPlan::setParam, slot_getattr(), SubPlan::subLinkType, TupIsNull, ParamExecData::value, and SubPlanState::xprstate.

Referenced by ExecEvalParamExec().

936 {
937  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
938  PlanState *planstate = node->planstate;
939  SubLinkType subLinkType = subplan->subLinkType;
940  MemoryContext oldcontext;
941  TupleTableSlot *slot;
942  ListCell *pvar;
943  ListCell *l;
944  bool found = false;
945  ArrayBuildStateAny *astate = NULL;
946 
947  if (subLinkType == ANY_SUBLINK ||
948  subLinkType == ALL_SUBLINK)
949  elog(ERROR, "ANY/ALL subselect unsupported as initplan");
950  if (subLinkType == CTE_SUBLINK)
951  elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan");
952 
953  /* Initialize ArrayBuildStateAny in caller's context, if needed */
954  if (subLinkType == ARRAY_SUBLINK)
955  astate = initArrayResultAny(subplan->firstColType,
956  CurrentMemoryContext, true);
957 
958  /*
959  * Must switch to per-query memory context.
960  */
961  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
962 
963  /*
964  * Set Params of this plan from parent plan correlation values. (Any
965  * calculation we have to do is done in the parent econtext, since the
966  * Param values don't need to have per-query lifetime.) Currently, we
967  * expect only MULTIEXPR_SUBLINK plans to have any correlation values.
968  */
969  Assert(subplan->parParam == NIL || subLinkType == MULTIEXPR_SUBLINK);
970  Assert(list_length(subplan->parParam) == list_length(node->args));
971 
972  forboth(l, subplan->parParam, pvar, node->args)
973  {
974  int paramid = lfirst_int(l);
975  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
976 
978  econtext,
979  &(prm->isnull));
980  planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
981  }
982 
983  /*
984  * Run the plan. (If it needs to be rescanned, the first ExecProcNode
985  * call will take care of that.)
986  */
987  for (slot = ExecProcNode(planstate);
988  !TupIsNull(slot);
989  slot = ExecProcNode(planstate))
990  {
991  TupleDesc tdesc = slot->tts_tupleDescriptor;
992  int i = 1;
993 
994  if (subLinkType == EXISTS_SUBLINK)
995  {
996  /* There can be only one setParam... */
997  int paramid = linitial_int(subplan->setParam);
998  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
999 
1000  prm->execPlan = NULL;
1001  prm->value = BoolGetDatum(true);
1002  prm->isnull = false;
1003  found = true;
1004  break;
1005  }
1006 
1007  if (subLinkType == ARRAY_SUBLINK)
1008  {
1009  Datum dvalue;
1010  bool disnull;
1011 
1012  found = true;
1013  /* stash away current value */
1014  Assert(subplan->firstColType == tdesc->attrs[0]->atttypid);
1015  dvalue = slot_getattr(slot, 1, &disnull);
1016  astate = accumArrayResultAny(astate, dvalue, disnull,
1017  subplan->firstColType, oldcontext);
1018  /* keep scanning subplan to collect all values */
1019  continue;
1020  }
1021 
1022  if (found &&
1023  (subLinkType == EXPR_SUBLINK ||
1024  subLinkType == MULTIEXPR_SUBLINK ||
1025  subLinkType == ROWCOMPARE_SUBLINK))
1026  ereport(ERROR,
1027  (errcode(ERRCODE_CARDINALITY_VIOLATION),
1028  errmsg("more than one row returned by a subquery used as an expression")));
1029 
1030  found = true;
1031 
1032  /*
1033  * We need to copy the subplan's tuple into our own context, in case
1034  * any of the params are pass-by-ref type --- the pointers stored in
1035  * the param structs will point at this copied tuple! node->curTuple
1036  * keeps track of the copied tuple for eventual freeing.
1037  */
1038  if (node->curTuple)
1039  heap_freetuple(node->curTuple);
1040  node->curTuple = ExecCopySlotTuple(slot);
1041 
1042  /*
1043  * Now set all the setParam params from the columns of the tuple
1044  */
1045  foreach(l, subplan->setParam)
1046  {
1047  int paramid = lfirst_int(l);
1048  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1049 
1050  prm->execPlan = NULL;
1051  prm->value = heap_getattr(node->curTuple, i, tdesc,
1052  &(prm->isnull));
1053  i++;
1054  }
1055  }
1056 
1057  if (subLinkType == ARRAY_SUBLINK)
1058  {
1059  /* There can be only one setParam... */
1060  int paramid = linitial_int(subplan->setParam);
1061  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1062 
1063  /*
1064  * We build the result array in query context so it won't disappear;
1065  * to avoid leaking memory across repeated calls, we have to remember
1066  * the latest value, much as for curTuple above.
1067  */
1068  if (node->curArray != PointerGetDatum(NULL))
1069  pfree(DatumGetPointer(node->curArray));
1070  node->curArray = makeArrayResultAny(astate,
1071  econtext->ecxt_per_query_memory,
1072  true);
1073  prm->execPlan = NULL;
1074  prm->value = node->curArray;
1075  prm->isnull = false;
1076  }
1077  else if (!found)
1078  {
1079  if (subLinkType == EXISTS_SUBLINK)
1080  {
1081  /* There can be only one setParam... */
1082  int paramid = linitial_int(subplan->setParam);
1083  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1084 
1085  prm->execPlan = NULL;
1086  prm->value = BoolGetDatum(false);
1087  prm->isnull = false;
1088  }
1089  else
1090  {
1091  /* For other sublink types, set all the output params to NULL */
1092  foreach(l, subplan->setParam)
1093  {
1094  int paramid = lfirst_int(l);
1095  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1096 
1097  prm->execPlan = NULL;
1098  prm->value = (Datum) 0;
1099  prm->isnull = true;
1100  }
1101  }
1102  }
1103 
1104  MemoryContextSwitchTo(oldcontext);
1105 }
#define NIL
Definition: pg_list.h:69
Oid firstColType
Definition: primnodes.h:670
void * execPlan
Definition: params.h:99
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
HeapTuple curTuple
Definition: execnodes.h:790
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5418
ExprState xprstate
Definition: execnodes.h:785
#define PointerGetDatum(X)
Definition: postgres.h:564
Form_pg_attribute * attrs
Definition: tupdesc.h:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SubLinkType subLinkType
Definition: primnodes.h:661
int errcode(int sqlerrcode)
Definition: elog.c:575
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4219
#define linitial_int(l)
Definition: pg_list.h:111
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:786
Expr * expr
Definition: execnodes.h:598
List * args
Definition: execnodes.h:789
#define lfirst_int(lc)
Definition: pg_list.h:107
bool isnull
Definition: params.h:101
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:137
#define TupIsNull(slot)
Definition: tuptable.h:138
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
SubLinkType
Definition: primnodes.h:595
ArrayBuildStateAny * accumArrayResultAny(ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5463
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:545
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
Datum curArray
Definition: execnodes.h:791
uintptr_t Datum
Definition: postgres.h:374
#define BoolGetDatum(X)
Definition: postgres.h:410
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
List * setParam
Definition: primnodes.h:683
static int list_length(const List *l)
Definition: pg_list.h:89
List * parParam
Definition: primnodes.h:685
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:133
#define DatumGetPointer(X)
Definition: postgres.h:557
Datum makeArrayResultAny(ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5491
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
Datum value
Definition: params.h:100
#define elog
Definition: elog.h:219