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

expression: fix cast string like '.1a1' to decimal has no warnings information #26005

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

yuqi1129
Copy link
Contributor

@yuqi1129 yuqi1129 commented Jul 6, 2021

What problem does this PR solve?

Issue Number: close #26004

Problem Summary:

also fix problem like

select cast('1.4a' as decimal); 

mysql> show warnings;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: '1.4' |
+---------+------+------------------------------------------+
1 row in set (0.02 sec)

warning information is 1.4 not 1.4a

mysql> select cast('' as decimal);
+---------------------+
| cast('' as decimal) |
+---------------------+
|                   0 |
+---------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+------------+
| Level   | Code | Message    |
+---------+------+------------+
| Warning | 8029 | Bad Number |
+---------+------+------------+
1 row in set (0.00 sec)

warning info is inconsistent with MySQL

mysql> select cast('1e - 1' as decimal)
    -> ;
+---------------------------+
| cast('1e - 1' as decimal) |
+---------------------------+
|                         1 |
+---------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column '%s' at row %d |
+---------+------+------------------------------------------+
1 row in set (0.00 sec)

Warning info is somewhat Semi-finished products

mysql> select cast('1 1' as decimal);
+------------------------+
| cast('1 1' as decimal) |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)

The above SQL should have warning information

What is changed and how it works?

Proposal: xxx

What's Changed:

How it Works:

Related changes

  • PR to update pingcap/docs/pingcap/docs-cn:
  • Need to cherry-pick to the release branch

Check List

Tests

  • Integration test

Side effects

  • Performance regression
    • Consumes more CPU
    • Consumes more MEM
  • Breaking backward compatibility

Release note

  • No release note.

@ti-chi-bot
Copy link
Member

[REVIEW NOTIFICATION]

This pull request has not been approved.

To complete the pull request process, please ask the reviewers in the list to review by filling /cc @reviewer in the comment.
After your PR has acquired the required number of LGTMs, you can assign this pull request to the committer in the list by filling /assign @committer in the comment to help you merge this pull request.

The full list of commands accepted by this bot can be found here.

Reviewer can indicate their review by submitting an approval review.
Reviewer can cancel approval by submitting a request changes review.

@ti-chi-bot ti-chi-bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jul 6, 2021
@ti-chi-bot ti-chi-bot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jul 6, 2021
@ichn-hu ichn-hu mentioned this pull request Jul 7, 2021
@yuqi1129 yuqi1129 marked this pull request as draft July 7, 2021 06:09
@ti-chi-bot ti-chi-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 7, 2021
@ti-chi-bot ti-chi-bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Jul 7, 2021
@yuqi1129 yuqi1129 marked this pull request as ready for review July 7, 2021 12: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 Jul 7, 2021
@ti-chi-bot ti-chi-bot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 9, 2021
@ti-chi-bot ti-chi-bot removed the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jul 9, 2021
@github-actions github-actions bot added the sig/sql-infra SIG: SQL Infra label Jul 9, 2021
@yuqi1129
Copy link
Contributor Author

/cc @wshwsh12 @lzmhhh123

@ti-chi-bot ti-chi-bot requested review from lzmhhh123 and wshwsh12 July 10, 2021 08:52
Copy link
Contributor

@tisonkun tisonkun left a comment

Choose a reason for hiding this comment

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

I agree on the original motivation to be compatible with MySQL. But the change set seems affect more than one behavior.

Would you mind to list the compatibility we'd like to keep preciously in the issue first? You can prepare your PR locally but we may figure out the problem first instead of rush into the code.

@@ -552,13 +552,14 @@ func (s *testColumnTypeChangeSuite) TestColumnTypeChangeFromStringToOthers(c *C)
tk.MustExec("insert into t values ('123.45', '123.45', '123.45', '123.45', '123.45', '123.45', '123', '123')")
tk.MustExec("alter table t modify c decimal(7, 4)")
tk.MustExec("alter table t modify vc decimal(7, 4)")
tk.MustExec("alter table t modify bny decimal(7, 4)")
// alter binary 0x3132332E34350000 to decimal(7,4) will get error
tk.MustGetErrCode("alter table t modify bny decimal(7, 4)", mysql.ErrTruncatedWrongValue)
Copy link
Contributor

