PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeSubplan.c File Reference
#include "postgres.h"
#include <limits.h>
#include <math.h>
#include "access/htup_details.h"
#include "executor/executor.h"
#include "executor/nodeSubplan.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "utils/array.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
Include dependency graph for nodeSubplan.c:

Go to the source code of this file.

Functions

static Datum ExecSubPlan (SubPlanState *node, ExprContext *econtext, bool *isNull)
 
static Datum ExecAlternativeSubPlan (AlternativeSubPlanState *node, ExprContext *econtext, bool *isNull)
 
static Datum ExecHashSubPlan (SubPlanState *node, ExprContext *econtext, bool *isNull)
 
static Datum ExecScanSubPlan (SubPlanState *node, ExprContext *econtext, bool *isNull)
 
static void buildSubPlanHash (SubPlanState *node, ExprContext *econtext)
 
static bool findPartialMatch (TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions)
 
static bool slotAllNulls (TupleTableSlot *slot)
 
static bool slotNoNulls (TupleTableSlot *slot)
 
SubPlanStateExecInitSubPlan (SubPlan *subplan, PlanState *parent)
 
void ExecSetParamPlan (SubPlanState *node, ExprContext *econtext)
 
void ExecReScanSetParamPlan (SubPlanState *node, PlanState *parent)
 
AlternativeSubPlanStateExecInitAlternativeSubPlan (AlternativeSubPlan *asplan, PlanState *parent)
 

Function Documentation

static void buildSubPlanHash ( SubPlanState node,
ExprContext econtext 
)
static

Definition at line 463 of file nodeSubplan.c.

References ANY_SUBLINK, Assert, BuildTupleHashTable(), ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_per_query_memory, ExecClearTuple(), ParamExecData::execPlan, ExecProcNode(), ExecProject(), ExecReScan(), ExprState::expr, SubPlanState::hashnulls, SubPlanState::hashtable, SubPlanState::hashtablecxt, SubPlanState::hashtempcxt, SubPlanState::havehashrows, SubPlanState::havenullrows, SubPlanState::innerecontext, ParamExecData::isnull, SubPlanState::keyColIdx, lfirst_int, list_length(), LookupTupleHashEntry(), MemoryContextReset(), MemoryContextSwitchTo(), Min, NULL, SubPlan::paramIds, ProjectionInfo::pi_slot, SubPlanState::planstate, SubPlanState::projRight, ResetExprContext, slot_getattr(), slotNoNulls(), SubPlan::subLinkType, SubPlanState::tab_eq_funcs, SubPlanState::tab_hash_funcs, TupIsNull, SubPlan::unknownEqFalse, ParamExecData::value, and SubPlanState::xprstate.

Referenced by ExecHashSubPlan().

