diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c index 89c2712b4c4..b2422260f61 100644 --- a/src/backend/access/hash/hashfunc.c +++ b/src/backend/access/hash/hashfunc.c @@ -26,7 +26,13 @@ #include "postgres.h" +#ifdef _MSC_VER +#include /* for _isnan */ +#endif +#include + #include "access/hash.h" +#include "utils/builtins.h" /* Note: this is used for both "char" and boolean datatypes */ @@ -94,6 +100,14 @@ hashfloat4(PG_FUNCTION_ARGS) if (key == (float4) 0) PG_RETURN_UINT32(0); + /* + * Similarly, NaNs can have different bit patterns but they should all + * compare as equal. For backwards-compatibility reasons we force them to + * have the hash value of a standard NaN. + */ + if (isnan(key)) + key = get_float4_nan(); + /* * To support cross-type hashing of float8 and float4, we want to return * the same hash value hashfloat8 would produce for an equal float8 value. @@ -119,6 +133,14 @@ hashfloat8(PG_FUNCTION_ARGS) if (key == (float8) 0) PG_RETURN_UINT32(0); + /* + * Similarly, NaNs can have different bit patterns but they should all + * compare as equal. For backwards-compatibility reasons we force them to + * have the hash value of a standard NaN. + */ + if (isnan(key)) + key = get_float8_nan(); + return hash_any((unsigned char *) &key, sizeof(key)); }