]> granicus.if.org Git - postgresql/commitdiff
Repair an embarrassingly large number of alphabetization mistakes in the
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 Jan 2003 00:26:49 +0000 (00:26 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 Jan 2003 00:26:49 +0000 (00:26 +0000)
datetime token tables.  Even more embarrassing, the regression tests
revealed some of the problems --- but evidently the bogus output wasn't
questioned.  Add code to postmaster startup to directly check the tables
for correct ordering, in hopes of not being embarrassed like this again.

src/backend/postmaster/postmaster.c
src/backend/utils/adt/datetime.c
src/include/utils/datetime.h
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out

index f5048372c03b70d50a1e66acadb97b7ae9991194..c9334ef514a2c9655f5c7f102d5b9b95a70ba107 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.304 2003/01/07 18:48:13 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.305 2003/01/16 00:26:44 tgl Exp $
  *
  * NOTES
  *
@@ -594,6 +594,15 @@ PostmasterMain(int argc, char *argv[])
                ExitPostmaster(1);
        }
 
+       /*
+        * Other one-time internal sanity checks can go here.
+        */
+       if (!CheckDateTokenTables())
+       {
+               postmaster_error("Invalid datetoken tables, please fix.");
+               ExitPostmaster(1);
+       }
+
        /*
         * Now that we are done processing the postmaster arguments, reset
         * getopt(3) library so that it will work correctly in subprocesses.
index 8173c7476f9c93e7034e35f41a4d0d737a1e0826..55e3e2a198450e770c4cbd3a1312e573c27c5b5b 100644 (file)
@@ -8,21 +8,21 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.97 2002/11/13 17:24:05 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.98 2003/01/16 00:26:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include <ctype.h>
-#include <math.h>
 #include <errno.h>
 #include <float.h>
 #include <limits.h>
+#include <math.h>
 
 #include "miscadmin.h"
-#include "utils/guc.h"
 #include "utils/datetime.h"
+#include "utils/guc.h"
 
 
 static int DecodeNumber(int flen, char *field,
@@ -37,7 +37,7 @@ static int    DecodeTimezone(char *str, int *tzp);
 static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
 static int     DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
 static int     DecodePosixTimezone(char *str, int *val);
-void           TrimTrailingZeros(char *str);
+static void TrimTrailingZeros(char *str);
 
 
 int                    day_tab[2][13] = {
@@ -69,14 +69,16 @@ char           *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
 #define TOVAL(tp, v)   ((tp)->value = ((v) < 0? NEG((-(v))/15): POS(v)/15))
 
 /*
- * datetktbl holds date/time keywords. Note that this table must be strictly
- * ordered to allow an O(ln(N)) search algorithm.
+ * datetktbl holds date/time keywords.
+ *
+ * Note that this table must be strictly alphabetically ordered to allow an
+ * O(ln(N)) search algorithm to be used.
  *
- * The text field is not guaranteed to be NULL-terminated.
+ * The text field is NOT guaranteed to be NULL-terminated.
  *
  * To keep this table reasonably small, we divide the lexval for TZ and DTZ
  * entries by 15 (so they are on 15 minute boundaries) and truncate the text
- * field at MAXTOKLEN characters.
+ * field at TOKMAXLEN characters.
  * Formerly, we divided by 10 rather than 15 but there are a few time zones
  * which are 30 or 45 minutes away from an even hour, most are on an hour
  * boundary, and none on other boundaries.
@@ -88,11 +90,11 @@ char           *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
 static datetkn datetktbl[] = {
 /*     text, token, lexval */
        {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
+       {"abstime", IGNORE_DTF, 0}, /* for pre-v6.1 "Invalid Abstime" */
        {"acsst", DTZ, POS(42)},        /* Cent. Australia */
        {"acst", DTZ, NEG(16)},         /* Atlantic/Porto Acre */
        {"act", TZ, NEG(20)},           /* Atlantic/Porto Acre */
        {DA_D, ADBC, AD},                       /* "ad" for years >= 0 */
-       {"abstime", IGNORE_DTF, 0}, /* for pre-v6.1 "Invalid Abstime" */
        {"adt", DTZ, NEG(12)},          /* Atlantic Daylight Time */
        {"aesst", DTZ, POS(44)},        /* E. Australia */
        {"aest", TZ, POS(40)},          /* Australia Eastern Std Time */
@@ -101,16 +103,18 @@ static datetkn datetktbl[] = {
        {"akdt", DTZ, NEG(32)},         /* Alaska Daylight Time */
        {"akst", DTZ, NEG(36)},         /* Alaska Standard Time */
        {"allballs", RESERV, DTK_ZULU},         /* 00:00:00 */
-       {"almt", TZ, POS(24)},          /* Almaty Time */
        {"almst", TZ, POS(28)},         /* Almaty Savings Time */
+       {"almt", TZ, POS(24)},          /* Almaty Time */
        {"am", AMPM, AM},
        {"amst", DTZ, POS(20)},         /* Armenia Summer Time (Yerevan) */
-       {"amt", TZ, POS(16)},           /* Armenia Time (Yerevan) */
 #if 0
        {"amst", DTZ, NEG(12)},         /* Porto Velho */
 #endif
+       {"amt", TZ, POS(16)},           /* Armenia Time (Yerevan) */
        {"anast", DTZ, POS(52)},        /* Anadyr Summer Time (Russia) */
        {"anat", TZ, POS(48)},          /* Anadyr Time (Russia) */
+       {"apr", MONTH, 4},
+       {"april", MONTH, 4},
 #if 0
        aqtst
        aqtt
@@ -122,8 +126,6 @@ static datetkn datetktbl[] = {
        ast                                                     /* Atlantic Standard Time, Arabia Standard
                                                                 * Time, Acre Standard Time */
 #endif
-       {"apr", MONTH, 4},
-       {"april", MONTH, 4},
        {"ast", TZ, NEG(16)},           /* Atlantic Std Time (Canada) */
        {"at", IGNORE_DTF, 0},          /* "at" (throwaway) */
        {"aug", MONTH, 8},
@@ -181,12 +183,12 @@ static datetkn datetktbl[] = {
 #endif
        {"cot", TZ, NEG(20)},           /* Columbia Time */
        {"cst", TZ, NEG(24)},           /* Central Standard Time */
+       {DCURRENT, RESERV, DTK_CURRENT},        /* "current" is always now */
 #if 0
        cvst
 #endif
        {"cvt", TZ, POS(28)},           /* Christmas Island Time (Indian Ocean) */
        {"cxt", TZ, POS(28)},           /* Christmas Island Time (Indian Ocean) */
-       {DCURRENT, RESERV, DTK_CURRENT},        /* "current" is always now */
        {"d", UNITS, DTK_DAY},          /* "day of month" for ISO input */
        {"davt", TZ, POS(28)},          /* Davis Time (Antarctica) */
        {"ddut", TZ, POS(40)},          /* Dumont-d'Urville Time (Antarctica) */
@@ -414,8 +416,8 @@ static datetkn datetktbl[] = {
        syot
 #endif
        {"t", ISOTIME, DTK_TIME},       /* Filler for ISO time fields */
-       {"that", TZ, NEG(40)},          /* Tahiti Time */
        {"tft", TZ, POS(20)},           /* Kerguelen Time */
+       {"that", TZ, NEG(40)},          /* Tahiti Time */
        {"thu", DOW, 4},
        {"thur", DOW, 4},
        {"thurs", DOW, 4},
@@ -516,9 +518,9 @@ static datetkn deltatktbl[] = {
        {DDAY, UNITS, DTK_DAY},         /* "day" relative */
        {"days", UNITS, DTK_DAY},       /* "days" relative */
        {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
-       {"decs", UNITS, DTK_DECADE},    /* "decades" relative */
        {DDECADE, UNITS, DTK_DECADE},           /* "decade" relative */
        {"decades", UNITS, DTK_DECADE},         /* "decades" relative */
+       {"decs", UNITS, DTK_DECADE},    /* "decades" relative */
        {"h", UNITS, DTK_HOUR},         /* "hour" relative */
        {DHOUR, UNITS, DTK_HOUR},       /* "hour" relative */
        {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
@@ -534,7 +536,6 @@ static datetkn deltatktbl[] = {
        {"mils", UNITS, DTK_MILLENNIUM},        /* "millennia" relative */
        {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
        {"mins", UNITS, DTK_MINUTE},    /* "minutes" relative */
-       {"mins", UNITS, DTK_MINUTE},    /* "minutes" relative */
        {DMINUTE, UNITS, DTK_MINUTE},           /* "minute" relative */
        {"minutes", UNITS, DTK_MINUTE},         /* "minutes" relative */
        {"mon", UNITS, DTK_MONTH},      /* "months" relative */
@@ -555,7 +556,6 @@ static datetkn deltatktbl[] = {
        {"seconds", UNITS, DTK_SECOND},
        {"secs", UNITS, DTK_SECOND},
        {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
-       {"timezone", UNITS, DTK_TZ},    /* "timezone" time offset */
        {"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
        {"timezone_m", UNITS, DTK_TZ_MINUTE},           /* timezone minutes units */
        {"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
@@ -576,9 +576,9 @@ static datetkn deltatktbl[] = {
 
 static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
 
-datetkn    *datecache[MAXDATEFIELDS] = {NULL};
+static datetkn    *datecache[MAXDATEFIELDS] = {NULL};
 
-datetkn    *deltacache[MAXDATEFIELDS] = {NULL};
+static datetkn    *deltacache[MAXDATEFIELDS] = {NULL};
 
 
 /*
@@ -653,7 +653,7 @@ j2day(int date)
 /* TrimTrailingZeros()
  * ... resulting from printing numbers with full precision.
  */
-void
+static void
 TrimTrailingZeros(char *str)
 {
        int                     len = strlen(str);
@@ -3690,3 +3690,40 @@ ClearDateCache(bool newval, bool doit, bool interactive)
 
        return true;
 }
+
+/*
+ * We've been burnt by stupid errors in the ordering of the datetkn tables
+ * once too often.  Arrange to check them during postmaster start.
+ */
+static bool
+CheckDateTokenTable(const char *tablename, datetkn *base, unsigned int nel)
+{
+       bool            ok = true;
+       unsigned int i;
+
+       for (i = 1; i < nel; i++)
+       {
+               if (strncmp(base[i-1].token, base[i].token, TOKMAXLEN) >= 0)
+               {
+                       elog(LOG, "Ordering error in %s table: \"%.*s\" >= \"%.*s\"",
+                                tablename,
+                                TOKMAXLEN, base[i-1].token,
+                                TOKMAXLEN, base[i].token);
+                       ok = false;
+               }
+       }
+       return ok;
+}
+
+bool
+CheckDateTokenTables(void)
+{
+       bool            ok = true;
+
+       ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
+       ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
+       ok &= CheckDateTokenTable("australian_datetktbl",
+                                                         australian_datetktbl,
+                                                         australian_szdatetktbl);
+       return ok;
+}
index be7283bf264d9ca1aef41c4f002082405a3871e4..3b81770152d7eec4b3e6ddbe8733136f22200636 100644 (file)
@@ -9,16 +9,16 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: datetime.h,v 1.33 2002/09/04 20:31:45 momjian Exp $
+ * $Id: datetime.h,v 1.34 2003/01/16 00:26:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef DATETIME_H
 #define DATETIME_H
 
-#include <time.h>
-#include <math.h>
 #include <limits.h>
+#include <math.h>
+#include <time.h>
 
 #include "utils/timestamp.h"
 
@@ -293,4 +293,6 @@ extern bool ClearDateCache(bool, bool, bool);
 
 extern int     j2day(int jd);
 
+extern bool CheckDateTokenTables(void);
+
 #endif   /* DATETIME_H */
index e7c8cc8086b7c42a0e63058eabcf367e1ed80ba2..73b8d1399573864d414321872656d9062ea9c469 100644 (file)
@@ -11,7 +11,7 @@ CREATE TABLE TIMESTAMP_TBL ( d1 timestamp(2) without time zone);
 -- statements.
 INSERT INTO TIMESTAMP_TBL VALUES ('now');
 INSERT INTO TIMESTAMP_TBL VALUES ('current');
-ERROR:  Bad timestamp external representation 'current'
+ERROR:  'CURRENT' is no longer supported
 INSERT INTO TIMESTAMP_TBL VALUES ('today');
 INSERT INTO TIMESTAMP_TBL VALUES ('yesterday');
 INSERT INTO TIMESTAMP_TBL VALUES ('tomorrow');
@@ -64,9 +64,9 @@ ERROR:  TIMESTAMP 'invalid' no longer supported
 -- Postgres v6.0 standard output format
 INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
 INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime');
-ERROR:  Bad timestamp external representation 'Invalid Abstime'
+ERROR:  TIMESTAMP 'Invalid Abstime' no longer supported
 INSERT INTO TIMESTAMP_TBL VALUES ('Undefined Abstime');
-ERROR:  Bad timestamp external representation 'Undefined Abstime'
+ERROR:  TIMESTAMP 'Undefined Abstime' no longer supported
 -- Variations on Postgres v6.1 standard output format
 INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST');
 INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST');
index 403a0bbd4afc94cf72ab52a32e343d6a72b3f704..ab54a06d8bfd994a6feda558b416718a1d760872 100644 (file)
@@ -6,7 +6,7 @@ SET australian_timezones = 'off';
 CREATE TABLE TIMESTAMPTZ_TBL ( d1 timestamp(2) with time zone);
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
-ERROR:  Bad timestamp external representation 'current'
+ERROR:  'CURRENT' is no longer supported
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('today');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('yesterday');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('tomorrow');
@@ -59,9 +59,9 @@ ERROR:  TIMESTAMP WITH TIME ZONE 'invalid' no longer supported
 -- Postgres v6.0 standard output format
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime');
-ERROR:  Bad timestamp external representation 'Invalid Abstime'
+ERROR:  TIMESTAMP WITH TIME ZONE 'Invalid Abstime' no longer supported
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Undefined Abstime');
-ERROR:  Bad timestamp external representation 'Undefined Abstime'
+ERROR:  TIMESTAMP WITH TIME ZONE 'Undefined Abstime' no longer supported
 -- Variations on Postgres v6.1 standard output format
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST');