mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Add a parse location field to struct FunctionParameter.
This allows an error cursor to be supplied for a bunch of bad-function-definition errors that previously lacked one, or that cheated a bit by pointing at the contained type name when the error isn't really about that. Bump catversion from an abundance of caution --- I don't think this node type can actually appear in stored views/rules, but better safe than sorry. Jian He and Tom Lane (extracted from a larger patch by Jian, with some additional work by me) Discussion: https://postgr.es/m/CACJufxEmONE3P2En=jopZy1m=cCCUs65M4+1o52MW5og9oaUPA@mail.gmail.com
This commit is contained in:
@@ -232,7 +232,7 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (fpmode == FUNC_PARAM_DEFAULT)
|
||||
fpmode = FUNC_PARAM_IN;
|
||||
|
||||
typtup = LookupTypeName(NULL, t, NULL, false);
|
||||
typtup = LookupTypeName(pstate, t, NULL, false);
|
||||
if (typtup)
|
||||
{
|
||||
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
|
||||
@@ -242,18 +242,21 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("SQL function cannot accept shell type %s",
|
||||
TypeNameToString(t))));
|
||||
TypeNameToString(t)),
|
||||
parser_errposition(pstate, t->location)));
|
||||
/* We don't allow creating aggregates on shell types either */
|
||||
else if (objtype == OBJECT_AGGREGATE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("aggregate cannot accept shell type %s",
|
||||
TypeNameToString(t))));
|
||||
TypeNameToString(t)),
|
||||
parser_errposition(pstate, t->location)));
|
||||
else
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("argument type %s is only a shell",
|
||||
TypeNameToString(t))));
|
||||
TypeNameToString(t)),
|
||||
parser_errposition(pstate, t->location)));
|
||||
}
|
||||
toid = typeTypeId(typtup);
|
||||
ReleaseSysCache(typtup);
|
||||
@@ -263,7 +266,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type %s does not exist",
|
||||
TypeNameToString(t))));
|
||||
TypeNameToString(t)),
|
||||
parser_errposition(pstate, t->location)));
|
||||
toid = InvalidOid; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
@@ -276,15 +280,18 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (objtype == OBJECT_AGGREGATE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("aggregates cannot accept set arguments")));
|
||||
errmsg("aggregates cannot accept set arguments"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
else if (objtype == OBJECT_PROCEDURE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("procedures cannot accept set arguments")));
|
||||
errmsg("procedures cannot accept set arguments"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("functions cannot accept set arguments")));
|
||||
errmsg("functions cannot accept set arguments"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
}
|
||||
|
||||
/* handle input parameters */
|
||||
@@ -294,7 +301,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (varCount > 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("VARIADIC parameter must be the last input parameter")));
|
||||
errmsg("VARIADIC parameter must be the last input parameter"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
inTypes[inCount++] = toid;
|
||||
isinput = true;
|
||||
if (parameterTypes_list)
|
||||
@@ -314,7 +322,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (varCount > 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("VARIADIC parameter must be the last parameter")));
|
||||
errmsg("VARIADIC parameter must be the last parameter"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
/* Procedures with output parameters always return RECORD */
|
||||
*requiredResultType = RECORDOID;
|
||||
}
|
||||
@@ -339,7 +348,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (!OidIsValid(get_element_type(toid)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("VARIADIC parameter must be an array")));
|
||||
errmsg("VARIADIC parameter must be an array"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -385,7 +395,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("parameter name \"%s\" used more than once",
|
||||
fp->name)));
|
||||
fp->name),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
}
|
||||
|
||||
paramNames[i] = CStringGetTextDatum(fp->name);
|
||||
@@ -402,7 +413,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (!isinput)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("only input parameters can have default values")));
|
||||
errmsg("only input parameters can have default values"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
|
||||
def = transformExpr(pstate, fp->defexpr,
|
||||
EXPR_KIND_FUNCTION_DEFAULT);
|
||||
@@ -417,7 +429,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
contain_var_clause(def))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("cannot use table references in parameter default value")));
|
||||
errmsg("cannot use table references in parameter default value"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
|
||||
/*
|
||||
* transformExpr() should have already rejected subqueries,
|
||||
@@ -441,7 +454,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (isinput && have_defaults)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("input parameters after one with a default value must also have defaults")));
|
||||
errmsg("input parameters after one with a default value must also have defaults"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
|
||||
/*
|
||||
* For procedures, we also can't allow OUT parameters after one
|
||||
@@ -451,7 +465,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
if (objtype == OBJECT_PROCEDURE && have_defaults)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("procedure OUT parameters cannot appear after one with a default value")));
|
||||
errmsg("procedure OUT parameters cannot appear after one with a default value"),
|
||||
parser_errposition(pstate, fp->location)));
|
||||
}
|
||||
|
||||
i++;
|
||||
|
Reference in New Issue
Block a user