1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-17 06:41:09 +03:00

Convert the reg* input functions to report (most) errors softly.

This is not really complete, but it catches most cases of practical
interest.  The main omissions are:

* regtype, regprocedure, and regoperator parse type names by
calling the main grammar, so any grammar-detected syntax error
will still be a hard error.  Also, if one includes a type
modifier in such a type specification, errors detected by the
typmodin function will be hard errors.

* Lookup errors are handled just by passing missing_ok = true
to the relevant catalog lookup function.  Because we've used
quite a restrictive definition of "missing_ok", this means that
edge cases such as "the named schema exists, but you lack
USAGE permission on it" are still hard errors.

It would make sense to me to replace most/all missing_ok
parameters with an escontext parameter and then allow these
additional lookup failure cases to be trapped too.  But that's
a job for some other day.

Discussion: https://postgr.es/m/3342239.1671988406@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2022-12-27 12:26:01 -05:00
parent 78212f2101
commit 858e776c84
16 changed files with 403 additions and 128 deletions

View File

@ -727,10 +727,15 @@ pts_error_callback(void *arg)
* Given a string that is supposed to be a SQL-compatible type declaration,
* such as "int4" or "integer" or "character varying(32)", parse
* the string and return the result as a TypeName.
* If the string cannot be parsed as a type, an error is raised.
*
* If the string cannot be parsed as a type, an error is raised,
* unless escontext is an ErrorSaveContext node, in which case we may
* fill that and return NULL. But note that the ErrorSaveContext option
* is mostly aspirational at present: errors detected by the main
* grammar, rather than here, will still be thrown.
*/
TypeName *
typeStringToTypeName(const char *str)
typeStringToTypeName(const char *str, Node *escontext)
{
List *raw_parsetree_list;
TypeName *typeName;
@ -763,49 +768,54 @@ typeStringToTypeName(const char *str)
return typeName;
fail:
ereport(ERROR,
ereturn(escontext, NULL,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid type name \"%s\"", str)));
return NULL; /* keep compiler quiet */
}
/*
* Given a string that is supposed to be a SQL-compatible type declaration,
* such as "int4" or "integer" or "character varying(32)", parse
* the string and convert it to a type OID and type modifier.
* If missing_ok is true, InvalidOid is returned rather than raising an error
* when the type name is not found.
*
* If escontext is an ErrorSaveContext node, then errors are reported by
* filling escontext and returning false, instead of throwing them.
*/
void
parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
bool
parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p,
Node *escontext)
{
TypeName *typeName;
Type tup;
typeName = typeStringToTypeName(str);
typeName = typeStringToTypeName(str, escontext);
if (typeName == NULL)
return false;
tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
tup = LookupTypeName(NULL, typeName, typmod_p,
(escontext && IsA(escontext, ErrorSaveContext)));
if (tup == NULL)
{
if (!missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typeName)),
parser_errposition(NULL, typeName->location)));
*typeid_p = InvalidOid;
ereturn(escontext, false,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typeName))));
}
else
{
Form_pg_type typ = (Form_pg_type) GETSTRUCT(tup);
if (!typ->typisdefined)
ereport(ERROR,
{
ReleaseSysCache(tup);
ereturn(escontext, false,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" is only a shell",
TypeNameToString(typeName)),
parser_errposition(NULL, typeName->location)));
TypeNameToString(typeName))));
}
*typeid_p = typ->oid;
ReleaseSysCache(tup);
}
return true;
}