From e3a87b4991cc2d00b7a3082abb54c5f12baedfd1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 24 Mar 2020 11:48:33 -0400 Subject: Re-implement the ereport() macro using __VA_ARGS__. Now that we require C99, we can depend on __VA_ARGS__ to work, and revising ereport() to use it has several significant benefits: * The extra parentheses around the auxiliary function calls are now optional. Aside from being a bit less ugly, this removes a common gotcha for new contributors, because in some cases the compiler errors you got from forgetting them were unintelligible. * The auxiliary function calls are now evaluated as a comma expression list rather than as extra arguments to errfinish(). This means that compilers can be expected to warn about no-op expressions in the list, allowing detection of several other common mistakes such as forgetting to add errmsg(...) when converting an elog() call to ereport(). * Unlike the situation with extra function arguments, comma expressions are guaranteed to be evaluated left-to-right, so this removes platform dependency in the order of the auxiliary function calls. While that dependency hasn't caused us big problems in the past, this change does allow dropping some rather shaky assumptions around errcontext() domain handling. There's no intention to make wholesale changes of existing ereport calls, but as proof-of-concept this patch removes the extra parens from a couple of calls in postgres.c. While new code can be written either way, code intended to be back-patched will need to use extra parens for awhile yet. It seems worth back-patching this change into v12, so as to reduce the window where we have to be careful about that by one year. Hence, this patch is careful to preserve ABI compatibility; a followup HEAD-only patch will make some additional simplifications. Andres Freund and Tom Lane Discussion: https://postgr.es/m/CA+fd4k6N8EjNvZpM8nme+y+05mz-SM8Z_BgkixzkA34R+ej0Kw@mail.gmail.com --- doc/src/sgml/sources.sgml | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml index 32ca2201b85..283c3e03573 100644 --- a/doc/src/sgml/sources.sgml +++ b/doc/src/sgml/sources.sgml @@ -103,9 +103,9 @@ less -x4 message text. In addition there are optional elements, the most common of which is an error identifier code that follows the SQL spec's SQLSTATE conventions. - ereport itself is just a shell function, that exists + ereport itself is just a shell macro, that exists mainly for the syntactic convenience of making message generation - look like a function call in the C source code. The only parameter + look like a single function call in the C source code. The only parameter accepted directly by ereport is the severity level. The primary message text and any optional message elements are generated by calling auxiliary functions, such as errmsg, @@ -116,36 +116,50 @@ less -x4 A typical call to ereport might look like this: ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); + errcode(ERRCODE_DIVISION_BY_ZERO), + errmsg("division by zero")); This specifies error severity level ERROR (a run-of-the-mill error). The errcode call specifies the SQLSTATE error code using a macro defined in src/include/utils/errcodes.h. The - errmsg call provides the primary message text. Notice the - extra set of parentheses surrounding the auxiliary function calls — - these are annoying but syntactically necessary. + errmsg call provides the primary message text. + + + + You will also frequently see this older style, with an extra set of + parentheses surrounding the auxiliary function calls: + +ereport(ERROR, + (errcode(ERRCODE_DIVISION_BY_ZERO), + errmsg("division by zero"))); + + The extra parentheses were required + before PostgreSQL version 12, but are now + optional. Here is a more complex example: ereport(ERROR, - (errcode(ERRCODE_AMBIGUOUS_FUNCTION), - errmsg("function %s is not unique", - func_signature_string(funcname, nargs, - NIL, actual_arg_types)), - errhint("Unable to choose a best candidate function. " - "You might need to add explicit typecasts."))); + errcode(ERRCODE_AMBIGUOUS_FUNCTION), + errmsg("function %s is not unique", + func_signature_string(funcname, nargs, + NIL, actual_arg_types)), + errhint("Unable to choose a best candidate function. " + "You might need to add explicit typecasts.")); This illustrates the use of format codes to embed run-time values into a message text. Also, an optional hint message is provided. + The auxiliary function calls can be written in any order, but + conventionally errcode + and errmsg appear first. If the severity level is ERROR or higher, - ereport aborts the execution of the user-defined - function and does not return to the caller. If the severity level is + ereport aborts execution of the current query + and does not return to the caller. If the severity level is lower than ERROR, ereport returns normally. @@ -390,7 +404,7 @@ elog(level, "format string", ...); is exactly equivalent to: -ereport(level, (errmsg_internal("format string", ...))); +ereport(level, errmsg_internal("format string", ...)); Notice that the SQLSTATE error code is always defaulted, and the message string is not subject to translation. -- cgit v1.2.3