77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.89 2007/05/17 19:35:08 tgl Exp $
10+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.90 2007/08/26 21:44:25 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -259,10 +259,14 @@ ExecScanSubPlan(SubPlanState *node,
259259 * ROWCOMPARE_SUBLINK.
260260 *
261261 * For EXPR_SUBLINK we require the subplan to produce no more than one
262- * tuple, else an error is raised. For ARRAY_SUBLINK we allow the subplan
263- * to produce more than one tuple. In either case, if zero tuples are
264- * produced, we return NULL. Assuming we get a tuple, we just use its
265- * first column (there can be only one non-junk column in this case).
262+ * tuple, else an error is raised. If zero tuples are produced, we return
263+ * NULL. Assuming we get a tuple, we just use its first column (there can
264+ * be only one non-junk column in this case).
265+ *
266+ * For ARRAY_SUBLINK we allow the subplan to produce any number of tuples,
267+ * and form an array of the first column's values. Note in particular
268+ * that we produce a zero-element array if no tuples are produced (this
269+ * is a change from pre-8.3 behavior of returning NULL).
266270 */
267271result = BoolGetDatum (subLinkType == ALL_SUBLINK );
268272* isNull = false;
@@ -317,10 +321,10 @@ ExecScanSubPlan(SubPlanState *node,
317321
318322found = true;
319323/* stash away current value */
324+ Assert (subplan -> firstColType == tdesc -> attrs [0 ]-> atttypid );
320325dvalue = slot_getattr (slot ,1 ,& disnull );
321326astate = accumArrayResult (astate ,dvalue ,disnull ,
322- tdesc -> attrs [0 ]-> atttypid ,
323- oldcontext );
327+ subplan -> firstColType ,oldcontext );
324328/* keep scanning subplan to collect all values */
325329continue ;
326330}
@@ -385,29 +389,30 @@ ExecScanSubPlan(SubPlanState *node,
385389}
386390}
387391
388- if (!found )
392+ MemoryContextSwitchTo (oldcontext );
393+
394+ if (subLinkType == ARRAY_SUBLINK )
395+ {
396+ /* We return the result in the caller's context */
397+ if (astate != NULL )
398+ result = makeArrayResult (astate ,oldcontext );
399+ else
400+ result = PointerGetDatum (construct_empty_array (subplan -> firstColType ));
401+ }
402+ else if (!found )
389403{
390404/*
391405 * deal with empty subplan result.result/isNull were previously
392- * initialized correctly for all sublink types except EXPR, ARRAY, and
406+ * initialized correctly for all sublink types except EXPR and
393407 * ROWCOMPARE; for those, return NULL.
394408 */
395409if (subLinkType == EXPR_SUBLINK ||
396- subLinkType == ARRAY_SUBLINK ||
397410subLinkType == ROWCOMPARE_SUBLINK )
398411{
399412result = (Datum )0 ;
400413* isNull = true;
401414}
402415}
403- else if (subLinkType == ARRAY_SUBLINK )
404- {
405- Assert (astate != NULL );
406- /* We return the result in the caller's context */
407- result = makeArrayResult (astate ,oldcontext );
408- }
409-
410- MemoryContextSwitchTo (oldcontext );
411416
412417return result ;
413418}
@@ -938,10 +943,10 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
938943
939944found = true;
940945/* stash away current value */
946+ Assert (subplan -> firstColType == tdesc -> attrs [0 ]-> atttypid );
941947dvalue = slot_getattr (slot ,1 ,& disnull );
942948astate = accumArrayResult (astate ,dvalue ,disnull ,
943- tdesc -> attrs [0 ]-> atttypid ,
944- oldcontext );
949+ subplan -> firstColType ,oldcontext );
945950/* keep scanning subplan to collect all values */
946951continue ;
947952}
@@ -980,7 +985,25 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
980985}
981986}
982987
983- if (!found )
988+ if (subLinkType == ARRAY_SUBLINK )
989+ {
990+ /* There can be only one param... */
991+ int paramid = linitial_int (subplan -> setParam );
992+ ParamExecData * prm = & (econtext -> ecxt_param_exec_vals [paramid ]);
993+
994+ prm -> execPlan = NULL ;
995+ /* We build the result in query context so it won't disappear */
996+ if (astate != NULL )
997+ prm -> value = makeArrayResult (astate ,
998+ econtext -> ecxt_per_query_memory );
999+ else
1000+ {
1001+ MemoryContextSwitchTo (econtext -> ecxt_per_query_memory );
1002+ prm -> value = PointerGetDatum (construct_empty_array (subplan -> firstColType ));
1003+ }
1004+ prm -> isnull = false;
1005+ }
1006+ else if (!found )
9841007{
9851008if (subLinkType == EXISTS_SUBLINK )
9861009{
@@ -1005,18 +1028,6 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
10051028}
10061029}
10071030}
1008- else if (subLinkType == ARRAY_SUBLINK )
1009- {
1010- /* There can be only one param... */
1011- int paramid = linitial_int (subplan -> setParam );
1012- ParamExecData * prm = & (econtext -> ecxt_param_exec_vals [paramid ]);
1013-
1014- Assert (astate != NULL );
1015- prm -> execPlan = NULL ;
1016- /* We build the result in query context so it won't disappear */
1017- prm -> value = makeArrayResult (astate ,econtext -> ecxt_per_query_memory );
1018- prm -> isnull = false;
1019- }
10201031
10211032MemoryContextSwitchTo (oldcontext );
10221033}