PostgreSQL Source Code  git master
nodeSubplan.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * nodeSubplan.c
4  * routines to support sub-selects appearing in expressions
5  *
6  * This module is concerned with executing SubPlan expression nodes, which
7  * should not be confused with sub-SELECTs appearing in FROM. SubPlans are
8  * divided into "initplans", which are those that need only one evaluation per
9  * query (among other restrictions, this requires that they don't use any
10  * direct correlation variables from the parent plan level), and "regular"
11  * subplans, which are re-evaluated every time their result is required.
12  *
13  *
14  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
15  * Portions Copyright (c) 1994, Regents of the University of California
16  *
17  * IDENTIFICATION
18  * src/backend/executor/nodeSubplan.c
19  *
20  *-------------------------------------------------------------------------
21  */
22 /*
23  * INTERFACE ROUTINES
24  * ExecSubPlan - process a subselect
25  * ExecInitSubPlan - initialize a subselect
26  */
27 #include "postgres.h"
28 
29 #include <limits.h>
30 #include <math.h>
31 
32 #include "access/htup_details.h"
33 #include "executor/executor.h"
34 #include "executor/nodeSubplan.h"
35 #include "nodes/makefuncs.h"
36 #include "miscadmin.h"
37 #include "optimizer/clauses.h"
38 #include "utils/array.h"
39 #include "utils/lsyscache.h"
40 #include "utils/memutils.h"
41 
42 
44  ExprContext *econtext,
45  bool *isNull);
47  ExprContext *econtext,
48  bool *isNull);
49 static void buildSubPlanHash(SubPlanState *node, ExprContext *econtext);
50 static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot,
51  FmgrInfo *eqfunctions);
52 static bool slotAllNulls(TupleTableSlot *slot);
53 static bool slotNoNulls(TupleTableSlot *slot);
54 
55 
56 /* ----------------------------------------------------------------
57  * ExecSubPlan
58  *
59  * This is the main entry point for execution of a regular SubPlan.
60  * ----------------------------------------------------------------
61  */
62 Datum
64  ExprContext *econtext,
65  bool *isNull)
66 {
67  SubPlan *subplan = node->subplan;
68 
70 
71  /* Set non-null as default */
72  *isNull = false;
73 
74  /* Sanity checks */
75  if (subplan->subLinkType == CTE_SUBLINK)
76  elog(ERROR, "CTE subplans should not be executed via ExecSubPlan");
77  if (subplan->setParam != NIL && subplan->subLinkType != MULTIEXPR_SUBLINK)
78  elog(ERROR, "cannot set parent params from subquery");
79 
80  /* Select appropriate evaluation strategy */
81  if (subplan->useHashTable)
82  return ExecHashSubPlan(node, econtext, isNull);
83  else
84  return ExecScanSubPlan(node, econtext, isNull);
85 }
86 
87 /*
88  * ExecHashSubPlan: store subselect result in an in-memory hash table
89  */
90 static Datum
92  ExprContext *econtext,
93  bool *isNull)
94 {
95  SubPlan *subplan = node->subplan;
96  PlanState *planstate = node->planstate;
97  TupleTableSlot *slot;
98 
99  /* Shouldn't have any direct correlation Vars */
100  if (subplan->parParam != NIL || node->args != NIL)
101  elog(ERROR, "hashed subplan with direct correlation not supported");
102 
103  /*
104  * If first time through or we need to rescan the subplan, build the hash
105  * table.
106  */
107  if (node->hashtable == NULL || planstate->chgParam != NULL)
108  buildSubPlanHash(node, econtext);
109 
110  /*
111  * The result for an empty subplan is always FALSE; no need to evaluate
112  * lefthand side.
113  */
114  *isNull = false;
115  if (!node->havehashrows && !node->havenullrows)
116  return BoolGetDatum(false);
117 
118  /*
119  * Evaluate lefthand expressions and form a projection tuple. First we
120  * have to set the econtext to use (hack alert!).
121  */
122  node->projLeft->pi_exprContext = econtext;
123  slot = ExecProject(node->projLeft);
124 
125  /*
126  * Note: because we are typically called in a per-tuple context, we have
127  * to explicitly clear the projected tuple before returning. Otherwise,
128  * we'll have a double-free situation: the per-tuple context will probably
129  * be reset before we're called again, and then the tuple slot will think
130  * it still needs to free the tuple.
131  */
132 
133  /*
134  * If the LHS is all non-null, probe for an exact match in the main hash
135  * table. If we find one, the result is TRUE. Otherwise, scan the
136  * partly-null table to see if there are any rows that aren't provably
137  * unequal to the LHS; if so, the result is UNKNOWN. (We skip that part
138  * if we don't care about UNKNOWN.) Otherwise, the result is FALSE.
139  *
140  * Note: the reason we can avoid a full scan of the main hash table is
141  * that the combining operators are assumed never to yield NULL when both
142  * inputs are non-null. If they were to do so, we might need to produce
143  * UNKNOWN instead of FALSE because of an UNKNOWN result in comparing the
144  * LHS to some main-table entry --- which is a comparison we will not even
145  * make, unless there's a chance match of hash keys.
146  */
147  if (slotNoNulls(slot))
148  {
149  if (node->havehashrows &&
151  slot,
152  node->cur_eq_comp,
153  node->lhs_hash_funcs) != NULL)
154  {
155  ExecClearTuple(slot);
156  return BoolGetDatum(true);
157  }
158  if (node->havenullrows &&
159  findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs))
160  {
161  ExecClearTuple(slot);
162  *isNull = true;
163  return BoolGetDatum(false);
164  }
165  ExecClearTuple(slot);
166  return BoolGetDatum(false);
167  }
168 
169  /*
170  * When the LHS is partly or wholly NULL, we can never return TRUE. If we
171  * don't care about UNKNOWN, just return FALSE. Otherwise, if the LHS is
172  * wholly NULL, immediately return UNKNOWN. (Since the combining
173  * operators are strict, the result could only be FALSE if the sub-select
174  * were empty, but we already handled that case.) Otherwise, we must scan
175  * both the main and partly-null tables to see if there are any rows that
176  * aren't provably unequal to the LHS; if so, the result is UNKNOWN.
177  * Otherwise, the result is FALSE.
178  */
179  if (node->hashnulls == NULL)
180  {
181  ExecClearTuple(slot);
182  return BoolGetDatum(false);
183  }
184  if (slotAllNulls(slot))
185  {
186  ExecClearTuple(slot);
187  *isNull = true;
188  return BoolGetDatum(false);
189  }
190  /* Scan partly-null table first, since more likely to get a match */
191  if (node->havenullrows &&
192  findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs))
193  {
194  ExecClearTuple(slot);
195  *isNull = true;
196  return BoolGetDatum(false);
197  }
198  if (node->havehashrows &&
199  findPartialMatch(node->hashtable, slot, node->cur_eq_funcs))
200  {
201  ExecClearTuple(slot);
202  *isNull = true;
203  return BoolGetDatum(false);
204  }
205  ExecClearTuple(slot);
206  return BoolGetDatum(false);
207 }
208 
209 /*
210  * ExecScanSubPlan: default case where we have to rescan subplan each time
211  */
212 static Datum
214  ExprContext *econtext,
215  bool *isNull)
216 {
217  SubPlan *subplan = node->subplan;
218  PlanState *planstate = node->planstate;
219  SubLinkType subLinkType = subplan->subLinkType;
220  MemoryContext oldcontext;
221  TupleTableSlot *slot;
222  Datum result;
223  bool found = false; /* true if got at least one subplan tuple */
224  ListCell *pvar;
225  ListCell *l;
226  ArrayBuildStateAny *astate = NULL;
227 
228  /*
229  * MULTIEXPR subplans, when "executed", just return NULL; but first we
230  * mark the subplan's output parameters as needing recalculation. (This
231  * is a bit of a hack: it relies on the subplan appearing later in its
232  * targetlist than any of the referencing Params, so that all the Params
233  * have been evaluated before we re-mark them for the next evaluation
234  * cycle. But in general resjunk tlist items appear after non-resjunk
235  * ones, so this should be safe.) Unlike ExecReScanSetParamPlan, we do
236  * *not* set bits in the parent plan node's chgParam, because we don't
237  * want to cause a rescan of the parent.
238  */
239  if (subLinkType == MULTIEXPR_SUBLINK)
240  {
241  EState *estate = node->parent->state;
242 
243  foreach(l, subplan->setParam)
244  {
245  int paramid = lfirst_int(l);
246  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
247 
248  prm->execPlan = node;
249  }
250  *isNull = true;
251  return (Datum) 0;
252  }
253 
254  /* Initialize ArrayBuildStateAny in caller's context, if needed */
255  if (subLinkType == ARRAY_SUBLINK)
256  astate = initArrayResultAny(subplan->firstColType,
257  CurrentMemoryContext, true);
258 
259  /*
260  * We are probably in a short-lived expression-evaluation context. Switch
261  * to the per-query context for manipulating the child plan's chgParam,
262  * calling ExecProcNode on it, etc.
263  */
264  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
265 
266  /*
267  * Set Params of this plan from parent plan correlation values. (Any
268  * calculation we have to do is done in the parent econtext, since the
269  * Param values don't need to have per-query lifetime.)
270  */
271  Assert(list_length(subplan->parParam) == list_length(node->args));
272 
273  forboth(l, subplan->parParam, pvar, node->args)
274  {
275  int paramid = lfirst_int(l);
276  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
277 
279  econtext,
280  &(prm->isnull));
281  planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
282  }
283 
284  /*
285  * Now that we've set up its parameters, we can reset the subplan.
286  */
287  ExecReScan(planstate);
288 
289  /*
290  * For all sublink types except EXPR_SUBLINK and ARRAY_SUBLINK, the result
291  * is boolean as are the results of the combining operators. We combine
292  * results across tuples (if the subplan produces more than one) using OR
293  * semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK.
294  * (ROWCOMPARE_SUBLINK doesn't allow multiple tuples from the subplan.)
295  * NULL results from the combining operators are handled according to the
296  * usual SQL semantics for OR and AND. The result for no input tuples is
297  * FALSE for ANY_SUBLINK, TRUE for ALL_SUBLINK, NULL for
298  * ROWCOMPARE_SUBLINK.
299  *
300  * For EXPR_SUBLINK we require the subplan to produce no more than one
301  * tuple, else an error is raised. If zero tuples are produced, we return
302  * NULL. Assuming we get a tuple, we just use its first column (there can
303  * be only one non-junk column in this case).
304  *
305  * For ARRAY_SUBLINK we allow the subplan to produce any number of tuples,
306  * and form an array of the first column's values. Note in particular
307  * that we produce a zero-element array if no tuples are produced (this is
308  * a change from pre-8.3 behavior of returning NULL).
309  */
310  result = BoolGetDatum(subLinkType == ALL_SUBLINK);
311  *isNull = false;
312 
313  for (slot = ExecProcNode(planstate);
314  !TupIsNull(slot);
315  slot = ExecProcNode(planstate))
316  {
317  TupleDesc tdesc = slot->tts_tupleDescriptor;
318  Datum rowresult;
319  bool rownull;
320  int col;
321  ListCell *plst;
322 
323  if (subLinkType == EXISTS_SUBLINK)
324  {
325  found = true;
326  result = BoolGetDatum(true);
327  break;
328  }
329 
330  if (subLinkType == EXPR_SUBLINK)
331  {
332  /* cannot allow multiple input tuples for EXPR sublink */
333  if (found)
334  ereport(ERROR,
335  (errcode(ERRCODE_CARDINALITY_VIOLATION),
336  errmsg("more than one row returned by a subquery used as an expression")));
337  found = true;
338 
339  /*
340  * We need to copy the subplan's tuple in case the result is of
341  * pass-by-ref type --- our return value will point into this
342  * copied tuple! Can't use the subplan's instance of the tuple
343  * since it won't still be valid after next ExecProcNode() call.
344  * node->curTuple keeps track of the copied tuple for eventual
345  * freeing.
346  */
347  if (node->curTuple)
348  heap_freetuple(node->curTuple);
349  node->curTuple = ExecCopySlotTuple(slot);
350 
351  result = heap_getattr(node->curTuple, 1, tdesc, isNull);
352  /* keep scanning subplan to make sure there's only one tuple */
353  continue;
354  }
355 
356  if (subLinkType == ARRAY_SUBLINK)
357  {
358  Datum dvalue;
359  bool disnull;
360 
361  found = true;
362  /* stash away current value */
363  Assert(subplan->firstColType == TupleDescAttr(tdesc, 0)->atttypid);
364  dvalue = slot_getattr(slot, 1, &disnull);
365  astate = accumArrayResultAny(astate, dvalue, disnull,
366  subplan->firstColType, oldcontext);
367  /* keep scanning subplan to collect all values */
368  continue;
369  }
370 
371  /* cannot allow multiple input tuples for ROWCOMPARE sublink either */
372  if (subLinkType == ROWCOMPARE_SUBLINK && found)
373  ereport(ERROR,
374  (errcode(ERRCODE_CARDINALITY_VIOLATION),
375  errmsg("more than one row returned by a subquery used as an expression")));
376 
377  found = true;
378 
379  /*
380  * For ALL, ANY, and ROWCOMPARE sublinks, load up the Params
381  * representing the columns of the sub-select, and then evaluate the
382  * combining expression.
383  */
384  col = 1;
385  foreach(plst, subplan->paramIds)
386  {
387  int paramid = lfirst_int(plst);
388  ParamExecData *prmdata;
389 
390  prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
391  Assert(prmdata->execPlan == NULL);
392  prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
393  col++;
394  }
395 
396  rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
397  &rownull);
398 
399  if (subLinkType == ANY_SUBLINK)
400  {
401  /* combine across rows per OR semantics */
402  if (rownull)
403  *isNull = true;
404  else if (DatumGetBool(rowresult))
405  {
406  result = BoolGetDatum(true);
407  *isNull = false;
408  break; /* needn't look at any more rows */
409  }
410  }
411  else if (subLinkType == ALL_SUBLINK)
412  {
413  /* combine across rows per AND semantics */
414  if (rownull)
415  *isNull = true;
416  else if (!DatumGetBool(rowresult))
417  {
418  result = BoolGetDatum(false);
419  *isNull = false;
420  break; /* needn't look at any more rows */
421  }
422  }
423  else
424  {
425  /* must be ROWCOMPARE_SUBLINK */
426  result = rowresult;
427  *isNull = rownull;
428  }
429  }
430 
431  MemoryContextSwitchTo(oldcontext);
432 
433  if (subLinkType == ARRAY_SUBLINK)
434  {
435  /* We return the result in the caller's context */
436  result = makeArrayResultAny(astate, oldcontext, true);
437  }
438  else if (!found)
439  {
440  /*
441  * deal with empty subplan result. result/isNull were previously
442  * initialized correctly for all sublink types except EXPR and
443  * ROWCOMPARE; for those, return NULL.
444  */
445  if (subLinkType == EXPR_SUBLINK ||
446  subLinkType == ROWCOMPARE_SUBLINK)
447  {
448  result = (Datum) 0;
449  *isNull = true;
450  }
451  }
452 
453  return result;
454 }
455 
456 /*
457  * buildSubPlanHash: load hash table by scanning subplan output.
458  */
459 static void
461 {
462  SubPlan *subplan = node->subplan;
463  PlanState *planstate = node->planstate;
464  int ncols = list_length(subplan->paramIds);
465  ExprContext *innerecontext = node->innerecontext;
466  MemoryContext oldcontext;
467  long nbuckets;
468  TupleTableSlot *slot;
469 
470  Assert(subplan->subLinkType == ANY_SUBLINK);
471 
472  /*
473  * If we already had any hash tables, destroy 'em; then create empty hash
474  * table(s).
475  *
476  * If we need to distinguish accurately between FALSE and UNKNOWN (i.e.,
477  * NULL) results of the IN operation, then we have to store subplan output
478  * rows that are partly or wholly NULL. We store such rows in a separate
479  * hash table that we expect will be much smaller than the main table. (We
480  * can use hashing to eliminate partly-null rows that are not distinct. We
481  * keep them separate to minimize the cost of the inevitable full-table
482  * searches; see findPartialMatch.)
483  *
484  * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't
485  * need to store subplan output rows that contain NULL.
486  */
488  node->hashtable = NULL;
489  node->hashnulls = NULL;
490  node->havehashrows = false;
491  node->havenullrows = false;
492 
493  nbuckets = (long) Min(planstate->plan->plan_rows, (double) LONG_MAX);
494  if (nbuckets < 1)
495  nbuckets = 1;
496 
497  node->hashtable = BuildTupleHashTable(node->parent,
498  node->descRight,
499  ncols,
500  node->keyColIdx,
501  node->tab_eq_funcoids,
502  node->tab_hash_funcs,
503  nbuckets,
504  0,
505  node->hashtablecxt,
506  node->hashtempcxt,
507  false);
508 
509  if (!subplan->unknownEqFalse)
510  {
511  if (ncols == 1)
512  nbuckets = 1; /* there can only be one entry */
513  else
514  {
515  nbuckets /= 16;
516  if (nbuckets < 1)
517  nbuckets = 1;
518  }
519  node->hashnulls = BuildTupleHashTable(node->parent,
520  node->descRight,
521  ncols,
522  node->keyColIdx,
523  node->tab_eq_funcoids,
524  node->tab_hash_funcs,
525  nbuckets,
526  0,
527  node->hashtablecxt,
528  node->hashtempcxt,
529  false);
530  }
531 
532  /*
533  * We are probably in a short-lived expression-evaluation context. Switch
534  * to the per-query context for manipulating the child plan.
535  */
536  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
537 
538  /*
539  * Reset subplan to start.
540  */
541  ExecReScan(planstate);
542 
543  /*
544  * Scan the subplan and load the hash table(s). Note that when there are
545  * duplicate rows coming out of the sub-select, only one copy is stored.
546  */
547  for (slot = ExecProcNode(planstate);
548  !TupIsNull(slot);
549  slot = ExecProcNode(planstate))
550  {
551  int col = 1;
552  ListCell *plst;
553  bool isnew;
554 
555  /*
556  * Load up the Params representing the raw sub-select outputs, then
557  * form the projection tuple to store in the hashtable.
558  */
559  foreach(plst, subplan->paramIds)
560  {
561  int paramid = lfirst_int(plst);
562  ParamExecData *prmdata;
563 
564  prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);
565  Assert(prmdata->execPlan == NULL);
566  prmdata->value = slot_getattr(slot, col,
567  &(prmdata->isnull));
568  col++;
569  }
570  slot = ExecProject(node->projRight);
571 
572  /*
573  * If result contains any nulls, store separately or not at all.
574  */
575  if (slotNoNulls(slot))
576  {
577  (void) LookupTupleHashEntry(node->hashtable, slot, &isnew);
578  node->havehashrows = true;
579  }
580  else if (node->hashnulls)
581  {
582  (void) LookupTupleHashEntry(node->hashnulls, slot, &isnew);
583  node->havenullrows = true;
584  }
585 
586  /*
587  * Reset innerecontext after each inner tuple to free any memory used
588  * during ExecProject.
589  */
590  ResetExprContext(innerecontext);
591  }
592 
593  /*
594  * Since the projected tuples are in the sub-query's context and not the
595  * main context, we'd better clear the tuple slot before there's any
596  * chance of a reset of the sub-query's context. Else we will have the
597  * potential for a double free attempt. (XXX possibly no longer needed,
598  * but can't hurt.)
599  */
601 
602  MemoryContextSwitchTo(oldcontext);
603 }
604 
605 /*
606  * execTuplesUnequal
607  * Return true if two tuples are definitely unequal in the indicated
608  * fields.
609  *
610  * Nulls are neither equal nor unequal to anything else. A true result
611  * is obtained only if there are non-null fields that compare not-equal.
612  *
613  * slot1, slot2: the tuples to compare (must have same columns!)
614  * numCols: the number of attributes to be examined
615  * matchColIdx: array of attribute column numbers
616  * eqFunctions: array of fmgr lookup info for the equality functions to use
617  * evalContext: short-term memory context for executing the functions
618  */
619 static bool
621  TupleTableSlot *slot2,
622  int numCols,
623  AttrNumber *matchColIdx,
624  FmgrInfo *eqfunctions,
625  MemoryContext evalContext)
626 {
627  MemoryContext oldContext;
628  bool result;
629  int i;
630 
631  /* Reset and switch into the temp context. */
632  MemoryContextReset(evalContext);
633  oldContext = MemoryContextSwitchTo(evalContext);
634 
635  /*
636  * We cannot report a match without checking all the fields, but we can
637  * report a non-match as soon as we find unequal fields. So, start
638  * comparing at the last field (least significant sort key). That's the
639  * most likely to be different if we are dealing with sorted input.
640  */
641  result = false;
642 
643  for (i = numCols; --i >= 0;)
644  {
645  AttrNumber att = matchColIdx[i];
646  Datum attr1,
647  attr2;
648  bool isNull1,
649  isNull2;
650 
651  attr1 = slot_getattr(slot1, att, &isNull1);
652 
653  if (isNull1)
654  continue; /* can't prove anything here */
655 
656  attr2 = slot_getattr(slot2, att, &isNull2);
657 
658  if (isNull2)
659  continue; /* can't prove anything here */
660 
661  /* Apply the type-specific equality function */
662 
663  if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
664  attr1, attr2)))
665  {
666  result = true; /* they are unequal */
667  break;
668  }
669  }
670 
671  MemoryContextSwitchTo(oldContext);
672 
673  return result;
674 }
675 
676 /*
677  * findPartialMatch: does the hashtable contain an entry that is not
678  * provably distinct from the tuple?
679  *
680  * We have to scan the whole hashtable; we can't usefully use hashkeys
681  * to guide probing, since we might get partial matches on tuples with
682  * hashkeys quite unrelated to what we'd get from the given tuple.
683  *
684  * Caller must provide the equality functions to use, since in cross-type
685  * cases these are different from the hashtable's internal functions.
686  */
687 static bool
689  FmgrInfo *eqfunctions)
690 {
691  int numCols = hashtable->numCols;
692  AttrNumber *keyColIdx = hashtable->keyColIdx;
693  TupleHashIterator hashiter;
694  TupleHashEntry entry;
695 
696  InitTupleHashIterator(hashtable, &hashiter);
697  while ((entry = ScanTupleHashTable(hashtable, &hashiter)) != NULL)
698  {
700 
701  ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false);
702  if (!execTuplesUnequal(slot, hashtable->tableslot,
703  numCols, keyColIdx,
704  eqfunctions,
705  hashtable->tempcxt))
706  {
707  TermTupleHashIterator(&hashiter);
708  return true;
709  }
710  }
711  /* No TermTupleHashIterator call needed here */
712  return false;
713 }
714 
715 /*
716  * slotAllNulls: is the slot completely NULL?
717  *
718  * This does not test for dropped columns, which is OK because we only
719  * use it on projected tuples.
720  */
721 static bool
723 {
724  int ncols = slot->tts_tupleDescriptor->natts;
725  int i;
726 
727  for (i = 1; i <= ncols; i++)
728  {
729  if (!slot_attisnull(slot, i))
730  return false;
731  }
732  return true;
733 }
734 
735 /*
736  * slotNoNulls: is the slot entirely not NULL?
737  *
738  * This does not test for dropped columns, which is OK because we only
739  * use it on projected tuples.
740  */
741 static bool
743 {
744  int ncols = slot->tts_tupleDescriptor->natts;
745  int i;
746 
747  for (i = 1; i <= ncols; i++)
748  {
749  if (slot_attisnull(slot, i))
750  return false;
751  }
752  return true;
753 }
754 
755 /* ----------------------------------------------------------------
756  * ExecInitSubPlan
757  *
758  * Create a SubPlanState for a SubPlan; this is the SubPlan-specific part
759  * of ExecInitExpr(). We split it out so that it can be used for InitPlans
760  * as well as regular SubPlans. Note that we don't link the SubPlan into
761  * the parent's subPlan list, because that shouldn't happen for InitPlans.
762  * Instead, ExecInitExpr() does that one part.
763  * ----------------------------------------------------------------
764  */
765 SubPlanState *
767 {
769  EState *estate = parent->state;
770 
771  sstate->subplan = subplan;
772 
773  /* Link the SubPlanState to already-initialized subplan */
774  sstate->planstate = (PlanState *) list_nth(estate->es_subplanstates,
775  subplan->plan_id - 1);
776 
777  /* ... and to its parent's state */
778  sstate->parent = parent;
779 
780  /* Initialize subexpressions */
781  sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent);
782  sstate->args = ExecInitExprList(subplan->args, parent);
783 
784  /*
785  * initialize my state
786  */
787  sstate->curTuple = NULL;
788  sstate->curArray = PointerGetDatum(NULL);
789  sstate->projLeft = NULL;
790  sstate->projRight = NULL;
791  sstate->hashtable = NULL;
792  sstate->hashnulls = NULL;
793  sstate->hashtablecxt = NULL;
794  sstate->hashtempcxt = NULL;
795  sstate->innerecontext = NULL;
796  sstate->keyColIdx = NULL;
797  sstate->tab_eq_funcoids = NULL;
798  sstate->tab_hash_funcs = NULL;
799  sstate->tab_eq_funcs = NULL;
800  sstate->lhs_hash_funcs = NULL;
801  sstate->cur_eq_funcs = NULL;
802 
803  /*
804  * If this is an initplan or MULTIEXPR subplan, it has output parameters
805  * that the parent plan will use, so mark those parameters as needing
806  * evaluation. We don't actually run the subplan until we first need one
807  * of its outputs.
808  *
809  * A CTE subplan's output parameter is never to be evaluated in the normal
810  * way, so skip this in that case.
811  *
812  * Note that we don't set parent->chgParam here: the parent plan hasn't
813  * been run yet, so no need to force it to re-run.
814  */
815  if (subplan->setParam != NIL && subplan->subLinkType != CTE_SUBLINK)
816  {
817  ListCell *lst;
818 
819  foreach(lst, subplan->setParam)
820  {
821  int paramid = lfirst_int(lst);
822  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
823 
824  prm->execPlan = sstate;
825  }
826  }
827 
828  /*
829  * If we are going to hash the subquery output, initialize relevant stuff.
830  * (We don't create the hashtable until needed, though.)
831  */
832  if (subplan->useHashTable)
833  {
834  int ncols,
835  i;
836  TupleDesc tupDescLeft;
837  TupleDesc tupDescRight;
838  TupleTableSlot *slot;
839  List *oplist,
840  *lefttlist,
841  *righttlist;
842  ListCell *l;
843 
844  /* We need a memory context to hold the hash table(s) */
845  sstate->hashtablecxt =
847  "Subplan HashTable Context",
849  /* and a small one for the hash tables to use as temp storage */
850  sstate->hashtempcxt =
852  "Subplan HashTable Temp Context",
854  /* and a short-lived exprcontext for function evaluation */
855  sstate->innerecontext = CreateExprContext(estate);
856  /* Silly little array of column numbers 1..n */
857  ncols = list_length(subplan->paramIds);
858  sstate->keyColIdx = (AttrNumber *) palloc(ncols * sizeof(AttrNumber));
859  for (i = 0; i < ncols; i++)
860  sstate->keyColIdx[i] = i + 1;
861 
862  /*
863  * We use ExecProject to evaluate the lefthand and righthand
864  * expression lists and form tuples. (You might think that we could
865  * use the sub-select's output tuples directly, but that is not the
866  * case if we had to insert any run-time coercions of the sub-select's
867  * output datatypes; anyway this avoids storing any resjunk columns
868  * that might be in the sub-select's output.) Run through the
869  * combining expressions to build tlists for the lefthand and
870  * righthand sides.
871  *
872  * We also extract the combining operators themselves to initialize
873  * the equality and hashing functions for the hash tables.
874  */
875  if (IsA(subplan->testexpr, OpExpr))
876  {
877  /* single combining operator */
878  oplist = list_make1(subplan->testexpr);
879  }
880  else if (and_clause((Node *) subplan->testexpr))
881  {
882  /* multiple combining operators */
883  oplist = castNode(BoolExpr, subplan->testexpr)->args;
884  }
885  else
886  {
887  /* shouldn't see anything else in a hashable subplan */
888  elog(ERROR, "unrecognized testexpr type: %d",
889  (int) nodeTag(subplan->testexpr));
890  oplist = NIL; /* keep compiler quiet */
891  }
892  Assert(list_length(oplist) == ncols);
893 
894  lefttlist = righttlist = NIL;
895  sstate->tab_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid));
896  sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
897  sstate->tab_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
898  sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
899  sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
900  i = 1;
901  foreach(l, oplist)
902  {
903  OpExpr *opexpr = lfirst_node(OpExpr, l);
904  Expr *expr;
905  TargetEntry *tle;
906  Oid rhs_eq_oper;
907  Oid left_hashfn;
908  Oid right_hashfn;
909 
910  Assert(list_length(opexpr->args) == 2);
911 
912  /* Process lefthand argument */
913  expr = (Expr *) linitial(opexpr->args);
914  tle = makeTargetEntry(expr,
915  i,
916  NULL,
917  false);
918  lefttlist = lappend(lefttlist, tle);
919 
920  /* Process righthand argument */
921  expr = (Expr *) lsecond(opexpr->args);
922  tle = makeTargetEntry(expr,
923  i,
924  NULL,
925  false);
926  righttlist = lappend(righttlist, tle);
927 
928  /* Lookup the equality function (potentially cross-type) */
929  sstate->tab_eq_funcoids[i - 1] = opexpr->opfuncid;
930  fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
931  fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]);
932 
933  /* Look up the equality function for the RHS type */
934  if (!get_compatible_hash_operators(opexpr->opno,
935  NULL, &rhs_eq_oper))
936  elog(ERROR, "could not find compatible hash operator for operator %u",
937  opexpr->opno);
938  fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]);
939 
940  /* Lookup the associated hash functions */
941  if (!get_op_hash_functions(opexpr->opno,
942  &left_hashfn, &right_hashfn))
943  elog(ERROR, "could not find hash function for hash operator %u",
944  opexpr->opno);
945  fmgr_info(left_hashfn, &sstate->lhs_hash_funcs[i - 1]);
946  fmgr_info(right_hashfn, &sstate->tab_hash_funcs[i - 1]);
947 
948  i++;
949  }
950 
951  /*
952  * Construct tupdescs, slots and projection nodes for left and right
953  * sides. The lefthand expressions will be evaluated in the parent
954  * plan node's exprcontext, which we don't have access to here.
955  * Fortunately we can just pass NULL for now and fill it in later
956  * (hack alert!). The righthand expressions will be evaluated in our
957  * own innerecontext.
958  */
959  tupDescLeft = ExecTypeFromTL(lefttlist, false);
960  slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
961  sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
962  NULL,
963  slot,
964  parent,
965  NULL);
966 
967  sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
968  slot = ExecInitExtraTupleSlot(estate, tupDescRight);
969  sstate->projRight = ExecBuildProjectionInfo(righttlist,
970  sstate->innerecontext,
971  slot,
972  sstate->planstate,
973  NULL);
974 
975  /*
976  * Create comparator for lookups of rows in the table (potentially
977  * across-type comparison).
978  */
979  sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight,
980  ncols,
981  sstate->keyColIdx,
982  sstate->tab_eq_funcoids,
983  parent);
984 
985  }
986 
987  return sstate;
988 }
989 
990 /* ----------------------------------------------------------------
991  * ExecSetParamPlan
992  *
993  * Executes a subplan and sets its output parameters.
994  *
995  * This is called from ExecEvalParamExec() when the value of a PARAM_EXEC
996  * parameter is requested and the param's execPlan field is set (indicating
997  * that the param has not yet been evaluated). This allows lazy evaluation
998  * of initplans: we don't run the subplan until/unless we need its output.
999  * Note that this routine MUST clear the execPlan fields of the plan's
1000  * output parameters after evaluating them!
1001  * ----------------------------------------------------------------
1002  */
1003 void
1005 {
1006  SubPlan *subplan = node->subplan;
1007  PlanState *planstate = node->planstate;
1008  SubLinkType subLinkType = subplan->subLinkType;
1009  MemoryContext oldcontext;
1010  TupleTableSlot *slot;
1011  ListCell *pvar;
1012  ListCell *l;
1013  bool found = false;
1014  ArrayBuildStateAny *astate = NULL;
1015 
1016  if (subLinkType == ANY_SUBLINK ||
1017  subLinkType == ALL_SUBLINK)
1018  elog(ERROR, "ANY/ALL subselect unsupported as initplan");
1019  if (subLinkType == CTE_SUBLINK)
1020  elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan");
1021 
1022  /* Initialize ArrayBuildStateAny in caller's context, if needed */
1023  if (subLinkType == ARRAY_SUBLINK)
1024  astate = initArrayResultAny(subplan->firstColType,
1025  CurrentMemoryContext, true);
1026 
1027  /*
1028  * Must switch to per-query memory context.
1029  */
1030  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1031 
1032  /*
1033  * Set Params of this plan from parent plan correlation values. (Any
1034  * calculation we have to do is done in the parent econtext, since the
1035  * Param values don't need to have per-query lifetime.) Currently, we
1036  * expect only MULTIEXPR_SUBLINK plans to have any correlation values.
1037  */
1038  Assert(subplan->parParam == NIL || subLinkType == MULTIEXPR_SUBLINK);
1039  Assert(list_length(subplan->parParam) == list_length(node->args));
1040 
1041  forboth(l, subplan->parParam, pvar, node->args)
1042  {
1043  int paramid = lfirst_int(l);
1044  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1045 
1047  econtext,
1048  &(prm->isnull));
1049  planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
1050  }
1051 
1052  /*
1053  * Run the plan. (If it needs to be rescanned, the first ExecProcNode
1054  * call will take care of that.)
1055  */
1056  for (slot = ExecProcNode(planstate);
1057  !TupIsNull(slot);
1058  slot = ExecProcNode(planstate))
1059  {
1060  TupleDesc tdesc = slot->tts_tupleDescriptor;
1061  int i = 1;
1062 
1063  if (subLinkType == EXISTS_SUBLINK)
1064  {
1065  /* There can be only one setParam... */
1066  int paramid = linitial_int(subplan->setParam);
1067  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1068 
1069  prm->execPlan = NULL;
1070  prm->value = BoolGetDatum(true);
1071  prm->isnull = false;
1072  found = true;
1073  break;
1074  }
1075 
1076  if (subLinkType == ARRAY_SUBLINK)
1077  {
1078  Datum dvalue;
1079  bool disnull;
1080 
1081  found = true;
1082  /* stash away current value */
1083  Assert(subplan->firstColType == TupleDescAttr(tdesc, 0)->atttypid);
1084  dvalue = slot_getattr(slot, 1, &disnull);
1085  astate = accumArrayResultAny(astate, dvalue, disnull,
1086  subplan->firstColType, oldcontext);
1087  /* keep scanning subplan to collect all values */
1088  continue;
1089  }
1090 
1091  if (found &&
1092  (subLinkType == EXPR_SUBLINK ||
1093  subLinkType == MULTIEXPR_SUBLINK ||
1094  subLinkType == ROWCOMPARE_SUBLINK))
1095  ereport(ERROR,
1096  (errcode(ERRCODE_CARDINALITY_VIOLATION),
1097  errmsg("more than one row returned by a subquery used as an expression")));
1098 
1099  found = true;
1100 
1101  /*
1102  * We need to copy the subplan's tuple into our own context, in case
1103  * any of the params are pass-by-ref type --- the pointers stored in
1104  * the param structs will point at this copied tuple! node->curTuple
1105  * keeps track of the copied tuple for eventual freeing.
1106  */
1107  if (node->curTuple)
1108  heap_freetuple(node->curTuple);
1109  node->curTuple = ExecCopySlotTuple(slot);
1110 
1111  /*
1112  * Now set all the setParam params from the columns of the tuple
1113  */
1114  foreach(l, subplan->setParam)
1115  {
1116  int paramid = lfirst_int(l);
1117  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1118 
1119  prm->execPlan = NULL;
1120  prm->value = heap_getattr(node->curTuple, i, tdesc,
1121  &(prm->isnull));
1122  i++;
1123  }
1124  }
1125 
1126  if (subLinkType == ARRAY_SUBLINK)
1127  {
1128  /* There can be only one setParam... */
1129  int paramid = linitial_int(subplan->setParam);
1130  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1131 
1132  /*
1133  * We build the result array in query context so it won't disappear;
1134  * to avoid leaking memory across repeated calls, we have to remember
1135  * the latest value, much as for curTuple above.
1136  */
1137  if (node->curArray != PointerGetDatum(NULL))
1138  pfree(DatumGetPointer(node->curArray));
1139  node->curArray = makeArrayResultAny(astate,
1140  econtext->ecxt_per_query_memory,
1141  true);
1142  prm->execPlan = NULL;
1143  prm->value = node->curArray;
1144  prm->isnull = false;
1145  }
1146  else if (!found)
1147  {
1148  if (subLinkType == EXISTS_SUBLINK)
1149  {
1150  /* There can be only one setParam... */
1151  int paramid = linitial_int(subplan->setParam);
1152  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1153 
1154  prm->execPlan = NULL;
1155  prm->value = BoolGetDatum(false);
1156  prm->isnull = false;
1157  }
1158  else
1159  {
1160  /* For other sublink types, set all the output params to NULL */
1161  foreach(l, subplan->setParam)
1162  {
1163  int paramid = lfirst_int(l);
1164  ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
1165 
1166  prm->execPlan = NULL;
1167  prm->value = (Datum) 0;
1168  prm->isnull = true;
1169  }
1170  }
1171  }
1172 
1173  MemoryContextSwitchTo(oldcontext);
1174 }
1175 
1176 /*
1177  * Mark an initplan as needing recalculation
1178  */
1179 void
1181 {
1182  PlanState *planstate = node->planstate;
1183  SubPlan *subplan = node->subplan;
1184  EState *estate = parent->state;
1185  ListCell *l;
1186 
1187  /* sanity checks */
1188  if (subplan->parParam != NIL)
1189  elog(ERROR, "direct correlated subquery unsupported as initplan");
1190  if (subplan->setParam == NIL)
1191  elog(ERROR, "setParam list of initplan is empty");
1192  if (bms_is_empty(planstate->plan->extParam))
1193  elog(ERROR, "extParam set of initplan is empty");
1194 
1195  /*
1196  * Don't actually re-scan: it'll happen inside ExecSetParamPlan if needed.
1197  */
1198 
1199  /*
1200  * Mark this subplan's output parameters as needing recalculation.
1201  *
1202  * CTE subplans are never executed via parameter recalculation; instead
1203  * they get run when called by nodeCtescan.c. So don't mark the output
1204  * parameter of a CTE subplan as dirty, but do set the chgParam bit for it
1205  * so that dependent plan nodes will get told to rescan.
1206  */
1207  foreach(l, subplan->setParam)
1208  {
1209  int paramid = lfirst_int(l);
1210  ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
1211 
1212  if (subplan->subLinkType != CTE_SUBLINK)
1213  prm->execPlan = node;
1214 
1215  parent->chgParam = bms_add_member(parent->chgParam, paramid);
1216  }
1217 }
1218 
1219 
1220 /*
1221  * ExecInitAlternativeSubPlan
1222  *
1223  * Initialize for execution of one of a set of alternative subplans.
1224  */
1227 {
1229  double num_calls;
1230  SubPlan *subplan1;
1231  SubPlan *subplan2;
1232  Cost cost1;
1233  Cost cost2;
1234  ListCell *lc;
1235 
1236  asstate->subplan = asplan;
1237 
1238  /*
1239  * Initialize subplans. (Can we get away with only initializing the one
1240  * we're going to use?)
1241  */
1242  foreach(lc, asplan->subplans)
1243  {
1244  SubPlan *sp = lfirst_node(SubPlan, lc);
1245  SubPlanState *sps = ExecInitSubPlan(sp, parent);
1246 
1247  asstate->subplans = lappend(asstate->subplans, sps);
1248  parent->subPlan = lappend(parent->subPlan, sps);
1249  }
1250 
1251  /*
1252  * Select the one to be used. For this, we need an estimate of the number
1253  * of executions of the subplan. We use the number of output rows
1254  * expected from the parent plan node. This is a good estimate if we are
1255  * in the parent's targetlist, and an underestimate (but probably not by
1256  * more than a factor of 2) if we are in the qual.
1257  */
1258  num_calls = parent->plan->plan_rows;
1259 
1260  /*
1261  * The planner saved enough info so that we don't have to work very hard
1262  * to estimate the total cost, given the number-of-calls estimate.
1263  */
1264  Assert(list_length(asplan->subplans) == 2);
1265  subplan1 = (SubPlan *) linitial(asplan->subplans);
1266  subplan2 = (SubPlan *) lsecond(asplan->subplans);
1267 
1268  cost1 = subplan1->startup_cost + num_calls * subplan1->per_call_cost;
1269  cost2 = subplan2->startup_cost + num_calls * subplan2->per_call_cost;
1270 
1271  if (cost1 < cost2)
1272  asstate->active = 0;
1273  else
1274  asstate->active = 1;
1275 
1276  return asstate;
1277 }
1278 
1279 /*
1280  * ExecAlternativeSubPlan
1281  *
1282  * Execute one of a set of alternative subplans.
1283  *
1284  * Note: in future we might consider changing to different subplans on the
1285  * fly, in case the original rowcount estimate turns out to be way off.
1286  */
1287 Datum
1289  ExprContext *econtext,
1290  bool *isNull)
1291 {
1292  /* Just pass control to the active subplan */
1294  node->subplans, node->active);
1295 
1296  return ExecSubPlan(activesp, econtext, isNull);
1297 }
#define NIL
Definition: pg_list.h:69
#define ScanTupleHashTable(htable, iter)
Definition: execnodes.h:654
Oid firstColType
Definition: primnodes.h:693
Definition: fmgr.h:56
double plan_rows
Definition: plannodes.h:131
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition: lsyscache.c:407
void * execPlan
Definition: params.h:147
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
ProjectionInfo * projLeft
Definition: execnodes.h:786
HeapTuple curTuple
Definition: execnodes.h:782
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:507
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:420
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:297
ExprState * ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, int numCols, AttrNumber *keyColIdx, Oid *eqfunctions, PlanState *parent)
Definition: execExpr.c:3209
TupleHashTable hashtable
Definition: execnodes.h:788
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
int plan_id
Definition: primnodes.h:689
ExprContext * innerecontext
Definition: execnodes.h:794
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5468
#define TermTupleHashIterator(iter)
Definition: execnodes.h:650
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
#define PointerGetDatum(X)
Definition: postgres.h:539
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
MinimalTuple firstTuple
Definition: execnodes.h:608
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
tuplehash_iterator TupleHashIterator
Definition: execnodes.h:641
#define Min(x, y)
Definition: c.h:846
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, FmgrInfo *hashfunctions)
Definition: execGrouping.c:291
List * subPlan
Definition: execnodes.h:891
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AttrNumber * keyColIdx
Definition: execnodes.h:626
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:605
SubLinkType subLinkType
Definition: primnodes.h:684
Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:1288
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid * tab_eq_funcoids
Definition: execnodes.h:796
List * paramIds
Definition: primnodes.h:687
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:134
ExprState * testexpr
Definition: execnodes.h:780
EState * state
Definition: execnodes.h:870
TupleTableSlot * resultslot
Definition: execnodes.h:73
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:79
#define lsecond(l)
Definition: pg_list.h:116
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
Definition: execTuples.c:910
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
Definition: nodeSubplan.c:766
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:797
#define list_make1(x1)
Definition: pg_list.h:139
#define linitial_int(l)
Definition: pg_list.h:112
ParamExecData * es_param_exec_vals
Definition: execnodes.h:483
void pfree(void *pointer)
Definition: mcxt.c:936
ExprState * cur_eq_comp
Definition: execnodes.h:801
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
struct PlanState * planstate
Definition: execnodes.h:778
void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
Definition: nodeSubplan.c:1180
List * args
Definition: execnodes.h:781
SubPlan * subplan
Definition: execnodes.h:777
#define lfirst_int(lc)
Definition: pg_list.h:107
void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:1004
bool isnull
Definition: params.h:149
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
AlternativeSubPlan * subplan
Definition: execnodes.h:811
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
AttrNumber * keyColIdx
Definition: execnodes.h:795
#define lfirst_node(type, lc)
Definition: pg_list.h:109
bool and_clause(Node *clause)
Definition: clauses.c:317
#define list_nth_node(type, list, n)
Definition: pg_list.h:227
void * list_nth(const List *list, int n)
Definition: list.c:410
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:104
#define DatumGetBool(X)
Definition: postgres.h:376
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:313
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:220
bool havenullrows
Definition: execnodes.h:791
#define TupIsNull(slot)
Definition: tuptable.h:139
struct PlanState * parent
Definition: execnodes.h:779
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:233
#define ereport(elevel, rest)
Definition: elog.h:122
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
static bool slotNoNulls(TupleTableSlot *slot)
Definition: nodeSubplan.c:742
static Datum ExecHashSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:91
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:944
Bitmapset * chgParam
Definition: execnodes.h:896
SubLinkType
Definition: primnodes.h:618
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:707
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
ArrayBuildStateAny * accumArrayResultAny(ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5513
static bool slotAllNulls(TupleTableSlot *slot)
Definition: nodeSubplan.c:722
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:581
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
Datum curArray
Definition: execnodes.h:783
uintptr_t Datum
Definition: postgres.h:365
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:234
Oid opfuncid
Definition: primnodes.h:497
Node * testexpr
Definition: primnodes.h:686
Plan * plan
Definition: execnodes.h:868
#define BoolGetDatum(X)
Definition: postgres.h:385
Cost per_call_cost
Definition: primnodes.h:713
MemoryContext hashtempcxt
Definition: execnodes.h:793
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1079
MemoryContext hashtablecxt
Definition: execnodes.h:792
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1329
static Datum ExecScanSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:213
#define makeNode(_type_)
Definition: nodes.h:561
AlternativeSubPlanState * ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
Definition: nodeSubplan.c:1226
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
FmgrInfo * tab_eq_funcs
Definition: execnodes.h:798
TupleTableSlot * tableslot
Definition: execnodes.h:632
static bool execTuplesUnequal(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: nodeSubplan.c:620
List * setParam
Definition: primnodes.h:707
bool unknownEqFalse
Definition: primnodes.h:700
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * extParam
Definition: plannodes.h:162
#define InitTupleHashIterator(htable, iter)
Definition: execnodes.h:648
List * parParam
Definition: primnodes.h:709
List * es_subplanstates
Definition: execnodes.h:503
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:216
FmgrInfo * lhs_hash_funcs
Definition: execnodes.h:799
#define nodeTag(nodeptr)
Definition: nodes.h:518
#define DatumGetPointer(X)
Definition: postgres.h:532
FmgrInfo * cur_eq_funcs
Definition: execnodes.h:800
static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions)
Definition: nodeSubplan.c:688
Datum makeArrayResultAny(ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5541
void * palloc(Size size)
Definition: mcxt.c:835
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:348
int errmsg(const char *fmt,...)
Definition: elog.c:797
TupleHashTable BuildTupleHashTable(PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, Oid *eqfuncoids, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:152
TupleDesc descRight
Definition: execnodes.h:785
Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:63
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1142
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:225
Datum value
Definition: params.h:148
static void buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:460
ExprState pi_state
Definition: execnodes.h:310
bool useHashTable
Definition: primnodes.h:698
MemoryContext tempcxt
Definition: execnodes.h:630
ProjectionInfo * projRight
Definition: execnodes.h:787
Cost startup_cost
Definition: primnodes.h:712
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:118
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
ExprContext * pi_exprContext
Definition: execnodes.h:312
Definition: pg_list.h:45
bool havehashrows
Definition: execnodes.h:790
int16 AttrNumber
Definition: attnum.h:21
TupleHashTable hashnulls
Definition: execnodes.h:789
double Cost
Definition: nodes.h:644
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: executor.h:325
#define ResetExprContext(econtext)
Definition: executor.h:484
List * args
Definition: primnodes.h:710