Fix interval input parser so that fractional weeks and months are
cascaded first to days and only what is leftover into seconds. This seems to satisfy the principle of least surprise given the general conversion to three-part interval values --- it was an oversight that these cases weren't dealt with in 8.1. Michael Glaesemann
This commit is contained in:
parent
091fe03775
commit
57bfb27e60
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.169 2006/07/25 03:51:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.170 2006/09/04 01:26:27 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2919,10 +2919,16 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
|
||||
case DTK_WEEK:
|
||||
tm->tm_mday += val * 7;
|
||||
if (fval != 0)
|
||||
{
|
||||
int extra_days;
|
||||
fval *= 7;
|
||||
extra_days = (int32) fval;
|
||||
tm->tm_mday += extra_days;
|
||||
fval -= extra_days;
|
||||
if (fval != 0)
|
||||
{
|
||||
int sec;
|
||||
|
||||
fval *= 7 * SECS_PER_DAY;
|
||||
fval *= SECS_PER_DAY;
|
||||
sec = fval;
|
||||
tm->tm_sec += sec;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@ -2931,16 +2937,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
|
||||
*fsec += fval - sec;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
|
||||
break;
|
||||
|
||||
case DTK_MONTH:
|
||||
tm->tm_mon += val;
|
||||
if (fval != 0)
|
||||
{
|
||||
int day;
|
||||
fval *= DAYS_PER_MONTH;
|
||||
day = fval;
|
||||
tm->tm_mday += day;
|
||||
fval -= day;
|
||||
if (fval != 0)
|
||||
{
|
||||
int sec;
|
||||
|
||||
fval *= DAYS_PER_MONTH * SECS_PER_DAY;
|
||||
fval *= SECS_PER_DAY;
|
||||
sec = fval;
|
||||
tm->tm_sec += sec;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@ -2949,6 +2962,7 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
|
||||
*fsec += fval - sec;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
tmask = DTK_M(MONTH);
|
||||
break;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.32 2006/06/06 11:31:55 meskes Exp $ */
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.33 2006/09/04 01:26:28 tgl Exp $ */
|
||||
|
||||
#include "postgres_fe.h"
|
||||
#include <time.h>
|
||||
@ -306,10 +306,16 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse
|
||||
case DTK_WEEK:
|
||||
tm->tm_mday += val * 7;
|
||||
if (fval != 0)
|
||||
{
|
||||
int extra_days;
|
||||
fval *= 7;
|
||||
extra_days = (int32) fval;
|
||||
tm->tm_mday += extra_days;
|
||||
fval -= extra_days;
|
||||
if (fval != 0)
|
||||
{
|
||||
int sec;
|
||||
|
||||
fval *= 7 * SECS_PER_DAY;
|
||||
fval *= SECS_PER_DAY;
|
||||
sec = fval;
|
||||
tm->tm_sec += sec;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@ -318,16 +324,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse
|
||||
*fsec += fval - sec;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
|
||||
break;
|
||||
|
||||
case DTK_MONTH:
|
||||
tm->tm_mon += val;
|
||||
if (fval != 0)
|
||||
{
|
||||
int day;
|
||||
fval *= DAYS_PER_MONTH;
|
||||
day = fval;
|
||||
tm->tm_mday += day;
|
||||
fval -= day;
|
||||
if (fval != 0)
|
||||
{
|
||||
int sec;
|
||||
|
||||
fval *= DAYS_PER_MONTH * SECS_PER_DAY;
|
||||
fval *= SECS_PER_DAY;
|
||||
sec = fval;
|
||||
tm->tm_sec += sec;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@ -336,6 +349,7 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse
|
||||
*fsec += fval - sec;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
tmask = DTK_M(MONTH);
|
||||
break;
|
||||
|
||||
|
@ -39,6 +39,18 @@ SELECT INTERVAL '-1 days +02:03' AS "22 hours ago...";
|
||||
-1 days +02:03:00
|
||||
(1 row)
|
||||
|
||||
SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours";
|
||||
Ten days twelve hours
|
||||
-----------------------
|
||||
10 days 12:00:00
|
||||
(1 row)
|
||||
|
||||
SELECT INTERVAL '1.5 months' AS "One month 15 days";
|
||||
One month 15 days
|
||||
-------------------
|
||||
1 mon 15 days
|
||||
(1 row)
|
||||
|
||||
SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
|
||||
9 years...
|
||||
----------------------------------
|
||||
|
@ -11,6 +11,8 @@ SELECT INTERVAL '-08:00' AS "Eight hours";
|
||||
SELECT INTERVAL '-05' AS "Five hours";
|
||||
SELECT INTERVAL '-1 +02:03' AS "22 hours ago...";
|
||||
SELECT INTERVAL '-1 days +02:03' AS "22 hours ago...";
|
||||
SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours";
|
||||
SELECT INTERVAL '1.5 months' AS "One month 15 days";
|
||||
SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
|
||||
|
||||
CREATE TABLE INTERVAL_TBL (f1 interval);
|
||||
|
Loading…
x
Reference in New Issue
Block a user