464 {
465  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
466  PlanState *planstate = node->planstate;
467  int ncols = list_length(subplan->paramIds);
468  ExprContext *innerecontext = node->innerecontext;
469  MemoryContext oldcontext;
470  long nbuckets;
471  TupleTableSlot *slot;
472 
473  Assert(subplan->subLinkType == ANY_SUBLINK);
474 
475  /*
476  * If we already had any hash tables, destroy 'em; then create empty hash
477  * table(s).
478  *
479  * If we need to distinguish accurately between FALSE and UNKNOWN (i.e.,
480  * NULL) results of the IN operation, then we have to store subplan output
481  * rows that are partly or wholly NULL. We store such rows in a separate
482  * hash table that we expect will be much smaller than the main table. (We
483  * can use hashing to eliminate partly-null rows that are not distinct. We
484  * keep them separate to minimize the cost of the inevitable full-table
485  * searches; see findPartialMatch.)
486  *
487  * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't
488  * need to store subplan output rows that contain NULL.
489  */
491  node->hashtable = NULL;
492  node->hashnulls = NULL;
493  node->havehashrows = false;
494  node->havenullrows = false;
495 
496  nbuckets = (long) Min(planstate->plan->plan_rows, (double) LONG_MAX);
497  if (nbuckets < 1)
498  nbuckets = 1;
499 
500  node->hashtable = BuildTupleHashTable(ncols,
501  node->keyColIdx,
502  node->tab_eq_funcs,
503  node->tab_hash_funcs,
504  nbuckets,
505  0,
506  node->hashtablecxt,
507  node->hashtempcxt,
508  false);
509 
510  if (!subplan->unknownEqFalse)
511  {
512  if (ncols == 1)
513  nbuckets = 1; /* there can only be one entry */
514  else
515  {
516  nbuckets /= 16;
517  if (nbuckets < 1)
518  nbuckets = 1;
519  }
520  node->hashnulls = BuildTupleHashTable(ncols,
521  node->keyColIdx,
522  node->tab_eq_funcs,
523  node->tab_hash_funcs,
524  nbuckets,
525  0,
526  node->hashtablecxt,
527  node->hashtempcxt,
528  false);
529  }
530 
531  /*
532  * We are probably in a short-lived expression-evaluation context. Switch
533  * to the per-query context for manipulating the child plan.
534  */
535  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
536 
537  /*
538  * Reset subplan to start.
539  */
540  ExecReScan(planstate);
541 
542  /*
543  * Scan the subplan and load the hash table(s). Note that when there are
544  * duplicate rows coming out of the sub-select, only one copy is stored.
545  */
546  for (slot = ExecProcNode(planstate);
547  !TupIsNull(slot);
548  slot = ExecProcNode(planstate))
549  {
550  int col = 1;
551  ListCell *plst;
552  bool isnew;
553 
554  /*
555  * Load up the Params representing the raw sub-select outputs, then
556  * form the projection tuple to store in the hashtable.
557  */
558  foreach(plst, subplan->paramIds)
559  {
560  int paramid = lfirst_int(plst);
561  ParamExecData *prmdata;
562 
563  prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);
564  Assert(prmdata->execPlan == NULL);
565  prmdata->value = slot_getattr(slot, col,
566  &(prmdata->isnull));
567  col++;
568  }
569  slot = ExecProject(node->projRight);
570 
571  /*
572  * If result contains any nulls, store separately or not at all.
573  */
574  if (slotNoNulls(slot))
575  {
576  (void) LookupTupleHashEntry(node->hashtable, slot, &isnew);
577  node->havehashrows = true;
578  }
579  else if (node->hashnulls)
580  {
581  (void) LookupTupleHashEntry(node->hashnulls, slot, &isnew);
582  node->havenullrows = true;
583  }
584 
585  /*
586  * Reset innerecontext after each inner tuple to free any memory used
587  * during ExecProject.
588  */
589  ResetExprContext(innerecontext);
590  }
591 
592  /*
593  * Since the projected tuples are in the sub-query's context and not the
594  * main context, we'd better clear the tuple slot before there's any
595  * chance of a reset of the sub-query's context. Else we will have the
596  * potential for a double free attempt. (XXX possibly no longer needed,
597  * but can't hurt.)
598  */
600 
601  MemoryContextSwitchTo(oldcontext);
602 }
void * execPlan
Definition: params.h:99
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5214
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
TupleHashTable hashtable
Definition: execnodes.h:794
ExprContext * innerecontext
Definition: execnodes.h:800
ExprState xprstate
Definition: execnodes.h:784
#define Min(x, y)
Definition: c.h:801
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SubLinkType subLinkType
Definition: primnodes.h:661
List * paramIds
Definition: primnodes.h:664
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:802
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
#define lfirst_int(lc)
Definition: pg_list.h:107
bool isnull
Definition: params.h:101
AttrNumber * keyColIdx
Definition: execnodes.h:801
TupleTableSlot * pi_slot
Definition: execnodes.h:251
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:137
bool havenullrows
Definition: execnodes.h:797
#define TupIsNull(slot)
Definition: tuptable.h:138
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:351
static bool slotNoNulls(TupleTableSlot *slot)
Definition: nodeSubplan.c:668
MemoryContext hashtempcxt
Definition: execnodes.h:799
MemoryContext hashtablecxt
Definition: execnodes.h:798
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
FmgrInfo * tab_eq_funcs
Definition: execnodes.h:803
bool unknownEqFalse
Definition: primnodes.h:677
static int list_length(const List *l)
Definition: pg_list.h:89
TupleHashTable BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:290
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:133
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
Datum value
Definition: params.h:100
ProjectionInfo * projRight
Definition: execnodes.h:793
bool havehashrows
Definition: execnodes.h:796
TupleHashTable hashnulls
Definition: execnodes.h:795
#define ResetExprContext(econtext)
Definition: executor.h:332
static Datum ExecAlternativeSubPlan ( AlternativeSubPlanState node,
ExprContext econtext,
bool isNull 
)
static

