Tweak our special-case logic for the IANA "Factory" timezone.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 26 Jul 2019 17:07:08 +0000 (13:07 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 26 Jul 2019 17:07:08 +0000 (13:07 -0400)
pg_timezone_names() tries to avoid showing the "Factory" zone in
the view, mainly because that has traditionally had a very long
"abbreviation" such as "Local time zone must be set--see zic manual page",
so that showing it messes up psql's formatting of the whole view.
Since tzdb version 2016g, IANA instead uses the abbreviation "-00",
which is sane enough that there's no reason to discriminate against it.

On the other hand, it emerges that FreeBSD and possibly other packagers
are so wedded to backwards compatibility that they hack the IANA data
to keep the old spelling --- and not just that old spelling, but even
older spellings that IANA used back in the stone age.  This caused the
filter logic to fail to suppress "Factory" at all on such platforms,
though the formatting problem is definitely real in that case.

To solve both problems, get rid of the hard-wired assumption about
exactly what Factory's abbreviation is, and instead reject abbreviations
exceeding 31 characters.  This will allow Factory to appear in the view
if and only if it's using the modern abbreviation.

In passing, simplify the code we add to zic.c to support "zic -P"
to remove its now-obsolete hacks to not print the Factory zone's
abbreviation.  Unlike pg_timezone_names(), there's no reason for
that code to support old/nonstandard timezone data.

Since we generally prefer to keep timezone-related behavior the
same in all branches, and since this is arguably a bug fix,
back-patch to all supported branches.

Discussion: https://postgr.es/m/3961.1564086915@sss.pgh.pa.us

src/backend/utils/adt/datetime.c
src/timezone/zic.c

index 4d8db1a0604762f1d214d527551e2cb2ae82b7bd..972fcd26a24c74388fb3b4af8fb589d5197781ca 100644 (file)
@@ -4826,16 +4826,15 @@ pg_timezone_names(PG_FUNCTION_ARGS)
            continue;           /* ignore if conversion fails */
 
        /*
-        * Ignore zic's rather silly "Factory" time zone.  The long string
-        * about "see zic manual page" is used in tzdata versions before
-        * 2016g; we can drop it someday when we're pretty sure no such data
-        * exists in the wild on platforms using --with-system-tzdata.  In
-        * 2016g and later, the time zone abbreviation "-00" is used for
-        * "Factory" as well as some invalid cases, all of which we can
-        * reasonably omit from the pg_timezone_names view.
+        * IANA's rather silly "Factory" time zone used to emit ridiculously
+        * long "abbreviations" such as "Local time zone must be set--see zic
+        * manual page" or "Local time zone must be set--use tzsetup".  While
+        * modern versions of tzdb emit the much saner "-00", it seems some
+        * benighted packagers are hacking the IANA data so that it continues
+        * to produce these strings.  To prevent producing a weirdly wide
+        * abbrev column, reject ridiculously long abbreviations.
         */
-       if (tzn && (strcmp(tzn, "-00") == 0 ||
-                   strcmp(tzn, "Local time zone must be set--see zic manual page") == 0))
+       if (tzn && strlen(tzn) > 31)
            continue;
 
        /* Found a displayable zone */
index 95ab8547126714cbf769f8ee4f3b511fc338d741..c27fb456d05972da0e4865139eebb8c5cc75005f 100644 (file)
@@ -2443,13 +2443,10 @@ writezone(const char *const name, const char *const string, char version,
                    unsigned char tm = types[i];
                    char       *thisabbrev = &thischars[indmap[desigidx[tm]]];
 
-                   /* filter out assorted junk entries */
-                   if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
-                       strcmp(thisabbrev, "zzz") != 0)
-                       fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
-                               thisabbrev,
-                               utoffs[tm],
-                               isdsts[tm] ? "\tD" : "");
+                   fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
+                           thisabbrev,
+                           utoffs[tm],
+                           isdsts[tm] ? "\tD" : "");
                }
            }
            /* Print the default type if we have no transitions at all */
@@ -2458,13 +2455,10 @@ writezone(const char *const name, const char *const string, char version,
                unsigned char tm = defaulttype;
                char       *thisabbrev = &thischars[indmap[desigidx[tm]]];
 
-               /* filter out assorted junk entries */
-               if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
-                   strcmp(thisabbrev, "zzz") != 0)
-                   fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
-                           thisabbrev,
-                           utoffs[tm],
-                           isdsts[tm] ? "\tD" : "");
+               fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
+                       thisabbrev,
+                       utoffs[tm],
+                       isdsts[tm] ? "\tD" : "");
            }
        }