-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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 different types compare error #21338
Changes from 15 commits
313ab85
0ba309c
0664e07
2431753
6ed6dcf
6968a16
849beff
904bf51
fd27373
579cd43
6fba459
ba4cc45
596dd27
cd6cea4
0e0a148
a29360c
7a6c730
9fcd148
5d2d0c1
671ab34
521d416
8d0794c
a6352f1
794473e
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 |
---|---|---|
|
@@ -148,6 +148,9 @@ func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Ex | |
return baseBuiltinFunc{}, errors.New("unexpected nil session ctx") | ||
} | ||
|
||
orgArgs := make([]Expression, len(args)) | ||
copy(orgArgs, args) | ||
|
||
for i := range args { | ||
switch argTps[i] { | ||
case types.ETInt: | ||
|
@@ -167,6 +170,7 @@ func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Ex | |
case types.ETJson: | ||
args[i] = WrapWithCastAsJSON(ctx, args[i]) | ||
} | ||
generateRetFlag(args[i], argTps[i], orgArgs) | ||
} | ||
|
||
if err = checkIllegalMixCollation(funcName, args, retType); err != nil { | ||
|
@@ -258,6 +262,34 @@ func newBaseBuiltinFuncWithTp(ctx sessionctx.Context, funcName string, args []Ex | |
return bf, nil | ||
} | ||
|
||
func generateRetFlag(res Expression, evalType types.EvalType, args []Expression) { | ||
if len(args) < 2 { | ||
return | ||
} | ||
var retType = res.GetType() | ||
lhs, rhs := args[0], args[1] | ||
if fun, ok := res.(*ScalarFunction); (ok && fun.FuncName.L == ast.Cast) || res.GetType().Tp == mysql.TypeBit { | ||
if evalType == types.ETInt || evalType == types.ETReal { | ||
lfg, rfg := args[0].GetType().Flag, args[1].GetType().Flag | ||
// set signedFlag to 0 when bit convert explicitly or implicitly to int or real | ||
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. I can't understand the logic. In the case, all evalType.flag don't contain UnsignedFlag, I think. Could you provide an example?
I have a try, only add builtin_cast.goL487 and builtin_cast_vec.goL111, it also works. Is there any negligence in what I thought? 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. I removed builtin.goL173,it not work,for this case i see the step: 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 the flag for column a is 32..? It doesn't has the unsigned flag when creating table. 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. If cast a as double explicitly, it works...
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. in ddl_api.goL537 invoke col.Flag |= mysql.UnsignedFlag when create table, 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. I have a try in mysql8.0.22.. So the behavior in tidb is right? It maybe a bug in mysql8.0.21 and the previous version?
But in mysql8.0.21,
|
||
if mysql.TypeBit == lhs.GetType().Tp || mysql.TypeBit == rhs.GetType().Tp { | ||
retType.Flag |= mysql.UnsignedFlag | ||
if mysql.TypeBit == rhs.GetType().Tp { | ||
retType.Flag &= ^(mysql.UnsignedFlag ^ lfg) | ||
} else { | ||
retType.Flag &= ^(mysql.UnsignedFlag ^ rfg) | ||
} | ||
} | ||
} else if evalType == types.ETDecimal && (mysql.TypeEnum == lhs.GetType().Tp || mysql.TypeEnum == rhs.GetType().Tp) { | ||
// set Flen and Decimal as unspecified length(-1) when the enum type is compare with decimal type,avoid loss of data, | ||
// like the enum'z'(26), wher Flen=2,Decimal=2 the enum=26.00 but when Flen= 1,Decimal=2 the enum=9 | ||
wshwsh12 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if mysql.TypeNewDecimal == retType.Tp { | ||
retType.Flen, retType.Decimal = types.UnspecifiedLength, types.UnspecifiedLength | ||
} | ||
} | ||
} | ||
} | ||
|
||
// newBaseBuiltinFuncWithFieldType create BaseBuiltinFunc with FieldType charset and collation. | ||
// do not check and compute collation. | ||
func newBaseBuiltinFuncWithFieldType(ctx sessionctx.Context, tp *types.FieldType, args []Expression) (baseBuiltinFunc, error) { | ||
|
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 do not understand the logic of this function.
Can you add some comment for it?
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.
done