Commit 17a28b03 authored by Tom Lane's avatar Tom Lane

Improve the internal implementation of ereport().

Change all the auxiliary error-reporting routines to return void,
now that we no longer need to pretend they are passing something
useful to errfinish().  While this probably doesn't save anything
significant at the machine-code level, it allows detection of some
additional types of mistakes.

Pass the error location details (__FILE__, __LINE__, PG_FUNCNAME_MACRO)
to errfinish not errstart.  This shaves a few cycles off the case where
errstart decides we're not going to emit anything.

Re-implement elog() as a trivial wrapper around ereport(), removing
the separate support infrastructure it used to have.  Aside from
getting rid of some now-surplus code, this means that elog() now
really does have exactly the same semantics as ereport(), in particular
that it can skip evaluation work if the message is not to be emitted.

Andres Freund and Tom Lane

Discussion: https://postgr.es/m/CA+fd4k6N8EjNvZpM8nme+y+05mz-SM8Z_BgkixzkA34R+ej0Kw@mail.gmail.com
parent e3a87b49
...@@ -832,21 +832,21 @@ UpdateChangedParamSet(PlanState *node, Bitmapset *newchg) ...@@ -832,21 +832,21 @@ UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
* normal non-error case: computing character indexes would be much more * normal non-error case: computing character indexes would be much more
* expensive than storing token offsets.) * expensive than storing token offsets.)
*/ */
int void
executor_errposition(EState *estate, int location) executor_errposition(EState *estate, int location)
{ {
int pos; int pos;
/* No-op if location was not provided */ /* No-op if location was not provided */
if (location < 0) if (location < 0)
return 0; return;
/* Can't do anything if source text is not available */ /* Can't do anything if source text is not available */
if (estate == NULL || estate->es_sourceText == NULL) if (estate == NULL || estate->es_sourceText == NULL)
return 0; return;
/* Convert offset to character number */ /* Convert offset to character number */
pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1; pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
/* And pass it to the ereport mechanism */ /* And pass it to the ereport mechanism */
return errposition(pos); errposition(pos);
} }
/* /*
......
...@@ -1246,15 +1246,15 @@ coerce_to_specific_type(ParseState *pstate, Node *node, ...@@ -1246,15 +1246,15 @@ coerce_to_specific_type(ParseState *pstate, Node *node,
* XXX possibly this is more generally useful than coercion errors; * XXX possibly this is more generally useful than coercion errors;
* if so, should rename and place with parser_errposition. * if so, should rename and place with parser_errposition.
*/ */
int void
parser_coercion_errposition(ParseState *pstate, parser_coercion_errposition(ParseState *pstate,
int coerce_location, int coerce_location,
Node *input_expr) Node *input_expr)
{ {
if (coerce_location >= 0) if (coerce_location >= 0)
return parser_errposition(pstate, coerce_location); parser_errposition(pstate, coerce_location);
else else
return parser_errposition(pstate, exprLocation(input_expr)); parser_errposition(pstate, exprLocation(input_expr));
} }
......
...@@ -106,21 +106,21 @@ free_parsestate(ParseState *pstate) ...@@ -106,21 +106,21 @@ free_parsestate(ParseState *pstate)
* normal non-error case: computing character indexes would be much more * normal non-error case: computing character indexes would be much more
* expensive than storing token offsets.) * expensive than storing token offsets.)
*/ */
int void
parser_errposition(ParseState *pstate, int location) parser_errposition(ParseState *pstate, int location)
{ {
int pos; int pos;
/* No-op if location was not provided */ /* No-op if location was not provided */
if (location < 0) if (location < 0)
return 0; return;
/* Can't do anything if source text is not available */ /* Can't do anything if source text is not available */
if (pstate == NULL || pstate->p_sourcetext == NULL) if (pstate == NULL || pstate->p_sourcetext == NULL)
return 0; return;
/* Convert offset to character number */ /* Convert offset to character number */
pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1; pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1;
/* And pass it to the ereport mechanism */ /* And pass it to the ereport mechanism */
return errposition(pos); errposition(pos);
} }
......
...@@ -1076,18 +1076,18 @@ other . ...@@ -1076,18 +1076,18 @@ other .
* (essentially, scan.l, parser.c, and gram.y), since it requires the * (essentially, scan.l, parser.c, and gram.y), since it requires the
* yyscanner struct to still be available. * yyscanner struct to still be available.
*/ */
int void
scanner_errposition(int location, core_yyscan_t yyscanner) scanner_errposition(int location, core_yyscan_t yyscanner)
{ {
int pos; int pos;
if (location < 0) if (location < 0)
return 0; /* no-op if location is unknown */ return; /* no-op if location is unknown */
/* Convert byte offset to character number */ /* Convert byte offset to character number */
pos = pg_mbstrlen_with_len(yyextra->scanbuf, location) + 1; pos = pg_mbstrlen_with_len(yyextra->scanbuf, location) + 1;
/* And pass it to the ereport mechanism */ /* And pass it to the ereport mechanism */
return errposition(pos); errposition(pos);
} }
/* /*
......
...@@ -92,7 +92,7 @@ static bool dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, ...@@ -92,7 +92,7 @@ static bool dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
void **impl_private, void **mapped_address, void **impl_private, void **mapped_address,
Size *mapped_size, int elevel); Size *mapped_size, int elevel);
#endif #endif
static int errcode_for_dynamic_shared_memory(void); static void errcode_for_dynamic_shared_memory(void);
const struct config_enum_entry dynamic_shared_memory_options[] = { const struct config_enum_entry dynamic_shared_memory_options[] = {
#ifdef USE_DSM_POSIX #ifdef USE_DSM_POSIX
...@@ -1030,11 +1030,11 @@ dsm_impl_unpin_segment(dsm_handle handle, void **impl_private) ...@@ -1030,11 +1030,11 @@ dsm_impl_unpin_segment(dsm_handle handle, void **impl_private)
} }
} }
static int static void
errcode_for_dynamic_shared_memory(void) errcode_for_dynamic_shared_memory(void)
{ {
if (errno == EFBIG || errno == ENOMEM) if (errno == EFBIG || errno == ENOMEM)
return errcode(ERRCODE_OUT_OF_MEMORY); errcode(ERRCODE_OUT_OF_MEMORY);
else else
return errcode_for_file_access(); errcode_for_file_access();
} }
...@@ -329,7 +329,7 @@ typedef struct JsObject ...@@ -329,7 +329,7 @@ typedef struct JsObject
hash_destroy((jso)->val.json_hash); \ hash_destroy((jso)->val.json_hash); \
} while (0) } while (0)
static int report_json_context(JsonLexContext *lex); static void report_json_context(JsonLexContext *lex);
/* semantic action functions for json_object_keys */ /* semantic action functions for json_object_keys */
static void okeys_object_field_start(void *state, char *fname, bool isnull); static void okeys_object_field_start(void *state, char *fname, bool isnull);
...@@ -631,7 +631,7 @@ json_ereport_error(JsonParseErrorType error, JsonLexContext *lex) ...@@ -631,7 +631,7 @@ json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
* The return value isn't meaningful, but we make it non-void so that this * The return value isn't meaningful, but we make it non-void so that this
* can be invoked inside ereport(). * can be invoked inside ereport().
*/ */
static int static void
report_json_context(JsonLexContext *lex) report_json_context(JsonLexContext *lex)
{ {
const char *context_start; const char *context_start;
...@@ -689,7 +689,7 @@ report_json_context(JsonLexContext *lex) ...@@ -689,7 +689,7 @@ report_json_context(JsonLexContext *lex)
prefix = (context_start > line_start) ? "..." : ""; prefix = (context_start > line_start) ? "..." : "";
suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : ""; suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : "";
return errcontext("JSON data, line %d: %s%s%s", errcontext("JSON data, line %d: %s%s%s",
line_number, prefix, ctxt, suffix); line_number, prefix, ctxt, suffix);
} }
......
...@@ -223,17 +223,15 @@ err_gettext(const char *str) ...@@ -223,17 +223,15 @@ err_gettext(const char *str)
/* /*
* errstart --- begin an error-reporting cycle * errstart --- begin an error-reporting cycle
* *
* Create a stack entry and store the given parameters in it. Subsequently, * Create and initialize error stack entry. Subsequently, errmsg() and
* errmsg() and perhaps other routines will be called to further populate * perhaps other routines will be called to further populate the stack entry.
* the stack entry. Finally, errfinish() will be called to actually process * Finally, errfinish() will be called to actually process the error report.
* the error report.
* *
* Returns true in normal case. Returns false to short-circuit the error * 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). * report (if it's a warning or lower and not to be reported anywhere).
*/ */
bool bool
errstart(int elevel, const char *filename, int lineno, errstart(int elevel, const char *domain)
const char *funcname, const char *domain)
{ {
ErrorData *edata; ErrorData *edata;
bool output_to_server; bool output_to_server;
...@@ -321,8 +319,7 @@ errstart(int elevel, const char *filename, int lineno, ...@@ -321,8 +319,7 @@ errstart(int elevel, const char *filename, int lineno,
if (ErrorContext == NULL) if (ErrorContext == NULL)
{ {
/* Oops, hard crash time; very little we can do safely here */ /* 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", write_stderr("error occurred before error message processing is available\n");
filename ? filename : "(unknown file)", lineno);
exit(2); exit(2);
} }
...@@ -368,18 +365,6 @@ errstart(int elevel, const char *filename, int lineno, ...@@ -368,18 +365,6 @@ errstart(int elevel, const char *filename, int lineno,
edata->elevel = elevel; edata->elevel = elevel;
edata->output_to_server = output_to_server; edata->output_to_server = output_to_server;
edata->output_to_client = output_to_client; 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 */ /* the default text domain is the backend's */
edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres"); edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
/* initialize context_domain the same way (see set_errcontext_domain()) */ /* initialize context_domain the same way (see set_errcontext_domain()) */
...@@ -434,11 +419,11 @@ matches_backtrace_functions(const char *funcname) ...@@ -434,11 +419,11 @@ matches_backtrace_functions(const char *funcname)
* *
* Produce the appropriate error report(s) and pop the error stack. * Produce the appropriate error report(s) and pop the error stack.
* *
* If elevel is ERROR or worse, control does not return to the caller. * If elevel, as passed to errstart(), is ERROR or worse, control does not
* See elog.h for the error level definitions. * return to the caller. See elog.h for the error level definitions.
*/ */
void void
errfinish(int dummy,...) errfinish(const char *filename, int lineno, const char *funcname)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
int elevel; int elevel;
...@@ -447,6 +432,22 @@ errfinish(int dummy,...) ...@@ -447,6 +432,22 @@ errfinish(int dummy,...)
recursion_depth++; recursion_depth++;
CHECK_STACK_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; elevel = edata->elevel;
/* /*
...@@ -605,7 +606,7 @@ errfinish(int dummy,...) ...@@ -605,7 +606,7 @@ errfinish(int dummy,...)
* *
* The code is expected to be represented as per MAKE_SQLSTATE(). * The code is expected to be represented as per MAKE_SQLSTATE().
*/ */
int void
errcode(int sqlerrcode) errcode(int sqlerrcode)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -614,8 +615,6 @@ errcode(int sqlerrcode) ...@@ -614,8 +615,6 @@ errcode(int sqlerrcode)
CHECK_STACK_DEPTH(); CHECK_STACK_DEPTH();
edata->sqlerrcode = sqlerrcode; edata->sqlerrcode = sqlerrcode;
return 0; /* return value does not matter */
} }
...@@ -628,7 +627,7 @@ errcode(int sqlerrcode) ...@@ -628,7 +627,7 @@ errcode(int sqlerrcode)
* NOTE: the primary error message string should generally include %m * NOTE: the primary error message string should generally include %m
* when this is used. * when this is used.
*/ */
int void
errcode_for_file_access(void) errcode_for_file_access(void)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -686,8 +685,6 @@ errcode_for_file_access(void) ...@@ -686,8 +685,6 @@ errcode_for_file_access(void)
edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
break; break;
} }
return 0; /* return value does not matter */
} }
/* /*
...@@ -699,7 +696,7 @@ errcode_for_file_access(void) ...@@ -699,7 +696,7 @@ errcode_for_file_access(void)
* NOTE: the primary error message string should generally include %m * NOTE: the primary error message string should generally include %m
* when this is used. * when this is used.
*/ */
int void
errcode_for_socket_access(void) errcode_for_socket_access(void)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -722,8 +719,6 @@ errcode_for_socket_access(void) ...@@ -722,8 +719,6 @@ errcode_for_socket_access(void)
edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
break; break;
} }
return 0; /* return value does not matter */
} }
...@@ -819,7 +814,7 @@ errcode_for_socket_access(void) ...@@ -819,7 +814,7 @@ errcode_for_socket_access(void)
* Note: no newline is needed at the end of the fmt string, since * Note: no newline is needed at the end of the fmt string, since
* ereport will provide one for the output methods that need it. * ereport will provide one for the output methods that need it.
*/ */
int void
errmsg(const char *fmt,...) errmsg(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -834,14 +829,13 @@ errmsg(const char *fmt,...) ...@@ -834,14 +829,13 @@ errmsg(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
* Add a backtrace to the containing ereport() call. This is intended to be * Add a backtrace to the containing ereport() call. This is intended to be
* added temporarily during debugging. * added temporarily during debugging.
*/ */
int void
errbacktrace(void) errbacktrace(void)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -855,8 +849,6 @@ errbacktrace(void) ...@@ -855,8 +849,6 @@ errbacktrace(void)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0;
} }
/* /*
...@@ -906,7 +898,7 @@ set_backtrace(ErrorData *edata, int num_skip) ...@@ -906,7 +898,7 @@ set_backtrace(ErrorData *edata, int num_skip)
* the message because the translation would fail and result in infinite * the message because the translation would fail and result in infinite
* error recursion. * error recursion.
*/ */
int void
errmsg_internal(const char *fmt,...) errmsg_internal(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -921,7 +913,6 @@ errmsg_internal(const char *fmt,...) ...@@ -921,7 +913,6 @@ errmsg_internal(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
...@@ -929,7 +920,7 @@ errmsg_internal(const char *fmt,...) ...@@ -929,7 +920,7 @@ errmsg_internal(const char *fmt,...)
* errmsg_plural --- add a primary error message text to the current error, * errmsg_plural --- add a primary error message text to the current error,
* with support for pluralization of the message text * with support for pluralization of the message text
*/ */
int void
errmsg_plural(const char *fmt_singular, const char *fmt_plural, errmsg_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...) unsigned long n,...)
{ {
...@@ -945,14 +936,13 @@ errmsg_plural(const char *fmt_singular, const char *fmt_plural, ...@@ -945,14 +936,13 @@ errmsg_plural(const char *fmt_singular, const char *fmt_plural,
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
* errdetail --- add a detail error message text to the current error * errdetail --- add a detail error message text to the current error
*/ */
int void
errdetail(const char *fmt,...) errdetail(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -966,7 +956,6 @@ errdetail(const char *fmt,...) ...@@ -966,7 +956,6 @@ errdetail(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
...@@ -979,7 +968,7 @@ errdetail(const char *fmt,...) ...@@ -979,7 +968,7 @@ errdetail(const char *fmt,...)
* messages that seem not worth translating for one reason or another * messages that seem not worth translating for one reason or another
* (typically, that they don't seem to be useful to average users). * (typically, that they don't seem to be useful to average users).
*/ */
int void
errdetail_internal(const char *fmt,...) errdetail_internal(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -993,14 +982,13 @@ errdetail_internal(const char *fmt,...) ...@@ -993,14 +982,13 @@ errdetail_internal(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
* errdetail_log --- add a detail_log error message text to the current error * errdetail_log --- add a detail_log error message text to the current error
*/ */
int void
errdetail_log(const char *fmt,...) errdetail_log(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1014,14 +1002,13 @@ errdetail_log(const char *fmt,...) ...@@ -1014,14 +1002,13 @@ errdetail_log(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
* errdetail_log_plural --- add a detail_log error message text to the current error * errdetail_log_plural --- add a detail_log error message text to the current error
* with support for pluralization of the message text * with support for pluralization of the message text
*/ */
int void
errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, errdetail_log_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...) unsigned long n,...)
{ {
...@@ -1036,7 +1023,6 @@ errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, ...@@ -1036,7 +1023,6 @@ errdetail_log_plural(const char *fmt_singular, const char *fmt_plural,
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
...@@ -1044,7 +1030,7 @@ errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, ...@@ -1044,7 +1030,7 @@ errdetail_log_plural(const char *fmt_singular, const char *fmt_plural,
* errdetail_plural --- add a detail error message text to the current error, * errdetail_plural --- add a detail error message text to the current error,
* with support for pluralization of the message text * with support for pluralization of the message text
*/ */
int void
errdetail_plural(const char *fmt_singular, const char *fmt_plural, errdetail_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n,...) unsigned long n,...)
{ {
...@@ -1059,14 +1045,13 @@ errdetail_plural(const char *fmt_singular, const char *fmt_plural, ...@@ -1059,14 +1045,13 @@ errdetail_plural(const char *fmt_singular, const char *fmt_plural,
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
* errhint --- add a hint error message text to the current error * errhint --- add a hint error message text to the current error
*/ */
int void
errhint(const char *fmt,...) errhint(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1080,7 +1065,6 @@ errhint(const char *fmt,...) ...@@ -1080,7 +1065,6 @@ errhint(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
...@@ -1091,7 +1075,7 @@ errhint(const char *fmt,...) ...@@ -1091,7 +1075,7 @@ errhint(const char *fmt,...)
* context information. We assume earlier calls represent more-closely-nested * context information. We assume earlier calls represent more-closely-nested
* states. * states.
*/ */
int void
errcontext_msg(const char *fmt,...) errcontext_msg(const char *fmt,...)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1105,7 +1089,6 @@ errcontext_msg(const char *fmt,...) ...@@ -1105,7 +1089,6 @@ errcontext_msg(const char *fmt,...)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
recursion_depth--; recursion_depth--;
return 0; /* return value does not matter */
} }
/* /*
...@@ -1117,7 +1100,7 @@ errcontext_msg(const char *fmt,...) ...@@ -1117,7 +1100,7 @@ errcontext_msg(const char *fmt,...)
* a set_errcontext_domain() call to specify the domain. This is usually * a set_errcontext_domain() call to specify the domain. This is usually
* done transparently by the errcontext() macro. * done transparently by the errcontext() macro.
*/ */
int void
set_errcontext_domain(const char *domain) set_errcontext_domain(const char *domain)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1127,8 +1110,6 @@ set_errcontext_domain(const char *domain) ...@@ -1127,8 +1110,6 @@ set_errcontext_domain(const char *domain)
/* the default text domain is the backend's */ /* the default text domain is the backend's */
edata->context_domain = domain ? domain : PG_TEXTDOMAIN("postgres"); edata->context_domain = domain ? domain : PG_TEXTDOMAIN("postgres");
return 0; /* return value does not matter */
} }
...@@ -1137,7 +1118,7 @@ set_errcontext_domain(const char *domain) ...@@ -1137,7 +1118,7 @@ set_errcontext_domain(const char *domain)
* *
* This should be called if the message text already includes the statement. * This should be called if the message text already includes the statement.
*/ */
int void
errhidestmt(bool hide_stmt) errhidestmt(bool hide_stmt)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1146,8 +1127,6 @@ errhidestmt(bool hide_stmt) ...@@ -1146,8 +1127,6 @@ errhidestmt(bool hide_stmt)
CHECK_STACK_DEPTH(); CHECK_STACK_DEPTH();
edata->hide_stmt = hide_stmt; edata->hide_stmt = hide_stmt;
return 0; /* return value does not matter */
} }
/* /*
...@@ -1156,7 +1135,7 @@ errhidestmt(bool hide_stmt) ...@@ -1156,7 +1135,7 @@ errhidestmt(bool hide_stmt)
* This should only be used for verbose debugging messages where the repeated * This should only be used for verbose debugging messages where the repeated
* inclusion of context would bloat the log volume too much. * inclusion of context would bloat the log volume too much.
*/ */
int void
errhidecontext(bool hide_ctx) errhidecontext(bool hide_ctx)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1165,8 +1144,6 @@ errhidecontext(bool hide_ctx) ...@@ -1165,8 +1144,6 @@ errhidecontext(bool hide_ctx)
CHECK_STACK_DEPTH(); CHECK_STACK_DEPTH();
edata->hide_ctx = hide_ctx; edata->hide_ctx = hide_ctx;
return 0; /* return value does not matter */
} }
...@@ -1177,7 +1154,7 @@ errhidecontext(bool hide_ctx) ...@@ -1177,7 +1154,7 @@ errhidecontext(bool hide_ctx)
* name appear in messages sent to old-protocol clients. Note that the * name appear in messages sent to old-protocol clients. Note that the
* passed string is expected to be a non-freeable constant string. * passed string is expected to be a non-freeable constant string.
*/ */
int void
errfunction(const char *funcname) errfunction(const char *funcname)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1187,14 +1164,12 @@ errfunction(const char *funcname) ...@@ -1187,14 +1164,12 @@ errfunction(const char *funcname)
edata->funcname = funcname; edata->funcname = funcname;
edata->show_funcname = true; edata->show_funcname = true;
return 0; /* return value does not matter */
} }
/* /*
* errposition --- add cursor position to the current error * errposition --- add cursor position to the current error
*/ */
int void
errposition(int cursorpos) errposition(int cursorpos)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1203,14 +1178,12 @@ errposition(int cursorpos) ...@@ -1203,14 +1178,12 @@ errposition(int cursorpos)
CHECK_STACK_DEPTH(); CHECK_STACK_DEPTH();
edata->cursorpos = cursorpos; edata->cursorpos = cursorpos;
return 0; /* return value does not matter */
} }
/* /*
* internalerrposition --- add internal cursor position to the current error * internalerrposition --- add internal cursor position to the current error
*/ */
int void
internalerrposition(int cursorpos) internalerrposition(int cursorpos)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1219,8 +1192,6 @@ internalerrposition(int cursorpos) ...@@ -1219,8 +1192,6 @@ internalerrposition(int cursorpos)
CHECK_STACK_DEPTH(); CHECK_STACK_DEPTH();
edata->internalpos = cursorpos; edata->internalpos = cursorpos;
return 0; /* return value does not matter */
} }
/* /*
...@@ -1230,7 +1201,7 @@ internalerrposition(int cursorpos) ...@@ -1230,7 +1201,7 @@ internalerrposition(int cursorpos)
* is intended for use in error callback subroutines that are editorializing * is intended for use in error callback subroutines that are editorializing
* on the layout of the error report. * on the layout of the error report.
*/ */
int void
internalerrquery(const char *query) internalerrquery(const char *query)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1246,8 +1217,6 @@ internalerrquery(const char *query) ...@@ -1246,8 +1217,6 @@ internalerrquery(const char *query)
if (query) if (query)
edata->internalquery = MemoryContextStrdup(edata->assoc_context, query); edata->internalquery = MemoryContextStrdup(edata->assoc_context, query);
return 0; /* return value does not matter */
} }
/* /*
...@@ -1260,7 +1229,7 @@ internalerrquery(const char *query) ...@@ -1260,7 +1229,7 @@ internalerrquery(const char *query)
* Most potential callers should not use this directly, but instead prefer * Most potential callers should not use this directly, but instead prefer
* higher-level abstractions, such as errtablecol() (see relcache.c). * higher-level abstractions, such as errtablecol() (see relcache.c).
*/ */
int void
err_generic_string(int field, const char *str) err_generic_string(int field, const char *str)
{ {
ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *edata = &errordata[errordata_stack_depth];
...@@ -1289,8 +1258,6 @@ err_generic_string(int field, const char *str) ...@@ -1289,8 +1258,6 @@ err_generic_string(int field, const char *str)
elog(ERROR, "unsupported ErrorData field id: %d", field); elog(ERROR, "unsupported ErrorData field id: %d", field);
break; break;
} }
return 0; /* return value does not matter */
} }
/* /*
...@@ -1355,108 +1322,6 @@ getinternalerrposition(void) ...@@ -1355,108 +1322,6 @@ getinternalerrposition(void)
} }
/*
* 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 * Functions to allow construction of error message strings separately from
* the ereport() call itself. * the ereport() call itself.
...@@ -1696,8 +1561,7 @@ ThrowErrorData(ErrorData *edata) ...@@ -1696,8 +1561,7 @@ ThrowErrorData(ErrorData *edata)
ErrorData *newedata; ErrorData *newedata;
MemoryContext oldcontext; MemoryContext oldcontext;
if (!errstart(edata->elevel, edata->filename, edata->lineno, if (!errstart(edata->elevel, edata->domain))
edata->funcname, NULL))
return; /* error is not to be reported at all */ return; /* error is not to be reported at all */
newedata = &errordata[errordata_stack_depth]; newedata = &errordata[errordata_stack_depth];
...@@ -1739,7 +1603,7 @@ ThrowErrorData(ErrorData *edata) ...@@ -1739,7 +1603,7 @@ ThrowErrorData(ErrorData *edata)
recursion_depth--; recursion_depth--;
/* Process the error. */ /* Process the error. */
errfinish(0); errfinish(edata->filename, edata->lineno, edata->funcname);
} }
/* /*
...@@ -1853,7 +1717,7 @@ pg_re_throw(void) ...@@ -1853,7 +1717,7 @@ pg_re_throw(void)
*/ */
error_context_stack = NULL; error_context_stack = NULL;
errfinish(0); errfinish(edata->filename, edata->lineno, edata->funcname);
} }
/* Doesn't return ... */ /* Doesn't return ... */
......
...@@ -546,7 +546,7 @@ exec_rt_fetch(Index rti, EState *estate) ...@@ -546,7 +546,7 @@ exec_rt_fetch(Index rti, EState *estate)
extern Relation ExecGetRangeTableRelation(EState *estate, Index rti); extern Relation ExecGetRangeTableRelation(EState *estate, Index rti);
extern int executor_errposition(EState *estate, int location); extern void executor_errposition(EState *estate, int location);
extern void RegisterExprContextCallback(ExprContext *econtext, extern void RegisterExprContextCallback(ExprContext *econtext,
ExprContextCallbackFunction function, ExprContextCallbackFunction function,
......
...@@ -61,7 +61,7 @@ extern Node *coerce_to_specific_type_typmod(ParseState *pstate, Node *node, ...@@ -61,7 +61,7 @@ extern Node *coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
Oid targetTypeId, int32 targetTypmod, Oid targetTypeId, int32 targetTypmod,
const char *constructName); const char *constructName);
extern int parser_coercion_errposition(ParseState *pstate, extern void parser_coercion_errposition(ParseState *pstate,
int coerce_location, int coerce_location,
Node *input_expr); Node *input_expr);
......
...@@ -307,7 +307,7 @@ typedef struct ParseCallbackState ...@@ -307,7 +307,7 @@ typedef struct ParseCallbackState
extern ParseState *make_parsestate(ParseState *parentParseState); extern ParseState *make_parsestate(ParseState *parentParseState);
extern void free_parsestate(ParseState *pstate); extern void free_parsestate(ParseState *pstate);
extern int parser_errposition(ParseState *pstate, int location); extern void parser_errposition(ParseState *pstate, int location);
extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate, extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate,
ParseState *pstate, int location); ParseState *pstate, int location);
......
...@@ -140,7 +140,7 @@ extern core_yyscan_t scanner_init(const char *str, ...@@ -140,7 +140,7 @@ extern core_yyscan_t scanner_init(const char *str,
extern void scanner_finish(core_yyscan_t yyscanner); extern void scanner_finish(core_yyscan_t yyscanner);
extern int core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp, extern int core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp,
core_yyscan_t yyscanner); core_yyscan_t yyscanner);
extern int scanner_errposition(int location, core_yyscan_t yyscanner); extern void scanner_errposition(int location, core_yyscan_t yyscanner);
extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate, extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate,
core_yyscan_t yyscanner, core_yyscan_t yyscanner,
int location); int location);
......
...@@ -124,8 +124,8 @@ ...@@ -124,8 +124,8 @@
#define ereport_domain(elevel, domain, ...) \ #define ereport_domain(elevel, domain, ...) \
do { \ do { \
pg_prevent_errno_in_scope(); \ pg_prevent_errno_in_scope(); \
if (errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \ if (errstart(elevel, domain)) \
__VA_ARGS__, errfinish(0); \ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
pg_unreachable(); \ pg_unreachable(); \
} while(0) } while(0)
...@@ -134,8 +134,8 @@ ...@@ -134,8 +134,8 @@
do { \ do { \
const int elevel_ = (elevel); \ const int elevel_ = (elevel); \
pg_prevent_errno_in_scope(); \ pg_prevent_errno_in_scope(); \
if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \ if (errstart(elevel_, domain)) \
__VA_ARGS__, errfinish(0); \ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
if (elevel_ >= ERROR) \ if (elevel_ >= ERROR) \
pg_unreachable(); \ pg_unreachable(); \
} while(0) } while(0)
...@@ -146,34 +146,33 @@ ...@@ -146,34 +146,33 @@
#define TEXTDOMAIN NULL #define TEXTDOMAIN NULL
extern bool errstart(int elevel, const char *filename, int lineno, extern bool errstart(int elevel, const char *domain);
const char *funcname, const char *domain); extern void errfinish(const char *filename, int lineno, const char *funcname);
extern void errfinish(int dummy,...);
extern int errcode(int sqlerrcode); extern void errcode(int sqlerrcode);
extern int errcode_for_file_access(void); extern void errcode_for_file_access(void);
extern int errcode_for_socket_access(void); extern void errcode_for_socket_access(void);
extern int errmsg(const char *fmt,...) pg_attribute_printf(1, 2); extern void errmsg(const char *fmt,...) pg_attribute_printf(1, 2);
extern int errmsg_internal(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); 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 void errdetail(const char *fmt,...) pg_attribute_printf(1, 2);
extern int errdetail_internal(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, const char *fmt_plural,
unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4); 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); 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 * errcontext() is typically called in error context callback functions, not
...@@ -185,22 +184,22 @@ extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2); ...@@ -185,22 +184,22 @@ extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2);
*/ */
#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg #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 void errhidestmt(bool hide_stmt);
extern int errhidecontext(bool hide_ctx); extern void errhidecontext(bool hide_ctx);
extern int errbacktrace(void); extern void errbacktrace(void);
extern int errfunction(const char *funcname); extern void errfunction(const char *funcname);
extern int errposition(int cursorpos); extern void errposition(int cursorpos);
extern int internalerrposition(int cursorpos); extern void internalerrposition(int cursorpos);
extern int internalerrquery(const char *query); 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 geterrcode(void);
extern int geterrposition(void); extern int geterrposition(void);
...@@ -212,37 +211,8 @@ extern int getinternalerrposition(void); ...@@ -212,37 +211,8 @@ extern int getinternalerrposition(void);
* elog(ERROR, "portal \"%s\" not found", stmt->portalname); * 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, ...) \ #define elog(elevel, ...) \
do { \ ereport(elevel, errmsg_internal(__VA_ARGS__))
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);
/* Support for constructing error strings separately from ereport() calls */ /* Support for constructing error strings separately from ereport() calls */
......
...@@ -468,20 +468,20 @@ plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) ...@@ -468,20 +468,20 @@ plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc)
* parsing of a plpgsql function, since it requires the scanorig string * parsing of a plpgsql function, since it requires the scanorig string
* to still be available. * to still be available.
*/ */
int void
plpgsql_scanner_errposition(int location) plpgsql_scanner_errposition(int location)
{ {
int pos; int pos;
if (location < 0 || scanorig == NULL) if (location < 0 || scanorig == NULL)
return 0; /* no-op if location is unknown */ return; /* no-op if location is unknown */
/* Convert byte offset to character number */ /* Convert byte offset to character number */
pos = pg_mbstrlen_with_len(scanorig, location) + 1; pos = pg_mbstrlen_with_len(scanorig, location) + 1;
/* And pass it to the ereport mechanism */ /* And pass it to the ereport mechanism */
(void) internalerrposition(pos); (void) internalerrposition(pos);
/* Also pass the function body string */ /* Also pass the function body string */
return internalerrquery(scanorig); internalerrquery(scanorig);
} }
/* /*
......
...@@ -1319,7 +1319,7 @@ extern void plpgsql_append_source_text(StringInfo buf, ...@@ -1319,7 +1319,7 @@ extern void plpgsql_append_source_text(StringInfo buf,
extern int plpgsql_peek(void); extern int plpgsql_peek(void);
extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc,
int *tok2_loc); int *tok2_loc);
extern int plpgsql_scanner_errposition(int location); extern void plpgsql_scanner_errposition(int location);
extern void plpgsql_yyerror(const char *message) pg_attribute_noreturn(); extern void plpgsql_yyerror(const char *message) pg_attribute_noreturn();
extern int plpgsql_location_to_lineno(int location); extern int plpgsql_location_to_lineno(int location);
extern int plpgsql_latest_lineno(void); extern int plpgsql_latest_lineno(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment