/*
* errstart --- begin an error-reporting cycle
*
- * Create a stack entry and store the given parameters in it. Subsequently,
- * errmsg() and perhaps other routines will be called to further populate
- * the stack entry. Finally, errfinish() will be called to actually process
- * the error report.
+ * Create and initialize error stack entry. Subsequently, errmsg() and
+ * perhaps other routines will be called to further populate the stack entry.
+ * Finally, errfinish() will be called to actually process the error report.
*
* Returns true in normal case. Returns false to short-circuit the error
* report (if it's a warning or lower and not to be reported anywhere).
*/
bool
-errstart(int elevel, const char *filename, int lineno,
- const char *funcname, const char *domain)
+errstart(int elevel, const char *domain)
{
ErrorData *edata;
bool output_to_server;
if (ErrorContext == NULL)
{
/* Oops, hard crash time; very little we can do safely here */
- write_stderr("error occurred at %s:%d before error message processing is available\n",
- filename ? filename : "(unknown file)", lineno);
+ write_stderr("error occurred before error message processing is available\n");
exit(2);
}
edata->elevel = elevel;
edata->output_to_server = output_to_server;
edata->output_to_client = output_to_client;
- if (filename)
- {
- const char *slash;
-
- /* keep only base name, useful especially for vpath builds */
- slash = strrchr(filename, '/');
- if (slash)
- filename = slash + 1;
- }
- edata->filename = filename;
- edata->lineno = lineno;
- edata->funcname = funcname;
/* the default text domain is the backend's */
edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
/* initialize context_domain the same way (see set_errcontext_domain()) */
*
* Produce the appropriate error report(s) and pop the error stack.
*
- * If elevel is ERROR or worse, control does not return to the caller.
- * See elog.h for the error level definitions.
+ * If elevel, as passed to errstart(), is ERROR or worse, control does not
+ * return to the caller. See elog.h for the error level definitions.
*/
void
-errfinish(int dummy,...)
+errfinish(const char *filename, int lineno, const char *funcname)
{
ErrorData *edata = &errordata[errordata_stack_depth];
int elevel;
recursion_depth++;
CHECK_STACK_DEPTH();
+
+ /* Save the last few bits of error state into the stack entry */
+ if (filename)
+ {
+ const char *slash;
+
+ /* keep only base name, useful especially for vpath builds */
+ slash = strrchr(filename, '/');
+ if (slash)
+ filename = slash + 1;
+ }
+
+ edata->filename = filename;
+ edata->lineno = lineno;
+ edata->funcname = funcname;
+
elevel = edata->elevel;
/*
*
* The code is expected to be represented as per MAKE_SQLSTATE().
*/
-int
+void
errcode(int sqlerrcode)
{
ErrorData *edata = &errordata[errordata_stack_depth];
CHECK_STACK_DEPTH();
edata->sqlerrcode = sqlerrcode;
-
- return 0; /* return value does not matter */
}
* NOTE: the primary error message string should generally include %m
* when this is used.
*/
-int
+void
errcode_for_file_access(void)
{
ErrorData *edata = &errordata[errordata_stack_depth];
edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
break;
}
-
- return 0; /* return value does not matter */
}
/*
* NOTE: the primary error message string should generally include %m
* when this is used.
*/
-int
+void
errcode_for_socket_access(void)
{
ErrorData *edata = &errordata[errordata_stack_depth];
edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
break;
}
-
- return 0; /* return value does not matter */
}
* Note: no newline is needed at the end of the fmt string, since
* ereport will provide one for the output methods that need it.
*/
-int
+void
errmsg(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* Add a backtrace to the containing ereport() call. This is intended to be
* added temporarily during debugging.
*/
-int
+void
errbacktrace(void)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
-
- return 0;
}
/*
* the message because the translation would fail and result in infinite
* error recursion.
*/
-int
+void
errmsg_internal(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
* errmsg_plural --- add a primary error message text to the current error,
* with support for pluralization of the message text
*/
-int
+void
errmsg_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...)
{
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* errdetail --- add a detail error message text to the current error
*/
-int
+void
errdetail(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
* messages that seem not worth translating for one reason or another
* (typically, that they don't seem to be useful to average users).
*/
-int
+void
errdetail_internal(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* errdetail_log --- add a detail_log error message text to the current error
*/
-int
+void
errdetail_log(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* errdetail_log_plural --- add a detail_log error message text to the current error
* with support for pluralization of the message text
*/
-int
+void
errdetail_log_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...)
{
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
* errdetail_plural --- add a detail error message text to the current error,
* with support for pluralization of the message text
*/
-int
+void
errdetail_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...)
{
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* errhint --- add a hint error message text to the current error
*/
-int
+void
errhint(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
* context information. We assume earlier calls represent more-closely-nested
* states.
*/
-int
+void
errcontext_msg(const char *fmt,...)
{
ErrorData *edata = &errordata[errordata_stack_depth];
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
- return 0; /* return value does not matter */
}
/*
* a set_errcontext_domain() call to specify the domain. This is usually
* done transparently by the errcontext() macro.
*/
-int
+void
set_errcontext_domain(const char *domain)
{
ErrorData *edata = &errordata[errordata_stack_depth];
/* the default text domain is the backend's */
edata->context_domain = domain ? domain : PG_TEXTDOMAIN("postgres");
-
- return 0; /* return value does not matter */
}
*
* This should be called if the message text already includes the statement.
*/
-int
+void
errhidestmt(bool hide_stmt)
{
ErrorData *edata = &errordata[errordata_stack_depth];
CHECK_STACK_DEPTH();
edata->hide_stmt = hide_stmt;
-
- return 0; /* return value does not matter */
}
/*
* This should only be used for verbose debugging messages where the repeated
* inclusion of context would bloat the log volume too much.
*/
-int
+void
errhidecontext(bool hide_ctx)
{
ErrorData *edata = &errordata[errordata_stack_depth];
CHECK_STACK_DEPTH();
edata->hide_ctx = hide_ctx;
-
- return 0; /* return value does not matter */
}
* name appear in messages sent to old-protocol clients. Note that the
* passed string is expected to be a non-freeable constant string.
*/
-int
+void
errfunction(const char *funcname)
{
ErrorData *edata = &errordata[errordata_stack_depth];
edata->funcname = funcname;
edata->show_funcname = true;
-
- return 0; /* return value does not matter */
}
/*
* errposition --- add cursor position to the current error
*/
-int
+void
errposition(int cursorpos)
{
ErrorData *edata = &errordata[errordata_stack_depth];
CHECK_STACK_DEPTH();
edata->cursorpos = cursorpos;
-
- return 0; /* return value does not matter */
}
/*
* internalerrposition --- add internal cursor position to the current error
*/
-int
+void
internalerrposition(int cursorpos)
{
ErrorData *edata = &errordata[errordata_stack_depth];
CHECK_STACK_DEPTH();
edata->internalpos = cursorpos;
-
- return 0; /* return value does not matter */
}
/*
* is intended for use in error callback subroutines that are editorializing
* on the layout of the error report.
*/
-int
+void
internalerrquery(const char *query)
{
ErrorData *edata = &errordata[errordata_stack_depth];
if (query)
edata->internalquery = MemoryContextStrdup(edata->assoc_context, query);
-
- return 0; /* return value does not matter */
}
/*
* Most potential callers should not use this directly, but instead prefer
* higher-level abstractions, such as errtablecol() (see relcache.c).
*/
-int
+void
err_generic_string(int field, const char *str)
{
ErrorData *edata = &errordata[errordata_stack_depth];
elog(ERROR, "unsupported ErrorData field id: %d", field);
break;
}
-
- return 0; /* return value does not matter */
}
/*
}
-/*
- * elog_start --- startup for old-style API
- *
- * All that we do here is stash the hidden filename/lineno/funcname
- * arguments into a stack entry, along with the current value of errno.
- *
- * We need this to be separate from elog_finish because there's no other
- * C89-compliant way to deal with inserting extra arguments into the elog
- * call. (When using C99's __VA_ARGS__, we could possibly merge this with
- * elog_finish, but there doesn't seem to be a good way to save errno before
- * evaluating the format arguments if we do that.)
- */
-void
-elog_start(const char *filename, int lineno, const char *funcname)
-{
- ErrorData *edata;
-
- /* Make sure that memory context initialization has finished */
- if (ErrorContext == NULL)
- {
- /* Oops, hard crash time; very little we can do safely here */
- write_stderr("error occurred at %s:%d before error message processing is available\n",
- filename ? filename : "(unknown file)", lineno);
- exit(2);
- }
-
- if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
- {
- /*
- * Wups, stack not big enough. We treat this as a PANIC condition
- * because it suggests an infinite loop of errors during error
- * recovery. Note that the message is intentionally not localized,
- * else failure to convert it to client encoding could cause further
- * recursion.
- */
- errordata_stack_depth = -1; /* make room on stack */
- ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
- }
-
- edata = &errordata[errordata_stack_depth];
- if (filename)
- {
- const char *slash;
-
- /* keep only base name, useful especially for vpath builds */
- slash = strrchr(filename, '/');
- if (slash)
- filename = slash + 1;
- }
- edata->filename = filename;
- edata->lineno = lineno;
- edata->funcname = funcname;
- /* errno is saved now so that error parameter eval can't change it */
- edata->saved_errno = errno;
-
- /* Use ErrorContext for any allocations done at this level. */
- edata->assoc_context = ErrorContext;
-}
-
-/*
- * elog_finish --- finish up for old-style API
- */
-void
-elog_finish(int elevel, const char *fmt,...)
-{
- ErrorData *edata = &errordata[errordata_stack_depth];
- MemoryContext oldcontext;
-
- CHECK_STACK_DEPTH();
-
- /*
- * Do errstart() to see if we actually want to report the message.
- */
- errordata_stack_depth--;
- errno = edata->saved_errno;
- if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname, NULL))
- return; /* nothing to do */
-
- /*
- * Format error message just like errmsg_internal().
- */
- recursion_depth++;
- oldcontext = MemoryContextSwitchTo(edata->assoc_context);
-
- if (!edata->backtrace &&
- edata->funcname &&
- matches_backtrace_functions(edata->funcname))
- set_backtrace(edata, 2);
-
- edata->message_id = fmt;
- EVALUATE_MESSAGE(edata->domain, message, false, false);
-
- MemoryContextSwitchTo(oldcontext);
- recursion_depth--;
-
- /*
- * And let errfinish() finish up.
- */
- errfinish(0);
-}
-
-
/*
* Functions to allow construction of error message strings separately from
* the ereport() call itself.
ErrorData *newedata;
MemoryContext oldcontext;
- if (!errstart(edata->elevel, edata->filename, edata->lineno,
- edata->funcname, NULL))
+ if (!errstart(edata->elevel, edata->domain))
return; /* error is not to be reported at all */
newedata = &errordata[errordata_stack_depth];
recursion_depth--;
/* Process the error. */
- errfinish(0);
+ errfinish(edata->filename, edata->lineno, edata->funcname);
}
/*
*/
error_context_stack = NULL;
- errfinish(0);
+ errfinish(edata->filename, edata->lineno, edata->funcname);
}
/* Doesn't return ... */
#define ereport_domain(elevel, domain, ...) \
do { \
pg_prevent_errno_in_scope(); \
- if (errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \
- __VA_ARGS__, errfinish(0); \
+ if (errstart(elevel, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
pg_unreachable(); \
} while(0)
do { \
const int elevel_ = (elevel); \
pg_prevent_errno_in_scope(); \
- if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \
- __VA_ARGS__, errfinish(0); \
+ if (errstart(elevel_, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
if (elevel_ >= ERROR) \
pg_unreachable(); \
} while(0)
#define TEXTDOMAIN NULL
-extern bool errstart(int elevel, const char *filename, int lineno,
- const char *funcname, const char *domain);
-extern void errfinish(int dummy,...);
+extern bool errstart(int elevel, const char *domain);
+extern void errfinish(const char *filename, int lineno, const char *funcname);
-extern int errcode(int sqlerrcode);
+extern void errcode(int sqlerrcode);
-extern int errcode_for_file_access(void);
-extern int errcode_for_socket_access(void);
+extern void errcode_for_file_access(void);
+extern void errcode_for_socket_access(void);
-extern int errmsg(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errmsg_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errmsg(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errmsg_internal(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errmsg_plural(const char *fmt_singular, const char *fmt_plural,
+extern void errmsg_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
-extern int errdetail(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errdetail_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errdetail(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errdetail_internal(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errdetail_log(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errdetail_log(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errdetail_log_plural(const char *fmt_singular,
+extern void errdetail_log_plural(const char *fmt_singular,
const char *fmt_plural,
unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
-extern int errdetail_plural(const char *fmt_singular, const char *fmt_plural,
+extern void errdetail_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
-extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errhint(const char *fmt,...) pg_attribute_printf(1, 2);
/*
* errcontext() is typically called in error context callback functions, not
*/
#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg
-extern int set_errcontext_domain(const char *domain);
+extern void set_errcontext_domain(const char *domain);
-extern int errcontext_msg(const char *fmt,...) pg_attribute_printf(1, 2);
+extern void errcontext_msg(const char *fmt,...) pg_attribute_printf(1, 2);
-extern int errhidestmt(bool hide_stmt);
-extern int errhidecontext(bool hide_ctx);
+extern void errhidestmt(bool hide_stmt);
+extern void errhidecontext(bool hide_ctx);
-extern int errbacktrace(void);
+extern void errbacktrace(void);
-extern int errfunction(const char *funcname);
-extern int errposition(int cursorpos);
+extern void errfunction(const char *funcname);
+extern void errposition(int cursorpos);
-extern int internalerrposition(int cursorpos);
-extern int internalerrquery(const char *query);
+extern void internalerrposition(int cursorpos);
+extern void internalerrquery(const char *query);
-extern int err_generic_string(int field, const char *str);
+extern void err_generic_string(int field, const char *str);
extern int geterrcode(void);
extern int geterrposition(void);
* elog(ERROR, "portal \"%s\" not found", stmt->portalname);
*----------
*/
-/*
- * Using variadic macros, we can give the compiler a hint about the
- * call not returning when elevel >= ERROR. See comments for ereport().
- * Note that historically elog() has called elog_start (which saves errno)
- * before evaluating "elevel", so we preserve that behavior here.
- */
-#ifdef HAVE__BUILTIN_CONSTANT_P
#define elog(elevel, ...) \
- do { \
- pg_prevent_errno_in_scope(); \
- elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
- elog_finish(elevel, __VA_ARGS__); \
- if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
- pg_unreachable(); \
- } while(0)
-#else /* !HAVE__BUILTIN_CONSTANT_P */
-#define elog(elevel, ...) \
- do { \
- pg_prevent_errno_in_scope(); \
- elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
- { \
- const int elevel_ = (elevel); \
- elog_finish(elevel_, __VA_ARGS__); \
- if (elevel_ >= ERROR) \
- pg_unreachable(); \
- } \
- } while(0)
-#endif /* HAVE__BUILTIN_CONSTANT_P */
-
-extern void elog_start(const char *filename, int lineno, const char *funcname);
-extern void elog_finish(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);
+ ereport(elevel, errmsg_internal(__VA_ARGS__))
/* Support for constructing error strings separately from ereport() calls */