Обсуждение: Strange results with date/interval arithmetic

Поиск
Список
Период
Сортировка

Strange results with date/interval arithmetic

От
Bruce Momjian
Дата:
I am seeing strange results from date/interval computations involving
months.

I get the correct answers because I have a negative setting relative to
GMT.  Here are my results with TZ=EST5EDT:test=> select '2001/3/1'::date - '1 month'::interval;        ?column?
------------------------2001-02-01 00:00:00-05(1 row)
 

With GMT it is OK too:
test=> select '2001/3/1'::date - '1 month'::interval;        ?column?        ------------------------ 2001-02-01
00:00:00+00(1row)
 

However, with GMT+1 I see a big failure:
test=> select '2001/3/1'::date - '1 month'::interval;        ?column?        ------------------------ 2001-01-29
00:00:00+01(1row)
 

Why does it say 2001-01-29?

This is interesting:test=> select '2001/7/1'::date - '1 month'::interval;        ?column?
------------------------2001-05-31 00:00:00+02(1 row)test=> select '2001/8/1'::date - '1 month'::interval;
?column?       ------------------------ 2001-07-01 00:00:00+02(1 row)
 

Because August and July have the same number of months, it worked.  I am
going to research this but someone may know the solution already.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: Strange results with date/interval arithmetic

От
Tom Lane
Дата:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> I am seeing strange results from date/interval computations involving
> months.

