diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index bf76f6d24cb8bbf3b1b8b19e0a1c007ff08e4035..c541b5a552d137e40db68e30f2f6c9f7033e38cb 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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)) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 0567ab003d4288d6be3a04cabd69dd5be3fe68c0..10c89c79b91b0130aabee43b33d9d358beaafcb6 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -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); diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 2e9fad0f9777eba7b1c4611d78db5de136c74232..91a1891e971206d31bd0a18cdb66c0391db437f8 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -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; } /* diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index bdcbe47ac9e9f5ce0db5f90b8ddb567bf34ade00..dddb6c0321f477b4ddabcf460d215cadadcb9873 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -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; } } diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 68b7ab3f5fbae8b76765b9370f1c5f5d1731aa91..c22190a8b3d8dc856021d80307f683d42ca27340 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -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); diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index e3bb35f1308350dc50481eaabb536fc623737b91..aa9c648e41912809551be9ab643ae501c706e7d1 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -206,7 +206,7 @@ typedef struct ParseCallbackState { ParseState *pstate; int location; - ErrorContextCallback errcontext; + ErrorContextCallback errcallback; } ParseCallbackState; diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 03298fbbaf05998c695580e23ef3299208f8363c..42c22cd90e86a1288e065a760a15a92b1442bd42 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -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 */