Error, warning, and log messages generated within the server code
should be created using ereport
, or its older cousin
elog
. The use of this function is complex enough to
require some explanation.
There are two required elements for every message: a severity level
(ranging from DEBUG
to PANIC
) and a primary
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 macro that exists
mainly for the syntactic convenience of making message generation
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
,
within the ereport
call.
A typical call to ereport
might look like this:
ereport(ERROR, 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.
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 LightDB 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."));
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 execution of the current query
and does not return to the caller. If the severity level is
lower than ERROR
, ereport
returns normally.
The available auxiliary routines for ereport
are:
errcode(sqlerrcode)
specifies the SQLSTATE error identifier
code for the condition. If this routine is not called, the error
identifier defaults to
ERRCODE_INTERNAL_ERROR
when the error severity level is
ERROR
or higher, ERRCODE_WARNING
when the
error level is WARNING
, otherwise (for NOTICE
and below) ERRCODE_SUCCESSFUL_COMPLETION
.
While these defaults are often convenient, always think whether they
are appropriate before omitting the errcode()
call.
errmsg(const char *msg, ...)
specifies the primary error
message text, and possibly run-time values to insert into it. Insertions
are specified by sprintf
-style format codes. In addition to
the standard format codes accepted by sprintf
, the format
code %m
can be used to insert the error message returned
by strerror
for the current value of errno
.
[14]
%m
does not require any
corresponding entry in the parameter list for errmsg
.
Note that the message string will be run through gettext
for possible localization before format codes are processed.
errmsg_internal(const char *msg, ...)
is the same as
errmsg
, except that the message string will not be
translated nor included in the internationalization message dictionary.
This should be used for “cannot happen” cases that are probably
not worth expending translation effort on.
errmsg_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n, ...)
is like errmsg
, but with
support for various plural forms of the message.
fmt_singular
is the English singular format,
fmt_plural
is the English plural format,
n
is the integer value that determines which plural
form is needed, and the remaining arguments are formatted according
to the selected format string. For more information see
Section 51.2.2.
errdetail(const char *msg, ...)
supplies an optional
“detail” message; this is to be used when there is additional
information that seems inappropriate to put in the primary message.
The message string is processed in just the same way as for
errmsg
.
errdetail_internal(const char *msg, ...)
is the same
as errdetail
, except that the message string will not be
translated nor included in the internationalization message dictionary.
This should be used for detail messages that are not worth expending
translation effort on, for instance because they are too technical to be
useful to most users.
errdetail_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n, ...)
is like errdetail
, but with
support for various plural forms of the message.
For more information see Section 51.2.2.
errdetail_log(const char *msg, ...)
is the same as
errdetail
except that this string goes only to the server
log, never to the client. If both errdetail
(or one of
its equivalents above) and
errdetail_log
are used then one string goes to the client
and the other to the log. This is useful for error details that are
too security-sensitive or too bulky to include in the report
sent to the client.
errdetail_log_plural(const char *fmt_singular, const char
*fmt_plural, unsigned long n, ...)
is like
errdetail_log
, but with support for various plural forms of
the message.
For more information see Section 51.2.2.
errhint(const char *msg, ...)
supplies an optional
“hint” message; this is to be used when offering suggestions
about how to fix the problem, as opposed to factual details about
what went wrong.
The message string is processed in just the same way as for
errmsg
.
errcontext(const char *msg, ...)
is not normally called
directly from an ereport
message site; rather it is used
in error_context_stack
callback functions to provide
information about the context in which an error occurred, such as the
current location in a PL function.
The message string is processed in just the same way as for
errmsg
. Unlike the other auxiliary functions, this can
be called more than once per ereport
call; the successive
strings thus supplied are concatenated with separating newlines.
errposition(int cursorpos)
specifies the textual location
of an error within a query string. Currently it is only useful for
errors detected in the lexical and syntactic analysis phases of
query processing.
errtable(Relation rel)
specifies a relation whose
name and schema name should be included as auxiliary fields in the error
report.
errtablecol(Relation rel, int attnum)
specifies
a column whose name, table name, and schema name should be included as
auxiliary fields in the error report.
errtableconstraint(Relation rel, const char *conname)
specifies a table constraint whose name, table name, and schema name
should be included as auxiliary fields in the error report. Indexes
should be considered to be constraints for this purpose, whether or
not they have an associated pg_constraint
entry. Be
careful to pass the underlying heap relation, not the index itself, as
rel
.
errdatatype(Oid datatypeOid)
specifies a data
type whose name and schema name should be included as auxiliary fields
in the error report.
errdomainconstraint(Oid datatypeOid, const char *conname)
specifies a domain constraint whose name, domain name, and schema name
should be included as auxiliary fields in the error report.
errcode_for_file_access()
is a convenience function that
selects an appropriate SQLSTATE error identifier for a failure in a
file-access-related system call. It uses the saved
errno
to determine which error code to generate.
Usually this should be used in combination with %m
in the
primary error message text.
errcode_for_socket_access()
is a convenience function that
selects an appropriate SQLSTATE error identifier for a failure in a
socket-related system call.
errhidestmt(bool hide_stmt)
can be called to specify
suppression of the STATEMENT:
portion of a message in the
postmaster log. Generally this is appropriate if the message text
includes the current statement already.
errhidecontext(bool hide_ctx)
can be called to
specify suppression of the CONTEXT:
portion of a message in
the postmaster log. This should only be used for verbose debugging
messages where the repeated inclusion of context would bloat the log
too much.
At most one of the functions errtable
,
errtablecol
, errtableconstraint
,
errdatatype
, or errdomainconstraint
should
be used in an ereport
call. These functions exist to
allow applications to extract the name of a database object associated
with the error condition without having to examine the
potentially-localized error message text.
These functions should be used in error reports for which it's likely
that applications would wish to have automatic error handling. As of
LightDB 9.3, complete coverage exists only for
errors in SQLSTATE class 23 (integrity constraint violation), but this
is likely to be expanded in future.
There is an older function elog
that is still heavily used.
An elog
call:
elog(level, "format string", ...);
is exactly equivalent to:
ereport(level, errmsg_internal("format string", ...));
Notice that the SQLSTATE error code is always defaulted, and the message
string is not subject to translation.
Therefore, elog
should be used only for internal errors and
low-level debug logging. Any message that is likely to be of interest to
ordinary users should go through ereport
. Nonetheless,
there are enough internal “cannot happen” error checks in the
system that elog
is still widely used; it is preferred for
those messages for its notational simplicity.
Advice about writing good error messages can be found in Section 50.3.
[14]
That is, the value that was current when the ereport
call
was reached; changes of errno
within the auxiliary reporting
routines will not affect it. That would not be true if you were to
write strerror(errno)
explicitly in errmsg
's
parameter list; accordingly, do not do so.