-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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/builtin_time: fix wrong precision for maketime #28068
base: master
Are you sure you want to change the base?
Conversation
[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 The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by submitting an approval review. |
/cc @wjhuang2016 |
/run-check_dev_2 |
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.
_
fe87238
to
cf5b468
Compare
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.
you can use setDecimalAndFlenForTime after #28252 gets merged.
expression/builtin_time.go
Outdated
decimal = args[2].GetType().Decimal | ||
if decimal > 6 || decimal == types.UnspecifiedLength { | ||
decimal = 6 | ||
case types.ETString: |
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.
bool resolve_type(THD *) override {
set_data_type_time(MY_MIN(args[2]->decimals, DATETIME_MAX_DECIMALS));
return false;
}
I think this can work, we don't need getExpressionFsp().
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.
But be careful with UnspecifiedLength, which is 31 in MySQL but -1 in TiDB
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.
thanks for your reply, I will continue after your works finished
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.
If the type is ETSTRING, then the decimal should be -1?
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.
Can we set the decimal be UnspecifiedLength
, if the type is ETSTRING
?
f3b6c57
to
6146a8c
Compare
Please follow PR Title Format:
Or if the count of mainly changed packages are more than 3, use
After you have format title, you can leave a comment |
switch tp { | ||
case types.ETString: | ||
decimal = 6 | ||
case types.ETInt: |
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.
If the type is ETINT, then the args[2].GetType().Decimal should be 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.
So the case ETint can be merged to default.
expression/builtin_time.go
Outdated
decimal = args[2].GetType().Decimal | ||
if decimal > 6 || decimal == types.UnspecifiedLength { | ||
decimal = 6 | ||
case types.ETString: |
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.
If the type is ETSTRING, then the decimal should be -1?
default: | ||
decimal = args[2].GetType().Decimal |
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.
Can we use this to handle all the cases?
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.
I add mores unit tests in expression/typeinfer_test.go
to cover all the cases . It seems to be good.
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.
For ETString, the decimal shoule be 31? Then it will be truncated to 6,
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.
I think set UnspecifiedLength
for ETSTRING
is more clear, because decimal is 31 in MySQL but -1 in TiDB.Decimal use 31 in ETSTRING
is not same as common rules in TIDB.
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.
Anyway, it's covered by L5836. We can set decimal = args[2].GetType().Decimal for ETString.
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.
Set decimal = args[2].GetType().Decimal for ETString can't cover the situation that the arg is varchar type({maketime(c_int_d, c_int_d, c_char)
test in expression/typeinfer_test.go
).
In that case, the decimal is zero not the UnspecifiedLength, and we will get zero decimal that is wrong result(expect decimal is 6).
So we have to specialize UnspecifiedLength in decimal for type ETSTRING.
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.
For literal "string", the decimal is 31.
mysql> select "asd";
Field 1: `asd`
Catalog: `def`
Database: ``
Table: ``
Org_table: ``
Type: VAR_STRING
Collation: utf8mb4_bin (46)
Length: 12
Max_length: 3
Decimals: 31
Flags: NOT_NULL
+-----+
| asd |
+-----+
| asd |
+-----+
1 row in set (0.01 sec)
Could you find out why it's 0 for the string column?
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.
MySQL [test]> select 'asd';
Field 1: `asd`
Catalog: `def`
Database: ``
Table: ``
Org_table: ``
Type: VAR_STRING
Collation: utf8mb3_general_ci (33)
Length: 9
Max_length: 3
Decimals: 31
Flags: NOT_NULL
+-----+
| asd |
+-----+
| asd |
+-----+
1 row in set (0.001 sec)
MySQL [test]> select a from t_test;
Field 1: `a`
Catalog: `def`
Database: `test`
Table: `t_test`
Org_table: `t_test`
Type: VAR_STRING
Collation: utf8mb3_general_ci (33)
Length: 75
Max_length: 0
Decimals: 0
Flags:
0 rows in set (0.002 sec)
type | decimal |
---|---|
mysql_string(literal) | 31 |
mysql_varstring | 0 |
mysql and tidb look same from the client side, but it has different implement for decimals in types.
for mysql
mysql change 31(DECIMAL_NOT_SPECIFIED) to 0 while sending column meta info (only for varstring, not for literal string).
type | decimal(inner) | decimal(column-meta) |
---|---|---|
mysql_string(literal) | 31(DECIMAL_NOT_SPECIFIED) | 31 |
mysql_varstring | 31(DECIMAL_NOT_SPECIFIED) | 0 |
for tidb
tidb change -1(types.UnspecifiedLength) to 0 while sending column meta info(only for literal string, not for var string)
Lines 409 to 413 in 5b5020d
if fld.Column.Decimal == types.UnspecifiedLength { | |
if fld.Column.Tp == mysql.TypeDuration { | |
ci.Decimal = uint8(types.DefaultFsp) | |
} else { | |
ci.Decimal = mysql.NotFixedDec |
type | decimal(inner) | decimal(column-meta) |
---|---|---|
mysql_string(literal) | -1(UnspecifiedLength) | 31(NotFixedDec) |
mysql_varstring | 0 | 0 |
in the end
according to the above reasons, use min
to check decimal is right for mysql but will get wrong result in tidb.
2ef4f04
to
4773a87
Compare
What problem does this PR solve?
Issue Number: close #27771
Problem Summary:
What is changed and how it works?
What's Changed:
How it Works:
Check List
Tests
Side effects
Documentation
Release note