Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0dcf68e

Browse files
committed
Fix some minor error-checking oversights in ParseFuncOrColumn().
Recent additions to ParseFuncOrColumn to make it reject non-procedurefunctions in CALL were neither adequate nor documented. Reorganizethe code to ensure uniform results for all the cases that should berejected. Also, use ERRCODE_WRONG_OBJECT_TYPE for this case as wellas the converse case of a procedure in a non-CALL context. Theoriginal coding used ERRCODE_UNDEFINED_FUNCTION which seems wrong,and is certainly inconsistent with the adjacent wrong-kind-of-routineerrors.This reorganization also causes the checks for aggregate decoration witha non-aggregate function to be made in the FUNCDETAIL_COERCION case;that they were not is a long-standing oversight.Discussion:https://postgr.es/m/14497.1529089235@sss.pgh.pa.us
1 parent15378c1 commit0dcf68e

File tree

2 files changed

+57
-42
lines changed

2 files changed

+57
-42
lines changed

‎src/backend/parser/parse_func.c

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
7275
Node*
7376
ParseFuncOrColumn(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-
returncoerce_type(pstate,linitial(fargs),
263-
actual_arg_types[0],rettype,-1,
264-
COERCION_EXPLICIT,COERCE_EXPLICIT_CALL,location);
265-
}
266-
elseif (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; wasthere anything indicating it must be an
270-
* aggregate?
294+
*In these cases, complain iftherewasanything indicating it must
295+
*be anaggregate 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
elseif (fdresult==FUNCDETAIL_AGGREGATE)
331344
{
@@ -336,15 +349,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
336349
Form_pg_aggregateclassForm;
337350
intcatDirectArgs;
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+
elseif (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+
returncoerce_type(pstate,linitial(fargs),
524+
actual_arg_types[0],rettype,-1,
525+
COERCION_EXPLICIT,COERCE_EXPLICIT_CALL,location);
526+
}
513527
else
514528
{
515529
/*

‎src/test/regress/expected/create_procedure.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ CALL sum(1); -- error: not a procedure
126126
ERROR: sum(integer) is not a procedure
127127
LINE 1: CALL sum(1);
128128
^
129+
HINT: To call a function, use SELECT.
129130
CREATE PROCEDURE ptestx() LANGUAGE SQL WINDOW AS $$ INSERT INTO cp_test VALUES (1, 'a') $$;
130131
ERROR: invalid attribute in procedure definition
131132
LINE 1: CREATE PROCEDURE ptestx() LANGUAGE SQL WINDOW AS $$ INSERT I...

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp