Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: fix float to integer casting #117798

Merged
merged 1 commit into from Feb 2, 2024
Merged

Conversation

da-ket
Copy link
Contributor

@da-ket da-ket commented Jan 16, 2024

Previously, casting a float value to an integer simply truncates the float. This commit fixes that by rounding the float value to the nearest integer, rounding ties to even, as in postgres.

Epic: None
Fixes: #112515

Release note (bug fix): A bug has been fixed where casts of floats to integers
truncated the value. These casts now round a float to the nearest integer,
rounding ties to even integers.

@da-ket da-ket requested a review from a team as a code owner January 16, 2024 08:39
@da-ket da-ket requested review from DrewKimball and removed request for a team January 16, 2024 08:39
Copy link

blathers-crl bot commented Jan 16, 2024

Thank you for contributing to CockroachDB. Please ensure you have followed the guidelines for creating a PR.

Before a member of our team reviews your PR, I have some potential action items for you:

  • Please ensure your git commit message contains a release note.
  • When CI has completed, please ensure no errors have appeared.

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

@blathers-crl blathers-crl bot added the O-community Originated from the community label Jan 16, 2024
@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Contributor Author

@da-ket da-ket left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! The updated test code all matches with postgres.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @DrewKimball)


pkg/ccl/logictestccl/testdata/logic_test/udf_plpgsql line 2419 at r1 (raw file):

SELECT f();
----
106
postgres=# CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
postgres$#   BEGIN
postgres$#     RETURN 105.67::FLOAT;
postgres$#   END  
postgres$# $$ LANGUAGE PLpgSQL;
CREATE FUNCTION
postgres=# SELECT f();
  f  
-----
 106
(1 row)

pkg/sql/logictest/testdata/logic_test/aggregate line 992 at r1 (raw file):

SELECT round(variance(n), 2), round(variance(n), 2), round(variance(p)) FROM mnop
----
0.08 0.08 9
postgres=# CREATE TABLE mnop (
postgres(#   m INT PRIMARY KEY, 
postgres(#   n FLOAT,
postgres(#   o DECIMAL,
postgres(#   p BIGINT
postgres(# )
postgres-# ;
CREATE TABLE
postgres=# INSERT INTO mnop (m, n) SELECT i, (1e9 + i/100.0)::float FROM 
postgres-#   generate_series(1, 100) AS i(i) ;
INSERT 0 100
postgres=# UPDATE mnop SET o = n::decimal, p = (n * 10)::bigint;
UPDATE 100
postgres=# select round(variance(p)) from mnop;
 round 
-------
     9
(1 row)

pkg/sql/logictest/testdata/logic_test/aggregate line 997 at r1 (raw file):

SELECT round(var_pop(n), 2), round(var_pop(n), 2), round(var_pop(p)) FROM mnop
----
0.08 0.08 9
postgres=# select round(var_pop(p)) FROM mnop;
 round 
-------
     9
(1 row)

pkg/sql/logictest/testdata/logic_test/target_names line 76 at r1 (raw file):

----
a   column1 cos
123 1       1
postgres=# SELECT (SELECT 123 AS a), 
postgres-#        (VALUES (cos(1)::INT)),
postgres-#        (SELECT cos(0)::INT);
  a  | column1 | cos 
-----+---------+-----
 123 |       1 |   1
(1 row)

Copy link
Collaborator

@mgartner mgartner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution! This looks great. I left one comment about the commit message.

Reviewed 7 of 7 files at r1, all commit messages.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @da-ket and @DrewKimball)


-- commits line 9 at r1:
Can you add a release note at the bottom of the commit, like:

Release note (bug fix): A bug has been fix where casts of floats to integers truncated
the value. These casts now round a float to the nearest integer, rounding ties to even
integers.

Copy link

blathers-crl bot commented Jan 16, 2024

Thank you for updating your pull request.

My owl senses detect your PR is good for review. Please keep an eye out for any test failures in CI.

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

Copy link
Contributor Author

@da-ket da-ket left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review! I followed your guidance on writing the release notes.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @DrewKimball and @mgartner)


-- commits line 9 at r1:

Previously, mgartner (Marcus Gartner) wrote…

Can you add a release note at the bottom of the commit, like:

Release note (bug fix): A bug has been fix where casts of floats to integers truncated
the value. These casts now round a float to the nearest integer, rounding ties to even
integers.

Done.

Copy link
Contributor Author

@da-ket da-ket left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mgartner , just a gentle reminder about the pending review of this pull request.
Your feedback would be greatly appreciated!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @DrewKimball and @mgartner)

@@ -271,7 +271,7 @@ func floatToInt(intWidth, floatWidth int32) castFunc {
if math.IsNaN(float64(%[2]s)) || %[2]s <= float%[4]d(math.MinInt%[3]d) || %[2]s >= float%[4]d(math.MaxInt%[3]d) {
colexecerror.ExpectedError(tree.ErrIntOutOfRange)
}
%[1]s = int%[3]d(%[2]s)
%[1]s = int%[3]d(math.RoundToEven(%[2]s))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why RoundToEven? Does postgres do that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I was reading the postgres docs for the ROUND function. I couldn't find specific documentation on casting.

Copy link
Contributor Author

@da-ket da-ket left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @DrewKimball, @mgartner, and @RaduBerinde)


pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go line 274 at r2 (raw file):

Previously, RaduBerinde wrote…

Ah, I was reading the postgres docs for the ROUND function. I couldn't find specific documentation on casting.

Yes, I used RoundToEven since postgres does do that when casting floats to integers. It isn't clearly mentioned in the documentation, but it can be found in their code for built-in functions for float type. PostgreSQL follows the round to nearest, ties to even rule for both rounding of float types and their casting to integers. CRDB was follows the same tie-breaking rule for rounding, but it just truncates when casting. I thought the issue #112515 wants to align this difference to be consistent.

@RaduBerinde
Copy link
Member

pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go line 274 at r2 (raw file):

Previously, da-ket (daket) wrote…

Yes, I used RoundToEven since postgres does do that when casting floats to integers. It isn't clearly mentioned in the documentation, but it can be found in their code for built-in functions for float type. PostgreSQL follows the round to nearest, ties to even rule for both rounding of float types and their casting to integers. CRDB was follows the same tie-breaking rule for rounding, but it just truncates when casting. I thought the issue #112515 wants to align this difference to be consistent.

Makes sense, thank you!

Previously, casting a float value to an integer simply truncates the float.
This commit fixes that by rounding the float value to the nearest integer,
rounding ties to even, as in postgres.

Epic: None
Fixes: cockroachdb#112515

Release note (bug fix): A bug has been fixed where casts of floats to integers
truncated the value. These casts now round a float to the nearest integer,
rounding ties to even integers.
Copy link
Collaborator

@mgartner mgartner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Thanks again from contributing! I added a regression test for the change in the vectorized engine cast_gen_util.go. I'll go ahead and merge this once all the tests pass.

:lgtm:

Reviewed 1 of 1 files at r3, all commit messages.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @da-ket and @DrewKimball)

@mgartner
Copy link
Collaborator

mgartner commented Feb 2, 2024

bors r+

@craig
Copy link
Contributor

craig bot commented Feb 2, 2024

Build succeeded:

@craig craig bot merged commit 9434801 into cockroachdb:master Feb 2, 2024
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-community Originated from the community
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sql: float cast to integer is incorrect
4 participants