• Tom Lane's avatar
    Fix float4/float8 hash functions to produce uniform results for NaNs. · 23c6bc58
    Tom Lane authored
    The IEEE 754 standard allows a wide variety of bit patterns for NaNs,
    of which at least two ("NaN" and "-NaN") are pretty easy to produce
    from SQL on most machines.  This is problematic because our btree
    comparison functions deem all NaNs to be equal, but our float hash
    functions know nothing about NaNs and will happily produce varying
    hash codes for them.  That causes unexpected results from queries
    that hash a column containing different NaN values.  It could also
    produce unexpected lookup failures when using a hash index on a
    float column, i.e. "WHERE x = 'NaN'" will not find all the rows
    it should.
    
    To fix, special-case NaN in the float hash functions, not too much
    unlike the existing special case that forces zero and minus zero
    to hash the same.  I arranged for the most vanilla sort of NaN
    (that coming from the C99 NAN constant) to still have the same
    hash code as before, to reduce the risk to existing hash indexes.
    
    I dithered about whether to back-patch this into stable branches,
    but ultimately decided to do so.  It's a clear improvement for
    queries that hash internally.  If there is anybody who has -NaN
    in a hash index, they'd be well advised to re-index after applying
    this patch ... but the misbehavior if they don't will not be much
    worse than the misbehavior they had before.
    
    Per bug #17172 from Ma Liangzhu.
    
    Discussion: https://postgr.es/m/17172-7505bea9e04e230f@postgresql.org
    23c6bc58
hash_func.sql 13.2 KB