OK, I tested the patch and found that it still does proper date validity checking: test=> select '2003-09-31'::date; ERROR: Bad date external representation '2003-09-31'
I did find the following change in the regression tests: INSERT INTO TIMESTAMP_TBL VALUES ('02-10-1997 17:32:01 PST'); INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 PST'); INSERT INTO TIMESTAMP_TBL VALUES ('97FEB10 5:32:01PM UTC'); + ERROR: Bad timestamp external representation '97FEB10 5:32:01PM UTC' INSERT INTO TIMESTAMP_TBL VALUES ('97/02/10 17:32:01 UTC'); + ERROR: Bad timestamp external representation '97/02/10 17:32:01 UTC' INSERT INTO TIMESTAMP_TBL VALUES ('97.041 17:32:01 UTC'); + ERROR: Bad timestamp external representation '97.041 17:32:01 UTC' I didn't know we supported the first format, though it looks nice. I don't think we want to support the second format, so the error is correct. The last format looks like it is year.days_from_year_start, which I also didn't know we supported, but again looks interesting, if strange. Comments? --------------------------------------------------------------------------- [EMAIL PROTECTED] wrote: [ There is text before PGP section. ] > [ PGP not available, raw data follows ] > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > NotDashEscaped: You need GnuPG to verify this message > > > > I believe this conditional is incorrect. The second part should be DTK_M(DAY). > > Thank you - that is correct. Revised patch below. -- Bruce Momjian | http://candle.pha.pa.us [EMAIL PROTECTED] | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Index: datetime.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/datetime.c,v retrieving revision 1.106 diff -c -r1.106 datetime.c *** datetime.c 25 Jun 2003 21:14:14 -0000 1.106 --- datetime.c 30 Jun 2003 17:26:22 -0000 *************** *** 2379,2440 **** ***/ else if (flen >= 4) { ! *tmask = DTK_M(YEAR); ! /* 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; ! *tmask = DTK_M(DAY); } ! ! tm->tm_year = val; } ! ! /* 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; } ! ! /* ! * Check for 2 or 4 or more digits, but currently we reach here only ! * if two digits. - thomas 2000-03-28 ! */ ! else if (!(fmask & DTK_M(YEAR)) ! && ((flen >= 4) || (flen == 2))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; ! ! /* adjust ONLY if exactly two digits... */ ! *is2digits = (flen == 2); } else ! return -1; return 0; } /* DecodeNumber() */ --- 2379,2447 ---- ***/ else if (flen >= 4) { ! /* ! * If no month or day, start of YYYY-MM-DD ! * If have month AND day, end of MM-DD-YYYY or DD-MM-YYYY ! * If neither case, throw an error ! */ ! if ((!(fmask & DTK_M(YEAR))) ! && (((!(fmask & DTK_M(DAY))) && (!(fmask & DTK_M(MONTH)))) ! || ! ((fmask & DTK_M(DAY)) && (fmask & DTK_M(MONTH))))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; } ! else ! return -1; } ! /* If we already have a day AND month, must be a 2-digit year */ ! else if ((fmask & DTK_M(DAY)) && (fmask & DTK_M(MONTH))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; ! *is2digits = TRUE; } ! ! /* If we already have a year and a month, must be day */ ! else if ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(MONTH))) { *tmask = DTK_M(DAY); tm->tm_mday = val; } ! /* A year and a day is currently an error, as YYYY-DD-MM is not allowed */ ! else if ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(DAY))) ! return -1; ! /* If have year or day, set the month */ ! else if ((fmask & DTK_M(YEAR)) || (fmask & DTK_M(DAY))) { + /* Do not allow month to roll over */ + if (val > 12) + return -1; *tmask = DTK_M(MONTH); tm->tm_mon = val; } ! /* If have a month, set the day */ ! else if ((fmask & DTK_M(MONTH))) { *tmask = DTK_M(DAY); tm->tm_mday = val; } ! /* If using EuroDates, this must be the day, otherwise month */ ! else if (EuroDates) { ! *tmask = DTK_M(DAY); ! tm->tm_mday = val; } else ! { ! /* Do not allow month to roll over */ ! if (val > 12) ! return -1; ! *tmask = DTK_M(MONTH); ! tm->tm_mon = val;-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 NotDashEscaped: You need GnuPG to verify this message > I believe this conditional is incorrect. The second part should be DTK_M(DAY). Thank you - that is correct. Revised patch below. Index: datetime.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/datetime.c,v retrieving revision 1.106 diff -c -r1.106 datetime.c *** datetime.c 25 Jun 2003 21:14:14 -0000 1.106 --- datetime.c 30 Jun 2003 17:26:22 -0000 *************** *** 2379,2440 **** ***/ else if (flen >= 4) { ! *tmask = DTK_M(YEAR); ! /* 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; ! *tmask = DTK_M(DAY); } ! ! tm->tm_year = val; } ! ! /* 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; } ! ! /* ! * Check for 2 or 4 or more digits, but currently we reach here only ! * if two digits. - thomas 2000-03-28 ! */ ! else if (!(fmask & DTK_M(YEAR)) ! && ((flen >= 4) || (flen == 2))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; ! ! /* adjust ONLY if exactly two digits... */ ! *is2digits = (flen == 2); } else ! return -1; return 0; } /* DecodeNumber() */ --- 2379,2447 ---- ***/ else if (flen >= 4) { ! /* ! * If no month or day, start of YYYY-MM-DD ! * If have month AND day, end of MM-DD-YYYY or DD-MM-YYYY ! * If neither case, throw an error ! */ ! if ((!(fmask & DTK_M(YEAR))) ! && (((!(fmask & DTK_M(DAY))) && (!(fmask & DTK_M(MONTH)))) ! || ! ((fmask & DTK_M(DAY)) && (fmask & DTK_M(MONTH))))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; } ! else ! return -1; } ! /* If we already have a day AND month, must be a 2-digit year */ ! else if ((fmask & DTK_M(DAY)) && (fmask & DTK_M(MONTH))) { ! *tmask = DTK_M(YEAR); ! tm->tm_year = val; ! *is2digits = TRUE; } ! ! /* If we already have a year and a month, must be day */ ! else if ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(MONTH))) { *tmask = DTK_M(DAY); tm->tm_mday = val; } ! /* A year and a day is currently an error, as YYYY-DD-MM is not allowed */ ! else if ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(DAY))) ! return -1; ! /* If have year or day, set the month */ ! else if ((fmask & DTK_M(YEAR)) || (fmask & DTK_M(DAY))) { + /* Do not allow month to roll over */ + if (val > 12) + return -1; *tmask = DTK_M(MONTH); tm->tm_mon = val; } ! /* If have a month, set the day */ ! else if ((fmask & DTK_M(MONTH))) { *tmask = DTK_M(DAY); tm->tm_mday = val; } ! /* If using EuroDates, this must be the day, otherwise month */ ! else if (EuroDates) { ! *tmask = DTK_M(DAY); ! tm->tm_mday = val; } else ! { ! /* Do not allow month to roll over */ ! if (val > 12) ! return -1; ! *tmask = DTK_M(MONTH); ! tm->tm_mon = val; ! } return 0; } /* DecodeNumber() */
---------------------------(end of broadcast)--------------------------- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match