diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 795500c5935..b040a2664ee 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1278,3 +1278,62 @@ libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) } #endif /* ENABLE_NLS */ + + +/* + * Append a formatted string to the given buffer, after translating it. A + * newline is automatically appended; the format should not end with a + * newline. + */ +void +libpq_append_error(PQExpBuffer errorMessage, const char *fmt, ...) +{ + int save_errno = errno; + bool done; + va_list args; + + Assert(fmt[strlen(fmt) - 1] != '\n'); + + if (PQExpBufferBroken(errorMessage)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args); + va_end(args); + } while (!done); + + appendPQExpBufferChar(errorMessage, '\n'); +} + +/* + * Append a formatted string to the error message buffer of the given + * connection, after translating it. A newline is automatically appended; the + * format should not end with a newline. + */ +void +libpq_append_conn_error(PGconn *conn, const char *fmt, ...) +{ + int save_errno = errno; + bool done; + va_list args; + + Assert(fmt[strlen(fmt) - 1] != '\n'); + + if (PQExpBufferBroken(&conn->errorMessage)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(&conn->errorMessage, libpq_gettext(fmt), args); + va_end(args); + } while (!done); + + appendPQExpBufferChar(&conn->errorMessage, '\n'); +} diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index c75ed63a2c6..c24645b4696 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -887,6 +887,9 @@ extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigne */ #undef _ +extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt, ...) pg_attribute_printf(2, 3); +extern void libpq_append_conn_error(PGconn *conn, const char *fmt, ...) pg_attribute_printf(2, 3); + /* * These macros are needed to let error-handling code be portable between * Unix and Windows. (ugh) diff --git a/src/interfaces/libpq/nls.mk b/src/interfaces/libpq/nls.mk index 9256b426c1d..4df544ecef5 100644 --- a/src/interfaces/libpq/nls.mk +++ b/src/interfaces/libpq/nls.mk @@ -1,5 +1,9 @@ # src/interfaces/libpq/nls.mk CATALOG_NAME = libpq GETTEXT_FILES = fe-auth.c fe-auth-scram.c fe-connect.c fe-exec.c fe-gssapi-common.c fe-lobj.c fe-misc.c fe-protocol3.c fe-secure.c fe-secure-common.c fe-secure-gssapi.c fe-secure-openssl.c win32.c ../../port/thread.c -GETTEXT_TRIGGERS = libpq_gettext pqInternalNotice:2 -GETTEXT_FLAGS = libpq_gettext:1:pass-c-format pqInternalNotice:2:c-format +GETTEXT_TRIGGERS = libpq_append_conn_error:2 \ + libpq_append_error:2 \ + libpq_gettext pqInternalNotice:2 +GETTEXT_FLAGS = libpq_append_conn_error:2:c-format \ + libpq_append_error:2:c-format \ + libpq_gettext:1:pass-c-format pqInternalNotice:2:c-format diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c index eb51e6d0884..10b32efdfeb 100644 --- a/src/interfaces/libpq/pqexpbuffer.c +++ b/src/interfaces/libpq/pqexpbuffer.c @@ -40,8 +40,6 @@ static const char oom_buffer[1] = ""; /* Need a char * for unconstify() compatibility */ static const char *oom_buffer_ptr = oom_buffer; -static bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) pg_attribute_printf(2, 0); - /* * markPQExpBufferBroken @@ -292,7 +290,7 @@ appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) * Caution: callers must be sure to preserve their entry-time errno * when looping, in case the fmt contains "%m". */ -static bool +bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) { size_t avail; diff --git a/src/interfaces/libpq/pqexpbuffer.h b/src/interfaces/libpq/pqexpbuffer.h index efd652c80a3..f7a4e24c1b9 100644 --- a/src/interfaces/libpq/pqexpbuffer.h +++ b/src/interfaces/libpq/pqexpbuffer.h @@ -157,6 +157,16 @@ extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute */ extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3); +/*------------------------ + * appendPQExpBufferVA + * Attempt to format data and append it to str. Returns true if done + * (either successful or hard failure), false if need to retry. + * + * Caution: callers must be sure to preserve their entry-time errno + * when looping, in case the fmt contains "%m". + */ +extern bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) pg_attribute_printf(2, 0); + /*------------------------ * appendPQExpBufferStr * Append the given string to a PQExpBuffer, allocating more space