Hello, postgresmen!
I found incorrect execution of ereport() macro.
If we pass into ereport() function 2 or more arguments, the macro errcontext does not correct execute. So, ereport() call stack is:
If we pass into ereport() function 2 or more arguments, the macro errcontext does not correct execute. So, ereport() call stack is:
errstart
errcontext_msg
set_errcontext_domain
errmsg
errfinish
pg_unreachable
errcontext_msg
set_errcontext_domain
errmsg
errfinish
pg_unreachable
This bug causes that error messages (for example, in PL/TCL) are not localized.
Solutions:
- Wrap all errcontext() macro in brackets, that is errcontext("error message %s", "end message") -> (errcontext("error message %s", "end message"))
Solutions:
- Wrap all errcontext() macro in brackets, that is errcontext("error message %s", "end message") -> (errcontext("error message %s", "end message"))
- Rewrite this macro
- ???
I am attaching to this letter a test case that shows the behavior errcontext() macro and the way to fix it.
I am using postgresql 9.4 and test it on gcc 4.7 and gcc 4.8.1.
-- Best regards, Dmitry Voronin
#include <stdio.h>
#define ereport_domain(elevel, domain, rest) \
do { \
const int elevel_ = (elevel); \
if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \
errfinish rest; \
if (elevel_ >= 2) \
pg_unreachable(); \
} while(0)
#define ereport(elevel, rest) \
ereport_domain(elevel, TEXTDOMAIN, rest)
#define TEXTDOMAIN NULL
#define PG_FUNCNAME_MACRO NULL
#define ERROR 20
#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg
int set_errcontext_domain(const char *domain)
{
printf("set_errcontext_domain\n");
}
int
errstart(int elevel, const char *filename, int lineno,
const char *funcname, const char *domain)
{
printf("errstart\n");
return 1;
}
void pg_unreachable()
{
printf("pg_unreachable\n");
}
void errfinish(int dummy, ...)
{
printf("errfinish\n");
}
int
errcontext_msg(const char *fmt,...)
{
printf("errcontext_msg\n");
return 0;
}
int errmsg(const char *fmt, ...)
{
printf("errmsg\n");
return 0;
}
int main()
{
/* this is incorrect */
ereport(ERROR,
(errmsg("%s", "error message"),
errcontext("%s\nin PL/Tcl function \"%s\"",
"test1", "test2")));
printf("\n");
/* this is correct */
ereport(ERROR,
(errmsg("%s", "error message"),
(errcontext("%s\nin PL/Tcl function \"%s\"",
"test1", "test2"))));
return 0;
}-- Sent via pgsql-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
