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

server: Make float rounding compatible with mysql for types: float, float(m,n) and double(m,n) #22823

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

johan-j
Copy link
Contributor

@johan-j johan-j commented Feb 19, 2021

What problem does this PR solve?

Issue Number: close #22791

Problem Summary:

  • Tidb type float, have to much precision compared to mysql
  • Tidb not printing decimals for custom sized float and double types.

What is changed and how it works?

What's Changed:
This resolve issue #22791: query result for float type is incompatible with previous version

When #21692 was resolved, it created a new problem reported in #22823 (float/double not displaying decimals)
This resolves issues: #22791, #21692, and a new issue with float I found while working on this (mentioned in comment on issue #22791)

Default width float issue:

create table t(a float);
insert into t(a) values( -34028236.66);
select a from t;

mysql8
+-----------+
| a         |
+-----------+
| -34028200 |
+-----------+

tidb:
+-----------+
| a         |
+-----------+
| -34028236 |
+-----------+

For this case there was actually even a test case. But the test case expected -34028236 as result, which ment it passed even though the value is to precis for mysql.

Previously we relied on go's built in strconv.AppendFloat to both round and format. However after much effort I came up with the solution to treat rounding and formatting separately.
Instead now it works in 2 steps:

  1. Call new rounding function that returns in mysql precision (if needed)
  2. Use strconv.AppendFloat to format output with correct number of decimals.

This also means that the documentation at: https://docs.pingcap.com/tidb/stable/mysql-compatibility#incompatibility-caused-by-deprecated-features
could mention that deprecated types are now compatible with mysql, even if its encouraged to migrate to Decimal. Many big companies still run older versions like 5.7 of mysql and have no plans to migrate. So keeping it compatible might still be important to get some companies to use TiDB.

The new output formatter supports the below scenarios (which is also the doc/comment in the code):

/*
	Formats a float value into a string (byte slice) and returns.

	The rounding/formatting is split into the following cases:
	1. Scientific notation (1.23.e4): Used for big numbers except when value comes from a custom width column or from the select part of the query
	1. mysql.TypeDouble: return string with as much precision as needed (precision = -1)
	2. mysql.TypeFloat: return a rounded value that corresponds to mysql's (precision = 5)
	3. mysql.TypeDouble(m,n):
		3.1 If the columnLength < defaultMySQLPrec64, return string with as much precision as needed (precision = n)
		3.2 else: return rounded string to precision defaultMySQLPrec64, and padded with 0's.
	4. mysql.TypeFloat(m,n): return a rounded value rounded with (precision = 5) and formatted with (precision = n)

	Note: 	Custom float/double column width is deprecated in mysql 8.0.14.
			However for compatibility, we still try to make the output the same as mysql for these types.
*/

Check List

Tests

  • Unit test

Release note

  • Resolve issue where float type was not returned in the same way as mysql8.0.
  • Resolve issue where custom length double/float was returned in incorrect format.

@ti-srebot ti-srebot added the first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. label Feb 19, 2021
@johan-j johan-j marked this pull request as draft February 19, 2021 10:37
@github-actions github-actions bot added the sig/sql-infra SIG: SQL Infra label Feb 19, 2021
@johan-j johan-j changed the title executioner: print decimals for float type server: always print decimals for float type Feb 19, 2021
@johan-j johan-j force-pushed the issue22791 branch 2 times, most recently from 884eb04 to 28502e6 Compare February 19, 2021 11:01
@ichn-hu ichn-hu mentioned this pull request Feb 20, 2021
@johan-j
Copy link
Contributor Author

johan-j commented Feb 22, 2021

Closing this PR this since mysql 8.0.14 have deprecated double(m,n) and float(m,n).

@johan-j johan-j closed this Feb 22, 2021
@johan-j johan-j reopened this Feb 25, 2021
@ti-chi-bot ti-chi-bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Feb 25, 2021
@johan-j johan-j force-pushed the issue22791 branch 3 times, most recently from 4345b5d to 1db348e Compare February 25, 2021 22:46
@ti-chi-bot ti-chi-bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Feb 26, 2021
@johan-j
Copy link
Contributor Author

johan-j commented Feb 26, 2021

I re-open this PR again since I found there are still float formatting issues even for the float type with default column width.

@johan-j johan-j force-pushed the issue22791 branch 2 times, most recently from ac416ed to d834d31 Compare February 26, 2021 16:57
@ti-chi-bot ti-chi-bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Feb 26, 2021
@johan-j johan-j force-pushed the issue22791 branch 3 times, most recently from c0ee5b2 to 20d9ff6 Compare February 26, 2021 18:32
@ti-chi-bot ti-chi-bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Feb 26, 2021
@ti-chi-bot ti-chi-bot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Feb 26, 2021
@johan-j johan-j force-pushed the issue22791 branch 2 times, most recently from 3a21b68 to 5db5666 Compare February 27, 2021 22:34
This resolve issue pingcap#22791: query result for float type is incompatible with previous version

