-
-
Notifications
You must be signed in to change notification settings - Fork 2k
MDEV-38670 Unary minus on empty string returns -0 #4632
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1998,3 +1998,10 @@ select cast(1 as unsigned) - cast(2 as unsigned); | |
| set sql_mode=default; | ||
|
|
||
| --echo # End of 10.5 tests | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is customary to end a test file with a version test end echo command. Please add one for the target version: 13 in your case I believe, unless the final reviewer requests otherwise. |
||
|
|
||
| --echo # | ||
| --echo # MDEV-38670 Unary minus on empty string should return 0 | ||
| --echo # | ||
| SELECT @x := -''; | ||
| SELECT @y := 0 - ''; | ||
| SELECT -0.0, -'0', -' ', -@x, --@x; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, these are not floating point literals. The tests with these are irrelevant. On how to specify constants in MariaDB, see: Please add relevant tests that cover all of your changes and nothing but. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1825,7 +1825,11 @@ double Item_func_neg::real_op() | |
| { | ||
| double value= args[0]->val_real(); | ||
| null_value= args[0]->null_value; | ||
| return -value; | ||
| double res= -value; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a very good start. But it's definitely not all there is to it. The problem is more wide-spread. It's everywhere a FP literal is used. I believe this is happening because MySQL does IEEE 754 arithmetic. And doesn't account for "the signed zero" (https://en.wikipedia.org/wiki/Signed_zero) phenomenon while doing it. As a result many operations done on the real and double data types internally can result in a signed zero. The question now is where do you want to stop with the signed zero. Approach 1: You could just acknowledge its presence in the docs. I.e. fully accept it. Approach 2: dispose of it in the producer. Audit all implementations of real_op() in Item subclasses and call a utility function for their return value to turn the signed zero into an unsigned zero when detected. Approach 3: dispose of it in the consumers. Every place where real_op() is called call a utility function to turn the signed zero into an unsigned zero when detected. Which one to take is a question for the final review of course. |
||
| // Normalize -0.0 to +0.0 to match binary subtraction behavior | ||
| if (res == 0.0) | ||
| res= 0.0; | ||
|
Comment on lines
+1830
to
+1831
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To a human, this looks like something a compiler might consider no-op.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. … but, checking on https://godbolt.org/, it’s not the case for either GCC
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really don't know why it works, but when I remove the condition, it prints -0 when run ( select -''; ), which is the issue |
||
| return res; | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -1858,6 +1862,9 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) | |
| { | ||
| my_decimal2decimal(value.ptr(), decimal_value); | ||
| my_decimal_neg(decimal_value); | ||
| // Normalize -0 to +0 in decimal representation | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need this? Do you actually have a test that hits this? I would be extremely surprised if you do. |
||
| if (my_decimal_is_zero(decimal_value)) | ||
| decimal_value->sign(false); | ||
| return decimal_value; | ||
| } | ||
| return 0; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func_math is failing on most of the build-bot platforms. Please fix this.