aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-01-16 00:27:17 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-01-16 00:27:17 +0000
commitdb398d05bea227cb2bbf8baca8e9abc5676a65cf (patch)
tree2c16e388b7cb679e95e8fdfb1356dec7c8cf14b7
parent1fb7158124685f05ad1083f1738d1e9dc7221b5c (diff)
downloadpostgresql-db398d05bea227cb2bbf8baca8e9abc5676a65cf.tar.gz
postgresql-db398d05bea227cb2bbf8baca8e9abc5676a65cf.zip
Repair an embarrassingly large number of alphabetization mistakes in the
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.
-rw-r--r--src/backend/postmaster/postmaster.c11
-rw-r--r--src/backend/utils/adt/datetime.c79
-rw-r--r--src/include/utils/datetime.h8
-rw-r--r--src/test/regress/expected/timestamp.out6
-rw-r--r--src/test/regress/expected/timestamptz.out6
5 files changed, 79 insertions, 31 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 12a6de4f0ce..d8b36b37cbf 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.290.2.1 2002/11/21 06:36:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.290.2.2 2003/01/16 00:27:17 tgl Exp $
*
* NOTES
*
@@ -593,6 +593,15 @@ PostmasterMain(int argc, char *argv[])
}
/*
+ * 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.
*/
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index e5e941e0d5b..38655ceb5b1 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,21 +8,21 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.96.2.1 2002/11/13 17:24:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.96.2.2 2003/01/16 00:27:17 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;
+}
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index be7283bf264..d788ea4d529 100644
--- a/src/include/utils/datetime.h
+++ b/src/include/utils/datetime.h
@@ -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.33.2.1 2003/01/16 00:27:17 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 */
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index e7c8cc8086b..73b8d139957 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -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');
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 403a0bbd4af..ab54a06d8bf 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -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');