It seems like this broke in the fix for issue pingcap#21692. In mysql, e-format
is only returned when used in the query, for example:
select 1e15, will print 1e15 back.
However, when stored in a table mysel will print it in decimal form.
issue pingcap#21692 resolved this by checking for empty table. However, that
fix applies for everything rather than only for e-format. And that
caused the new issue pingcap#22791.

This resolves both pingcap#22791 and pingcap#21692.

It also resolve an issue where for a default width float column we do
not round to the mysql default precision.
@johan-j johan-j changed the title server: always print decimals for float type server: Make float rounding compatible with mysql for types: float, float(m,n) and double(m,n) Feb 28, 2021
"0.111",
3,
64,
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I deleted this test because for a column of 3 decimals, the input is already rounded when we store it. So the result is correct in an integration test.
However the result from the function test will not be correct. Let me know if you want me to implement this in the output formatter too, even though its truncated on input.

@johan-j johan-j marked this pull request as ready for review February 28, 2021 09:45
@ti-chi-bot ti-chi-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 28, 2021
@tangenta tangenta requested a review from AilinKid March 1, 2021 15:23
server/util.go Outdated Show resolved Hide resolved
Co-authored-by: djshow832 <zhangming@pingcap.com>
@johan-j
Copy link
Contributor Author

johan-j commented Mar 10, 2021

Hi @djshow832 , thank you for your comment. Do you or @AilinKid (who is also assinged to this PR) have anymore feedback on this MR? Thanks in advance to have a look!

@johan-j
Copy link
Contributor Author

johan-j commented Apr 12, 2021

seems like you guys has no interest to resolve these bugs, so closing this PR instead.

@johan-j johan-j closed this Apr 12, 2021
@AilinKid
Copy link
Contributor

AilinKid commented May 24, 2021

I'm so sorry for the late response to your PR cause my notification mechanism is broken recently. Even for now, the float problem is still one of the big compatibility problems on our list.
You can refer to some details from: #11328

I'm not sure whether your pull request can solve this problem, so let's review it first, and if you are interested you can add a more detailed design about your work.

More again, thanks for your contribution. @johan-j

@AilinKid AilinKid reopened this May 24, 2021
@johan-j
Copy link
Contributor Author

johan-j commented May 24, 2021

thank you @AilinKid for showing interest in this pull request. I hope it can resolve the compatibility issues. I put quite some effort into making this PR.

"and if you are interested you can add a more detailed design about your work."
Any suggestion what information is missing? I thought the comment on how the formatter works is already quite detailed. Im happy to clarify where needed! but some specific questions I can answer to make it more clear?

@AilinKid AilinKid added the compatibility-breaker Violation of forwards/backwards compatibility in a design-time piece. label Jul 22, 2021
5. mysql.TypeFloat(m,n): return a rounded value rounded with (precision = 5) and formatted with (precision = n)

Note: Custom float/double column width is deprecated in mysql 8.0.14.
However for compatibility, we still try to make the output the same as mysql for these types.
Copy link
Contributor

@AilinKid AilinKid Jul 22, 2021

Choose a reason for hiding this comment

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

better add a mysql referrence link here, and could you descript the imcompatiable behavior with mysql here a little bit?

func appendFormatFloat(in []byte, fVal float64, bitSize int, colDecimal uint8, colLength uint32, isFromSelect bool) []byte {
isCustomColumnWidth := false
prec := types.UnspecifiedLength
if colDecimal > 0 && colDecimal != mysql.NotFixedDec {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if colDecimal > 0 && colDecimal != mysql.NotFixedDec {
if colDecimal > 0 && int(colDecimal) != mysql.NotFixedDec {

case isEFormat:
return formatFloatScientificNotation(in, fVal, prec, bitSize)
case bitSize == 32 && isCustomColumnWidth:
return strconv.AppendFloat(in, fVal, 'f', prec, bitSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

it's same as the default logic

Copy link
Contributor

@AilinKid AilinKid left a comment

Choose a reason for hiding this comment

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

Rest LGTM, thx for your detailed work.

@ti-chi-bot ti-chi-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 13, 2021
@ti-chi-bot
Copy link
Member

@johan-j: PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility-breaker Violation of forwards/backwards compatibility in a design-time piece. first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. sig/sql-infra SIG: SQL Infra size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

query result for float type is incompatible with previous version
5 participants