errcontext-domain-1.patch
text/x-diff
Filename: errcontext-domain-1.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 3 | 0 |
| src/backend/catalog/pg_proc.c | 3 | 0 |
| src/backend/commands/copy.c | 3 | 0 |
| src/backend/executor/functions.c | 3 | 0 |
| src/backend/executor/spi.c | 3 | 0 |
| src/backend/optimizer/util/clauses.c | 3 | 0 |
| src/backend/parser/parse_type.c | 3 | 0 |
| src/backend/storage/buffer/bufmgr.c | 6 | 0 |
| src/backend/tsearch/ts_locale.c | 3 | 0 |
| src/backend/utils/error/elog.c | 42 | 0 |
| src/include/utils/elog.h | 11 | 0 |
| src/pl/plperl/plperl.c | 7 | 0 |
| src/pl/plpgsql/src/pl_comp.c | 3 | 0 |
| src/pl/plpgsql/src/pl_exec.c | 3 | 0 |
| src/pl/plpython/plpy_exec.c | 6 | 0 |
| src/pl/plpython/plpy_main.c | 4 | 0 |
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 0c301b2..e267ff2 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -9913,6 +9913,9 @@ rm_redo_error_callback(void *arg)
XLogRecord *record = (XLogRecord *) arg;
StringInfoData buf;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
initStringInfo(&buf);
RmgrTable[record->xl_rmid].rm_desc(&buf,
record->xl_info,
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 1fffe1c..59ff1c9 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -914,6 +914,9 @@ sql_function_parse_error_callback(void *arg)
{
parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
/* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
if (!function_parse_error_transpose(callback_arg->prosrc))
{
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 95fec8d..8533914 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1743,6 +1743,9 @@ CopyFromErrorCallback(void *arg)
{
CopyState cstate = (CopyState) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
if (cstate->binary)
{
/* can't usefully display the data */
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index ae8d374..7643733 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1294,6 +1294,9 @@ sql_exec_error_callback(void *arg)
if (fcache == NULL || fcache->fname == NULL)
return;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
/*
* If there is a syntax error position, convert to internal syntax error
*/
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 5e4ae42..fd43106 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -2154,7 +2154,10 @@ _SPI_error_callback(void *arg)
internalerrquery(query);
}
else
+ {
+ set_errtextdomain();
errcontext("SQL statement \"%s\"", query);
+ }
}
/*
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 344ebb7..c747bb6 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4350,6 +4350,9 @@ sql_inline_error_callback(void *arg)
inline_error_callback_arg *callback_arg = (inline_error_callback_arg *) arg;
int syntaxerrposition;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
/* If it's a syntax error, convert to internal syntax error report */
syntaxerrposition = geterrposition();
if (syntaxerrposition > 0)
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 5314954..dcbc275 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -644,6 +644,9 @@ pts_error_callback(void *arg)
{
const char *str = (const char *) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
errcontext("invalid type name \"%s\"", str);
/*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 613d754..6630755 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2849,6 +2849,9 @@ shared_buffer_write_error_callback(void *arg)
{
volatile BufferDesc *bufHdr = (volatile BufferDesc *) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
/* Buffer is pinned, so we can read the tag without locking the spinlock */
if (bufHdr != NULL)
{
@@ -2868,6 +2871,9 @@ local_buffer_write_error_callback(void *arg)
{
volatile BufferDesc *bufHdr = (volatile BufferDesc *) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
if (bufHdr != NULL)
{
char *path = relpathbackend(bufHdr->tag.rnode, MyBackendId,
diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c
index 5b42a93..b2511bf 100644
--- a/src/backend/tsearch/ts_locale.c
+++ b/src/backend/tsearch/ts_locale.c
@@ -166,6 +166,9 @@ tsearch_readline_callback(void *arg)
{
tsearch_readline_state *stp = (tsearch_readline_state *) arg;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
/*
* We can't include the text of the config line for errors that occur
* during t_readline() itself. This is only partly a consequence of our
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 239ac19..3d17036 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -395,6 +395,7 @@ errfinish(int dummy,...)
int elevel = edata->elevel;
MemoryContext oldcontext;
ErrorContextCallback *econtext;
+ const char *olddomain;
recursion_depth++;
CHECK_STACK_DEPTH();
@@ -410,10 +411,23 @@ errfinish(int dummy,...)
* functions will be treated as recursive errors --- this ensures we will
* avoid infinite recursion (see errstart).
*/
+ olddomain = edata->domain;
for (econtext = error_context_stack;
econtext != NULL;
econtext = econtext->previous)
+ {
+ /*
+ * Callback can set the text domain, so restore it after the call.
+ * This isn't strictly necessary, every callback should set the domain
+ * explicitly if the messages are translatable to begin with. But
+ * just in case a callback forgets to do it (perhaps because it's a
+ * an external module that was written before version 9.2, where
+ * errtextdomain() was added), let's be consistent and always use the
+ * domain specified in errstart.
+ */
(*econtext->callback) (econtext->arg);
+ edata->domain = olddomain;
+ }
/*
* If ERROR (not more nor less) we pass it off to the current handler.
@@ -980,6 +994,34 @@ errcontext(const char *fmt,...)
/*
+ * errtextdomain --- set the message domain used for errcontext calls
+ *
+ * This is used in error callback functions, before calling errcontext(). It
+ * sets the message domain that will be used to translate the messages in
+ * the errcontext() call(s) that follow. Normally we set the domain in
+ * errstart(), but an error context callback often resides in a different
+ * module than where the error originates and where errstart() called, so the
+ * text domain needs to be set explicitly in the callback.
+ *
+ * Actually, this affects not only errcontext() calls but also errmsg(),
+ * errdetail() etc, but errcontext() is the only function that is normally
+ * called at a distance from the original ereport() site.
+ */
+int
+errtextdomain(const char *domain)
+{
+ ErrorData *edata = &errordata[errordata_stack_depth];
+
+ /* we don't bother incrementing recursion_depth */
+ CHECK_STACK_DEPTH();
+
+ edata->domain = domain;
+
+ return 0; /* return value does not matter */
+}
+
+
+/*
* errhidestmt --- optionally suppress STATEMENT: field of log entry
*
* This should be called if the message text already includes the statement.
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 7b5bcfa..a78b949 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -178,6 +178,8 @@ errcontext(const char *fmt,...)
the supplied arguments. */
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
+extern int errtextdomain(const char *domain);
+
extern int errhidestmt(bool hide_stmt);
extern int errfunction(const char *funcname);
@@ -227,6 +229,15 @@ typedef struct ErrorContextCallback
extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
+/*
+ * This is a convenience macro to set text-domain to the default for the
+ * current source file. This should be called in every error callback
+ * function, before calling errcontext(), to make sure the right gettext
+ * domain is used to translate the context message.
+ */
+#define set_errtextdomain() \
+ errtextdomain(TEXTDOMAIN)
+
/*----------
* API for catching ereport(ERROR) exits. Use these macros like so:
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 7a92f3d..22006e3 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -3649,7 +3649,10 @@ plperl_exec_callback(void *arg)
char *procname = (char *) arg;
if (procname)
+ {
+ set_errtextdomain();
errcontext("PL/Perl function \"%s\"", procname);
+ }
}
/*
@@ -3661,7 +3664,10 @@ plperl_compile_callback(void *arg)
char *procname = (char *) arg;
if (procname)
+ {
+ set_errtextdomain();
errcontext("compilation of PL/Perl function \"%s\"", procname);
+ }
}
/*
@@ -3670,6 +3676,7 @@ plperl_compile_callback(void *arg)
static void
plperl_inline_callback(void *arg)
{
+ set_errtextdomain();
errcontext("PL/Perl anonymous code block");
}
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index d43b8e0..8e53f04 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -908,8 +908,11 @@ plpgsql_compile_error_callback(void *arg)
}
if (plpgsql_error_funcname)
+ {
+ set_errtextdomain();
errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
plpgsql_error_funcname, plpgsql_latest_lineno());
+ }
}
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index a385b9a..a5b9866 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -786,6 +786,9 @@ plpgsql_exec_error_callback(void *arg)
if (estate->err_text == raise_skip_msg)
return;
+ /* use the right domain to translate the errcontext() calls */
+ set_errtextdomain();
+
if (estate->err_text != NULL)
{
/*
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 280d3ed..0356d56 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -458,7 +458,10 @@ plpython_return_error_callback(void *arg)
PLyExecutionContext *exec_ctx = PLy_current_execution_context();
if (exec_ctx->curr_proc)
+ {
+ set_errtextdomain();
errcontext("while creating return value");
+ }
}
static PyObject *
@@ -786,7 +789,10 @@ plpython_trigger_error_callback(void *arg)
PLyExecutionContext *exec_ctx = PLy_current_execution_context();
if (exec_ctx->curr_proc)
+ {
+ set_errtextdomain();
errcontext("while modifying trigger row");
+ }
}
/* execute Python code, propagate Python errors to the backend */
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
index c126db9..da7c8ed 100644
--- a/src/pl/plpython/plpy_main.c
+++ b/src/pl/plpython/plpy_main.c
@@ -343,13 +343,17 @@ plpython_error_callback(void *arg)
PLyExecutionContext *exec_ctx = PLy_current_execution_context();
if (exec_ctx->curr_proc)
+ {
+ set_errtextdomain();
errcontext("PL/Python function \"%s\"",
PLy_procedure_name(exec_ctx->curr_proc));
+ }
}
static void
plpython_inline_error_callback(void *arg)
{
+ set_errtextdomain();
errcontext("PL/Python anonymous code block");
}