mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
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.
This commit is contained in:
parent
e060701f51
commit
f2b6bb42ab
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.89 2003/08/04 02:40:04 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.90 2003/08/08 00:10:31 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1671,12 +1671,13 @@ timetz_larger(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
||||||
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
||||||
|
TimeTzADT *result;
|
||||||
|
|
||||||
if (DatumGetBool(DirectFunctionCall2(timetz_gt,
|
if (timetz_cmp_internal(time1, time2) > 0)
|
||||||
TimeTzADTPGetDatum(time1),
|
result = time1;
|
||||||
TimeTzADTPGetDatum(time2))))
|
else
|
||||||
PG_RETURN_TIMETZADT_P(time1);
|
result = time2;
|
||||||
PG_RETURN_TIMETZADT_P(time2);
|
PG_RETURN_TIMETZADT_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -1684,12 +1685,13 @@ timetz_smaller(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
||||||
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
||||||
|
TimeTzADT *result;
|
||||||
|
|
||||||
if (DatumGetBool(DirectFunctionCall2(timetz_lt,
|
if (timetz_cmp_internal(time1, time2) < 0)
|
||||||
TimeTzADTPGetDatum(time1),
|
result = time1;
|
||||||
TimeTzADTPGetDatum(time2))))
|
else
|
||||||
PG_RETURN_TIMETZADT_P(time1);
|
result = time2;
|
||||||
PG_RETURN_TIMETZADT_P(time2);
|
PG_RETURN_TIMETZADT_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* timetz_pl_interval()
|
/* timetz_pl_interval()
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.90 2003/08/04 02:40:05 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.91 2003/08/08 00:10:31 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,6 +20,10 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
/* for finite() on Solaris */
|
||||||
|
#ifdef HAVE_IEEEFP_H
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "access/hash.h"
|
#include "access/hash.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
@ -1290,6 +1294,9 @@ SetEpochTimestamp(void)
|
|||||||
} /* SetEpochTimestamp() */
|
} /* SetEpochTimestamp() */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* We are currently sharing some code between timestamp and timestamptz.
|
||||||
|
* The comparison functions are among them. - thomas 2001-09-25
|
||||||
|
*
|
||||||
* timestamp_relop - is timestamp1 relop timestamp2
|
* timestamp_relop - is timestamp1 relop timestamp2
|
||||||
*
|
*
|
||||||
* collate invalid timestamp at the end
|
* collate invalid timestamp at the end
|
||||||
@ -1297,7 +1304,37 @@ SetEpochTimestamp(void)
|
|||||||
static int
|
static int
|
||||||
timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
|
timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
|
return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* When using float representation, we have to be wary of NaNs.
|
||||||
|
*
|
||||||
|
* We consider all NANs to be equal and larger than any non-NAN. This
|
||||||
|
* is somewhat arbitrary; the important thing is to have a consistent
|
||||||
|
* sort order.
|
||||||
|
*/
|
||||||
|
if (isnan(dt1))
|
||||||
|
{
|
||||||
|
if (isnan(dt2))
|
||||||
|
return 0; /* NAN = NAN */
|
||||||
|
else
|
||||||
|
return 1; /* NAN > non-NAN */
|
||||||
|
}
|
||||||
|
else if (isnan(dt2))
|
||||||
|
{
|
||||||
|
return -1; /* non-NAN < NAN */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dt1 > dt2)
|
||||||
|
return 1;
|
||||||
|
else if (dt1 < dt2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -1610,9 +1647,6 @@ overlaps_timestamp(PG_FUNCTION_ARGS)
|
|||||||
* "Arithmetic" operators on date/times.
|
* "Arithmetic" operators on date/times.
|
||||||
*---------------------------------------------------------*/
|
*---------------------------------------------------------*/
|
||||||
|
|
||||||
/* We are currently sharing some code between timestamp and timestamptz.
|
|
||||||
* The comparison functions are among them. - thomas 2001-09-25
|
|
||||||
*/
|
|
||||||
Datum
|
Datum
|
||||||
timestamp_smaller(PG_FUNCTION_ARGS)
|
timestamp_smaller(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
@ -1620,8 +1654,11 @@ timestamp_smaller(PG_FUNCTION_ARGS)
|
|||||||
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
|
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
|
||||||
Timestamp result;
|
Timestamp result;
|
||||||
|
|
||||||
result = ((dt2 < dt1) ? dt2 : dt1);
|
/* use timestamp_cmp_internal to be sure this agrees with comparisons */
|
||||||
|
if (timestamp_cmp_internal(dt1, dt2) < 0)
|
||||||
|
result = dt1;
|
||||||
|
else
|
||||||
|
result = dt2;
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1632,8 +1669,10 @@ timestamp_larger(PG_FUNCTION_ARGS)
|
|||||||
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
|
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
|
||||||
Timestamp result;
|
Timestamp result;
|
||||||
|
|
||||||
result = ((dt2 > dt1) ? dt2 : dt1);
|
if (timestamp_cmp_internal(dt1, dt2) > 0)
|
||||||
|
result = dt1;
|
||||||
|
else
|
||||||
|
result = dt2;
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1846,42 +1885,11 @@ interval_smaller(PG_FUNCTION_ARGS)
|
|||||||
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
|
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
|
||||||
Interval *result;
|
Interval *result;
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
/* use interval_cmp_internal to be sure this agrees with comparisons */
|
||||||
int64 span1,
|
if (interval_cmp_internal(interval1, interval2) < 0)
|
||||||
span2;
|
result = interval1;
|
||||||
|
|
||||||
#else
|
|
||||||
double span1,
|
|
||||||
span2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = (Interval *) palloc(sizeof(Interval));
|
|
||||||
|
|
||||||
span1 = interval1->time;
|
|
||||||
span2 = interval2->time;
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
|
||||||
if (interval1->month != 0)
|
|
||||||
span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
|
|
||||||
if (interval2->month != 0)
|
|
||||||
span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
|
|
||||||
#else
|
|
||||||
if (interval1->month != 0)
|
|
||||||
span1 += (interval1->month * (30.0 * 86400));
|
|
||||||
if (interval2->month != 0)
|
|
||||||
span2 += (interval2->month * (30.0 * 86400));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (span2 < span1)
|
|
||||||
{
|
|
||||||
result->time = interval2->time;
|
|
||||||
result->month = interval2->month;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
result = interval2;
|
||||||
result->time = interval1->time;
|
|
||||||
result->month = interval1->month;
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_INTERVAL_P(result);
|
PG_RETURN_INTERVAL_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1892,42 +1900,10 @@ interval_larger(PG_FUNCTION_ARGS)
|
|||||||
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
|
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
|
||||||
Interval *result;
|
Interval *result;
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
if (interval_cmp_internal(interval1, interval2) > 0)
|
||||||
int64 span1,
|
result = interval1;
|
||||||
span2;
|
|
||||||
|
|
||||||
#else
|
|
||||||
double span1,
|
|
||||||
span2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = (Interval *) palloc(sizeof(Interval));
|
|
||||||
|
|
||||||
span1 = interval1->time;
|
|
||||||
span2 = interval2->time;
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
|
||||||
if (interval1->month != 0)
|
|
||||||
span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
|
|
||||||
if (interval2->month != 0)
|
|
||||||
span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
|
|
||||||
#else
|
|
||||||
if (interval1->month != 0)
|
|
||||||
span1 += (interval1->month * (30.0 * 86400));
|
|
||||||
if (interval2->month != 0)
|
|
||||||
span2 += (interval2->month * (30.0 * 86400));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (span2 > span1)
|
|
||||||
{
|
|
||||||
result->time = interval2->time;
|
|
||||||
result->month = interval2->month;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
result = interval2;
|
||||||
result->time = interval1->time;
|
|
||||||
result->month = interval1->month;
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_INTERVAL_P(result);
|
PG_RETURN_INTERVAL_P(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user