From: Tom Lane Date: Mon, 1 Jun 2009 16:55:11 +0000 (+0000) Subject: Fix DecodeInterval to report an error for multiple occurrences of DAY, WEEK, X-Git-Tag: REL8_4_RC1~67 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b3b89fd1f1ab3b1f3052695e51a94713921808a5;p=postgresql Fix DecodeInterval to report an error for multiple occurrences of DAY, WEEK, YEAR, DECADE, CENTURY, or MILLENIUM fields, just as it always has done for other types of fields. The previous behavior seems to have been a hack to avoid defining bit-positions for all these field types in DTK_M() masks, rather than something that was really considered to be desired behavior. But there is room in the masks for these, and we really need to tighten up at least the behavior of DAY and YEAR fields to avoid unexpected behavior associated with the 8.4 changes to interpret ambiguous fields based on the interval qualifier (typmod) value. Per my example and proposed patch. --- diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 13681016b5..cf8009df91 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.205 2009/05/26 02:17:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.206 2009/06/01 16:55:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3022,19 +3022,19 @@ DecodeInterval(char **field, int *ftype, int nf, int range, tm->tm_hour += val; AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR); tmask = DTK_M(HOUR); - type = DTK_DAY; + type = DTK_DAY; /* set for next field */ break; case DTK_DAY: tm->tm_mday += val; AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY); - tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY); + tmask = DTK_M(DAY); break; case DTK_WEEK: tm->tm_mday += val * 7; AdjustFractDays(fval, tm, fsec, 7); - tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY); + tmask = DTK_M(WEEK); break; case DTK_MONTH: @@ -3047,28 +3047,28 @@ DecodeInterval(char **field, int *ftype, int nf, int range, tm->tm_year += val; if (fval != 0) tm->tm_mon += fval * MONTHS_PER_YEAR; - tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); + tmask = DTK_M(YEAR); break; case DTK_DECADE: tm->tm_year += val * 10; if (fval != 0) tm->tm_mon += fval * MONTHS_PER_YEAR * 10; - tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); + tmask = DTK_M(DECADE); break; case DTK_CENTURY: tm->tm_year += val * 100; if (fval != 0) tm->tm_mon += fval * MONTHS_PER_YEAR * 100; - tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); + tmask = DTK_M(CENTURY); break; case DTK_MILLENNIUM: tm->tm_year += val * 1000; if (fval != 0) tm->tm_mon += fval * MONTHS_PER_YEAR * 1000; - tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); + tmask = DTK_M(MILLENNIUM); break; default: diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 0704e60c91..0b757021de 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.73 2009/05/26 02:17:50 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.74 2009/06/01 16:55:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -114,6 +114,11 @@ /* generic fields to help with parsing */ #define ISODATE 22 #define ISOTIME 23 +/* these are only for parsing intervals */ +#define WEEK 24 +#define DECADE 25 +#define CENTURY 26 +#define MILLENNIUM 27 /* reserved for unrecognized string values */ #define UNKNOWN_FIELD 31