@@ -68,6 +68,9 @@ static Node *ParseComplexProjection(ParseState *pstate, const char *funcname,
6868 * last_srf should be a copy of pstate->p_last_srf from just before we
6969 * started transforming fargs. If the caller knows that fargs couldn't
7070 * contain any SRF calls, last_srf can just be pstate->p_last_srf.
71+ *
72+ * proc_call is true if we are considering a CALL statement, so that the
73+ * name must resolve to a procedure name, not anything else.
7174 */
7275Node *
7376ParseFuncOrColumn (ParseState * pstate , List * funcname , List * fargs ,
@@ -204,7 +207,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
204207 * the "function call" could be a projection. We also check that there
205208 * wasn't any aggregate or variadic decoration, nor an argument name.
206209 */
207- if (nargs == 1 && agg_order == NIL && agg_filter == NULL && !agg_star &&
210+ if (nargs == 1 && !proc_call &&
211+ agg_order == NIL && agg_filter == NULL && !agg_star &&
208212 !agg_distinct && over == NULL && !func_variadic && argnames == NIL &&
209213 list_length (funcname ) == 1 )
210214 {
@@ -253,21 +257,42 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
253257
254258 cancel_parser_errposition_callback (& pcbstate );
255259
256- if (fdresult == FUNCDETAIL_COERCION )
257- {
258- /*
259- * We interpreted it as a type coercion. coerce_type can handle these
260- * cases, so why duplicate code...
261- */
262- return coerce_type (pstate , linitial (fargs ),
263- actual_arg_types [0 ], rettype , -1 ,
264- COERCION_EXPLICIT , COERCE_EXPLICIT_CALL , location );
265- }
266- else if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE )
260+ /*
261+ * Check for various wrong-kind-of-routine cases.
262+ */
263+
264+ /* If this is a CALL, reject things that aren't procedures */
265+ if (proc_call &&
266+ (fdresult == FUNCDETAIL_NORMAL ||
267+ fdresult == FUNCDETAIL_AGGREGATE ||
268+ fdresult == FUNCDETAIL_WINDOWFUNC ||
269+ fdresult == FUNCDETAIL_COERCION ))
270+ ereport (ERROR ,
271+ (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
272+ errmsg ("%s is not a procedure" ,
273+ func_signature_string (funcname , nargs ,
274+ argnames ,
275+ actual_arg_types )),
276+ errhint ("To call a function, use SELECT." ),
277+ parser_errposition (pstate , location )));
278+ /* Conversely, if not a CALL, reject procedures */
279+ if (fdresult == FUNCDETAIL_PROCEDURE && !proc_call )
280+ ereport (ERROR ,
281+ (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
282+ errmsg ("%s is a procedure" ,
283+ func_signature_string (funcname , nargs ,
284+ argnames ,
285+ actual_arg_types )),
286+ errhint ("To call a procedure, use CALL." ),
287+ parser_errposition (pstate , location )));
288+
289+ if (fdresult == FUNCDETAIL_NORMAL ||
290+ fdresult == FUNCDETAIL_PROCEDURE ||
291+ fdresult == FUNCDETAIL_COERCION )
267292 {
268293 /*
269- * Normal function found; was there anything indicating it must be an
270- * aggregate?
294+ * In these cases, complain if there was anything indicating it must
295+ * be an aggregate or window function.
271296 */
272297 if (agg_star )
273298 ereport (ERROR ,
@@ -306,26 +331,14 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
306331 errmsg ("OVER specified, but %s is not a window function nor an aggregate function" ,
307332 NameListToString (funcname )),
308333 parser_errposition (pstate , location )));
334+ }
309335
310- if (fdresult == FUNCDETAIL_NORMAL && proc_call )
311- ereport (ERROR ,
312- (errcode (ERRCODE_UNDEFINED_FUNCTION ),
313- errmsg ("%s is not a procedure" ,
314- func_signature_string (funcname , nargs ,
315- argnames ,
316- actual_arg_types )),
317- errhint ("To call a function, use SELECT." ),
318- parser_errposition (pstate , location )));
319-
320- if (fdresult == FUNCDETAIL_PROCEDURE && !proc_call )
321- ereport (ERROR ,
322- (errcode (ERRCODE_UNDEFINED_FUNCTION ),
323- errmsg ("%s is a procedure" ,
324- func_signature_string (funcname , nargs ,
325- argnames ,
326- actual_arg_types )),
327- errhint ("To call a procedure, use CALL." ),
328- parser_errposition (pstate , location )));
336+ /*
337+ * So far so good, so do some routine-type-specific processing.
338+ */
339+ if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE )
340+ {
341+ /* Nothing special to do for these cases. */
329342 }
330343 else if (fdresult == FUNCDETAIL_AGGREGATE )
331344 {
@@ -336,15 +349,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
336349 Form_pg_aggregate classForm ;
337350 int catDirectArgs ;
338351
339- if (proc_call )
340- ereport (ERROR ,
341- (errcode (ERRCODE_UNDEFINED_FUNCTION ),
342- errmsg ("%s is not a procedure" ,
343- func_signature_string (funcname , nargs ,
344- argnames ,
345- actual_arg_types )),
346- parser_errposition (pstate , location )));
347-
348352 tup = SearchSysCache1 (AGGFNOID , ObjectIdGetDatum (funcid ));
349353 if (!HeapTupleIsValid (tup )) /* should not happen */
350354 elog (ERROR , "cache lookup failed for aggregate %u" , funcid );
@@ -510,6 +514,16 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
510514 NameListToString (funcname )),
511515 parser_errposition (pstate , location )));
512516 }
517+ else if (fdresult == FUNCDETAIL_COERCION )
518+ {
519+ /*
520+ * We interpreted it as a type coercion. coerce_type can handle these
521+ * cases, so why duplicate code...
522+ */
523+ return coerce_type (pstate , linitial (fargs ),
524+ actual_arg_types [0 ], rettype , -1 ,
525+ COERCION_EXPLICIT , COERCE_EXPLICIT_CALL , location );
526+ }
513527 else
514528 {
515529 /*
0 commit comments