Re: Error-safe user functions - Mailing list pgsql-hackers
| From | Tom Lane |
|---|---|
| Subject | Re: Error-safe user functions |
| Date | |
| Msg-id | 3910031.1672095600@sss.pgh.pa.us Whole thread Raw |
| In response to | Re: Error-safe user functions (Tom Lane <tgl@sss.pgh.pa.us>) |
| Responses |
Re: Error-safe user functions
|
| List | pgsql-hackers |
I wrote:
> (Perhaps we should go further than this, and convert all these
> functions to just be DirectInputFunctionCallSafe wrappers
> around the corresponding input functions? That would save
> some duplicative code, but I've not done it here.)
I looked closer at that idea, and realized that it would do more than
just save some code: it'd cause the to_regfoo functions to accept
numeric OIDs, as they did not before (and are documented not to).
It is unclear to me whether that inconsistency with the input
functions is really desirable or not --- but I don't offhand see a
good argument for it. If we change this though, it should probably
happen in a separate commit. Accordingly, here's a delta patch
doing that.
regards, tom lane
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 836b9254fb..3bf8d021c3 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -24100,8 +24100,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regclass</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24118,8 +24117,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regcollation</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24136,8 +24134,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regnamespace</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24154,8 +24151,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regoper</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found or is ambiguous. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found or is ambiguous.
</para></entry>
</row>
@@ -24172,8 +24168,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regoperator</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24190,8 +24185,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regproc</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found or is ambiguous. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found or is ambiguous.
</para></entry>
</row>
@@ -24208,8 +24202,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regprocedure</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24226,8 +24219,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regrole</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
@@ -24244,8 +24236,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
obtained by casting the string to type <type>regtype</type> (see
<xref linkend="datatype-oid"/>); however, this function will return
<literal>NULL</literal> rather than throwing an error if the name is
- not found. Also unlike the cast, this does not accept
- a numeric OID as input.
+ not found.
</para></entry>
</row>
</tbody>
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 14d76c856d..3635a94633 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -118,24 +118,15 @@ Datum
to_regproc(PG_FUNCTION_ARGS)
{
char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- List *names;
- FuncCandidateList clist;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name into components and see if it matches any pg_proc
- * entries in the current search path.
- */
- names = stringToQualifiedNameList(pro_name, (Node *) &escontext);
- if (names == NIL)
- PG_RETURN_NULL();
-
- clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true);
-
- if (clist == NULL || clist->next != NULL)
+ if (!DirectInputFunctionCallSafe(regprocin, pro_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
-
- PG_RETURN_OID(clist->oid);
+ PG_RETURN_DATUM(result);
}
/*
@@ -287,31 +278,15 @@ Datum
to_regprocedure(PG_FUNCTION_ARGS)
{
char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- List *names;
- int nargs;
- Oid argtypes[FUNC_MAX_ARGS];
- FuncCandidateList clist;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name and arguments, look up potential matches in the current
- * namespace search list, and scan to see which one exactly matches the
- * given argument types. (There will not be more than one match.)
- */
- if (!parseNameAndArgTypes(pro_name, false,
- &names, &nargs, argtypes,
- (Node *) &escontext))
+ if (!DirectInputFunctionCallSafe(regprocedurein, pro_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
-
- clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false, true);
-
- for (; clist; clist = clist->next)
- {
- if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
- PG_RETURN_OID(clist->oid);
- }
-
- PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
@@ -552,24 +527,15 @@ Datum
to_regoper(PG_FUNCTION_ARGS)
{
char *opr_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- List *names;
- FuncCandidateList clist;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name into components and see if it matches any pg_operator
- * entries in the current search path.
- */
- names = stringToQualifiedNameList(opr_name, (Node *) &escontext);
- if (names == NIL)
+ if (!DirectInputFunctionCallSafe(regoperin, opr_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
-
- clist = OpernameGetCandidates(names, '\0', true);
-
- if (clist == NULL || clist->next != NULL)
- PG_RETURN_NULL();
-
- PG_RETURN_OID(clist->oid);
+ PG_RETURN_DATUM(result);
}
/*
@@ -728,31 +694,15 @@ Datum
to_regoperator(PG_FUNCTION_ARGS)
{
char *opr_name_or_oid = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- List *names;
- int nargs;
- Oid argtypes[FUNC_MAX_ARGS];
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name and arguments, look up potential matches in the current
- * namespace search list, and scan to see which one exactly matches the
- * given argument types. (There will not be more than one match.)
- */
- if (!parseNameAndArgTypes(opr_name_or_oid, true,
- &names, &nargs, argtypes,
- (Node *) &escontext))
- PG_RETURN_NULL();
-
- if (nargs != 2)
+ if (!DirectInputFunctionCallSafe(regoperatorin, opr_name_or_oid,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
-
- result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
-
- if (!OidIsValid(result))
- PG_RETURN_NULL();
-
- PG_RETURN_OID(result);
+ PG_RETURN_DATUM(result);
}
/*
@@ -975,25 +925,15 @@ Datum
to_regclass(PG_FUNCTION_ARGS)
{
char *class_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- List *names;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name into components and see if it matches any pg_class
- * entries in the current search path.
- */
- names = stringToQualifiedNameList(class_name, (Node *) &escontext);
- if (names == NIL)
- PG_RETURN_NULL();
-
- /* We might not even have permissions on this relation; don't lock it. */
- result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
-
- if (OidIsValid(result))
- PG_RETURN_OID(result);
- else
+ if (!DirectInputFunctionCallSafe(regclassin, class_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
@@ -1128,24 +1068,15 @@ Datum
to_regcollation(PG_FUNCTION_ARGS)
{
char *collation_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- List *names;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Parse the name into components and see if it matches any pg_collation
- * entries in the current search path.
- */
- names = stringToQualifiedNameList(collation_name, (Node *) &escontext);
- if (names == NIL)
- PG_RETURN_NULL();
-
- result = get_collation_oid(names, true);
-
- if (OidIsValid(result))
- PG_RETURN_OID(result);
- else
+ if (!DirectInputFunctionCallSafe(regcollationin, collation_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
@@ -1278,17 +1209,15 @@ Datum
to_regtype(PG_FUNCTION_ARGS)
{
char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- int32 typmod;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- /*
- * Invoke the full parser to deal with special cases such as array syntax.
- */
- if (parseTypeString(typ_name, &result, &typmod, (Node *) &escontext))
- PG_RETURN_OID(result);
- else
+ if (!DirectInputFunctionCallSafe(regtypein, typ_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
@@ -1634,23 +1563,15 @@ Datum
to_regrole(PG_FUNCTION_ARGS)
{
char *role_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- List *names;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- names = stringToQualifiedNameList(role_name, (Node *) &escontext);
- if (names == NIL)
- PG_RETURN_NULL();
-
- if (list_length(names) != 1)
- PG_RETURN_NULL();
-
- result = get_role_oid(strVal(linitial(names)), true);
-
- if (OidIsValid(result))
- PG_RETURN_OID(result);
- else
+ if (!DirectInputFunctionCallSafe(regrolein, role_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
@@ -1759,23 +1680,15 @@ Datum
to_regnamespace(PG_FUNCTION_ARGS)
{
char *nsp_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
- Oid result;
- List *names;
+ Datum result;
ErrorSaveContext escontext = {T_ErrorSaveContext};
- names = stringToQualifiedNameList(nsp_name, (Node *) &escontext);
- if (names == NIL)
- PG_RETURN_NULL();
-
- if (list_length(names) != 1)
- PG_RETURN_NULL();
-
- result = get_namespace_oid(strVal(linitial(names)), true);
-
- if (OidIsValid(result))
- PG_RETURN_OID(result);
- else
+ if (!DirectInputFunctionCallSafe(regnamespacein, nsp_name,
+ InvalidOid, -1,
+ (Node *) &escontext,
+ &result))
PG_RETURN_NULL();
+ PG_RETURN_DATUM(result);
}
/*
pgsql-hackers by date: