@@ -29,10 +29,11 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
29
29
{
30
30
Plan * plan = node -> plan ;
31
31
SubLink * sublink = node -> sublink ;
32
+ SubLinkType subLinkType = sublink -> subLinkType ;
32
33
TupleTableSlot * slot ;
33
34
List * lst ;
34
- bool result = false;
35
- bool found = false;
35
+ Datum result = ( Datum ) false;
36
+ bool found = false; /* TRUE if got at least one subplan tuple */
36
37
37
38
if (node -> setParam != NULL )
38
39
elog (ERROR , "ExecSubPlan: can't set parent params from subquery" );
@@ -56,6 +57,18 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
56
57
57
58
ExecReScan (plan , (ExprContext * ) NULL , plan );
58
59
60
+ /*
61
+ * For all sublink types except EXPR_SUBLINK, the result type is boolean,
62
+ * and we have a fairly clear idea of how to combine multiple subitems
63
+ * and deal with NULL values or an empty subplan result.
64
+ *
65
+ * For EXPR_SUBLINK, the result type is whatever the combining operator
66
+ * returns. We have no way to deal with more than one column in the
67
+ * subplan result --- hopefully the parser forbids that. More seriously,
68
+ * it's unclear what to do with NULL values or an empty subplan result.
69
+ * For now, we error out, but should something else happen?
70
+ */
71
+
59
72
for (slot = ExecProcNode (plan , plan );
60
73
!TupIsNull (slot );
61
74
slot = ExecProcNode (plan , plan ))
@@ -64,13 +77,13 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
64
77
TupleDesc tdesc = slot -> ttc_tupleDescriptor ;
65
78
int i = 1 ;
66
79
67
- if (sublink -> subLinkType == EXPR_SUBLINK && found )
80
+ if (subLinkType == EXPR_SUBLINK && found )
68
81
{
69
82
elog (ERROR , "ExecSubPlan: more than one tuple returned by expression subselect" );
70
83
return (Datum ) false;
71
84
}
72
85
73
- if (sublink -> subLinkType == EXISTS_SUBLINK )
86
+ if (subLinkType == EXISTS_SUBLINK )
74
87
return (Datum ) true;
75
88
76
89
found = true;
@@ -82,23 +95,39 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
82
95
bool isnull ;
83
96
84
97
con -> constvalue = heap_getattr (tup , i , tdesc , & (con -> constisnull ));
85
- result = ( bool ) ExecEvalExpr ((Node * ) expr , econtext , & isnull , (bool * ) NULL );
98
+ result = ExecEvalExpr ((Node * ) expr , econtext , & isnull , (bool * ) NULL );
86
99
if (isnull )
87
- result = false;
88
- if ((!result && !(sublink -> useor )) || (result && sublink -> useor ))
89
- break ;
100
+ {
101
+ if (subLinkType == EXPR_SUBLINK )
102
+ elog (ERROR , "ExecSubPlan: null value returned by expression subselect" );
103
+ else
104
+ result = (Datum ) false;
105
+ }
106
+ if (subLinkType != EXPR_SUBLINK )
107
+ {
108
+ if ((! (bool ) result && !(sublink -> useor )) ||
109
+ ((bool ) result && sublink -> useor ))
110
+ break ;
111
+ }
90
112
i ++ ;
91
113
}
92
114
93
- if ((!result && sublink -> subLinkType == ALL_SUBLINK ) ||
94
- (result && sublink -> subLinkType == ANY_SUBLINK ))
115
+ if (subLinkType == ALL_SUBLINK && ! (bool ) result )
116
+ break ;
117
+ if (subLinkType == ANY_SUBLINK && (bool ) result )
95
118
break ;
96
119
}
97
120
98
- if (!found && sublink -> subLinkType == ALL_SUBLINK )
99
- return (Datum ) true;
121
+ if (!found )
122
+ {
123
+ /* deal with empty subplan result. Note default result is 'false' */
124
+ if (subLinkType == ALL_SUBLINK )
125
+ result = (Datum ) true;
126
+ else if (subLinkType == EXPR_SUBLINK )
127
+ elog (ERROR , "ExecSubPlan: no tuples returned by expression subselect" );
128
+ }
100
129
101
- return ( Datum ) result ;
130
+ return result ;
102
131
}
103
132
104
133
/* ----------------------------------------------------------------
0 commit comments