Re: New version numbering practices - Mailing list pgsql-hackers

From Tom Lane
Subject Re: New version numbering practices
Date
Msg-id 27647.1471296687@sss.pgh.pa.us
Whole thread Raw
In response to Re: New version numbering practices  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
I wrote:
> I've pushed this with minor additional twiddling.  We can work on the
> "UI issues" you mentioned at leisure.  One that I noted is that psql's
> version-mismatch-warning messages aren't two-part-version aware, and
> will print "10.0" where they should say "10".  Probably that fix should
> get back-patched, so that older psql branches will do the right thing
> if possible.

Attached is a WIP patch for that.  I've only fixed psql/command.c
so far, but I put the support logic into fe_utils since we're going
to need it in some other places too (pg_dump at least).  Any objections
to this general approach?

            regards, tom lane

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 9c0af4e..4aaf657 100644
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** exec_command(const char *cmd,
*** 635,642 ****

          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);
              status = PSQL_CMD_ERROR;
          }
          else if (!query_buf)
--- 635,645 ----

          if (pset.sversion < 80400)
          {
!             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)
*************** exec_command(const char *cmd,
*** 731,738 ****

          if (pset.sversion < 70400)
          {
!             psql_error("The server (version %d.%d) does not support editing view definitions.\n",
!                        pset.sversion / 10000, (pset.sversion / 100) % 100);
              status = PSQL_CMD_ERROR;
          }
          else if (!query_buf)
--- 734,744 ----

          if (pset.sversion < 70400)
          {
!             char        sverbuf[32];
!
!             psql_error("The server (version %s) does not support editing view definitions.\n",
!                        formatPGVersionNumber(pset.sversion, false,
!                                              sverbuf, sizeof(sverbuf)));
              status = PSQL_CMD_ERROR;
          }
          else if (!query_buf)
*************** exec_command(const char *cmd,
*** 1362,1369 ****
                                        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);
              status = PSQL_CMD_ERROR;
          }
          else if (!func)
--- 1368,1378 ----
                                        OT_WHOLE_LINE, NULL, true);
          if (pset.sversion < 80400)
          {
!             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)
*************** exec_command(const char *cmd,
*** 1441,1448 ****
                                        OT_WHOLE_LINE, NULL, true);
          if (pset.sversion < 70400)
          {
!             psql_error("The server (version %d.%d) does not support showing view definitions.\n",
!                        pset.sversion / 10000, (pset.sversion / 100) % 100);
              status = PSQL_CMD_ERROR;
          }
          else if (!view)
--- 1450,1460 ----
                                        OT_WHOLE_LINE, NULL, true);
          if (pset.sversion < 70400)
          {
!             char        sverbuf[32];
!
!             psql_error("The server (version %s) does not support showing view definitions.\n",
!                        formatPGVersionNumber(pset.sversion, false,
!                                              sverbuf, sizeof(sverbuf)));
              status = PSQL_CMD_ERROR;
          }
          else if (!view)
*************** connection_warnings(bool in_startup)
*** 2014,2035 ****
      if (!pset.quiet && !pset.notty)
      {
          int            client_ver = PG_VERSION_NUM;

          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");
              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;
              }

              printf(_("%s (%s, server %s)\n"),
--- 2026,2046 ----
      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;

              /* 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)
              {
!                 formatPGVersionNumber(pset.sversion, true,
!                                       sverbuf, sizeof(sverbuf));
!                 server_version = sverbuf;
              }

              printf(_("%s (%s, server %s)\n"),
*************** connection_warnings(bool in_startup)
*** 2040,2049 ****
              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"
                       "         Some psql features might not work.\n"),
!                  pset.progname, client_ver / 10000, (client_ver / 100) % 100,
!                    pset.sversion / 10000, (pset.sversion / 100) % 100);

  #ifdef WIN32
          checkWin32Codepage();
--- 2051,2063 ----
              printf("%s (%s)\n", pset.progname, PG_VERSION);

          if (pset.sversion / 100 > client_ver / 100)
!             printf(_("WARNING: %s major version %s, server major version %s.\n"
                       "         Some psql features might not work.\n"),
!                    pset.progname,
!                    formatPGVersionNumber(client_ver, false,
!                                          cverbuf, sizeof(cverbuf)),
!                    formatPGVersionNumber(pset.sversion, false,
!                                          sverbuf, sizeof(sverbuf)));

  #ifdef WIN32
          checkWin32Codepage();
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index f986dbc..2c566b1 100644
*** a/src/fe_utils/string_utils.c
--- b/src/fe_utils/string_utils.c
*************** fmtQualifiedId(int remoteVersion, const
*** 169,174 ****
--- 169,212 ----


  /*
+  * 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
   * standard_conforming_strings settings.
diff --git a/src/include/fe_utils/string_utils.h b/src/include/fe_utils/string_utils.h
index 7bbed36..452ffc0 100644
*** a/src/include/fe_utils/string_utils.h
--- b/src/include/fe_utils/string_utils.h
*************** extern const char *fmtId(const char *ide
*** 30,35 ****
--- 30,38 ----
  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,

pgsql-hackers by date:

Previous
From: Stephen Frost
Date:
Subject: Re: Let's get rid of the separate minor version numbers for shlibs
Next
From: Josh Berkus
Date:
Subject: Re: PSA: Systemd will kill PostgreSQL