Definition at line 1213 of file nodeSubplan.c.

References AlternativeSubPlanState::active, castNode, ExecSubPlan(), list_nth(), and AlternativeSubPlanState::subplans.

Referenced by ExecInitAlternativeSubPlan().

1216 {
1217  /* Just pass control to the active subplan */
1218  SubPlanState *activesp = castNode(SubPlanState,
1219  list_nth(node->subplans, node->active));
1220 
1221  return ExecSubPlan(activesp, econtext, isNull);
1222 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
void * list_nth(const List *list, int n)
Definition: list.c:410
static Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:68
static Datum ExecHashSubPlan ( SubPlanState node,
ExprContext econtext,
bool isNull 
)
static

Definition at line 94 of file nodeSubplan.c.

References SubPlanState::args, BoolGetDatum, buildSubPlanHash(), SubPlanState::cur_eq_funcs, elog, ERROR, ExecClearTuple(), ExecProject(), ExprState::expr, findPartialMatch(), FindTupleHashEntry(), SubPlanState::hashnulls, SubPlanState::hashtable, SubPlanState::havehashrows, SubPlanState::havenullrows, SubPlanState::lhs_hash_funcs, NIL, NULL, SubPlan::parParam, ProjectionInfo::pi_exprContext, SubPlanState::planstate, SubPlanState::projLeft, slotAllNulls(), slotNoNulls(), and SubPlanState::xprstate.

Referenced by ExecSubPlan().

97 {
98  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
99  PlanState *planstate = node->planstate;
100  TupleTableSlot *slot;
101 
102  /* Shouldn't have any direct correlation Vars */
103  if (subplan->parParam != NIL || node->args != NIL)
104  elog(ERROR, "hashed subplan with direct correlation not supported");
105 
106  /*
107  * If first time through or we need to rescan the subplan, build the hash
108  * table.
109  */
110  if (node->hashtable == NULL || planstate->chgParam != NULL)
111  buildSubPlanHash(node, econtext);
112 
113  /*
114  * The result for an empty subplan is always FALSE; no need to evaluate
115  * lefthand side.
116  */
117  *isNull = false;
118  if (!node->havehashrows && !node->havenullrows)
119  return BoolGetDatum(false);
120 
121  /*
122  * Evaluate lefthand expressions and form a projection tuple. First we
123  * have to set the econtext to use (hack alert!).
124  */
125  node->projLeft->pi_exprContext = econtext;
126  slot = ExecProject(node->projLeft);
127 
128  /*
129  * Note: because we are typically called in a per-tuple context, we have
130  * to explicitly clear the projected tuple before returning. Otherwise,
131  * we'll have a double-free situation: the per-tuple context will probably
132  * be reset before we're called again, and then the tuple slot will think
133  * it still needs to free the tuple.
134  */
135 
136  /*
137  * If the LHS is all non-null, probe for an exact match in the main hash
138  * table. If we find one, the result is TRUE. Otherwise, scan the
139  * partly-null table to see if there are any rows that aren't provably
140  * unequal to the LHS; if so, the result is UNKNOWN. (We skip that part
141  * if we don't care about UNKNOWN.) Otherwise, the result is FALSE.
142  *
143  * Note: the reason we can avoid a full scan of the main hash table is
144  * that the combining operators are assumed never to yield NULL when both
145  * inputs are non-null. If they were to do so, we might need to produce
146  * UNKNOWN instead of FALSE because of an UNKNOWN result in comparing the
147  * LHS to some main-table entry --- which is a comparison we will not even
148  * make, unless there's a chance match of hash keys.
149  */
150  if (slotNoNulls(slot))
151  {
152  if (node->havehashrows &&
154  slot,
155  node->cur_eq_funcs,
156  node->lhs_hash_funcs) != NULL)
157  {
158  ExecClearTuple(slot);
159  return BoolGetDatum(true);
160  }
161  if (node->havenullrows &&
162  findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs))
163  {
164  ExecClearTuple(slot);
165  *isNull = true;
166  return BoolGetDatum(false);
167  }
168  ExecClearTuple(slot);
169  return BoolGetDatum(false);
170  }
171 
172  /*
173  * When the LHS is partly or wholly NULL, we can never return TRUE. If we
174  * don't care about UNKNOWN, just return FALSE. Otherwise, if the LHS is
175  * wholly NULL, immediately return UNKNOWN. (Since the combining
176  * operators are strict, the result could only be FALSE if the sub-select
177  * were empty, but we already handled that case.) Otherwise, we must scan
178  * both the main and partly-null tables to see if there are any rows that
179  * aren't provably unequal to the LHS; if so, the result is UNKNOWN.
180  * Otherwise, the result is FALSE.
181  */
182  if (node->hashnulls == NULL)
183  {
184  ExecClearTuple(slot);
185  return BoolGetDatum(false);
186  }
187  if (slotAllNulls(slot))
188  {
189  ExecClearTuple(slot);
190  *isNull = true;
191  return BoolGetDatum(false);
192  }
193  /* Scan partly-null table first, since more likely to get a match */
194  if (node->havenullrows &&
195  findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs))
196  {
197  ExecClearTuple(slot);
198  *isNull = true;
199  return BoolGetDatum(false);
200  }
201  if (node->havehashrows &&
202  findPartialMatch(node->hashtable, slot, node->cur_eq_funcs))
203  {
204  ExecClearTuple(slot);
205  *isNull = true;
206  return BoolGetDatum(false);
207  }
208  ExecClearTuple(slot);
209  return BoolGetDatum(false);
210 }
#define NIL
Definition: pg_list.h:69
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5214
ProjectionInfo * projLeft
Definition: execnodes.h:792
TupleHashTable hashtable
Definition: execnodes.h:794
ExprState xprstate
Definition: execnodes.h:784
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
List * args
Definition: execnodes.h:788
bool havenullrows
Definition: execnodes.h:797
static bool slotNoNulls(TupleTableSlot *slot)
Definition: nodeSubplan.c:668
static bool slotAllNulls(TupleTableSlot *slot)
Definition: nodeSubplan.c:648
#define BoolGetDatum(X)
Definition: postgres.h:410
#define NULL
Definition: c.h:226
List * parParam
Definition: primnodes.h:685
FmgrInfo * lhs_hash_funcs
Definition: execnodes.h:804
FmgrInfo * cur_eq_funcs
Definition: execnodes.h:805
static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions)
Definition: nodeSubplan.c:616
static void buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:463
#define elog
Definition: elog.h:219
ExprContext * pi_exprContext
Definition: execnodes.h:250
bool havehashrows
Definition: execnodes.h:796
TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions)
Definition: execGrouping.c:425
TupleHashTable hashnulls
Definition: execnodes.h:795
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:590
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
#define linitial(l)
Definition: pg_list.h:110
Expr * expr
Definition: execnodes.h:597
ExprStateEvalFunc evalfunc
Definition: execnodes.h:598
Plan * plan
Definition: execnodes.h:1046
Cost per_call_cost
Definition: primnodes.h:689
#define makeNode(_type_)
Definition: nodes.h:556
#define Assert(condition)
Definition: c.h:670
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:632
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:559
ProjectionInfo * projLeft
Definition: execnodes.h:792
HeapTuple curTuple
Definition: execnodes.h:789
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:794
ExprState xprstate
Definition: execnodes.h:610
int plan_id
Definition: primnodes.h:666
ExprContext * innerecontext
Definition: execnodes.h:800
ExprState xprstate
Definition: execnodes.h:784
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
#define PointerGetDatum(X)
Definition: postgres.h:564
List * args
Definition: execnodes.h:696
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:155
SubLinkType subLinkType
Definition: primnodes.h:661
Definition: nodes.h:508
List * paramIds
Definition: primnodes.h:664
ExprState * testexpr
Definition: execnodes.h:787
EState * state
Definition: execnodes.h:1048
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:590
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:802
#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:393
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
List * args
Definition: execnodes.h:788
#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:145
AttrNumber * keyColIdx
Definition: execnodes.h:801
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:598
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:481
struct PlanState * parent
Definition: execnodes.h:786
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:611
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
Datum curArray
Definition: execnodes.h:790
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:799
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
MemoryContext hashtablecxt
Definition: execnodes.h:798
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
FmgrInfo * tab_eq_funcs
Definition: execnodes.h:803
List * setParam
Definition: primnodes.h:683
static int list_length(const List *l)
Definition: pg_list.h:89
List * es_subplanstates
Definition: execnodes.h:411
ExprState xprstate
Definition: execnodes.h:695
FmgrInfo * lhs_hash_funcs
Definition: execnodes.h:804
#define nodeTag(nodeptr)
Definition: nodes.h:513
FmgrInfo * cur_eq_funcs
Definition: execnodes.h:805
void * palloc(Size size)
Definition: mcxt.c:891
int i
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:207
bool useHashTable
Definition: primnodes.h:675
ProjectionInfo * projRight
Definition: execnodes.h:793
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:795
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:784
SubLinkType subLinkType
Definition: primnodes.h:661
EState * state
Definition: execnodes.h:1048
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
#define lfirst_int(lc)
Definition: pg_list.h:107
Bitmapset * chgParam
Definition: execnodes.h:1071
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:633
Plan * plan
Definition: execnodes.h:1046
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
static Datum ExecScanSubPlan ( SubPlanState node,
ExprContext econtext,
bool isNull 
)
static

