1 /*-------------------------------------------------------------------------
4 * routines to support subselects
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
12 *-------------------------------------------------------------------------
16 * ExecSubPlan - process a subselect
17 * ExecInitSubPlan - initialize a subselect
23 #include "executor/executor.h"
24 #include "executor/nodeSubplan.h"
25 #include "nodes/makefuncs.h"
26 #include "optimizer/clauses.h"
27 #include "utils/array.h"
28 #include "utils/lsyscache.h"
29 #include "utils/memutils.h"
32 static Datum
ExecSubPlan(SubPlanState
*node
,
33 ExprContext
*econtext
,
35 ExprDoneCond
*isDone
);
36 static Datum
ExecAlternativeSubPlan(AlternativeSubPlanState
*node
,
37 ExprContext
*econtext
,
39 ExprDoneCond
*isDone
);
40 static Datum
ExecHashSubPlan(SubPlanState
*node
,
41 ExprContext
*econtext
,
43 static Datum
ExecScanSubPlan(SubPlanState
*node
,
44 ExprContext
*econtext
,
46 static void buildSubPlanHash(SubPlanState
*node
, ExprContext
*econtext
);
47 static bool findPartialMatch(TupleHashTable hashtable
, TupleTableSlot
*slot
);
48 static bool slotAllNulls(TupleTableSlot
*slot
);
49 static bool slotNoNulls(TupleTableSlot
*slot
);
52 /* ----------------------------------------------------------------
54 * ----------------------------------------------------------------
57 ExecSubPlan(SubPlanState
*node
,
58 ExprContext
*econtext
,
62 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
64 /* Set default values for result flags: non-null, not a set result */
67 *isDone
= ExprSingleResult
;
70 if (subplan
->subLinkType
== CTE_SUBLINK
)
71 elog(ERROR
, "CTE subplans should not be executed via ExecSubPlan");
72 if (subplan
->setParam
!= NIL
)
73 elog(ERROR
, "cannot set parent params from subquery");
75 /* Select appropriate evaluation strategy */
76 if (subplan
->useHashTable
)
77 return ExecHashSubPlan(node
, econtext
, isNull
);
79 return ExecScanSubPlan(node
, econtext
, isNull
);
83 * ExecHashSubPlan: store subselect result in an in-memory hash table
86 ExecHashSubPlan(SubPlanState
*node
,
87 ExprContext
*econtext
,
90 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
91 PlanState
*planstate
= node
->planstate
;
92 ExprContext
*innerecontext
= node
->innerecontext
;
95 /* Shouldn't have any direct correlation Vars */
96 if (subplan
->parParam
!= NIL
|| node
->args
!= NIL
)
97 elog(ERROR
, "hashed subplan with direct correlation not supported");
100 * If first time through or we need to rescan the subplan, build the hash
103 if (node
->hashtable
== NULL
|| planstate
->chgParam
!= NULL
)
104 buildSubPlanHash(node
, econtext
);
107 * The result for an empty subplan is always FALSE; no need to evaluate
111 if (!node
->havehashrows
&& !node
->havenullrows
)
112 return BoolGetDatum(false);
115 * Evaluate lefthand expressions and form a projection tuple. First we
116 * have to set the econtext to use (hack alert!).
118 node
->projLeft
->pi_exprContext
= econtext
;
119 slot
= ExecProject(node
->projLeft
, NULL
);
122 * Note: because we are typically called in a per-tuple context, we have
123 * to explicitly clear the projected tuple before returning. Otherwise,
124 * we'll have a double-free situation: the per-tuple context will probably
125 * be reset before we're called again, and then the tuple slot will think
126 * it still needs to free the tuple.
130 * Since the hashtable routines will use innerecontext's per-tuple memory
131 * as working memory, be sure to reset it for each tuple.
133 ResetExprContext(innerecontext
);
136 * If the LHS is all non-null, probe for an exact match in the main hash
137 * table. If we find one, the result is TRUE. Otherwise, scan the
138 * partly-null table to see if there are any rows that aren't provably
139 * unequal to the LHS; if so, the result is UNKNOWN. (We skip that part
140 * if we don't care about UNKNOWN.) Otherwise, the result is FALSE.
142 * Note: the reason we can avoid a full scan of the main hash table is
143 * that the combining operators are assumed never to yield NULL when both
144 * inputs are non-null. If they were to do so, we might need to produce
145 * UNKNOWN instead of FALSE because of an UNKNOWN result in comparing the
146 * LHS to some main-table entry --- which is a comparison we will not even
147 * make, unless there's a chance match of hash keys.
149 if (slotNoNulls(slot
))
151 if (node
->havehashrows
&&
152 FindTupleHashEntry(node
->hashtable
,
155 node
->lhs_hash_funcs
) != NULL
)
157 ExecClearTuple(slot
);
158 return BoolGetDatum(true);
160 if (node
->havenullrows
&&
161 findPartialMatch(node
->hashnulls
, slot
))
163 ExecClearTuple(slot
);
165 return BoolGetDatum(false);
167 ExecClearTuple(slot
);
168 return BoolGetDatum(false);
172 * When the LHS is partly or wholly NULL, we can never return TRUE. If we
173 * don't care about UNKNOWN, just return FALSE. Otherwise, if the LHS is
174 * wholly NULL, immediately return UNKNOWN. (Since the combining
175 * operators are strict, the result could only be FALSE if the sub-select
176 * were empty, but we already handled that case.) Otherwise, we must scan
177 * both the main and partly-null tables to see if there are any rows that
178 * aren't provably unequal to the LHS; if so, the result is UNKNOWN.
179 * Otherwise, the result is FALSE.
181 if (node
->hashnulls
== NULL
)
183 ExecClearTuple(slot
);
184 return BoolGetDatum(false);
186 if (slotAllNulls(slot
))
188 ExecClearTuple(slot
);
190 return BoolGetDatum(false);
192 /* Scan partly-null table first, since more likely to get a match */
193 if (node
->havenullrows
&&
194 findPartialMatch(node
->hashnulls
, slot
))
196 ExecClearTuple(slot
);
198 return BoolGetDatum(false);
200 if (node
->havehashrows
&&
201 findPartialMatch(node
->hashtable
, slot
))
203 ExecClearTuple(slot
);
205 return BoolGetDatum(false);
207 ExecClearTuple(slot
);
208 return BoolGetDatum(false);
212 * ExecScanSubPlan: default case where we have to rescan subplan each time
215 ExecScanSubPlan(SubPlanState
*node
,
216 ExprContext
*econtext
,
219 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
220 PlanState
*planstate
= node
->planstate
;
221 SubLinkType subLinkType
= subplan
->subLinkType
;
222 MemoryContext oldcontext
;
223 TupleTableSlot
*slot
;
225 bool found
= false; /* TRUE if got at least one subplan tuple */
228 ArrayBuildState
*astate
= NULL
;
231 * We are probably in a short-lived expression-evaluation context. Switch
232 * to the per-query context for manipulating the child plan's chgParam,
233 * calling ExecProcNode on it, etc.
235 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
238 * Set Params of this plan from parent plan correlation values. (Any
239 * calculation we have to do is done in the parent econtext, since the
240 * Param values don't need to have per-query lifetime.)
242 Assert(list_length(subplan
->parParam
) == list_length(node
->args
));
244 forboth(l
, subplan
->parParam
, pvar
, node
->args
)
246 int paramid
= lfirst_int(l
);
247 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
249 prm
->value
= ExecEvalExprSwitchContext((ExprState
*) lfirst(pvar
),
253 planstate
->chgParam
= bms_add_member(planstate
->chgParam
, paramid
);
257 * Now that we've set up its parameters, we can reset the subplan.
259 ExecReScan(planstate
, NULL
);
262 * For all sublink types except EXPR_SUBLINK and ARRAY_SUBLINK, the result
263 * is boolean as are the results of the combining operators. We combine
264 * results across tuples (if the subplan produces more than one) using OR
265 * semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK.
266 * (ROWCOMPARE_SUBLINK doesn't allow multiple tuples from the subplan.)
267 * NULL results from the combining operators are handled according to the
268 * usual SQL semantics for OR and AND. The result for no input tuples is
269 * FALSE for ANY_SUBLINK, TRUE for ALL_SUBLINK, NULL for
270 * ROWCOMPARE_SUBLINK.
272 * For EXPR_SUBLINK we require the subplan to produce no more than one
273 * tuple, else an error is raised. If zero tuples are produced, we return
274 * NULL. Assuming we get a tuple, we just use its first column (there can
275 * be only one non-junk column in this case).
277 * For ARRAY_SUBLINK we allow the subplan to produce any number of tuples,
278 * and form an array of the first column's values. Note in particular
279 * that we produce a zero-element array if no tuples are produced (this is
280 * a change from pre-8.3 behavior of returning NULL).
282 result
= BoolGetDatum(subLinkType
== ALL_SUBLINK
);
285 for (slot
= ExecProcNode(planstate
);
287 slot
= ExecProcNode(planstate
))
289 TupleDesc tdesc
= slot
->tts_tupleDescriptor
;
295 if (subLinkType
== EXISTS_SUBLINK
)
298 result
= BoolGetDatum(true);
302 if (subLinkType
== EXPR_SUBLINK
)
304 /* cannot allow multiple input tuples for EXPR sublink */
307 (errcode(ERRCODE_CARDINALITY_VIOLATION
),
308 errmsg("more than one row returned by a subquery used as an expression")));
312 * We need to copy the subplan's tuple in case the result is of
313 * pass-by-ref type --- our return value will point into this
314 * copied tuple! Can't use the subplan's instance of the tuple
315 * since it won't still be valid after next ExecProcNode() call.
316 * node->curTuple keeps track of the copied tuple for eventual
320 heap_freetuple(node
->curTuple
);
321 node
->curTuple
= ExecCopySlotTuple(slot
);
323 result
= heap_getattr(node
->curTuple
, 1, tdesc
, isNull
);
324 /* keep scanning subplan to make sure there's only one tuple */
328 if (subLinkType
== ARRAY_SUBLINK
)
334 /* stash away current value */
335 Assert(subplan
->firstColType
== tdesc
->attrs
[0]->atttypid
);
336 dvalue
= slot_getattr(slot
, 1, &disnull
);
337 astate
= accumArrayResult(astate
, dvalue
, disnull
,
338 subplan
->firstColType
, oldcontext
);
339 /* keep scanning subplan to collect all values */
343 /* cannot allow multiple input tuples for ROWCOMPARE sublink either */
344 if (subLinkType
== ROWCOMPARE_SUBLINK
&& found
)
346 (errcode(ERRCODE_CARDINALITY_VIOLATION
),
347 errmsg("more than one row returned by a subquery used as an expression")));
352 * For ALL, ANY, and ROWCOMPARE sublinks, load up the Params
353 * representing the columns of the sub-select, and then evaluate the
354 * combining expression.
357 foreach(plst
, subplan
->paramIds
)
359 int paramid
= lfirst_int(plst
);
360 ParamExecData
*prmdata
;
362 prmdata
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
363 Assert(prmdata
->execPlan
== NULL
);
364 prmdata
->value
= slot_getattr(slot
, col
, &(prmdata
->isnull
));
368 rowresult
= ExecEvalExprSwitchContext(node
->testexpr
, econtext
,
371 if (subLinkType
== ANY_SUBLINK
)
373 /* combine across rows per OR semantics */
376 else if (DatumGetBool(rowresult
))
378 result
= BoolGetDatum(true);
380 break; /* needn't look at any more rows */
383 else if (subLinkType
== ALL_SUBLINK
)
385 /* combine across rows per AND semantics */
388 else if (!DatumGetBool(rowresult
))
390 result
= BoolGetDatum(false);
392 break; /* needn't look at any more rows */
397 /* must be ROWCOMPARE_SUBLINK */
403 MemoryContextSwitchTo(oldcontext
);
405 if (subLinkType
== ARRAY_SUBLINK
)
407 /* We return the result in the caller's context */
409 result
= makeArrayResult(astate
, oldcontext
);
411 result
= PointerGetDatum(construct_empty_array(subplan
->firstColType
));
416 * deal with empty subplan result. result/isNull were previously
417 * initialized correctly for all sublink types except EXPR and
418 * ROWCOMPARE; for those, return NULL.
420 if (subLinkType
== EXPR_SUBLINK
||
421 subLinkType
== ROWCOMPARE_SUBLINK
)
432 * buildSubPlanHash: load hash table by scanning subplan output.
435 buildSubPlanHash(SubPlanState
*node
, ExprContext
*econtext
)
437 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
438 PlanState
*planstate
= node
->planstate
;
439 int ncols
= list_length(subplan
->paramIds
);
440 ExprContext
*innerecontext
= node
->innerecontext
;
441 MemoryContext tempcxt
= innerecontext
->ecxt_per_tuple_memory
;
442 MemoryContext oldcontext
;
444 TupleTableSlot
*slot
;
446 Assert(subplan
->subLinkType
== ANY_SUBLINK
);
449 * If we already had any hash tables, destroy 'em; then create empty hash
452 * If we need to distinguish accurately between FALSE and UNKNOWN (i.e.,
453 * NULL) results of the IN operation, then we have to store subplan output
454 * rows that are partly or wholly NULL. We store such rows in a separate
455 * hash table that we expect will be much smaller than the main table. (We
456 * can use hashing to eliminate partly-null rows that are not distinct. We
457 * keep them separate to minimize the cost of the inevitable full-table
458 * searches; see findPartialMatch.)
460 * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't
461 * need to store subplan output rows that contain NULL.
463 MemoryContextReset(node
->tablecxt
);
464 node
->hashtable
= NULL
;
465 node
->hashnulls
= NULL
;
466 node
->havehashrows
= false;
467 node
->havenullrows
= false;
469 nbuckets
= (int) ceil(planstate
->plan
->plan_rows
);
473 node
->hashtable
= BuildTupleHashTable(ncols
,
476 node
->tab_hash_funcs
,
478 sizeof(TupleHashEntryData
),
482 if (!subplan
->unknownEqFalse
)
485 nbuckets
= 1; /* there can only be one entry */
492 node
->hashnulls
= BuildTupleHashTable(ncols
,
495 node
->tab_hash_funcs
,
497 sizeof(TupleHashEntryData
),
503 * We are probably in a short-lived expression-evaluation context. Switch
504 * to the per-query context for manipulating the child plan.
506 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
509 * Reset subplan to start.
511 ExecReScan(planstate
, NULL
);
514 * Scan the subplan and load the hash table(s). Note that when there are
515 * duplicate rows coming out of the sub-select, only one copy is stored.
517 for (slot
= ExecProcNode(planstate
);
519 slot
= ExecProcNode(planstate
))
526 * Load up the Params representing the raw sub-select outputs, then
527 * form the projection tuple to store in the hashtable.
529 foreach(plst
, subplan
->paramIds
)
531 int paramid
= lfirst_int(plst
);
532 ParamExecData
*prmdata
;
534 prmdata
= &(innerecontext
->ecxt_param_exec_vals
[paramid
]);
535 Assert(prmdata
->execPlan
== NULL
);
536 prmdata
->value
= slot_getattr(slot
, col
,
540 slot
= ExecProject(node
->projRight
, NULL
);
543 * If result contains any nulls, store separately or not at all.
545 if (slotNoNulls(slot
))
547 (void) LookupTupleHashEntry(node
->hashtable
, slot
, &isnew
);
548 node
->havehashrows
= true;
550 else if (node
->hashnulls
)
552 (void) LookupTupleHashEntry(node
->hashnulls
, slot
, &isnew
);
553 node
->havenullrows
= true;
557 * Reset innerecontext after each inner tuple to free any memory used
558 * in hash computation or comparison routines.
560 ResetExprContext(innerecontext
);
564 * Since the projected tuples are in the sub-query's context and not the
565 * main context, we'd better clear the tuple slot before there's any
566 * chance of a reset of the sub-query's context. Else we will have the
567 * potential for a double free attempt. (XXX possibly no longer needed,
570 ExecClearTuple(node
->projRight
->pi_slot
);
572 MemoryContextSwitchTo(oldcontext
);
576 * findPartialMatch: does the hashtable contain an entry that is not
577 * provably distinct from the tuple?
579 * We have to scan the whole hashtable; we can't usefully use hashkeys
580 * to guide probing, since we might get partial matches on tuples with
581 * hashkeys quite unrelated to what we'd get from the given tuple.
584 findPartialMatch(TupleHashTable hashtable
, TupleTableSlot
*slot
)
586 int numCols
= hashtable
->numCols
;
587 AttrNumber
*keyColIdx
= hashtable
->keyColIdx
;
588 TupleHashIterator hashiter
;
589 TupleHashEntry entry
;
591 InitTupleHashIterator(hashtable
, &hashiter
);
592 while ((entry
= ScanTupleHashTable(&hashiter
)) != NULL
)
594 ExecStoreMinimalTuple(entry
->firstTuple
, hashtable
->tableslot
, false);
595 if (!execTuplesUnequal(slot
, hashtable
->tableslot
,
597 hashtable
->cur_eq_funcs
,
600 TermTupleHashIterator(&hashiter
);
604 /* No TermTupleHashIterator call needed here */
609 * slotAllNulls: is the slot completely NULL?
611 * This does not test for dropped columns, which is OK because we only
612 * use it on projected tuples.
615 slotAllNulls(TupleTableSlot
*slot
)
617 int ncols
= slot
->tts_tupleDescriptor
->natts
;
620 for (i
= 1; i
<= ncols
; i
++)
622 if (!slot_attisnull(slot
, i
))
629 * slotNoNulls: is the slot entirely not NULL?
631 * This does not test for dropped columns, which is OK because we only
632 * use it on projected tuples.
635 slotNoNulls(TupleTableSlot
*slot
)
637 int ncols
= slot
->tts_tupleDescriptor
->natts
;
640 for (i
= 1; i
<= ncols
; i
++)
642 if (slot_attisnull(slot
, i
))
648 /* ----------------------------------------------------------------
651 * Create a SubPlanState for a SubPlan; this is the SubPlan-specific part
652 * of ExecInitExpr(). We split it out so that it can be used for InitPlans
653 * as well as regular SubPlans. Note that we don't link the SubPlan into
654 * the parent's subPlan list, because that shouldn't happen for InitPlans.
655 * Instead, ExecInitExpr() does that one part.
656 * ----------------------------------------------------------------
659 ExecInitSubPlan(SubPlan
*subplan
, PlanState
*parent
)
661 SubPlanState
*sstate
= makeNode(SubPlanState
);
662 EState
*estate
= parent
->state
;
664 sstate
->xprstate
.evalfunc
= (ExprStateEvalFunc
) ExecSubPlan
;
665 sstate
->xprstate
.expr
= (Expr
*) subplan
;
667 /* Link the SubPlanState to already-initialized subplan */
668 sstate
->planstate
= (PlanState
*) list_nth(estate
->es_subplanstates
,
669 subplan
->plan_id
- 1);
671 /* Initialize subexpressions */
672 sstate
->testexpr
= ExecInitExpr((Expr
*) subplan
->testexpr
, parent
);
673 sstate
->args
= (List
*) ExecInitExpr((Expr
*) subplan
->args
, parent
);
676 * initialize my state
678 sstate
->curTuple
= NULL
;
679 sstate
->projLeft
= NULL
;
680 sstate
->projRight
= NULL
;
681 sstate
->hashtable
= NULL
;
682 sstate
->hashnulls
= NULL
;
683 sstate
->tablecxt
= NULL
;
684 sstate
->innerecontext
= NULL
;
685 sstate
->keyColIdx
= NULL
;
686 sstate
->tab_hash_funcs
= NULL
;
687 sstate
->tab_eq_funcs
= NULL
;
688 sstate
->lhs_hash_funcs
= NULL
;
689 sstate
->cur_eq_funcs
= NULL
;
692 * If this plan is un-correlated or undirect correlated one and want to
693 * set params for parent plan then mark parameters as needing evaluation.
695 * A CTE subplan's output parameter is never to be evaluated in the normal
696 * way, so skip this in that case.
698 * Note that in the case of un-correlated subqueries we don't care about
699 * setting parent->chgParam here: indices take care about it, for others -
700 * it doesn't matter...
702 if (subplan
->setParam
!= NIL
&& subplan
->subLinkType
!= CTE_SUBLINK
)
706 foreach(lst
, subplan
->setParam
)
708 int paramid
= lfirst_int(lst
);
709 ParamExecData
*prm
= &(estate
->es_param_exec_vals
[paramid
]);
711 prm
->execPlan
= sstate
;
716 * If we are going to hash the subquery output, initialize relevant stuff.
717 * (We don't create the hashtable until needed, though.)
719 if (subplan
->useHashTable
)
725 TupleTableSlot
*slot
;
733 /* We need a memory context to hold the hash table(s) */
735 AllocSetContextCreate(CurrentMemoryContext
,
736 "Subplan HashTable Context",
737 ALLOCSET_DEFAULT_MINSIZE
,
738 ALLOCSET_DEFAULT_INITSIZE
,
739 ALLOCSET_DEFAULT_MAXSIZE
);
740 /* and a short-lived exprcontext for function evaluation */
741 sstate
->innerecontext
= CreateExprContext(estate
);
742 /* Silly little array of column numbers 1..n */
743 ncols
= list_length(subplan
->paramIds
);
744 sstate
->keyColIdx
= (AttrNumber
*) palloc(ncols
* sizeof(AttrNumber
));
745 for (i
= 0; i
< ncols
; i
++)
746 sstate
->keyColIdx
[i
] = i
+ 1;
749 * We use ExecProject to evaluate the lefthand and righthand
750 * expression lists and form tuples. (You might think that we could
751 * use the sub-select's output tuples directly, but that is not the
752 * case if we had to insert any run-time coercions of the sub-select's
753 * output datatypes; anyway this avoids storing any resjunk columns
754 * that might be in the sub-select's output.) Run through the
755 * combining expressions to build tlists for the lefthand and
756 * righthand sides. We need both the ExprState list (for ExecProject)
757 * and the underlying parse Exprs (for ExecTypeFromTL).
759 * We also extract the combining operators themselves to initialize
760 * the equality and hashing functions for the hash tables.
762 if (IsA(sstate
->testexpr
->expr
, OpExpr
))
764 /* single combining operator */
765 oplist
= list_make1(sstate
->testexpr
);
767 else if (and_clause((Node
*) sstate
->testexpr
->expr
))
769 /* multiple combining operators */
770 Assert(IsA(sstate
->testexpr
, BoolExprState
));
771 oplist
= ((BoolExprState
*) sstate
->testexpr
)->args
;
775 /* shouldn't see anything else in a hashable subplan */
776 elog(ERROR
, "unrecognized testexpr type: %d",
777 (int) nodeTag(sstate
->testexpr
->expr
));
778 oplist
= NIL
; /* keep compiler quiet */
780 Assert(list_length(oplist
) == ncols
);
782 lefttlist
= righttlist
= NIL
;
783 leftptlist
= rightptlist
= NIL
;
784 sstate
->tab_hash_funcs
= (FmgrInfo
*) palloc(ncols
* sizeof(FmgrInfo
));
785 sstate
->tab_eq_funcs
= (FmgrInfo
*) palloc(ncols
* sizeof(FmgrInfo
));
786 sstate
->lhs_hash_funcs
= (FmgrInfo
*) palloc(ncols
* sizeof(FmgrInfo
));
787 sstate
->cur_eq_funcs
= (FmgrInfo
*) palloc(ncols
* sizeof(FmgrInfo
));
791 FuncExprState
*fstate
= (FuncExprState
*) lfirst(l
);
792 OpExpr
*opexpr
= (OpExpr
*) fstate
->xprstate
.expr
;
796 GenericExprState
*tlestate
;
801 Assert(IsA(fstate
, FuncExprState
));
802 Assert(IsA(opexpr
, OpExpr
));
803 Assert(list_length(fstate
->args
) == 2);
805 /* Process lefthand argument */
806 exstate
= (ExprState
*) linitial(fstate
->args
);
807 expr
= exstate
->expr
;
808 tle
= makeTargetEntry(expr
,
812 tlestate
= makeNode(GenericExprState
);
813 tlestate
->xprstate
.expr
= (Expr
*) tle
;
814 tlestate
->xprstate
.evalfunc
= NULL
;
815 tlestate
->arg
= exstate
;
816 lefttlist
= lappend(lefttlist
, tlestate
);
817 leftptlist
= lappend(leftptlist
, tle
);
819 /* Process righthand argument */
820 exstate
= (ExprState
*) lsecond(fstate
->args
);
821 expr
= exstate
->expr
;
822 tle
= makeTargetEntry(expr
,
826 tlestate
= makeNode(GenericExprState
);
827 tlestate
->xprstate
.expr
= (Expr
*) tle
;
828 tlestate
->xprstate
.evalfunc
= NULL
;
829 tlestate
->arg
= exstate
;
830 righttlist
= lappend(righttlist
, tlestate
);
831 rightptlist
= lappend(rightptlist
, tle
);
833 /* Lookup the equality function (potentially cross-type) */
834 fmgr_info(opexpr
->opfuncid
, &sstate
->cur_eq_funcs
[i
- 1]);
835 sstate
->cur_eq_funcs
[i
- 1].fn_expr
= (Node
*) opexpr
;
837 /* Look up the equality function for the RHS type */
838 if (!get_compatible_hash_operators(opexpr
->opno
,
840 elog(ERROR
, "could not find compatible hash operator for operator %u",
842 fmgr_info(get_opcode(rhs_eq_oper
), &sstate
->tab_eq_funcs
[i
- 1]);
844 /* Lookup the associated hash functions */
845 if (!get_op_hash_functions(opexpr
->opno
,
846 &left_hashfn
, &right_hashfn
))
847 elog(ERROR
, "could not find hash function for hash operator %u",
849 fmgr_info(left_hashfn
, &sstate
->lhs_hash_funcs
[i
- 1]);
850 fmgr_info(right_hashfn
, &sstate
->tab_hash_funcs
[i
- 1]);
856 * Create a tupletable to hold these tuples. (Note: we never bother
857 * to free the tupletable explicitly; that's okay because it will
858 * never store raw disk tuples that might have associated buffer pins.
859 * The only resource involved is memory, which will be cleaned up by
860 * freeing the query context.)
862 tupTable
= ExecCreateTupleTable(2);
865 * Construct tupdescs, slots and projection nodes for left and right
866 * sides. The lefthand expressions will be evaluated in the parent
867 * plan node's exprcontext, which we don't have access to here.
868 * Fortunately we can just pass NULL for now and fill it in later
869 * (hack alert!). The righthand expressions will be evaluated in our
872 tupDesc
= ExecTypeFromTL(leftptlist
, false);
873 slot
= ExecAllocTableSlot(tupTable
);
874 ExecSetSlotDescriptor(slot
, tupDesc
);
875 sstate
->projLeft
= ExecBuildProjectionInfo(lefttlist
,
880 tupDesc
= ExecTypeFromTL(rightptlist
, false);
881 slot
= ExecAllocTableSlot(tupTable
);
882 ExecSetSlotDescriptor(slot
, tupDesc
);
883 sstate
->projRight
= ExecBuildProjectionInfo(righttlist
,
884 sstate
->innerecontext
,
892 /* ----------------------------------------------------------------
895 * Executes an InitPlan subplan and sets its output parameters.
897 * This is called from ExecEvalParam() when the value of a PARAM_EXEC
898 * parameter is requested and the param's execPlan field is set (indicating
899 * that the param has not yet been evaluated). This allows lazy evaluation
900 * of initplans: we don't run the subplan until/unless we need its output.
901 * Note that this routine MUST clear the execPlan fields of the plan's
902 * output parameters after evaluating them!
903 * ----------------------------------------------------------------
906 ExecSetParamPlan(SubPlanState
*node
, ExprContext
*econtext
)
908 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
909 PlanState
*planstate
= node
->planstate
;
910 SubLinkType subLinkType
= subplan
->subLinkType
;
911 MemoryContext oldcontext
;
912 TupleTableSlot
*slot
;
915 ArrayBuildState
*astate
= NULL
;
917 if (subLinkType
== ANY_SUBLINK
||
918 subLinkType
== ALL_SUBLINK
)
919 elog(ERROR
, "ANY/ALL subselect unsupported as initplan");
920 if (subLinkType
== CTE_SUBLINK
)
921 elog(ERROR
, "CTE subplans should not be executed via ExecSetParamPlan");
924 * Must switch to per-query memory context.
926 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
929 * Run the plan. (If it needs to be rescanned, the first ExecProcNode
930 * call will take care of that.)
932 for (slot
= ExecProcNode(planstate
);
934 slot
= ExecProcNode(planstate
))
936 TupleDesc tdesc
= slot
->tts_tupleDescriptor
;
939 if (subLinkType
== EXISTS_SUBLINK
)
941 /* There can be only one setParam... */
942 int paramid
= linitial_int(subplan
->setParam
);
943 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
945 prm
->execPlan
= NULL
;
946 prm
->value
= BoolGetDatum(true);
952 if (subLinkType
== ARRAY_SUBLINK
)
958 /* stash away current value */
959 Assert(subplan
->firstColType
== tdesc
->attrs
[0]->atttypid
);
960 dvalue
= slot_getattr(slot
, 1, &disnull
);
961 astate
= accumArrayResult(astate
, dvalue
, disnull
,
962 subplan
->firstColType
, oldcontext
);
963 /* keep scanning subplan to collect all values */
968 (subLinkType
== EXPR_SUBLINK
||
969 subLinkType
== ROWCOMPARE_SUBLINK
))
971 (errcode(ERRCODE_CARDINALITY_VIOLATION
),
972 errmsg("more than one row returned by a subquery used as an expression")));
977 * We need to copy the subplan's tuple into our own context, in case
978 * any of the params are pass-by-ref type --- the pointers stored in
979 * the param structs will point at this copied tuple! node->curTuple
980 * keeps track of the copied tuple for eventual freeing.
983 heap_freetuple(node
->curTuple
);
984 node
->curTuple
= ExecCopySlotTuple(slot
);
987 * Now set all the setParam params from the columns of the tuple
989 foreach(l
, subplan
->setParam
)
991 int paramid
= lfirst_int(l
);
992 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
994 prm
->execPlan
= NULL
;
995 prm
->value
= heap_getattr(node
->curTuple
, i
, tdesc
,
1001 if (subLinkType
== ARRAY_SUBLINK
)
1003 /* There can be only one setParam... */
1004 int paramid
= linitial_int(subplan
->setParam
);
1005 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
1007 prm
->execPlan
= NULL
;
1008 /* We build the result in query context so it won't disappear */
1010 prm
->value
= makeArrayResult(astate
,
1011 econtext
->ecxt_per_query_memory
);
1014 MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
1015 prm
->value
= PointerGetDatum(construct_empty_array(subplan
->firstColType
));
1017 prm
->isnull
= false;
1021 if (subLinkType
== EXISTS_SUBLINK
)
1023 /* There can be only one setParam... */
1024 int paramid
= linitial_int(subplan
->setParam
);
1025 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
1027 prm
->execPlan
= NULL
;
1028 prm
->value
= BoolGetDatum(false);
1029 prm
->isnull
= false;
1033 foreach(l
, subplan
->setParam
)
1035 int paramid
= lfirst_int(l
);
1036 ParamExecData
*prm
= &(econtext
->ecxt_param_exec_vals
[paramid
]);
1038 prm
->execPlan
= NULL
;
1039 prm
->value
= (Datum
) 0;
1045 MemoryContextSwitchTo(oldcontext
);
1049 * Mark an initplan as needing recalculation
1052 ExecReScanSetParamPlan(SubPlanState
*node
, PlanState
*parent
)
1054 PlanState
*planstate
= node
->planstate
;
1055 SubPlan
*subplan
= (SubPlan
*) node
->xprstate
.expr
;
1056 EState
*estate
= parent
->state
;
1060 if (subplan
->parParam
!= NIL
)
1061 elog(ERROR
, "direct correlated subquery unsupported as initplan");
1062 if (subplan
->setParam
== NIL
)
1063 elog(ERROR
, "setParam list of initplan is empty");
1064 if (bms_is_empty(planstate
->plan
->extParam
))
1065 elog(ERROR
, "extParam set of initplan is empty");
1068 * Don't actually re-scan: it'll happen inside ExecSetParamPlan if needed.
1072 * Mark this subplan's output parameters as needing recalculation.
1074 * CTE subplans are never executed via parameter recalculation; instead
1075 * they get run when called by nodeCtescan.c. So don't mark the output
1076 * parameter of a CTE subplan as dirty, but do set the chgParam bit
1077 * for it so that dependent plan nodes will get told to rescan.
1079 foreach(l
, subplan
->setParam
)
1081 int paramid
= lfirst_int(l
);
1082 ParamExecData
*prm
= &(estate
->es_param_exec_vals
[paramid
]);
1084 if (subplan
->subLinkType
!= CTE_SUBLINK
)
1085 prm
->execPlan
= node
;
1087 parent
->chgParam
= bms_add_member(parent
->chgParam
, paramid
);
1093 * ExecInitAlternativeSubPlan
1095 * Initialize for execution of one of a set of alternative subplans.
1097 AlternativeSubPlanState
*
1098 ExecInitAlternativeSubPlan(AlternativeSubPlan
*asplan
, PlanState
*parent
)
1100 AlternativeSubPlanState
*asstate
= makeNode(AlternativeSubPlanState
);
1107 asstate
->xprstate
.evalfunc
= (ExprStateEvalFunc
) ExecAlternativeSubPlan
;
1108 asstate
->xprstate
.expr
= (Expr
*) asplan
;
1111 * Initialize subplans. (Can we get away with only initializing the
1112 * one we're going to use?)
1114 asstate
->subplans
= (List
*) ExecInitExpr((Expr
*) asplan
->subplans
,
1118 * Select the one to be used. For this, we need an estimate of the
1119 * number of executions of the subplan. We use the number of output
1120 * rows expected from the parent plan node. This is a good estimate
1121 * if we are in the parent's targetlist, and an underestimate (but
1122 * probably not by more than a factor of 2) if we are in the qual.
1124 num_calls
= parent
->plan
->plan_rows
;
1127 * The planner saved enough info so that we don't have to work very hard
1128 * to estimate the total cost, given the number-of-calls estimate.
1130 Assert(list_length(asplan
->subplans
) == 2);
1131 subplan1
= (SubPlan
*) linitial(asplan
->subplans
);
1132 subplan2
= (SubPlan
*) lsecond(asplan
->subplans
);
1134 cost1
= subplan1
->startup_cost
+ num_calls
* subplan1
->per_call_cost
;
1135 cost2
= subplan2
->startup_cost
+ num_calls
* subplan2
->per_call_cost
;
1138 asstate
->active
= 0;
1140 asstate
->active
= 1;
1146 * ExecAlternativeSubPlan
1148 * Execute one of a set of alternative subplans.
1150 * Note: in future we might consider changing to different subplans on the
1151 * fly, in case the original rowcount estimate turns out to be way off.
1154 ExecAlternativeSubPlan(AlternativeSubPlanState
*node
,
1155 ExprContext
*econtext
,
1157 ExprDoneCond
*isDone
)
1159 /* Just pass control to the active subplan */
1160 SubPlanState
*activesp
= (SubPlanState
*) list_nth(node
->subplans
,
1163 Assert(IsA(activesp
, SubPlanState
));
1165 return ExecSubPlan(activesp
,