Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite482dcb

Browse files
committed
Make selectivity routines cope gracefully with NaNs, infinities, and
NUMERIC values that are out of the range of 'double'. Per troublereport from Mike Quinn.
1 parentd1c6983 commite482dcb

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

‎src/backend/utils/adt/numeric.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
*1998 Jan Wieck
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.44 2001/10/03 05:29:24 thomas Exp $
8+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.45 2001/10/13 23:32:33 tgl Exp $
99
*
1010
* ----------
1111
*/
@@ -1663,6 +1663,35 @@ numeric_float8(PG_FUNCTION_ARGS)
16631663
}
16641664

16651665

1666+
/* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
1667+
Datum
1668+
numeric_float8_no_overflow(PG_FUNCTION_ARGS)
1669+
{
1670+
Numericnum=PG_GETARG_NUMERIC(0);
1671+
char*tmp;
1672+
doubleval;
1673+
char*endptr;
1674+
1675+
if (NUMERIC_IS_NAN(num))
1676+
PG_RETURN_FLOAT8(NAN);
1677+
1678+
tmp=DatumGetCString(DirectFunctionCall1(numeric_out,
1679+
NumericGetDatum(num)));
1680+
1681+
/* unlike float8in, we ignore ERANGE from strtod */
1682+
val=strtod(tmp,&endptr);
1683+
if (*endptr!='\0')
1684+
{
1685+
/* shouldn't happen ... */
1686+
elog(ERROR,"Bad float8 input format '%s'",tmp);
1687+
}
1688+
1689+
pfree(tmp);
1690+
1691+
PG_RETURN_FLOAT8(val);
1692+
}
1693+
1694+
16661695
Datum
16671696
float4_numeric(PG_FUNCTION_ARGS)
16681697
{

‎src/backend/utils/adt/selfuncs.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.98 2001/10/03 18:25:59 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.99 2001/10/13 23:32:33 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -581,7 +581,18 @@ scalarineqsel(Query *root, Oid operator, bool isgt,
581581
elseif (val >=high)
582582
binfrac=1.0;
583583
else
584+
{
584585
binfrac= (val-low) / (high-low);
586+
/*
587+
* Watch out for the possibility that we got a NaN
588+
* or Infinity from the division. This can happen
589+
* despite the previous checks, if for example
590+
* "low" is -Infinity.
591+
*/
592+
if (isnan(binfrac)||
593+
binfrac<0.0||binfrac>1.0)
594+
binfrac=0.5;
595+
}
585596
}
586597
else
587598
{
@@ -1665,8 +1676,8 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
16651676
* subroutines in pg_type.
16661677
*
16671678
* All numeric datatypes are simply converted to their equivalent
1668-
* "double" values.XXX what aboutNUMERIC values that are outside
1669-
*the range of "double"?
1679+
* "double" values.(NUMERIC values that are outside the range of "double"
1680+
*are clamped to +/- HUGE_VAL.)
16701681
*
16711682
* String datatypes are converted by convert_string_to_scalar(),
16721683
* which is explained below. The reason why this routine deals with
@@ -1677,8 +1688,9 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
16771688
*
16781689
* The several datatypes representing absolute times are all converted
16791690
* to Timestamp, which is actually a double, and then we just use that
1680-
* double value. Note this will give bad results for the various "special"
1681-
* values of Timestamp --- what can we do with those?
1691+
* double value. Note this will give correct results even for the "special"
1692+
* values of Timestamp, since those are chosen to compare correctly;
1693+
* see timestamp_cmp.
16821694
*
16831695
* The several datatypes representing relative times (intervals) are all
16841696
* converted to measurements expressed in seconds.
@@ -1793,8 +1805,10 @@ convert_numeric_to_scalar(Datum value, Oid typid)
17931805
caseFLOAT8OID:
17941806
return (double)DatumGetFloat8(value);
17951807
caseNUMERICOID:
1796-
return (double)DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1797-
value));
1808+
/* Note: out-of-range values will be clamped to +-HUGE_VAL */
1809+
return (double)
1810+
DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow,
1811+
value));
17981812
caseOIDOID:
17991813
caseREGPROCOID:
18001814
/* we can treat OIDs as integers... */

‎src/include/utils/builtins.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.167 2001/10/1316:34:08 tgl Exp $
10+
* $Id: builtins.h,v 1.168 2001/10/1323:32:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -553,6 +553,7 @@ extern Datum int2_numeric(PG_FUNCTION_ARGS);
553553
externDatumnumeric_int2(PG_FUNCTION_ARGS);
554554
externDatumfloat8_numeric(PG_FUNCTION_ARGS);
555555
externDatumnumeric_float8(PG_FUNCTION_ARGS);
556+
externDatumnumeric_float8_no_overflow(PG_FUNCTION_ARGS);
556557
externDatumfloat4_numeric(PG_FUNCTION_ARGS);
557558
externDatumnumeric_float4(PG_FUNCTION_ARGS);
558559
externDatumnumeric_accum(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp