Skip to content

Commit 858e776

Browse files
committed
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
1 parent 78212f2 commit 858e776

File tree

16 files changed

+403
-128
lines changed

16 files changed

+403
-128
lines changed

src/backend/catalog/objectaddress.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,7 +2182,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
21822182
ereport(ERROR,
21832183
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
21842184
errmsg("name or argument lists may not contain nulls")));
2185-
typename = typeStringToTypeName(TextDatumGetCString(elems[0]));
2185+
typename = typeStringToTypeName(TextDatumGetCString(elems[0]), NULL);
21862186
}
21872187
else if (type == OBJECT_LARGEOBJECT)
21882188
{
@@ -2238,7 +2238,8 @@ pg_get_object_address(PG_FUNCTION_ARGS)
22382238
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
22392239
errmsg("name or argument lists may not contain nulls")));
22402240
args = lappend(args,
2241-
typeStringToTypeName(TextDatumGetCString(elems[i])));
2241+
typeStringToTypeName(TextDatumGetCString(elems[i]),
2242+
NULL));
22422243
}
22432244
}
22442245
else

src/backend/parser/parse_type.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -727,10 +727,15 @@ pts_error_callback(void *arg)
727727
* Given a string that is supposed to be a SQL-compatible type declaration,
728728
* such as "int4" or "integer" or "character varying(32)", parse
729729
* the string and return the result as a TypeName.
730-
* If the string cannot be parsed as a type, an error is raised.
730+
*
731+
* If the string cannot be parsed as a type, an error is raised,
732+
* unless escontext is an ErrorSaveContext node, in which case we may
733+
* fill that and return NULL. But note that the ErrorSaveContext option
734+
* is mostly aspirational at present: errors detected by the main
735+
* grammar, rather than here, will still be thrown.
731736
*/
732737
TypeName *
733-
typeStringToTypeName(const char *str)
738+
typeStringToTypeName(const char *str, Node *escontext)
734739
{
735740
List *raw_parsetree_list;
736741
TypeName *typeName;
@@ -763,49 +768,54 @@ typeStringToTypeName(const char *str)
763768
return typeName;
764769

765770
fail:
766-
ereport(ERROR,
771+
ereturn(escontext, NULL,
767772
(errcode(ERRCODE_SYNTAX_ERROR),
768773
errmsg("invalid type name \"%s\"", str)));
769-
return NULL; /* keep compiler quiet */
770774
}
771775

772776
/*
773777
* Given a string that is supposed to be a SQL-compatible type declaration,
774778
* such as "int4" or "integer" or "character varying(32)", parse
775779
* the string and convert it to a type OID and type modifier.
776-
* If missing_ok is true, InvalidOid is returned rather than raising an error
777-
* when the type name is not found.
780+
*
781+
* If escontext is an ErrorSaveContext node, then errors are reported by
782+
* filling escontext and returning false, instead of throwing them.
778783
*/
779-
void
780-
parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
784+
bool
785+
parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p,
786+
Node *escontext)
781787
{
782788
TypeName *typeName;
783789
Type tup;
784790

785-
typeName = typeStringToTypeName(str);
791+
typeName = typeStringToTypeName(str, escontext);
792+
if (typeName == NULL)
793+
return false;
786794

787-
tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
795+
tup = LookupTypeName(NULL, typeName, typmod_p,
796+
(escontext && IsA(escontext, ErrorSaveContext)));
788797
if (tup == NULL)
789798
{
790-
if (!missing_ok)
791-
ereport(ERROR,
792-
(errcode(ERRCODE_UNDEFINED_OBJECT),
793-
errmsg("type \"%s\" does not exist",
794-
TypeNameToString(typeName)),
795-
parser_errposition(NULL, typeName->location)));
796-
*typeid_p = InvalidOid;
799+
ereturn(escontext, false,
800+
(errcode(ERRCODE_UNDEFINED_OBJECT),
801+
errmsg("type \"%s\" does not exist",
802+
TypeNameToString(typeName))));
797803
}
798804
else
799805
{
800806
Form_pg_type typ = (Form_pg_type) GETSTRUCT(tup);
801807

802808
if (!typ->typisdefined)
803-
ereport(ERROR,
809+
{
810+
ReleaseSysCache(tup);
811+
ereturn(escontext, false,
804812
(errcode(ERRCODE_UNDEFINED_OBJECT),
805813
errmsg("type \"%s\" is only a shell",
806-
TypeNameToString(typeName)),
807-
parser_errposition(NULL, typeName->location)));
814+
TypeNameToString(typeName))));
815+
}
808816
*typeid_p = typ->oid;
809817
ReleaseSysCache(tup);
810818
}
819+
820+
return true;
811821
}

src/backend/tsearch/dict_thesaurus.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ thesaurus_init(PG_FUNCTION_ARGS)
599599
DictThesaurus *d;
600600
char *subdictname = NULL;
601601
bool fileloaded = false;
602+
List *namelist;
602603
ListCell *l;
603604

604605
d = (DictThesaurus *) palloc0(sizeof(DictThesaurus));
@@ -642,7 +643,8 @@ thesaurus_init(PG_FUNCTION_ARGS)
642643
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
643644
errmsg("missing Dictionary parameter")));
644645

645-
d->subdictOid = get_ts_dict_oid(stringToQualifiedNameList(subdictname), false);
646+
namelist = stringToQualifiedNameList(subdictname, NULL);
647+
d->subdictOid = get_ts_dict_oid(namelist, false);
646648
d->subdict = lookup_ts_dictionary_cache(d->subdictOid);
647649

648650
compileTheLexeme(d);

src/backend/utils/adt/misc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ pg_input_is_valid_common(FunctionCallInfo fcinfo,
724724
Oid typoid;
725725

726726
/* Parse type-name argument to obtain type OID and encoded typmod. */
727-
parseTypeString(typnamestr, &typoid, &my_extra->typmod, false);
727+
(void) parseTypeString(typnamestr, &typoid, &my_extra->typmod, NULL);
728728

729729
/* Update type-specific info if typoid changed. */
730730
if (my_extra->typoid != typoid)

0 commit comments

Comments
 (0)