summaryrefslogtreecommitdiff
path: root/src
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 /src
parent1fb7158124685f05ad1083f1738d1e9dc7221b5c (diff)
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.
Diffstat (limited to 'src')
-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');