Definition at line 216 of file nodeSubplan.c.

References accumArrayResultAny(), ALL_SUBLINK, ANY_SUBLINK, SubPlanState::args, ARRAY_SUBLINK, Assert, tupleDesc::attrs, bms_add_member(), BoolGetDatum, CurrentMemoryContext, SubPlanState::curTuple, DatumGetBool, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, EState::es_param_exec_vals, ExecCopySlotTuple(), ExecEvalExprSwitchContext(), ParamExecData::execPlan, ExecProcNode(), ExecReScan(), EXISTS_SUBLINK, ExprState::expr, EXPR_SUBLINK, SubPlan::firstColType, forboth, heap_freetuple(), heap_getattr, initArrayResultAny(), ParamExecData::isnull, lfirst, lfirst_int, list_length(), makeArrayResultAny(), MemoryContextSwitchTo(), MULTIEXPR_SUBLINK, NULL, SubPlan::paramIds, SubPlanState::parent, SubPlan::parParam, SubPlanState::planstate, ROWCOMPARE_SUBLINK, SubPlan::setParam, slot_getattr(), PlanState::state, SubPlan::subLinkType, SubPlanState::testexpr, TupIsNull, ParamExecData::value, and SubPlanState::xprstate.

Referenced by ExecSubPlan().

