]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeSubplan.c
Post-feature-freeze pgindent run.
[postgresql] / src / backend / executor / nodeSubplan.c
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
43 static Datum ExecHashSubPlan(SubPlanState *node,
44                                 ExprContext *econtext,
45                                 bool *isNull);
46 static Datum ExecScanSubPlan(SubPlanState *node,
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
63 ExecSubPlan(SubPlanState *node,
64                         ExprContext *econtext,
65                         bool *isNull)
66 {
67         SubPlan    *subplan = node->subplan;
68
69         CHECK_FOR_INTERRUPTS();
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
91 ExecHashSubPlan(SubPlanState *node,
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 &&
150                         FindTupleHashEntry(node->hashtable,
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
213 ExecScanSubPlan(SubPlanState *node,
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
278                 prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
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
460 buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
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          */
487         MemoryContextReset(node->hashtablecxt);
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          */
600         ExecClearTuple(node->projRight->pi_state.resultslot);
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
620 execTuplesUnequal(TupleTableSlot *slot1,
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
688 findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot,
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         {
699                 CHECK_FOR_INTERRUPTS();
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
722 slotAllNulls(TupleTableSlot *slot)
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
742 slotNoNulls(TupleTableSlot *slot)
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 *
766 ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
767 {
768         SubPlanState *sstate = makeNode(SubPlanState);
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 =
846                         AllocSetContextCreate(CurrentMemoryContext,
847                                                                   "Subplan HashTable Context",
848                                                                   ALLOCSET_DEFAULT_SIZES);
849                 /* and a small one for the hash tables to use as temp storage */
850                 sstate->hashtempcxt =
851                         AllocSetContextCreate(CurrentMemoryContext,
852                                                                   "Subplan HashTable Temp Context",
853                                                                   ALLOCSET_SMALL_SIZES);
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
1004 ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
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
1046                 prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
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
1180 ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
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  */
1225 AlternativeSubPlanState *
1226 ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
1227 {
1228         AlternativeSubPlanState *asstate = makeNode(AlternativeSubPlanState);
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
1288 ExecAlternativeSubPlan(AlternativeSubPlanState *node,
1289                                            ExprContext *econtext,
1290                                            bool *isNull)
1291 {
1292         /* Just pass control to the active subplan */
1293         SubPlanState *activesp = list_nth_node(SubPlanState,
1294                                                                                    node->subplans, node->active);
1295
1296         return ExecSubPlan(activesp, econtext, isNull);
1297 }