@@ -1607,9 +1607,7 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
1607
1607
* init_fcache is presumed already run on the FuncExprState.
1608
1608
*
1609
1609
* This function handles the most general case, wherein the function or
1610
- * one of its arguments might (or might not) return a set. If we find
1611
- * no sets involved, we will change the FuncExprState's function pointer
1612
- * to use a simpler method on subsequent calls.
1610
+ * one of its arguments can return a set.
1613
1611
*/
1614
1612
static Datum
1615
1613
ExecMakeFunctionResult (FuncExprState * fcache ,
@@ -1888,13 +1886,12 @@ ExecMakeFunctionResult(FuncExprState *fcache,
1888
1886
/*
1889
1887
* Non-set case: much easier.
1890
1888
*
1891
- * We change the ExprState function pointer to use the simpler
1892
- * ExecMakeFunctionResultNoSets on subsequent calls. This amounts to
1893
- * assuming that no argument can return a set if it didn't do so the
1894
- * first time.
1889
+ * In common cases, this code path is unreachable because we'd have
1890
+ * selected ExecMakeFunctionResultNoSets instead. However, it's
1891
+ * possible to get here if an argument sometimes produces set results
1892
+ * and sometimes scalar results. For example, a CASE expression might
1893
+ * call a set-returning function in only some of its arms.
1895
1894
*/
1896
- fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResultNoSets ;
1897
-
1898
1895
if (isDone )
1899
1896
* isDone = ExprSingleResult ;
1900
1897
@@ -2350,10 +2347,22 @@ ExecEvalFunc(FuncExprState *fcache,
2350
2347
/* Initialize function lookup info */
2351
2348
init_fcache (func -> funcid , fcache , econtext -> ecxt_per_query_memory , true);
2352
2349
2353
- /* Go directly to ExecMakeFunctionResult on subsequent uses */
2354
- fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResult ;
2355
-
2356
- return ExecMakeFunctionResult (fcache , econtext , isNull , isDone );
2350
+ /*
2351
+ * We need to invoke ExecMakeFunctionResult if either the function itself
2352
+ * or any of its input expressions can return a set. Otherwise, invoke
2353
+ * ExecMakeFunctionResultNoSets. In either case, change the evalfunc
2354
+ * pointer to go directly there on subsequent uses.
2355
+ */
2356
+ if (fcache -> func .fn_retset || expression_returns_set ((Node * ) func -> args ))
2357
+ {
2358
+ fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResult ;
2359
+ return ExecMakeFunctionResult (fcache , econtext , isNull , isDone );
2360
+ }
2361
+ else
2362
+ {
2363
+ fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResultNoSets ;
2364
+ return ExecMakeFunctionResultNoSets (fcache , econtext , isNull , isDone );
2365
+ }
2357
2366
}
2358
2367
2359
2368
/* ----------------------------------------------------------------
@@ -2372,10 +2381,22 @@ ExecEvalOper(FuncExprState *fcache,
2372
2381
/* Initialize function lookup info */
2373
2382
init_fcache (op -> opfuncid , fcache , econtext -> ecxt_per_query_memory , true);
2374
2383
2375
- /* Go directly to ExecMakeFunctionResult on subsequent uses */
2376
- fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResult ;
2377
-
2378
- return ExecMakeFunctionResult (fcache , econtext , isNull , isDone );
2384
+ /*
2385
+ * We need to invoke ExecMakeFunctionResult if either the function itself
2386
+ * or any of its input expressions can return a set. Otherwise, invoke
2387
+ * ExecMakeFunctionResultNoSets. In either case, change the evalfunc
2388
+ * pointer to go directly there on subsequent uses.
2389
+ */
2390
+ if (fcache -> func .fn_retset || expression_returns_set ((Node * ) op -> args ))
2391
+ {
2392
+ fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResult ;
2393
+ return ExecMakeFunctionResult (fcache , econtext , isNull , isDone );
2394
+ }
2395
+ else
2396
+ {
2397
+ fcache -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecMakeFunctionResultNoSets ;
2398
+ return ExecMakeFunctionResultNoSets (fcache , econtext , isNull , isDone );
2399
+ }
2379
2400
}
2380
2401
2381
2402
/* ----------------------------------------------------------------
0 commit comments