diff --git a/pkg/util/codec/codec_test.go b/pkg/util/codec/codec_test.go index 6abc1c382c16f..1e0222233605e 100644 --- a/pkg/util/codec/codec_test.go +++ b/pkg/util/codec/codec_test.go @@ -1333,3 +1333,22 @@ func TestDatumHashEquals(t *testing.T) { require.NotEqual(t, hasher1.Sum64(), hasher2.Sum64()) require.False(t, tests[len(tests)-1].d1.Equals(tests[len(tests)-1].d2)) } + +func TestEncodeFloatForNegativeZero(t *testing.T) { + floatNum := 0.0 + floatNum = -floatNum + + b := EncodeFloat(nil, floatNum) + _, v, err := DecodeFloat(b) + require.NoError(t, err) + require.Equal(t, floatNum, v) + require.Equal(t, math.Signbit(floatNum), math.Signbit(v)) + require.Equal(t, math.Atan2(0, v), math.Pi) + + b = EncodeFloatDesc(nil, floatNum) + _, v, err = DecodeFloatDesc(b) + require.NoError(t, err) + require.Equal(t, floatNum, v) + require.Equal(t, math.Signbit(floatNum), math.Signbit(v)) + require.Equal(t, math.Atan2(0, v), math.Pi) +} diff --git a/pkg/util/codec/float.go b/pkg/util/codec/float.go index df8d697463cbe..9301db3e93ca0 100644 --- a/pkg/util/codec/float.go +++ b/pkg/util/codec/float.go @@ -22,9 +22,17 @@ import ( func encodeFloatToCmpUint64(f float64) uint64 { u := math.Float64bits(f) - if f >= 0 { + // Check the sign bit (the highest bit in the IEEE 754 representation). + // If the sign bit is 0, the number is non-negative (+0 is considered non-negative). + if u&signMask == 0 { + // For non-negative numbers (+0 included), set the sign bit to 1. + // This ensures non-negative numbers are ordered after negative numbers + // when compared as unsigned integers. u |= signMask } else { + // For negative numbers (-0 included), invert all bits. + // This reorders negative numbers so that the smallest (closest to 0) + // has the smallest encoded value, and the most negative has the largest. u = ^u } return u diff --git a/tests/integrationtest/r/expression/issues.result b/tests/integrationtest/r/expression/issues.result index 40c90698a0d3b..127b1bd2180ed 100644 --- a/tests/integrationtest/r/expression/issues.result +++ b/tests/integrationtest/r/expression/issues.result @@ -3230,3 +3230,9 @@ INSERT INTO test.t VALUES (1234567890123456); SELECT IFNULL(id, 'abcdef') FROM test.t; IFNULL(id, 'abcdef') 1234567890123456 +DROP TABLE IF EXISTS test.t; +CREATE TABLE test.t (c0 decimal(10,0)); +INSERT INTO test.t VALUES (0); +SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME); +c0 +0 diff --git a/tests/integrationtest/t/expression/issues.test b/tests/integrationtest/t/expression/issues.test index 1b73368e5da79..a8e11fc25a5d4 100644 --- a/tests/integrationtest/t/expression/issues.test +++ b/tests/integrationtest/t/expression/issues.test @@ -2182,3 +2182,9 @@ DROP TABLE IF EXISTS test.t; CREATE TABLE test.t (id bigint(11) UNSIGNED PRIMARY KEY); INSERT INTO test.t VALUES (1234567890123456); SELECT IFNULL(id, 'abcdef') FROM test.t; + +# TestIssue41878 +DROP TABLE IF EXISTS test.t; +CREATE TABLE test.t (c0 decimal(10,0)); +INSERT INTO test.t VALUES (0); +SELECT c0 FROM test.t WHERE CAST(ATAN2(((t.c0) IS NULL), (- (''))) AS TIME); \ No newline at end of file