Commit b3b89fd1 authored by Tom Lane's avatar Tom Lane

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.
parent 5377ccbe
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -3022,19 +3022,19 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
tm->tm_hour += val; tm->tm_hour += val;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR); AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
tmask = DTK_M(HOUR); tmask = DTK_M(HOUR);
type = DTK_DAY; type = DTK_DAY; /* set for next field */
break; break;
case DTK_DAY: case DTK_DAY:
tm->tm_mday += val; tm->tm_mday += val;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY); AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY); tmask = DTK_M(DAY);
break; break;
case DTK_WEEK: case DTK_WEEK:
tm->tm_mday += val * 7; tm->tm_mday += val * 7;
AdjustFractDays(fval, tm, fsec, 7); AdjustFractDays(fval, tm, fsec, 7);
tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY); tmask = DTK_M(WEEK);
break; break;
case DTK_MONTH: case DTK_MONTH:
...@@ -3047,28 +3047,28 @@ DecodeInterval(char **field, int *ftype, int nf, int range, ...@@ -3047,28 +3047,28 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
tm->tm_year += val; tm->tm_year += val;
if (fval != 0) if (fval != 0)
tm->tm_mon += fval * MONTHS_PER_YEAR; tm->tm_mon += fval * MONTHS_PER_YEAR;
tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); tmask = DTK_M(YEAR);
break; break;
case DTK_DECADE: case DTK_DECADE:
tm->tm_year += val * 10; tm->tm_year += val * 10;
if (fval != 0) if (fval != 0)
tm->tm_mon += fval * MONTHS_PER_YEAR * 10; tm->tm_mon += fval * MONTHS_PER_YEAR * 10;
tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); tmask = DTK_M(DECADE);
break; break;
case DTK_CENTURY: case DTK_CENTURY:
tm->tm_year += val * 100; tm->tm_year += val * 100;
if (fval != 0) if (fval != 0)
tm->tm_mon += fval * MONTHS_PER_YEAR * 100; tm->tm_mon += fval * MONTHS_PER_YEAR * 100;
tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); tmask = DTK_M(CENTURY);
break; break;
case DTK_MILLENNIUM: case DTK_MILLENNIUM:
tm->tm_year += val * 1000; tm->tm_year += val * 1000;
if (fval != 0) if (fval != 0)
tm->tm_mon += fval * MONTHS_PER_YEAR * 1000; tm->tm_mon += fval * MONTHS_PER_YEAR * 1000;
tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR); tmask = DTK_M(MILLENNIUM);
break; break;
default: default:
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -114,6 +114,11 @@
/* generic fields to help with parsing */ /* generic fields to help with parsing */
#define ISODATE 22 #define ISODATE 22
#define ISOTIME 23 #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 */ /* reserved for unrecognized string values */
#define UNKNOWN_FIELD 31 #define UNKNOWN_FIELD 31
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment