Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f2b6bb4

Browse files
committed
Fix floating-point timestamp comparisons to not go nuts if NaN is
encountered; per bug report from Christian van der Leeden 8/7/03. Also, adjust larger/smaller routines (MAX/MIN) to share code with comparisons for timestamp, interval, timetz.
1 parent e060701 commit f2b6bb4

File tree

2 files changed

+67
-89
lines changed

2 files changed

+67
-89
lines changed

src/backend/utils/adt/date.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.89 2003/08/04 02:40:04 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.90 2003/08/08 00:10:31 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1671,25 +1671,27 @@ timetz_larger(PG_FUNCTION_ARGS)
16711671
{
16721672
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
16731673
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
1674+
TimeTzADT *result;
16741675

1675-
if (DatumGetBool(DirectFunctionCall2(timetz_gt,
1676-
TimeTzADTPGetDatum(time1),
1677-
TimeTzADTPGetDatum(time2))))
1678-
PG_RETURN_TIMETZADT_P(time1);
1679-
PG_RETURN_TIMETZADT_P(time2);
1676+
if (timetz_cmp_internal(time1, time2) > 0)
1677+
result = time1;
1678+
else
1679+
result = time2;
1680+
PG_RETURN_TIMETZADT_P(result);
16801681
}
16811682

16821683
Datum
16831684
timetz_smaller(PG_FUNCTION_ARGS)
16841685
{
16851686
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
16861687
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
1688+
TimeTzADT *result;
16871689

1688-
if (DatumGetBool(DirectFunctionCall2(timetz_lt,
1689-
TimeTzADTPGetDatum(time1),
1690-
TimeTzADTPGetDatum(time2))))
1691-
PG_RETURN_TIMETZADT_P(time1);
1692-
PG_RETURN_TIMETZADT_P(time2);
1690+
if (timetz_cmp_internal(time1, time2) < 0)
1691+
result = time1;
1692+
else
1693+
result = time2;
1694+
PG_RETURN_TIMETZADT_P(result);
16931695
}
16941696

16951697
/* timetz_pl_interval()

src/backend/utils/adt/timestamp.c

Lines changed: 54 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.90 2003/08/04 02:40:05 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.91 2003/08/08 00:10:31 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -20,6 +20,10 @@
2020
#include <errno.h>
2121
#include <float.h>
2222
#include <limits.h>
23+
/* for finite() on Solaris */
24+
#ifdef HAVE_IEEEFP_H
25+
#include <ieeefp.h>
26+
#endif
2327

2428
#include "access/hash.h"
2529
#include "access/xact.h"
@@ -1290,14 +1294,47 @@ SetEpochTimestamp(void)
12901294
} /* SetEpochTimestamp() */
12911295

12921296
/*
1297+
* We are currently sharing some code between timestamp and timestamptz.
1298+
* The comparison functions are among them. - thomas 2001-09-25
1299+
*
12931300
* timestamp_relop - is timestamp1 relop timestamp2
12941301
*
12951302
* collate invalid timestamp at the end
12961303
*/
12971304
static int
12981305
timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
12991306
{
1307+
#ifdef HAVE_INT64_TIMESTAMP
13001308
return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
1309+
#else
1310+
/*
1311+
* When using float representation, we have to be wary of NaNs.
1312+
*
1313+
* We consider all NANs to be equal and larger than any non-NAN. This
1314+
* is somewhat arbitrary; the important thing is to have a consistent
1315+
* sort order.
1316+
*/
1317+
if (isnan(dt1))
1318+
{
1319+
if (isnan(dt2))
1320+
return 0; /* NAN = NAN */
1321+
else
1322+
return 1; /* NAN > non-NAN */
1323+
}
1324+
else if (isnan(dt2))
1325+
{
1326+
return -1; /* non-NAN < NAN */
1327+
}
1328+
else
1329+
{
1330+
if (dt1 > dt2)
1331+
return 1;
1332+
else if (dt1 < dt2)
1333+
return -1;
1334+
else
1335+
return 0;
1336+
}
1337+
#endif
13011338
}
13021339

13031340
Datum
@@ -1610,18 +1647,18 @@ overlaps_timestamp(PG_FUNCTION_ARGS)
16101647
* "Arithmetic" operators on date/times.
16111648
*---------------------------------------------------------*/
16121649

1613-
/* We are currently sharing some code between timestamp and timestamptz.
1614-
* The comparison functions are among them. - thomas 2001-09-25
1615-
*/
16161650
Datum
16171651
timestamp_smaller(PG_FUNCTION_ARGS)
16181652
{
16191653
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
16201654
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
16211655
Timestamp result;
16221656

1623-
result = ((dt2 < dt1) ? dt2 : dt1);
1624-
1657+
/* use timestamp_cmp_internal to be sure this agrees with comparisons */
1658+
if (timestamp_cmp_internal(dt1, dt2) < 0)
1659+
result = dt1;
1660+
else
1661+
result = dt2;
16251662
PG_RETURN_TIMESTAMP(result);
16261663
}
16271664

@@ -1632,8 +1669,10 @@ timestamp_larger(PG_FUNCTION_ARGS)
16321669
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
16331670
Timestamp result;
16341671

1635-
result = ((dt2 > dt1) ? dt2 : dt1);
1636-
1672+
if (timestamp_cmp_internal(dt1, dt2) > 0)
1673+
result = dt1;
1674+
else
1675+
result = dt2;
16371676
PG_RETURN_TIMESTAMP(result);
16381677
}
16391678

@@ -1846,42 +1885,11 @@ interval_smaller(PG_FUNCTION_ARGS)
18461885
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
18471886
Interval *result;
18481887

1849-
#ifdef HAVE_INT64_TIMESTAMP
1850-
int64 span1,
1851-
span2;
1852-
1853-
#else
1854-
double span1,
1855-
span2;
1856-
#endif
1857-
1858-
result = (Interval *) palloc(sizeof(Interval));
1859-
1860-
span1 = interval1->time;
1861-
span2 = interval2->time;
1862-
#ifdef HAVE_INT64_TIMESTAMP
1863-
if (interval1->month != 0)
1864-
span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
1865-
if (interval2->month != 0)
1866-
span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
1867-
#else
1868-
if (interval1->month != 0)
1869-
span1 += (interval1->month * (30.0 * 86400));
1870-
if (interval2->month != 0)
1871-
span2 += (interval2->month * (30.0 * 86400));
1872-
#endif
1873-
1874-
if (span2 < span1)
1875-
{
1876-
result->time = interval2->time;
1877-
result->month = interval2->month;
1878-
}
1888+
/* use interval_cmp_internal to be sure this agrees with comparisons */
1889+
if (interval_cmp_internal(interval1, interval2) < 0)
1890+
result = interval1;
18791891
else
1880-
{
1881-
result->time = interval1->time;
1882-
result->month = interval1->month;
1883-
}
1884-
1892+
result = interval2;
18851893
PG_RETURN_INTERVAL_P(result);
18861894
}
18871895

@@ -1892,42 +1900,10 @@ interval_larger(PG_FUNCTION_ARGS)
18921900
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
18931901
Interval *result;
18941902

1895-
#ifdef HAVE_INT64_TIMESTAMP
1896-
int64 span1,
1897-
span2;
1898-
1899-
#else
1900-
double span1,
1901-
span2;
1902-
#endif
1903-
1904-
result = (Interval *) palloc(sizeof(Interval));
1905-
1906-
span1 = interval1->time;
1907-
span2 = interval2->time;
1908-
#ifdef HAVE_INT64_TIMESTAMP
1909-
if (interval1->month != 0)
1910-
span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
1911-
if (interval2->month != 0)
1912-
span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
1913-
#else
1914-
if (interval1->month != 0)
1915-
span1 += (interval1->month * (30.0 * 86400));
1916-
if (interval2->month != 0)
1917-
span2 += (interval2->month * (30.0 * 86400));
1918-
#endif
1919-
1920-
if (span2 > span1)
1921-
{
1922-
result->time = interval2->time;
1923-
result->month = interval2->month;
1924-
}
1903+
if (interval_cmp_internal(interval1, interval2) > 0)
1904+
result = interval1;
19251905
else
1926-
{
1927-
result->time = interval1->time;
1928-
result->month = interval1->month;
1929-
}
1930-
1906+
result = interval2;
19311907
PG_RETURN_INTERVAL_P(result);
19321908
}
19331909

0 commit comments

Comments
 (0)