-
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
execution: avoid decimal overflow and check valid #34399
Changes from 18 commits
ae64cf9
3a81824
4d39de1
cd215f3
d63f9f7
32a64ef
8ba1962
def5817
4fa7047
489cb64
cfdf243
b1130bb
786b12b
4ddc492
3f69a21
dc2eb04
3761b82
cc45764
6df6a09
c2627fd
2db77e7
41a9043
15fe79f
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 |
---|---|---|
|
@@ -99,46 +99,49 @@ func (desc *baseFuncDesc) GetTiPBExpr(tryWindowDesc bool) (tp tipb.ExprType) { | |
} | ||
|
||
// AggFuncToPBExpr converts aggregate function to pb. | ||
func AggFuncToPBExpr(sctx sessionctx.Context, client kv.Client, aggFunc *AggFuncDesc) *tipb.Expr { | ||
func AggFuncToPBExpr(sctx sessionctx.Context, client kv.Client, aggFunc *AggFuncDesc, storeType kv.StoreType) (*tipb.Expr, error) { | ||
pc := expression.NewPBConverter(client, sctx.GetSessionVars().StmtCtx) | ||
tp := aggFunc.GetTiPBExpr(false) | ||
if !client.IsRequestTypeSupported(kv.ReqTypeSelect, int64(tp)) { | ||
return nil | ||
return nil, errors.New("select request is not supported by client") | ||
} | ||
|
||
children := make([]*tipb.Expr, 0, len(aggFunc.Args)) | ||
for _, arg := range aggFunc.Args { | ||
pbArg := pc.ExprToPB(arg) | ||
if pbArg == nil { | ||
return nil | ||
return nil, errors.New(aggFunc.String() + " can't be converted to PB.") | ||
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. ditto |
||
} | ||
children = append(children, pbArg) | ||
} | ||
retType, err := expression.ToPBFieldTypeWithCheck(aggFunc.RetTp, storeType) | ||
fzhedu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
|
||
if tp == tipb.ExprType_GroupConcat { | ||
orderBy := make([]*tipb.ByItem, 0, len(aggFunc.OrderByItems)) | ||
sc := sctx.GetSessionVars().StmtCtx | ||
for _, arg := range aggFunc.OrderByItems { | ||
pbArg := expression.SortByItemToPB(sc, client, arg.Expr, arg.Desc) | ||
if pbArg == nil { | ||
return nil | ||
return nil, errors.New(aggFunc.String() + " can't be converted to PB.") | ||
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. ditto |
||
} | ||
orderBy = append(orderBy, pbArg) | ||
} | ||
// encode GroupConcatMaxLen | ||
GCMaxLen, err := variable.GetSessionOrGlobalSystemVar(sctx.GetSessionVars(), variable.GroupConcatMaxLen) | ||
if err != nil { | ||
sc.AppendWarning(errors.Errorf("Error happened when buildGroupConcat: no system variable named '%s'", variable.GroupConcatMaxLen)) | ||
return nil | ||
return nil, errors.Errorf("Error happened when buildGroupConcat: no system variable named '%s'", variable.GroupConcatMaxLen) | ||
} | ||
maxLen, err := strconv.ParseUint(GCMaxLen, 10, 64) | ||
// Should never happen | ||
if err != nil { | ||
sc.AppendWarning(errors.Errorf("Error happened when buildGroupConcat: %s", err.Error())) | ||
return nil | ||
return nil, errors.Errorf("Error happened when buildGroupConcat: %s", err.Error()) | ||
} | ||
return &tipb.Expr{Tp: tp, Val: codec.EncodeUint(nil, maxLen), Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct, OrderBy: orderBy, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)} | ||
return &tipb.Expr{Tp: tp, Val: codec.EncodeUint(nil, maxLen), Children: children, FieldType: retType, HasDistinct: aggFunc.HasDistinct, OrderBy: orderBy, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)}, nil | ||
} | ||
return &tipb.Expr{Tp: tp, Children: children, FieldType: expression.ToPBFieldType(aggFunc.RetTp), HasDistinct: aggFunc.HasDistinct, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)} | ||
return &tipb.Expr{Tp: tp, Children: children, FieldType: retType, HasDistinct: aggFunc.HasDistinct, AggFuncMode: AggFunctionModeToPB(aggFunc.Mode)}, nil | ||
} | ||
|
||
// AggFunctionModeToPB converts aggregate function mode to PB. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1934,8 +1934,8 @@ func WrapWithCastAsDecimal(ctx sessionctx.Context, expr Expression) Expression { | |
return expr | ||
} | ||
tp := types.NewFieldType(mysql.TypeNewDecimal) | ||
tp.SetFlen(expr.GetType().GetFlen()) | ||
tp.SetDecimal(expr.GetType().GetDecimal()) | ||
tp.SetFlenUnderLimit(expr.GetType().GetFlen()) | ||
tp.SetDecimalUnderLimit(expr.GetType().GetDecimal()) | ||
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 not use 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. because it would change the logic if they are -1. 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. besides, UpdateFlenAndDecimalUnderLimit aims to maintain valid when update the flen or decimal, where the flen and decimal should be not be -1. |
||
|
||
if expr.GetType().EvalType() == types.ETInt { | ||
tp.SetFlen(mysql.MaxIntWidth) | ||
|
@@ -1952,14 +1952,8 @@ func WrapWithCastAsDecimal(ctx sessionctx.Context, expr Expression) Expression { | |
if !isnull && err == nil { | ||
precision, frac := val.PrecisionAndFrac() | ||
castTp := castExpr.GetType() | ||
castTp.SetDecimal(frac) | ||
castTp.SetFlen(precision) | ||
if castTp.GetFlen() > mysql.MaxDecimalWidth { | ||
castTp.SetFlen(mysql.MaxDecimalWidth) | ||
} | ||
if castTp.GetDecimal() > mysql.MaxDecimalScale { | ||
castTp.SetDecimal(mysql.MaxDecimalScale) | ||
} | ||
castTp.SetDecimalUnderLimit(frac) | ||
castTp.SetFlenUnderLimit(precision) | ||
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. ditto 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. we suppose the setting values are valid after |
||
} | ||
} | ||
return castExpr | ||
|
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.
We should not return an error here, it'll be a compatibility-breaker.
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.
These errors are not reported to the client, because these functions are called in order to check the functions can be pushed down or not. if not, the functions are not pushed down without errors but with some warnings.