]> granicus.if.org Git - postgresql/commitdiff
Fix DecodeInterval to report an error for multiple occurrences of DAY, WEEK,
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 1 Jun 2009 16:55:11 +0000 (16:55 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 1 Jun 2009 16:55:11 +0000 (16:55 +0000)
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.

src/backend/utils/adt/datetime.c
src/include/utils/datetime.h

index 13681016b516386095f35bfd711d2c9b89b80721..cf8009df9104817190a816873730a116ff9dfb65 100644 (file)
@@ -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:
index 0704e60c919a54f1a23849692d0fa3cfce1e941e..0b757021deb07e8320fc7e9dbef96e4541a06013 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 /* 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