]> granicus.if.org Git - postgresql/commitdiff
Use correct text domain for translating errcontext() messages.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 12 Nov 2012 13:10:24 +0000 (15:10 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 12 Nov 2012 15:07:29 +0000 (17:07 +0200)
errcontext() is typically used in an error context callback function, not
within an ereport() invocation like e.g errmsg and errdetail are. That means
that the message domain that the TEXTDOMAIN magic in ereport() determines
is not the right one for the errcontext() calls. The message domain needs to
be determined by the C file containing the errcontext() call, not the file
containing the ereport() call.

Fix by turning errcontext() into a macro that passes the TEXTDOMAIN to use
for the errcontext message. "errcontext" was used in a few places as a
variable or struct field name, I had to rename those out of the way, now
that errcontext is a macro.

We've had this problem all along, but this isn't doesn't seem worth
backporting. It's a fairly minor issue, and turning errcontext from a
function to a macro requires at least a recompile of any external code that
calls errcontext().

src/backend/access/transam/xlog.c
src/backend/commands/copy.c
src/backend/parser/parse_node.c
src/backend/storage/buffer/bufmgr.c
src/backend/utils/error/elog.c
src/include/parser/parse_node.h
src/include/utils/elog.h

index bf76f6d24cb8bbf3b1b8b19e0a1c007ff08e4035..c541b5a552d137e40db68e30f2f6c9f7033e38cb 100644 (file)
@@ -5698,7 +5698,7 @@ StartupXLOG(void)
                        bool            recoveryContinue = true;
                        bool            recoveryApply = true;
                        bool            recoveryPause = false;
-                       ErrorContextCallback errcontext;
+                       ErrorContextCallback errcallback;
                        TimestampTz xtime;
 
                        InRedo = true;
@@ -5760,10 +5760,10 @@ StartupXLOG(void)
                                }
 
                                /* Setup error traceback support for ereport() */
-                               errcontext.callback = rm_redo_error_callback;
-                               errcontext.arg = (void *) record;
-                               errcontext.previous = error_context_stack;
-                               error_context_stack = &errcontext;
+                               errcallback.callback = rm_redo_error_callback;
+                               errcallback.arg = (void *) record;
+                               errcallback.previous = error_context_stack;
+                               error_context_stack = &errcallback;
 
                                /*
                                 * ShmemVariableCache->nextXid must be beyond record's xid.
@@ -5808,7 +5808,7 @@ StartupXLOG(void)
                                RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
 
                                /* Pop the error context stack */
-                               error_context_stack = errcontext.previous;
+                               error_context_stack = errcallback.previous;
 
                                if (!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) &&
                                        XLByteLE(ControlFile->backupEndPoint, EndRecPtr))
index 0567ab003d4288d6be3a04cabd69dd5be3fe68c0..10c89c79b91b0130aabee43b33d9d358beaafcb6 100644 (file)
@@ -1901,7 +1901,7 @@ CopyFrom(CopyState cstate)
        TupleTableSlot *myslot;
        MemoryContext oldcontext = CurrentMemoryContext;
 
-       ErrorContextCallback errcontext;
+       ErrorContextCallback errcallback;
        CommandId       mycid = GetCurrentCommandId(true);
        int                     hi_options = 0; /* start with default heap_insert options */
        BulkInsertState bistate;
@@ -2046,10 +2046,10 @@ CopyFrom(CopyState cstate)
        econtext = GetPerTupleExprContext(estate);
 
        /* Set up callback to identify error line number */
-       errcontext.callback = CopyFromErrorCallback;
-       errcontext.arg = (void *) cstate;
-       errcontext.previous = error_context_stack;
-       error_context_stack = &errcontext;
+       errcallback.callback = CopyFromErrorCallback;
+       errcallback.arg = (void *) cstate;
+       errcallback.previous = error_context_stack;
+       error_context_stack = &errcallback;
 
        for (;;)
        {
@@ -2164,7 +2164,7 @@ CopyFrom(CopyState cstate)
                                                        nBufferedTuples, bufferedTuples);
 
        /* Done, clean up */
-       error_context_stack = errcontext.previous;
+       error_context_stack = errcallback.previous;
 
        FreeBulkInsertState(bistate);
 
index 2e9fad0f9777eba7b1c4611d78db5de136c74232..91a1891e971206d31bd0a18cdb66c0391db437f8 100644 (file)
@@ -145,10 +145,10 @@ setup_parser_errposition_callback(ParseCallbackState *pcbstate,
        /* Setup error traceback support for ereport() */
        pcbstate->pstate = pstate;
        pcbstate->location = location;
-       pcbstate->errcontext.callback = pcb_error_callback;
-       pcbstate->errcontext.arg = (void *) pcbstate;
-       pcbstate->errcontext.previous = error_context_stack;
-       error_context_stack = &pcbstate->errcontext;
+       pcbstate->errcallback.callback = pcb_error_callback;
+       pcbstate->errcallback.arg = (void *) pcbstate;
+       pcbstate->errcallback.previous = error_context_stack;
+       error_context_stack = &pcbstate->errcallback;
 }
 
 /*
@@ -158,7 +158,7 @@ void
 cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
 {
        /* Pop the error context stack */