Choose a reason for hiding this comment

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

We change existing test case here. Does it mean this PR changes TiDB behavior explicitly (more than a warning)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, In MySQL, this case will directly return error

tk.MustExec("alter table t modify vbny decimal(7, 4)")
tk.MustExec("alter table t modify bb decimal(7, 4)")
tk.MustExec("alter table t modify txt decimal(7, 4)")
tk.MustExec("alter table t modify e decimal(7, 4)")
tk.MustExec("alter table t modify s decimal(7, 4)")
tk.MustQuery("select * from t").Check(testkit.Rows("123.4500 123.4500 123.4500 123.4500 123.4500 123.4500 1.0000 1.0000"))
tk.MustQuery("select * from t").Check(testkit.Rows("123.4500 123.4500 123.45\x00\x00 123.4500 123.4500 123.4500 1.0000 1.0000"))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto, it seems result changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

see the reason above

@@ -836,7 +836,7 @@ func (b *builtinCastRealAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, result
if types.ErrOverflow.Equal(err) {
warnErr := types.ErrTruncatedWrongVal.GenWithStackByArgs("DECIMAL", b.args[0])
err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, warnErr)
} else if types.ErrTruncated.Equal(err) {
} else if strings.Contains(err.Error(), "Truncated incorrect") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we do string matching for identifying an error? It is quite brittle.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, sorry, i can't find more elegant methods to handle this, please do me a favor about this point

Copy link
Contributor

@wshwsh12 wshwsh12 Jul 19, 2021

Choose a reason for hiding this comment

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

  1. Can we use types.ErrTruncatedWrongVal.Equal(err)?
  2. Non-vec implement also need modify.
  3. Are you sure we need modify CastRealAsDecimal, instead of CastStringAsDecimal?
  4. Is there any related test? I didn't find the test cover the case.. Or maybe I ignore the test?
  5. May also need to modify the implementation in tikv....

