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