-       error_context_stack = pcbstate->errcontext.previous;
+       error_context_stack = pcbstate->errcallback.previous;
 }
 
 /*
index bdcbe47ac9e9f5ce0db5f90b8ddb567bf34ade00..dddb6c0321f477b4ddabcf460d215cadadcb9873 100644 (file)
@@ -1888,7 +1888,7 @@ static void
 FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
 {
        XLogRecPtr      recptr;
-       ErrorContextCallback errcontext;
+       ErrorContextCallback errcallback;
        instr_time      io_start,
                                io_time;
 
@@ -1901,10 +1901,10 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
                return;
 
        /* Setup error traceback support for ereport() */
-       errcontext.callback = shared_buffer_write_error_callback;
-       errcontext.arg = (void *) buf;
-       errcontext.previous = error_context_stack;
-       error_context_stack = &errcontext;
+       errcallback.callback = shared_buffer_write_error_callback;
+       errcallback.arg = (void *) buf;
+       errcallback.previous = error_context_stack;
+       error_context_stack = &errcallback;
 
        /* Find smgr relation for buffer */
        if (reln == NULL)
@@ -1967,7 +1967,7 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
                                                                           reln->smgr_rnode.node.relNode);
 
        /* Pop the error context stack */
-       error_context_stack = errcontext.previous;
+       error_context_stack = errcallback.previous;
 }
 
 /*
@@ -2253,13 +2253,13 @@ FlushRelationBuffers(Relation rel)
                        if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
                                (bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
                        {
-                               ErrorContextCallback errcontext;
+                               ErrorContextCallback errcallback;
 
                                /* Setup error traceback support for ereport() */
-                               errcontext.callback = local_buffer_write_error_callback;
-                               errcontext.arg = (void *) bufHdr;
-                               errcontext.previous = error_context_stack;
-                               error_context_stack = &errcontext;
+                               errcallback.callback = local_buffer_write_error_callback;
+                               errcallback.arg = (void *) bufHdr;
+                               errcallback.previous = error_context_stack;
+                               error_context_stack = &errcallback;
 
                                smgrwrite(rel->rd_smgr,
                                                  bufHdr->tag.forkNum,
@@ -2270,7 +2270,7 @@ FlushRelationBuffers(Relation rel)
                                bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
 
                                /* Pop the error context stack */
-                               error_context_stack = errcontext.previous;
+                               error_context_stack = errcallback.previous;
                        }
                }
 
index 68b7ab3f5fbae8b76765b9370f1c5f5d1731aa91..c22190a8b3d8dc856021d80307f683d42ca27340 100644 (file)
@@ -683,13 +683,13 @@ errcode_for_socket_access(void)
  * to the edata field because the buffer might be considerably larger than
  * really necessary.
  */
