From 41bea9904503f36b51ff94ee68edfa6b0f5cd3f8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 16 Aug 2016 15:58:31 -0400 Subject: [PATCH] Fix assorted places in psql to print version numbers >= 10 in new style. This is somewhat cosmetic, since as long as you know what you are looking at, "10.0" is a serviceable substitute for "10". But there is a potential for confusion between version numbers with minor numbers and those without --- we don't want people asking "why is psql saying 10.0 when my server is 10.2". Therefore, back-patch as far as practical, which turns out to be 9.3. I could have redone the patch to use fprintf(stderr) in place of psql_error(), but it seems more work than is warranted for branches that will be EOL or nearly so by the time v10 comes out. Although only psql seems to contain any code that needs this, I chose to put the support function into fe_utils, since it seems likely we'll need it in other client programs in future. (In 9.3-9.5, use dumputils.c, the predecessor of fe_utils/string_utils.c.) In HEAD, also fix the backend code that whines about loadable-library version mismatch. I don't see much need to back-patch that. --- src/bin/pg_dump/dumputils.c | 38 ++++++++++++++ src/bin/pg_dump/dumputils.h | 2 + src/bin/psql/command.c | 36 ++++++++------ src/bin/psql/common.c | 8 ++- src/bin/psql/describe.c | 98 ++++++++++++++++++++++++++----------- 5 files changed, 138 insertions(+), 44 deletions(-) diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 1ff7372277..ffc342f6e8 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -178,6 +178,44 @@ fmtQualifiedId(int remoteVersion, const char *schema, const char *id) return id_return->data; } +/* + * Format a Postgres version number (in the PG_VERSION_NUM integer format + * returned by PQserverVersion()) as a string. This exists mainly to + * encapsulate knowledge about two-part vs. three-part version numbers. + * + * For re-entrancy, caller must supply the buffer the string is put in. + * Recommended size of the buffer is 32 bytes. + * + * Returns address of 'buf', as a notational convenience. + */ +char * +formatPGVersionNumber(int version_number, bool include_minor, + char *buf, size_t buflen) +{ + if (version_number >= 100000) + { + /* New two-part style */ + if (include_minor) + snprintf(buf, buflen, "%d.%d", version_number / 10000, + version_number % 10000); + else + snprintf(buf, buflen, "%d", version_number / 10000); + } + else + { + /* Old three-part style */ + if (include_minor) + snprintf(buf, buflen, "%d.%d.%d", version_number / 10000, + (version_number / 100) % 100, + version_number % 100); + else + snprintf(buf, buflen, "%d.%d", version_number / 10000, + (version_number / 100) % 100); + } + return buf; +} + + /* * Convert a string value to an SQL string literal and append it to * the given buffer. We assume the specified client_encoding and diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index 3e7a1da5ef..ed66651e4f 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -38,6 +38,8 @@ extern PQExpBuffer (*getLocalPQExpBuffer) (void); extern const char *fmtId(const char *identifier); extern const char *fmtQualifiedId(int remoteVersion, const char *schema, const char *id); +extern char *formatPGVersionNumber(int version_number, bool include_minor, + char *buf, size_t buflen); extern void appendStringLiteral(PQExpBuffer buf, const char *str, int encoding, bool std_strings); extern void appendStringLiteralConn(PQExpBuffer buf, const char *str, diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index e210d072f1..d345f5b9f3 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -589,8 +589,11 @@ exec_command(const char *cmd, if (pset.sversion < 80400) { - psql_error("The server (version %d.%d) does not support editing function source.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support editing function source.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); status = PSQL_CMD_ERROR; } else if (!query_buf) @@ -1198,8 +1201,11 @@ exec_command(const char *cmd, OT_WHOLE_LINE, NULL, true); if (pset.sversion < 80400) { - psql_error("The server (version %d.%d) does not support showing function source.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support showing function source.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); status = PSQL_CMD_ERROR; } else if (!func) @@ -1809,22 +1815,21 @@ connection_warnings(bool in_startup) if (!pset.quiet && !pset.notty) { int client_ver = PG_VERSION_NUM; + char cverbuf[32]; + char sverbuf[32]; if (pset.sversion != client_ver) { const char *server_version; - char server_ver_str[16]; /* Try to get full text form, might include "devel" etc */ server_version = PQparameterStatus(pset.db, "server_version"); + /* Otherwise fall back on pset.sversion */ if (!server_version) { - snprintf(server_ver_str, sizeof(server_ver_str), - "%d.%d.%d", - pset.sversion / 10000, - (pset.sversion / 100) % 100, - pset.sversion % 100); - server_version = server_ver_str; + formatPGVersionNumber(pset.sversion, true, + sverbuf, sizeof(sverbuf)); + server_version = sverbuf; } printf(_("%s (%s, server %s)\n"), @@ -1835,10 +1840,13 @@ connection_warnings(bool in_startup) printf("%s (%s)\n", pset.progname, PG_VERSION); if (pset.sversion / 100 > client_ver / 100) - printf(_("WARNING: %s major version %d.%d, server major version %d.%d.\n" + printf(_("WARNING: %s major version %s, server major version %s.\n" " Some psql features might not work.\n"), - pset.progname, client_ver / 10000, (client_ver / 100) % 100, - pset.sversion / 10000, (pset.sversion / 100) % 100); + pset.progname, + formatPGVersionNumber(client_ver, false, + cverbuf, sizeof(cverbuf)), + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); #ifdef WIN32 checkWin32Codepage(); diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index bd23be5aca..31fcfbafb3 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -22,6 +22,7 @@ #include "settings.h" #include "command.h" #include "copy.h" +#include "dumputils.h" #include "mbprint.h" @@ -926,8 +927,11 @@ SendQuery(const char *query) { if (on_error_rollback_warning == false && pset.sversion < 80000) { - psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support savepoints for ON_ERROR_ROLLBACK.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); on_error_rollback_warning = true; } else diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 3465117282..aad1455e4d 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -134,8 +134,11 @@ describeTablespaces(const char *pattern, bool verbose) if (pset.sversion < 80000) { - psql_error("The server (version %d.%d) does not support tablespaces.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support tablespaces.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -227,8 +230,11 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool if (showWindow && pset.sversion < 80400) { - psql_error("\\df does not take a \"w\" option with server version %d.%d\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("\\df does not take a \"w\" option with server version %s\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -806,8 +812,11 @@ listDefaultACLs(const char *pattern) if (pset.sversion < 90000) { - psql_error("The server (version %d.%d) does not support altering default privileges.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support altering default privileges.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3187,8 +3196,11 @@ listCollations(const char *pattern, bool verbose, bool showSystem) if (pset.sversion < 90100) { - psql_error("The server (version %d.%d) does not support collations.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support collations.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3318,8 +3330,11 @@ listTSParsers(const char *pattern, bool verbose) if (pset.sversion < 80300) { - psql_error("The server (version %d.%d) does not support full text search.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support full text search.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3551,8 +3566,11 @@ listTSDictionaries(const char *pattern, bool verbose) if (pset.sversion < 80300) { - psql_error("The server (version %d.%d) does not support full text search.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support full text search.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3619,8 +3637,11 @@ listTSTemplates(const char *pattern, bool verbose) if (pset.sversion < 80300) { - psql_error("The server (version %d.%d) does not support full text search.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support full text search.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3687,8 +3708,11 @@ listTSConfigs(const char *pattern, bool verbose) if (pset.sversion < 80300) { - psql_error("The server (version %d.%d) does not support full text search.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support full text search.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3885,8 +3909,11 @@ listForeignDataWrappers(const char *pattern, bool verbose) if (pset.sversion < 80400) { - psql_error("The server (version %d.%d) does not support foreign-data wrappers.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support foreign-data wrappers.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -3965,8 +3992,11 @@ listForeignServers(const char *pattern, bool verbose) if (pset.sversion < 80400) { - psql_error("The server (version %d.%d) does not support foreign servers.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support foreign servers.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -4044,8 +4074,11 @@ listUserMappings(const char *pattern, bool verbose) if (pset.sversion < 80400) { - psql_error("The server (version %d.%d) does not support user mappings.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support user mappings.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -4102,8 +4135,11 @@ listForeignTables(const char *pattern, bool verbose) if (pset.sversion < 90100) { - psql_error("The server (version %d.%d) does not support foreign tables.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support foreign tables.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -4177,8 +4213,11 @@ listExtensions(const char *pattern) if (pset.sversion < 90100) { - psql_error("The server (version %d.%d) does not support extensions.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support extensions.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } @@ -4231,8 +4270,11 @@ listExtensionContents(const char *pattern) if (pset.sversion < 90100) { - psql_error("The server (version %d.%d) does not support extensions.\n", - pset.sversion / 10000, (pset.sversion / 100) % 100); + char sverbuf[32]; + + psql_error("The server (version %s) does not support extensions.\n", + formatPGVersionNumber(pset.sversion, false, + sverbuf, sizeof(sverbuf))); return true; } -- 2.30.2