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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions pkg/ccl/logictestccl/testdata/logic_test/udf_plpgsql
Original file line number Diff line number Diff line change
Expand Up @@ -2405,7 +2405,6 @@ subtest plpgsql_types
# If an assignment cast is available, the cast is performed automatically.
#
# float -> int
# TODO(112515): the float value is incorrectly truncated instead of rounded.
statement ok
DROP FUNCTION F();
CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
Expand All @@ -2417,7 +2416,7 @@ $$ LANGUAGE PLpgSQL;
query I
SELECT f();
----
105
106

# decimal -> int
statement ok
Expand Down
24 changes: 12 additions & 12 deletions pkg/sql/colexec/colexecbase/cast.eg.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.

`
if intWidth == anyWidth {
intWidth = 64
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/aggregate
Original file line number Diff line number Diff line change
Expand Up @@ -989,12 +989,12 @@ UPDATE mnop SET o = n::decimal, p = (n * 10)::bigint
query RRR
SELECT round(variance(n), 2), round(variance(n), 2), round(variance(p)) FROM mnop
----
0.08 0.08 8
0.08 0.08 9

query RRR
SELECT round(var_pop(n), 2), round(var_pop(n), 2), round(var_pop(p)) FROM mnop
----
0.08 0.08 8
0.08 0.08 9

query RRR
SELECT round(stddev_samp(n), 2), round(stddev(n), 2), round(stddev_samp(p)) FROM mnop
Expand Down
15 changes: 15 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/cast
Original file line number Diff line number Diff line change
Expand Up @@ -1533,3 +1533,18 @@ array_agg
array_agg
array_agg
array_agg

subtest regression_112515

statement ok
CREATE TABLE t112515 (f FLOAT);
INSERT INTO t112515 VALUES (-1.5), (-0.5), (0.5), (1.5), (2.5);

query I rowsort
SELECT f::INT FROM t112515
----
-2
0
0
2
2
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/target_names
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ SELECT (SELECT 123 AS a),
(SELECT cos(0)::INT)
----
a column1 cos
123 0 1
123 1 1
2 changes: 1 addition & 1 deletion pkg/sql/sem/eval/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func performCastWithoutPrecisionTruncation(
if math.IsNaN(f) || f <= float64(math.MinInt64) || f >= float64(math.MaxInt64) {
return nil, tree.ErrIntOutOfRange
}
res = tree.NewDInt(tree.DInt(f))
res = tree.NewDInt(tree.DInt(math.RoundToEven(f)))
case *tree.DDecimal:
i, err := roundDecimalToInt(&v.Decimal)
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions pkg/sql/sem/eval/testdata/eval/cast
Original file line number Diff line number Diff line change
Expand Up @@ -1460,3 +1460,25 @@ eval
text(1.11::float8)
----
'1.11'

# Issue #112515: float casting returns the nearest integer,
# rounding ties to even (Banker's rounding).
eval
int8(0.5::float8)
----
0

eval
int8(1.5::float8)
----
2

eval
int8(-0.5::float8)
----
0

eval
int8(-1.5::float8)
----
-2