@@ -68,6 +68,9 @@ static Node *ParseComplexProjection(ParseState *pstate, const char *funcname,
68
68
* last_srf should be a copy of pstate->p_last_srf from just before we
69
69
* started transforming fargs. If the caller knows that fargs couldn't
70
70
* 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.
71
74
*/
72
75
Node *
73
76
ParseFuncOrColumn (ParseState * pstate , List * funcname , List * fargs ,
@@ -204,7 +207,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
204
207
* the "function call" could be a projection. We also check that there
205
208
* wasn't any aggregate or variadic decoration, nor an argument name.
206
209
*/
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 &&
208
212
!agg_distinct && over == NULL && !func_variadic && argnames == NIL &&
209
213
list_length (funcname ) == 1 )
210
214
{
@@ -253,21 +257,42 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
253
257
254
258
cancel_parser_errposition_callback (& pcbstate );
255
259
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 )
267
292
{
268
293
/*
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.
271
296
*/
272
297
if (agg_star )
273
298
ereport (ERROR ,
@@ -306,26 +331,14 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
306
331
errmsg ("OVER specified, but %s is not a window function nor an aggregate function" ,
307
332
NameListToString (funcname )),
308
333
parser_errposition (pstate , location )));
334
+ }
309
335
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. */
329
342
}
330
343
else if (fdresult == FUNCDETAIL_AGGREGATE )
331
344
{
@@ -336,15 +349,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
336
349
Form_pg_aggregate classForm ;
337
350
int catDirectArgs ;
338
351
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
-
348
352
tup = SearchSysCache1 (AGGFNOID , ObjectIdGetDatum (funcid ));
349
353
if (!HeapTupleIsValid (tup )) /* should not happen */
350
354
elog (ERROR , "cache lookup failed for aggregate %u" , funcid );
@@ -510,6 +514,16 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
510
514
NameListToString (funcname )),
511
515
parser_errposition (pstate , location )));
512
516
}
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
+ }
513
527
else
514
528
{
515
529
/*
0 commit comments