diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/commands/variable.c | 74 | ||||
| -rw-r--r-- | src/backend/tcop/postgres.c | 8 | ||||
| -rw-r--r-- | src/backend/utils/adt/datetime.c | 226 | ||||
| -rw-r--r-- | src/backend/utils/init/globals.c | 4 | ||||
| -rw-r--r-- | src/backend/utils/misc/README | 6 | ||||
| -rw-r--r-- | src/backend/utils/misc/guc.c | 10 | ||||
| -rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 2 |
7 files changed, 189 insertions, 141 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index a9fc94adc3..e0b041636e 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.84 2003/07/28 00:09:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.85 2003/07/29 00:03:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,10 +51,10 @@ const char * assign_datestyle(const char *value, bool doit, bool interactive) { int newDateStyle = DateStyle; - bool newEuroDates = EuroDates; + int newDateOrder = DateOrder; bool ok = true; - int dcnt = 0, - ecnt = 0; + int scnt = 0, + ocnt = 0; char *rawstring; char *result; List *elemlist; @@ -85,38 +85,43 @@ assign_datestyle(const char *value, bool doit, bool interactive) if (strcasecmp(tok, "ISO") == 0) { newDateStyle = USE_ISO_DATES; - dcnt++; + scnt++; } else if (strcasecmp(tok, "SQL") == 0) { newDateStyle = USE_SQL_DATES; - dcnt++; + scnt++; } else if (strncasecmp(tok, "POSTGRES", 8) == 0) { newDateStyle = USE_POSTGRES_DATES; - dcnt++; + scnt++; } else if (strcasecmp(tok, "GERMAN") == 0) { newDateStyle = USE_GERMAN_DATES; - dcnt++; - if ((ecnt > 0) && (!newEuroDates)) - ok = false; - newEuroDates = TRUE; + scnt++; + /* GERMAN also sets DMY, unless explicitly overridden */ + if (ocnt == 0) + newDateOrder = DATEORDER_DMY; } - else if (strncasecmp(tok, "EURO", 4) == 0) + else if (strcasecmp(tok, "YMD") == 0) { - newEuroDates = TRUE; - ecnt++; + newDateOrder = DATEORDER_YMD; + ocnt++; } - else if (strcasecmp(tok, "US") == 0 - || strncasecmp(tok, "NONEURO", 7) == 0) + else if (strcasecmp(tok, "DMY") == 0 || + strncasecmp(tok, "EURO", 4) == 0) { - newEuroDates = FALSE; - ecnt++; - if ((dcnt > 0) && (newDateStyle == USE_GERMAN_DATES)) - ok = false; + newDateOrder = DATEORDER_DMY; + ocnt++; + } + else if (strcasecmp(tok, "MDY") == 0 || + strcasecmp(tok, "US") == 0 || + strncasecmp(tok, "NONEURO", 7) == 0) + { + newDateOrder = DATEORDER_MDY; + ocnt++; } else if (strcasecmp(tok, "DEFAULT") == 0) { @@ -128,15 +133,17 @@ assign_datestyle(const char *value, bool doit, bool interactive) * to handle constructs like "DEFAULT, ISO". */ int saveDateStyle = DateStyle; - bool saveEuroDates = EuroDates; + int saveDateOrder = DateOrder; const char *subval; subval = assign_datestyle(GetConfigOptionResetString("datestyle"), true, interactive); - newDateStyle = DateStyle; - newEuroDates = EuroDates; + if (scnt == 0) + newDateStyle = DateStyle; + if (ocnt == 0) + newDateOrder = DateOrder; DateStyle = saveDateStyle; - EuroDates = saveEuroDates; + DateOrder = saveDateOrder; if (!subval) { ok = false; @@ -145,8 +152,6 @@ assign_datestyle(const char *value, bool doit, bool interactive) /* Here we know that our own return value is always malloc'd */ /* when doit is true */ free((char *) subval); - dcnt++; - ecnt++; } else { @@ -160,7 +165,7 @@ assign_datestyle(const char *value, bool doit, bool interactive) } } - if (dcnt > 1 || ecnt > 1) + if (scnt > 1 || ocnt > 1) ok = false; pfree(rawstring); @@ -203,14 +208,25 @@ assign_datestyle(const char *value, bool doit, bool interactive) strcpy(result, "Postgres"); break; } - strcat(result, newEuroDates ? ", European" : ", US"); + switch (newDateOrder) + { + case DATEORDER_YMD: + strcat(result, ", YMD"); + break; + case DATEORDER_DMY: + strcat(result, ", DMY"); + break; + default: + strcat(result, ", MDY"); + break; + } /* * Finally, it's safe to assign to the global variables; the * assignment cannot fail now. */ DateStyle = newDateStyle; - EuroDates = newEuroDates; + DateOrder = newDateOrder; return result; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 9b2324b220..80f2be70ed 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.352 2003/07/27 21:49:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.353 2003/07/29 00:03:18 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1958,7 +1958,7 @@ usage(char *progname) printf(" -c NAME=VALUE set run-time parameter\n"); printf(" -d 0-5 debugging level (0 is off)\n"); printf(" -D DATADIR database directory\n"); - printf(" -e use European date format\n"); + printf(" -e use European date input format (DMY)\n"); printf(" -E echo query before execution\n"); printf(" -F turn fsync off\n"); printf(" -N do not use newline as interactive query delimiter\n"); @@ -2155,7 +2155,7 @@ PostgresMain(int argc, char *argv[], const char *username) case 'e': /* - * Use european date formats. + * Use European date input format (DMY) */ SetConfigOption("datestyle", "euro", ctx, gucsource); break; @@ -2626,7 +2626,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.352 $ $Date: 2003/07/27 21:49:54 $\n"); + puts("$Revision: 1.353 $ $Date: 2003/07/29 00:03:18 $\n"); } /* diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 1b9b4fcc82..f053c9ebb2 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.107 2003/07/27 04:53:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.108 2003/07/29 00:03:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1425,23 +1425,47 @@ DecodeDateTime(char **field, int *ftype, int nf, fmask |= tmask; } - /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */ - if (bc) + if (fmask & DTK_M(YEAR)) { - if (tm->tm_year > 0) - tm->tm_year = -(tm->tm_year - 1); - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_DATETIME_FORMAT), - errmsg("inconsistent use of year %04d and \"BC\"", - tm->tm_year))); + /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */ + if (bc) + { + if (tm->tm_year > 0) + tm->tm_year = -(tm->tm_year - 1); + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_DATETIME_FORMAT), + errmsg("inconsistent use of year %04d and \"BC\"", + tm->tm_year))); + } + else if (is2digits) + { + if (tm->tm_year < 70) + tm->tm_year += 2000; + else if (tm->tm_year < 100) + tm->tm_year += 1900; + } } - else if (is2digits) + + /* now that we have correct year, decode DOY */ + if (fmask & DTK_M(DOY)) { - if (tm->tm_year < 70) - tm->tm_year += 2000; - else if (tm->tm_year < 100) - tm->tm_year += 1900; + j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1, + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + } + + /* check for valid month */ + if (fmask & DTK_M(MONTH)) + { + if (tm->tm_mon < 1 || tm->tm_mon > 12) + return -1; + } + + /* minimal check for valid day */ + if (fmask & DTK_M(DAY)) + { + if (tm->tm_mday < 1 || tm->tm_mday > 31) + return -1; } if ((mer != HR24) && (tm->tm_hour > 12)) @@ -1461,13 +1485,11 @@ DecodeDateTime(char **field, int *ftype, int nf, * check for valid day of month, now that we know for sure the * month and year... */ - if ((tm->tm_mday < 1) - || (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])) + if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) return -1; /* timezone not specified? then find local timezone if possible */ - if (((fmask & DTK_DATE_M) == DTK_DATE_M) - && (tzp != NULL) && (!(fmask & DTK_M(TZ)))) + if ((tzp != NULL) && (!(fmask & DTK_M(TZ)))) { /* * daylight savings time modifier but no standard timezone? @@ -2259,6 +2281,22 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm) tm->tm_year += 1900; } + /* now that we have correct year, decode DOY */ + if (fmask & DTK_M(DOY)) + { + j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1, + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + } + + /* check for valid month */ + if (tm->tm_mon < 1 || tm->tm_mon > 12) + return -1; + + /* check for valid day */ + if (tm->tm_mday < 1 || + tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) + return -1; + return 0; } /* DecodeDate() */ @@ -2356,8 +2394,8 @@ DecodeNumber(int flen, char *str, int fmask, if (*cp == '.') { /* - * More than two digits? Then could be a date or a run-together - * time: 2001.360 20011225 040506.789 + * More than two digits before decimal point? Then could be a date + * or a run-together time: 2001.360 20011225 040506.789 */ if ((cp - str) > 2) return DecodeNumberField(flen, str, (fmask | DTK_DATE_M), @@ -2370,85 +2408,91 @@ DecodeNumber(int flen, char *str, int fmask, else if (*cp != '\0') return -1; - /* Special case day of year? */ - if ((flen == 3) && (fmask & DTK_M(YEAR)) - && ((val >= 1) && (val <= 366))) + /* Special case for day of year */ + if ((flen == 3) && + ((fmask & DTK_DATE_M) == DTK_M(YEAR)) && + ((val >= 1) && (val <= 366))) { *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY)); tm->tm_yday = val; - j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1, - &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + /* tm_mon and tm_mday can't actually be set yet ... */ + return 0; } - /*** - * Enough digits to be unequivocal year? Used to test for 4 digits or - * more, but we now test first for a three-digit doy so anything - * bigger than two digits had better be an explicit year. - * - thomas 1999-01-09 - * Back to requiring a 4 digit year. We accept a two digit - * year farther down. - thomas 2000-03-28 - ***/ - else if (flen >= 4) + /* Switch based on what we have so far */ + switch (fmask & DTK_DATE_M) { - *tmask = DTK_M(YEAR); + case 0: + /* + * Nothing so far; make a decision about what we think the + * input is. There used to be lots of heuristics here, but + * the consensus now is to be paranoid. It *must* be either + * YYYY-MM-DD (with a more-than-two-digit year field), or the + * field order defined by DateOrder. + */ + if (flen >= 3 || DateOrder == DATEORDER_YMD) + { + *tmask = DTK_M(YEAR); + tm->tm_year = val; + } + else if (DateOrder == DATEORDER_DMY) + { + *tmask = DTK_M(DAY); + tm->tm_mday = val; + } + else + { + *tmask = DTK_M(MONTH); + tm->tm_mon = val; + } + break; - /* already have a year? then see if we can substitute... */ - if ((fmask & DTK_M(YEAR)) && (!(fmask & DTK_M(DAY))) - && ((tm->tm_year >= 1) && (tm->tm_year <= 31))) - { - tm->tm_mday = tm->tm_year; + case (DTK_M(YEAR)): + /* Must be at second field of YY-MM-DD */ + *tmask = DTK_M(MONTH); + tm->tm_mon = val; + break; + + case (DTK_M(YEAR) | DTK_M(MONTH)): + /* Must be at third field of YY-MM-DD */ *tmask = DTK_M(DAY); - } + tm->tm_mday = val; + break; - tm->tm_year = val; - } + case (DTK_M(DAY)): + /* Must be at second field of DD-MM-YY */ + *tmask = DTK_M(MONTH); + tm->tm_mon = val; + break; - /* already have year? then could be month */ - else if ((fmask & DTK_M(YEAR)) && (!(fmask & DTK_M(MONTH))) - && ((val >= 1) && (val <= 12))) - { - *tmask = DTK_M(MONTH); - tm->tm_mon = val; - } - /* no year and EuroDates enabled? then could be day */ - else if ((EuroDates || (fmask & DTK_M(MONTH))) - && (!(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY))) - && ((val >= 1) && (val <= 31))) - { - *tmask = DTK_M(DAY); - tm->tm_mday = val; - } - else if ((!(fmask & DTK_M(MONTH))) - && ((val >= 1) && (val <= 12))) - { - *tmask = DTK_M(MONTH); - tm->tm_mon = val; - } - else if ((!(fmask & DTK_M(DAY))) - && ((val >= 1) && (val <= 31))) - { - *tmask = DTK_M(DAY); - tm->tm_mday = val; + case (DTK_M(MONTH) | DTK_M(DAY)): + /* Must be at third field of DD-MM-YY or MM-DD-YY */ + *tmask = DTK_M(YEAR); + tm->tm_year = val; + break; + + case (DTK_M(MONTH)): + /* Must be at second field of MM-DD-YY */ + *tmask = DTK_M(DAY); + tm->tm_mday = val; + break; + + default: + /* Anything else is bogus input */ + return -1; } /* - * Check for 2 or 4 or more digits, but currently we reach here only - * if two digits. - thomas 2000-03-28 + * When processing a year field, mark it for adjustment if it's + * exactly two digits. */ - else if (!(fmask & DTK_M(YEAR)) - && ((flen >= 4) || (flen == 2))) + if (*tmask == DTK_M(YEAR)) { - *tmask = DTK_M(YEAR); - tm->tm_year = val; - - /* adjust ONLY if exactly two digits... */ *is2digits = (flen == 2); } - else - return -1; return 0; -} /* DecodeNumber() */ +} /* DecodeNumberField() @@ -2514,18 +2558,6 @@ DecodeNumberField(int len, char *str, int fmask, return DTK_DATE; } - /* yyddd? */ - else if (len == 5) - { - *tmask = DTK_DATE_M; - tm->tm_mday = atoi(str + 2); - *(str + 2) = '\0'; - tm->tm_mon = 1; - tm->tm_year = atoi(str + 0); - *is2digits = TRUE; - - return DTK_DATE; - } } /* not all time fields are specified? */ @@ -3152,7 +3184,7 @@ EncodeDateOnly(struct tm * tm, int style, char *str) case USE_SQL_DATES: /* compatible with Oracle/Ingres date formats */ - if (EuroDates) + if (DateOrder == DATEORDER_DMY) sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); @@ -3174,7 +3206,7 @@ EncodeDateOnly(struct tm * tm, int style, char *str) case USE_POSTGRES_DATES: default: /* traditional date-only style for Postgres */ - if (EuroDates) + if (DateOrder == DATEORDER_DMY) sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday); @@ -3308,7 +3340,7 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha case USE_SQL_DATES: /* Compatible with Oracle/Ingres date formats */ - if (EuroDates) + if (DateOrder == DATEORDER_DMY) sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); @@ -3410,7 +3442,7 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha strncpy(str, days[tm->tm_wday], 3); strcpy((str + 3), " "); - if (EuroDates) + if (DateOrder == DATEORDER_DMY) sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]); else sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday); diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 2a7a372fa6..6e6551f101 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.72 2003/06/27 14:45:30 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.73 2003/07/29 00:03:18 tgl Exp $ * * NOTES * Globals used all over the place should be declared here and not @@ -62,7 +62,7 @@ bool IsUnderPostmaster = false; bool ExitOnAnyError = false; int DateStyle = USE_ISO_DATES; -bool EuroDates = false; +int DateOrder = DATEORDER_MDY; bool HasCTZSet = false; int CTimeZone = 0; diff --git a/src/backend/utils/misc/README b/src/backend/utils/misc/README index fe252d534d..b8610a97b8 100644 --- a/src/backend/utils/misc/README +++ b/src/backend/utils/misc/README @@ -1,4 +1,4 @@ -$Header: /cvsroot/pgsql/src/backend/utils/misc/README,v 1.1 2002/05/17 01:19:18 tgl Exp $ +$Header: /cvsroot/pgsql/src/backend/utils/misc/README,v 1.2 2003/07/29 00:03:18 tgl Exp $ GUC IMPLEMENTATION NOTES @@ -49,8 +49,8 @@ variables, but the return value is handled differently: malloc'd (not palloc'd!!!) string --- assign that value instead The third choice is allowed in case the assign_hook wants to return a "canonical" version of the new value. For example, the assign_hook for -datestyle always returns a string that includes both basic datestyle and -us/euro option, although the input might have specified only one. +datestyle always returns a string that includes both output and input +datestyle options, although the input might have specified only one. If a show_hook is provided, it points to a function of the signature const char *show_hook(void) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index d6ed9ba462..a7eb4f5ed1 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.143 2003/07/28 19:31:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.144 2003/07/29 00:03:18 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -1338,13 +1338,13 @@ static struct config_string ConfigureNamesString[] = { {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE, - gettext_noop("The display format for date and time values"), - gettext_noop("As well as the rules for interpreting ambiguous date " - "input values"), + gettext_noop("The display format for date and time values, "), + gettext_noop("as well as the rules for interpreting ambiguous " + "date input values"), GUC_LIST_INPUT | GUC_REPORT }, &datestyle_string, - "ISO, US", assign_datestyle, NULL + "ISO, MDY", assign_datestyle, NULL }, { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 584e24f428..6ed1aae208 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -212,7 +212,7 @@ # - Locale and Formatting - -#datestyle = 'iso, us' +#datestyle = 'iso, mdy' #timezone = unknown # actually, defaults to TZ environment setting #australian_timezones = false #extra_float_digits = 0 # min -15, max 2 |