219 {
220  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
221  PlanState *planstate = node->planstate;
222  SubLinkType subLinkType = subplan->subLinkType;
223  MemoryContext oldcontext;
224  TupleTableSlot *slot;
225  Datum result;
226  bool found = false; /* TRUE if got at least one subplan tuple */
227  ListCell *pvar;
228  ListCell *l;
229  ArrayBuildStateAny *astate = NULL;
230 
231  /*
232  * MULTIEXPR subplans, when "executed", just return NULL; but first we
233  * mark the subplan's output parameters as needing recalculation. (This
234  * is a bit of a hack: it relies on the subplan appearing later in its
235  * targetlist than any of the referencing Params, so that all the Params
236  * have been evaluated before we re-mark them for the next evaluation
237  * cycle. But in general resjunk tlist items appear after non-resjunk
238  * ones, so this should be safe.) Unlike ExecReScanSetParamPlan, we do
239  * *not* set bits in the parent plan node's chgParam, because we don't
240  * want to cause a rescan of the parent.
241  */
242  if (subLinkType == MULTIEXPR_SUBLINK)
243  {
244  EState *estate = node->parent->state;
245 
246  foreach(l, subplan->setParam)
247  {
248  int paramid = lfirst_int(l);
249  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
250 
251  prm->execPlan = node;
252  }
253  *isNull = true;
254  return (Datum) 0;
255  }
256 
257  /* Initialize ArrayBuildStateAny in caller's context, if needed */
258  if (subLinkType == ARRAY_SUBLINK)
259  astate = initArrayResultAny(subplan->firstColType,
260  CurrentMemoryContext, true);
261 
262  /*
263  * We are probably in a short-lived expression-evaluation context. Switch
264  * to the per-query context for manipulating the child plan's chgParam,
265  * calling ExecProcNode on it, etc.
266  */
267  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
268 
269  /*
270  * Set Params of this plan from parent plan correlation values. (Any
271  * calculation we have to do is done in the parent econtext, since the
272  * Param values don't need to have per-query lifetime.)
273  */
274  Assert(list_length(subplan->parParam) == list_length(node->args));
275 
276  forboth(l, subplan->parParam, pvar, node->args)
277  {
278  int paramid = lfirst_int(l);
279  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
280 
282  econtext,
283  &(prm->isnull));
284  planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
285  }
286 
287  /*
288  * Now that we've set up its parameters, we can reset the subplan.
289  */
290  ExecReScan(planstate);
291 
292  /*
293  * For all sublink types except EXPR_SUBLINK and ARRAY_SUBLINK, the result
294  * is boolean as are the results of the combining operators. We combine
295  * results across tuples (if the subplan produces more than one) using OR
296  * semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK.
297  * (ROWCOMPARE_SUBLINK doesn't allow multiple tuples from the subplan.)
298  * NULL results from the combining operators are handled according to the
299  * usual SQL semantics for OR and AND. The result for no input tuples is
300  * FALSE for ANY_SUBLINK, TRUE for ALL_SUBLINK, NULL for
301  * ROWCOMPARE_SUBLINK.
302  *
303  * For EXPR_SUBLINK we require the subplan to produce no more than one
304  * tuple, else an error is raised. If zero tuples are produced, we return
305  * NULL. Assuming we get a tuple, we just use its first column (there can
306  * be only one non-junk column in this case).
307  *
308  * For ARRAY_SUBLINK we allow the subplan to produce any number of tuples,
309  * and form an array of the first column's values. Note in particular
310  * that we produce a zero-element array if no tuples are produced (this is
311  * a change from pre-8.3 behavior of returning NULL).
312  */
313  result = BoolGetDatum(subLinkType == ALL_SUBLINK);
314  *isNull = false;
315 
316  for (slot = ExecProcNode(planstate);
317  !TupIsNull(slot);
318  slot = ExecProcNode(planstate))
319  {
320  TupleDesc tdesc = slot->tts_tupleDescriptor;
321  Datum rowresult;
322  bool rownull;
323  int col;
324  ListCell *plst;
325 
326  if (subLinkType == EXISTS_SUBLINK)
327  {
328  found = true;
329  result = BoolGetDatum(true);
330  break;
331  }
332 
333  if (subLinkType == EXPR_SUBLINK)
334  {
335  /* cannot allow multiple input tuples for EXPR sublink */
336  if (found)
337  ereport(ERROR,
338  (errcode(ERRCODE_CARDINALITY_VIOLATION),
339  errmsg("more than one row returned by a subquery used as an expression")));
340  found = true;
341 
342  /*
343  * We need to copy the subplan's tuple in case the result is of
344  * pass-by-ref type --- our return value will point into this
345  * copied tuple! Can't use the subplan's instance of the tuple
346  * since it won't still be valid after next ExecProcNode() call.
347  * node->curTuple keeps track of the copied tuple for eventual
348  * freeing.
349  */
350  if (node->curTuple)
351  heap_freetuple(node->curTuple);
352  node->curTuple = ExecCopySlotTuple(slot);
353 
354  result = heap_getattr(node->curTuple, 1, tdesc, isNull);
355  /* keep scanning subplan to make sure there's only one tuple */
356  continue;
357  }
358 
359  if (subLinkType == ARRAY_SUBLINK)
360  {
361  Datum dvalue;
362  bool disnull;
363 
364  found = true;
365  /* stash away current value */
366  Assert(subplan->firstColType == tdesc->attrs[0]->atttypid);
367  dvalue = slot_getattr(slot, 1, &disnull);
368  astate = accumArrayResultAny(astate, dvalue, disnull,
369  subplan->firstColType, oldcontext);
370  /* keep scanning subplan to collect all values */
371  continue;
372  }
373 
374  /* cannot allow multiple input tuples for ROWCOMPARE sublink either */
375  if (subLinkType == ROWCOMPARE_SUBLINK && found)
376  ereport(ERROR,
377  (errcode(ERRCODE_CARDINALITY_VIOLATION),
378  errmsg("more than one row returned by a subquery used as an expression")));
379 
380  found = true;
381 
382  /*
383  * For ALL, ANY, and ROWCOMPARE sublinks, load up the Params
384  * representing the columns of the sub-select, and then evaluate the
385  * combining expression.
386  */
387  col = 1;
388  foreach(plst, subplan->paramIds)
389  {
390  int paramid = lfirst_int(plst);
391  ParamExecData *prmdata;
392 
393  prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
394  Assert(prmdata->execPlan == NULL);
395  prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
396  col++;
397  }
398 
399  rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
400  &rownull);
401 
402  if (subLinkType == ANY_SUBLINK)
403  {
404  /* combine across rows per OR semantics */
405  if (rownull)
406  *isNull = true;
407  else if (DatumGetBool(rowresult))
408  {
409  result = BoolGetDatum(true);
410  *isNull = false;
411  break; /* needn't look at any more rows */
412  }
413  }
414  else if (subLinkType == ALL_SUBLINK)
415  {
416  /* combine across rows per AND semantics */
417  if (rownull)
418  *isNull = true;
419  else if (!DatumGetBool(rowresult))
420  {
421  result = BoolGetDatum(false);
422  *isNull = false;
423  break; /* needn't look at any more rows */
424  }
425  }
426  else
427  {
428  /* must be ROWCOMPARE_SUBLINK */
429  result = rowresult;
430  *isNull = rownull;
431  }
432  }
433 
434  MemoryContextSwitchTo(oldcontext);
435 
436  if (subLinkType == ARRAY_SUBLINK)
437  {
438  /* We return the result in the caller's context */
439  result = makeArrayResultAny(astate, oldcontext, true);
440  }
441  else if (!found)
442  {
443  /*
444  * deal with empty subplan result. result/isNull were previously
445  * initialized correctly for all sublink types except EXPR and
446  * ROWCOMPARE; for those, return NULL.
447  */
448  if (subLinkType == EXPR_SUBLINK ||
449  subLinkType == ROWCOMPARE_SUBLINK)
450  {
451  result = (Datum) 0;
452  *isNull = true;
453  }
454  }
455 
456  return result;
457 }
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:789
#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:784
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
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
List * paramIds
Definition: primnodes.h:664
ExprState * testexpr
Definition: execnodes.h:787
EState * state
Definition: execnodes.h:1048
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4219
ParamExecData * es_param_exec_vals
Definition: execnodes.h:393
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
List * args
Definition: execnodes.h:788
#define lfirst_int(lc)
Definition: pg_list.h:107
bool isnull
Definition: params.h:101
#define DatumGetBool(X)
Definition: postgres.h:401
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:137
#define TupIsNull(slot)
Definition: tuptable.h:138
struct PlanState * parent
Definition: execnodes.h:786
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
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:670
#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
Datum makeArrayResultAny(ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5491
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
Datum value
Definition: params.h:100
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:789
#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:784
#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:785
Expr * expr
Definition: execnodes.h:597
List * args
Definition: execnodes.h:788
#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:790
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:670
#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
static Datum ExecSubPlan ( SubPlanState node,
ExprContext econtext,
bool isNull 
)
static

Definition at line 68 of file nodeSubplan.c.

References CTE_SUBLINK, elog, ERROR, ExecHashSubPlan(), ExecScanSubPlan(), ExprState::expr, MULTIEXPR_SUBLINK, NIL, SubPlan::setParam, SubPlan::subLinkType, SubPlan::useHashTable, and SubPlanState::xprstate.

Referenced by ExecAlternativeSubPlan(), and ExecInitSubPlan().

71 {
72  SubPlan *subplan = (SubPlan *) node->xprstate.expr;
73 
74  /* Set non-null as default */
75  *isNull = false;
76 
77  /* Sanity checks */
78  if (subplan->subLinkType == CTE_SUBLINK)
79  elog(ERROR, "CTE subplans should not be executed via ExecSubPlan");
80  if (subplan->setParam != NIL && subplan->subLinkType != MULTIEXPR_SUBLINK)
81  elog(ERROR, "cannot set parent params from subquery");
82 
83  /* Select appropriate evaluation strategy */
84  if (subplan->useHashTable)
85  return ExecHashSubPlan(node, econtext, isNull);
86  else
87  return ExecScanSubPlan(node, econtext, isNull);
88 }
#define NIL
Definition: pg_list.h:69
ExprState xprstate
Definition: execnodes.h:784
SubLinkType subLinkType
Definition: primnodes.h:661
#define ERROR
Definition: elog.h:43
Expr * expr
Definition: execnodes.h:597
static Datum ExecHashSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:94
static Datum ExecScanSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:216
List * setParam
Definition: primnodes.h:683
bool useHashTable
Definition: primnodes.h:675
#define elog
Definition: elog.h:219
static bool findPartialMatch ( TupleHashTable  hashtable,
TupleTableSlot slot,
FmgrInfo eqfunctions 
)
static

Definition at line 616 of file nodeSubplan.c.

References ExecStoreMinimalTuple(), execTuplesUnequal(), TupleHashEntryData::firstTuple, InitTupleHashIterator, TupleHashTableData::keyColIdx, NULL, TupleHashTableData::numCols, ScanTupleHashTable, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and TermTupleHashIterator.

Referenced by ExecHashSubPlan().

618 {
619  int numCols = hashtable->numCols;
620  AttrNumber *keyColIdx = hashtable->keyColIdx;
621  TupleHashIterator hashiter;
622  TupleHashEntry entry;
623 
624  InitTupleHashIterator(hashtable, &hashiter);
625  while ((entry = ScanTupleHashTable(hashtable, &hashiter)) != NULL)
626  {
627  ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false);
628  if (!execTuplesUnequal(slot, hashtable->tableslot,
629  numCols, keyColIdx,
630  eqfunctions,
631  hashtable->tempcxt))
632  {
633  TermTupleHashIterator(&hashiter);
634  return true;
635  }
636  }
637  /* No TermTupleHashIterator call needed here */
638  return false;
639 }
#define ScanTupleHashTable(htable, iter)
Definition: execnodes.h:559
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:384
#define TermTupleHashIterator(iter)
Definition: execnodes.h:555
MinimalTuple firstTuple
Definition: execnodes.h:514
tuplehash_iterator TupleHashIterator
Definition: execnodes.h:546
AttrNumber * keyColIdx
Definition: execnodes.h:532
bool execTuplesUnequal(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: execGrouping.c:139
#define NULL
Definition: c.h:226
TupleTableSlot * tableslot
Definition: execnodes.h:538
#define InitTupleHashIterator(htable, iter)
Definition: execnodes.h:553
MemoryContext tempcxt
Definition: execnodes.h:536
int16 AttrNumber
Definition: attnum.h:21
static bool slotAllNulls ( TupleTableSlot slot)
static

Definition at line 648 of file nodeSubplan.c.

References i, tupleDesc::natts, slot_attisnull(), and TupleTableSlot::tts_tupleDescriptor.

Referenced by ExecHashSubPlan().

649 {
650  int ncols = slot->tts_tupleDescriptor->natts;
651  int i;
652 
653  for (i = 1; i <= ncols; i++)
654  {
655  if (!slot_attisnull(slot, i))
656  return false;
657  }
658  return true;
659 }
int natts
Definition: tupdesc.h:73
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1330
int i
static bool slotNoNulls ( TupleTableSlot slot)
static

Definition at line 668 of file nodeSubplan.c.

References i, tupleDesc::natts, slot_attisnull(), and TupleTableSlot::tts_tupleDescriptor.

Referenced by buildSubPlanHash(), and ExecHashSubPlan().

669 {
670  int ncols = slot->tts_tupleDescriptor->natts;
671  int i;
672 
673  for (i = 1; i <= ncols; i++)
674  {
675  if (slot_attisnull(slot, i))
676  return false;
677  }
678  return true;
679 }
int natts
Definition: tupdesc.h:73
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1330
int i