Re: Datetime patch

Поиск
Список
Период
Сортировка
Искать
От
Bruce Momjian
Тема
Re: Datetime patch
Дата
Msg-id
200307251728.h6PHSEi13494@candle.pha.pa.us
Ответ на
Re: Datetime patch (greg@turnstep.com)
Список
Дерево обсуждения
Datetime patch greg@turnstep.com
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch Peter Eisentraut <peter_e@gmx.net>
Re: Datetime patch greg@turnstep.com
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch greg@turnstep.com
Re: Datetime patch Tom Lane <tgl@sss.pgh.pa.us>
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch Tom Lane <tgl@sss.pgh.pa.us>
Re: Datetime patch Bruce Momjian <pgman@candle.pha.pa.us>
Re: Datetime patch Tom Lane <tgl@sss.pgh.pa.us>

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?

---------------------------------------------------------------------------

greg@turnstep.com 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
  pgman@candle.pha.pa.us               |  (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() */
В списке pgsql-patches по дате отправления
От: greg@turnstep.com
Дата:
Сообщение: Re: Datetime patch
От: Tom Lane
Дата:
FAQ