@@ -244,10 +244,11 @@ func (s *testTypeConvertSuite) TestConvertType(c *C) {
c.Assert(terror.ErrorEqual(err, ErrOverflow), IsTrue, Commentf("err %v", err))
c.Assert(v.(*MyDecimal).String(), Equals, "-9999.9999")
v, err = Convert("1,999.00", ft)
c.Assert(terror.ErrorEqual(err, ErrBadNumber), IsTrue, Commentf("err %v", err))
c.Assert(terror.ErrorEqual(err,
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto behavior changes

c.Assert(v.(*MyDecimal).String(), Equals, "1.0000")
v, err = Convert("1,999,999.00", ft)
c.Assert(terror.ErrorEqual(err, ErrBadNumber), IsTrue, Commentf("err %v", err))
c.Assert(terror.ErrorEqual(err, ErrTruncatedWrongVal.GenWithStackByArgs("DECIMAL", "1,999,999.00")), IsTrue, Commentf("err %v", err))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto behavior changes

if len(str) == 0 {
*d = zeroMyDecimal
return ErrBadNumber
return ErrTruncatedWrongVal.GenWithStackByArgs("DECIMAL", string(strBak))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto behavior changes

@@ -549,6 +576,7 @@ func (d *MyDecimal) FromString(str []byte) error {
if strErr != nil {
return strErr
}

Copy link
Contributor

Choose a reason for hiding this comment

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

please avoid unnecessary diff.

@@ -46,7 +46,8 @@ func init() {
ast.NewDecimal = func(str string) (interface{}, error) {
dec := new(types.MyDecimal)
err := dec.FromString(hack.Slice(str))
if err == types.ErrTruncated {
if err == types.ErrTruncated || (err != nil &&
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto brittle string matching.

@tisonkun
Copy link
Contributor

tisonkun commented Jul 10, 2021

Well I see the information in PR description. However, issue keeps the analyze and PR focuses on the implementation. Please update the information in issue and it'd be better to label with number so that we know how much cases we'd like to cover.

Besides, I don't find a case matches the result of ALTER statement changes in the description.

@yuqi1129
Copy link
Contributor Author

yuqi1129 commented Jul 10, 2021

Well I see the information in PR description. However, issue keeps the analyze and PR focuses on the implementation. Please update the information in issue and it'd be better to label with number so that we know how much cases we'd like to cover.

OK, i will make more description about this problem in the issue page

Besides, I don't find a case matches the result of ALTER statement changes in the description.

In Order to fix the problem , i change the stringToDecimal logic, which however affect the ALTER statements, for example
cast binary type to decimal will use stringToDecimal methods.

@tisonkun tisonkun self-requested a review July 10, 2021 09:45
@tisonkun
Copy link
Contributor

@yuqi1129 Thanks for your update. I'll schedule another review tomorrow.

@tisonkun tisonkun removed their request for review July 11, 2021 09:14
@tisonkun
Copy link
Contributor

tisonkun commented Jul 11, 2021

@yuqi1129 I verify locally with MySQL 8.0.23 and behavior changes. I'd prefer discuss the expected behavior on the issue first.

Copy link
Contributor

@tisonkun tisonkun left a comment

Choose a reason for hiding this comment

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

I'm hesitated to approve this PR without enough background knowledge. Shall the other reviewers give significant suggestion.

@tisonkun
Copy link
Contributor

ping @lzmhhh123 @wshwsh12

/cc @tangenta

@ti-chi-bot ti-chi-bot requested a review from tangenta July 12, 2021 12:26
Copy link
Contributor

@wshwsh12 wshwsh12 left a comment

Choose a reason for hiding this comment

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

Looks like the behavior is even stranger now.... Now this sql will return two warning messages.

[tidb]> select cast('1.4a' as decimal); 
+-------------------------+
| cast('1.4a' as decimal) |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set, 2 warnings (0.001 sec)

[tidb]> show warnings;
+---------+------+-------------------------------------------+
| Level   | Code | Message                                   |
+---------+------+-------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: '1.4a' |
| Warning | 1292 | Truncated incorrect DECIMAL value: '1.4'  |
+---------+------+-------------------------------------------+
2 rows in set (0.000 sec)

In my opinion, we should not focus on fixing the inconsistency between these warning information and mysql at this stage, but other more serious problems (eg, returning wrong data).

@@ -836,7 +836,7 @@ func (b *builtinCastRealAsDecimalSig) vecEvalDecimal(input *chunk.Chunk, result
if types.ErrOverflow.Equal(err) {
warnErr := types.ErrTruncatedWrongVal.GenWithStackByArgs("DECIMAL", b.args[0])
err = b.ctx.GetSessionVars().StmtCtx.HandleOverflow(err, warnErr)
} else if types.ErrTruncated.Equal(err) {
} else if strings.Contains(err.Error(), "Truncated incorrect") {
Copy link
Contributor

@wshwsh12 wshwsh12 Jul 19, 2021

Choose a reason for hiding this comment

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

  1. Can we use types.ErrTruncatedWrongVal.Equal(err)?
  2. Non-vec implement also need modify.
  3. Are you sure we need modify CastRealAsDecimal, instead of CastStringAsDecimal?
  4. Is there any related test? I didn't find the test cover the case.. Or maybe I ignore the test?
  5. May also need to modify the implementation in tikv....

@yuqi1129
Copy link
Contributor Author

@wshwsh12

Looks like the behavior is even stranger now.... Now this sql will return two warning messages.

Just now, i am busy fix this, seems that in order to fix this, more code should be updated and change.

In my opinion, we should not focus on fixing the inconsistency between these warning information and mysql at this stage, but other more serious problems (eg, returning wrong data).

You are right, much attention has been put to this minor problem and the output is not of much importance. we can ignore warning info inconsistence currently and focus on more meaningful problem. i will close the PR and submit it in the future.

thanks for your kindly advice.

@yuqi1129 yuqi1129 marked this pull request as draft July 19, 2021 08:47
@ti-chi-bot ti-chi-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 19, 2021
@ti-chi-bot
Copy link
Member

@yuqi1129: 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.

@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 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/expression do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. sig/sql-infra SIG: SQL Infra size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cast string like '.1a1' to decimal has no warnings information
4 participants