-#define EVALUATE_MESSAGE(targetfield, appendval, translateit)  \
+#define EVALUATE_MESSAGE(domain, targetfield, appendval, translateit)  \
        { \
                char               *fmtbuf; \
                StringInfoData  buf; \
                /* Internationalize the error format string */ \
                if (translateit && !in_error_recursion_trouble()) \
-                       fmt = dgettext(edata->domain, fmt); \
+                       fmt = dgettext((domain), fmt);                            \
                /* Expand %m in format string */ \
                fmtbuf = expand_fmt_string(fmt, edata); \
                initStringInfo(&buf); \
@@ -723,14 +723,14 @@ errcode_for_socket_access(void)
  * must be declared like "const char *fmt_singular, const char *fmt_plural,
  * unsigned long n, ...".  Translation is assumed always wanted.
  */
-#define EVALUATE_MESSAGE_PLURAL(targetfield, appendval)  \
+#define EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval)  \
        { \
                const char         *fmt; \
                char               *fmtbuf; \
                StringInfoData  buf; \
                /* Internationalize the error format string */ \
                if (!in_error_recursion_trouble()) \
-                       fmt = dngettext(edata->domain, fmt_singular, fmt_plural, n); \
+                       fmt = dngettext((domain), fmt_singular, fmt_plural, n); \
                else \
                        fmt = (n == 1 ? fmt_singular : fmt_plural); \
                /* Expand %m in format string */ \
@@ -781,7 +781,7 @@ errmsg(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(message, false, true);
+       EVALUATE_MESSAGE(edata->domain, message, false, true);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -810,7 +810,7 @@ errmsg_internal(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(message, false, false);
+       EVALUATE_MESSAGE(edata->domain, message, false, false);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -833,7 +833,7 @@ errmsg_plural(const char *fmt_singular, const char *fmt_plural,
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE_PLURAL(message, false);
+       EVALUATE_MESSAGE_PLURAL(edata->domain, message, false);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -854,7 +854,7 @@ errdetail(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(detail, false, true);
+       EVALUATE_MESSAGE(edata->domain, detail, false, true);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -881,7 +881,7 @@ errdetail_internal(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(detail, false, false);
+       EVALUATE_MESSAGE(edata->domain, detail, false, false);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -902,7 +902,7 @@ errdetail_log(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(detail_log, false, true);
+       EVALUATE_MESSAGE(edata->domain, detail_log, false, true);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -925,7 +925,7 @@ errdetail_plural(const char *fmt_singular, const char *fmt_plural,
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE_PLURAL(detail, false);
+       EVALUATE_MESSAGE_PLURAL(edata->domain, detail, false);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -946,7 +946,7 @@ errhint(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(hint, false, true);
+       EVALUATE_MESSAGE(edata->domain, hint, false, true);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -955,14 +955,14 @@ errhint(const char *fmt,...)
 
 
 /*
- * errcontext --- add a context error message text to the current error
+ * errcontext_msg --- add a context error message text to the current error
  *
  * Unlike other cases, multiple calls are allowed to build up a stack of
  * context information.  We assume earlier calls represent more-closely-nested
  * states.
  */
 int
-errcontext(const char *fmt,...)
+errcontext_msg(const char *fmt,...)
 {
        ErrorData  *edata = &errordata[errordata_stack_depth];
        MemoryContext oldcontext;
@@ -971,13 +971,35 @@ errcontext(const char *fmt,...)
        CHECK_STACK_DEPTH();
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(context, true, true);
+       EVALUATE_MESSAGE(edata->context_domain, context, true, true);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
        return 0;                                       /* return value does not matter */
 }
 
+/*
+ * set_errcontext_domain --- set message domain to be used by errcontext()
+ *
+ * errcontext_msg() can be called from a different module than the original
+ * ereport(), so we cannot use the message domain passed in errstart() to
+ * translate it.  Instead, each errcontext_msg() call should be preceded by
+ * a set_errcontext_domain() call to specify the domain.  This is usually
+ * done transparently by the errcontext() macro.
+ */
+int
+set_errcontext_domain(const char *domain)
+{
+       ErrorData  *edata = &errordata[errordata_stack_depth];
+
+       /* we don't bother incrementing recursion_depth */
+       CHECK_STACK_DEPTH();
+
+       edata->context_domain = domain;
+
+       return 0;                                       /* return value does not matter */
+}
+
 
 /*
  * errhidestmt --- optionally suppress STATEMENT: field of log entry
@@ -1201,7 +1223,7 @@ elog_finish(int elevel, const char *fmt,...)
        recursion_depth++;
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(message, false, false);
+       EVALUATE_MESSAGE(edata->domain, message, false, false);
 
        MemoryContextSwitchTo(oldcontext);
        recursion_depth--;
@@ -1260,7 +1282,7 @@ format_elog_string(const char *fmt,...)
 
        oldcontext = MemoryContextSwitchTo(ErrorContext);
 
-       EVALUATE_MESSAGE(message, false, true);
+       EVALUATE_MESSAGE(edata->domain, message, false, true);
 
        MemoryContextSwitchTo(oldcontext);
 
index e3bb35f1308350dc50481eaabb536fc623737b91..aa9c648e41912809551be9ab643ae501c706e7d1 100644 (file)
@@ -206,7 +206,7 @@ typedef struct ParseCallbackState
 {
        ParseState *pstate;
        int                     location;
-       ErrorContextCallback errcontext;
+       ErrorContextCallback errcallback;
 } ParseCallbackState;
 
 
index 03298fbbaf05998c695580e23ef3299208f8363c..42c22cd90e86a1288e065a760a15a92b1442bd42 100644 (file)
@@ -177,8 +177,19 @@ errhint(const char *fmt,...)
    the supplied arguments. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
 
+/*
+ * errcontext() is typically called in error context callback functions, not
+ * within an ereport() invocation. The callback function can be in a different
+ * module than the ereport() call, so the message domain passed in errstart()
+ * is not usually the correct domain for translating the context message.
+ * set_errcontext_domain() first sets the domain to be used, and
+ * errcontext_msg() passes the actual message.
+ */
+#define errcontext     set_errcontext_domain(TEXTDOMAIN),  errcontext_msg
+
+extern int     set_errcontext_domain(const char *domain);
 extern int
-errcontext(const char *fmt,...)
+errcontext_msg(const char *fmt,...)
 /* This extension allows gcc to check the format string for consistency with
    the supplied arguments. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
@@ -320,6 +331,7 @@ typedef struct ErrorData
        int                     lineno;                 /* __LINE__ of ereport() call */
        const char *funcname;           /* __func__ of ereport() call */
        const char *domain;                     /* message domain */
+       const char *context_domain;     /* message domain for context message */
        int                     sqlerrcode;             /* encoded ERRSTATE */
        char       *message;            /* primary error message */
        char       *detail;                     /* detail error message */