Ah, this is what we get for running the regression tests in only one
time zone :-(

The problem appears to be cut-and-paste errors in timestamp.c and
pg_proc.h: various things that should be timestamp are timestamptz
or vice versa.  See attached proposed patches.

Fixing this causes the horology regress tests to change, apparently
with good reason.  I would say that
'Wed Feb 28 17:32:01 1996 PST'::timestamptz + interval '1 year'

is more nearly Fri Feb 28 17:32:01 1997 PST than
Thu Feb 27 17:32:01 1997 PST (currently enshrined in the expected
results).  However I have not gone through all the diffs to verify each.

Thomas, you said you had additional horology tests to commit; since
we are going to have to fix and resync the horology files anyway,
do you want to go ahead and add them?

Another question: do we bump catversion and force an initdb for our
long-suffering beta testers, just to adjust two pg_proc entries?
We may not have much choice.

Sigh.  RC1 is off again.
        regards, tom lane

*** src/backend/utils/adt/timestamp.c~    Sat Dec 29 19:48:03 2001
--- src/backend/utils/adt/timestamp.c    Tue Jan  8 16:55:50 2002
***************
*** 1290,1296 **** }  
! /* timestamp_pl_span()  * Add a interval to a timestamp with time zone data type.  * Note that interval has
provisionsfor qualitative year/month  *    units, so try to do the right thing with them.
 
--- 1290,1296 ---- }  
! /* timestamptz_pl_span()  * Add a interval to a timestamp with time zone data type.  * Note that interval has
provisionsfor qualitative year/month  *    units, so try to do the right thing with them.
 
***************
*** 1371,1377 ****     tspan.month = -span->month;     tspan.time = -span->time; 
!     return DirectFunctionCall2(timestamp_pl_span,                                TimestampGetDatum(timestamp),
                       PointerGetDatum(&tspan)); }
 
--- 1371,1377 ----     tspan.month = -span->month;     tspan.time = -span->time; 
!     return DirectFunctionCall2(timestamptz_pl_span,                                TimestampGetDatum(timestamp),
                         PointerGetDatum(&tspan)); }
 
*** src/include/catalog/pg_proc.h~    Mon Nov  5 14:44:24 2001
--- src/include/catalog/pg_proc.h    Tue Jan  8 17:09:38 2002
***************
*** 1458,1466 ****  DATA(insert OID = 1188 (  timestamptz_mi   PGUID 12 f t t t 2 f 1186 "1184 1184" 100 0 0 100
timestamp_mi- )); DESCR("subtract");
 
! DATA(insert OID = 1189 (  timestamptz_pl_span PGUID 12 f t t t 2 f 1184 "1184 1186" 100 0 0 100  timestamp_pl_span -
));DESCR("plus");
 
! DATA(insert OID = 1190 (  timestamptz_mi_span PGUID 12 f t t t 2 f 1184 "1184 1186" 100 0 0 100  timestamp_mi_span -
));DESCR("minus"); DATA(insert OID = 1191 (  timestamptz        PGUID 12 f t f t 1 f 1184 "25" 100 0 0 100
text_timestamptz- )); DESCR("convert text to timestamp with time zone");
 
--- 1458,1466 ----  DATA(insert OID = 1188 (  timestamptz_mi   PGUID 12 f t t t 2 f 1186 "1184 1184" 100 0 0 100
timestamp_mi- )); DESCR("subtract");
 
! DATA(insert OID = 1189 (  timestamptz_pl_span PGUID 12 f t t t 2 f 1184 "1184 1186" 100 0 0 100  timestamptz_pl_span
-)); DESCR("plus");
 
! DATA(insert OID = 1190 (  timestamptz_mi_span PGUID 12 f t t t 2 f 1184 "1184 1186" 100 0 0 100  timestamptz_mi_span
-)); DESCR("minus"); DATA(insert OID = 1191 (  timestamptz        PGUID 12 f t f t 1 f 1184 "25" 100 0 0 100
text_timestamptz- )); DESCR("convert text to timestamp with time zone");
 


Re: Strange results with date/interval arithmetic

От
Bruce Momjian
Дата:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > I am seeing strange results from date/interval computations involving
> > months.
> 
> Ah, this is what we get for running the regression tests in only one
> time zone :-(

Yes, I realized the problem was that "2001-03-01" for +1 GMT timezone
comes out as "2001-02-28 23:00 GMT", and when you subtract a month from
that, you get "2001-01-28 23:00" and adding the +1 timezone gives you
"2001-01-29" which is not what you expected.

> The problem appears to be cut-and-paste errors in timestamp.c and
> pg_proc.h: various things that should be timestamp are timestamptz
> or vice versa.  See attached proposed patches.

Oh, so that is why the difference between timestamp and timestamptz is
so important.

> long-suffering beta testers, just to adjust two pg_proc entries?
> We may not have much choice.
> 
> Sigh.  RC1 is off again.

Ouch.  :-)  

At least it is before final.  Can we give people on hackers an SQL
script to run in every database to fix this?  That is how we have
handled this in the past.  Perhaps we can update the catversion as part
of the patch too.  (We have never done that before.)

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: Strange results with date/interval arithmetic

От
Tom Lane
Дата:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> At least it is before final.  Can we give people on hackers an SQL
> script to run in every database to fix this?  That is how we have
> handled this in the past.

We have?  I don't really know how one would adjust catversion without
an initdb.  (Bear in mind it's inside a binary, CRC-protected control
file; couldn't be done without a special-purpose C program AFAICS.)

If you wanted to *not* bump the catversion then we could let people run
a script to fix the two pg_proc entries, but I think that way is likely
to do more harm than good in the long run.  Too much chance of someone
carrying the wrong entries into production and not noticing their wrong
answers for a long time.

The ground rules for beta testers have always been "you may have to
initdb before final", and I think that's where we are now, annoying
as it is.

(Too bad we don't have a working pg_upgrade...)
        regards, tom lane


Re: Strange results with date/interval arithmetic

От
Bruce Momjian
Дата:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > At least it is before final.  Can we give people on hackers an SQL
> > script to run in every database to fix this?  That is how we have
> > handled this in the past.
> 
> We have?  I don't really know how one would adjust catversion without
> an initdb.  (Bear in mind it's inside a binary, CRC-protected control
> file; couldn't be done without a special-purpose C program AFAICS.)
>

Yes, that seems like a problem.  Also, will this affect regression tests
for people who don't apply the patch?  That makes it extra important we
make sure the patch is applied which gives more weight to the catversion
bump.

> If you wanted to *not* bump the catversion then we could let people run
> a script to fix the two pg_proc entries, but I think that way is likely
> to do more harm than good in the long run.  Too much chance of someone
> carrying the wrong entries into production and not noticing their wrong
> answers for a long time.

Yes.

> The ground rules for beta testers have always been "you may have to
> initdb before final", and I think that's where we are now, annoying
> as it is.
> 
> (Too bad we don't have a working pg_upgrade...)

I could probably get it working tomorrow if people want it.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026