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: not push invalid cast to tiflash (#28458) #28652

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions executor/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ func (s *testSuite5) TestShowWarningsForExprPushdown(c *C) {
tk.MustExec(testSQL)
tk.MustExec("explain select * from show_warnings_expr_pushdown where date_add(value, interval 1 day) = '2020-01-01'")
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt) can not be pushed to tikv"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt, return type: datetime(6)) can not be pushed to tikv"))
tk.MustExec("explain select max(date_add(value, interval 1 day)) from show_warnings_expr_pushdown group by a")
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt) can not be pushed to tikv", "Warning|1105|Aggregation can not be pushed to tikv because arguments of AggFunc `max` contains unsupported exprs"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt, return type: datetime(6)) can not be pushed to tikv", "Warning|1105|Aggregation can not be pushed to tikv because arguments of AggFunc `max` contains unsupported exprs"))
tk.MustExec("explain select max(a) from show_warnings_expr_pushdown group by date_add(value, interval 1 day)")
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(2))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt) can not be pushed to tikv", "Warning|1105|Aggregation can not be pushed to tikv because groupByItems contain unsupported exprs"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|Scalar function 'date_add'(signature: AddDateDatetimeInt, return type: datetime(6)) can not be pushed to tikv", "Warning|1105|Aggregation can not be pushed to tikv because groupByItems contain unsupported exprs"))
tk.MustExec("set tidb_opt_distinct_agg_push_down=0")
tk.MustExec("explain select max(distinct a) from show_warnings_expr_pushdown group by value")
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1))
Expand Down
47 changes: 42 additions & 5 deletions expression/expr_to_pb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ func (s *testEvaluatorSuite) TestExprPushDownToFlash(c *C) {
datetimeColumn := dg.genColumn(mysql.TypeDatetime, 6)
binaryStringColumn := dg.genColumn(mysql.TypeString, 7)
binaryStringColumn.RetType.Collate = charset.CollationBin
int32Column := dg.genColumn(mysql.TypeLong, 8)
float32Column := dg.genColumn(mysql.TypeFloat, 9)

function, err := NewFunction(mock.NewContext(), ast.JSONLength, types.NewFieldType(mysql.TypeLonglong), jsonColumn)
c.Assert(err, IsNil)
Expand Down Expand Up @@ -654,28 +656,31 @@ func (s *testEvaluatorSuite) TestExprPushDownToFlash(c *C) {
c.Assert(err, IsNil)
exprs = append(exprs, function)

validDecimalType := types.NewFieldType(mysql.TypeNewDecimal)
validDecimalType.Flen = 20
validDecimalType.Decimal = 2
// CastIntAsDecimal
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), intColumn)
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, intColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// CastRealAsDecimal
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), realColumn)
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, realColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// CastDecimalAsDecimal
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn)
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, decimalColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// CastStringAsDecimal
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), stringColumn)
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, stringColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// CastTimeAsDecimal
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), datetimeColumn)
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, datetimeColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

Expand Down Expand Up @@ -869,6 +874,16 @@ func (s *testEvaluatorSuite) TestExprPushDownToFlash(c *C) {
c.Assert(function.(*ScalarFunction).Function.PbCode(), Equals, tipb.ScalarFuncSig_StrToDateDatetime)
exprs = append(exprs, function)

// cast Int32 to Int32
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLong), int32Column)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// cast float32 to float32
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeFloat), float32Column)
c.Assert(err, IsNil)
exprs = append(exprs, function)

canPush := CanExprsPushDown(sc, exprs, client, kv.TiFlash)
c.Assert(canPush, Equals, true)

Expand All @@ -893,8 +908,30 @@ func (s *testEvaluatorSuite) TestExprPushDownToFlash(c *C) {
c.Assert(err, IsNil)
exprs = append(exprs, function)

<<<<<<< HEAD
// RoundDecimal: can not be pushed
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn)
=======
// Cast to Int32: not supported
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLong), stringColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// Cast to Float: not supported
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeFloat), intColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// Cast to invalid Decimal Type: not supported
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), intColumn)
c.Assert(err, IsNil)
exprs = append(exprs, function)

// cast Int32 to UInt32
unsignedInt32Type := types.NewFieldType(mysql.TypeLong)
unsignedInt32Type.Flag = mysql.UnsignedFlag
function, err = NewFunction(mock.NewContext(), ast.Cast, unsignedInt32Type, int32Column)
>>>>>>> 36d0b4067... expression: not push invalid cast to tiflash (#28458)
c.Assert(err, IsNil)
exprs = append(exprs, function)

Expand Down
34 changes: 26 additions & 8 deletions expression/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,13 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool {
return false
}

func isValidTiFlashDecimalType(tp *types.FieldType) bool {
if tp.Tp != mysql.TypeNewDecimal {
return false
}
return tp.Flen > 0 && tp.Flen <= 65 && tp.Decimal >= 0 && tp.Decimal <= 30 && tp.Flen >= tp.Decimal
}

func scalarExprSupportedByFlash(function *ScalarFunction) bool {
switch function.FuncName.L {
case ast.Floor, ast.Ceil, ast.Ceiling:
Expand Down Expand Up @@ -1025,16 +1032,27 @@ func scalarExprSupportedByFlash(function *ScalarFunction) bool {
return true
}
case ast.Cast:
sourceType := function.GetArgs()[0].GetType()
retType := function.RetType
switch function.Function.PbCode() {
case tipb.ScalarFuncSig_CastIntAsTime:
case tipb.ScalarFuncSig_CastDecimalAsInt, tipb.ScalarFuncSig_CastIntAsInt, tipb.ScalarFuncSig_CastRealAsInt, tipb.ScalarFuncSig_CastTimeAsInt,
tipb.ScalarFuncSig_CastStringAsInt /*, tipb.ScalarFuncSig_CastDurationAsInt, tipb.ScalarFuncSig_CastJsonAsInt*/ :
// TiFlash cast only support cast to Int64 or the source type is the same as the target type
return (sourceType.Tp == retType.Tp && mysql.HasUnsignedFlag(sourceType.Flag) == mysql.HasUnsignedFlag(retType.Flag)) || retType.Tp == mysql.TypeLonglong
case tipb.ScalarFuncSig_CastIntAsReal, tipb.ScalarFuncSig_CastRealAsReal, tipb.ScalarFuncSig_CastStringAsReal: /*, tipb.ScalarFuncSig_CastDecimalAsReal,
tipb.ScalarFuncSig_CastDurationAsReal, tipb.ScalarFuncSig_CastTimeAsReal, tipb.ScalarFuncSig_CastJsonAsReal*/
// TiFlash cast only support cast to Float64 or the source type is the same as the target type
return sourceType.Tp == retType.Tp || retType.Tp == mysql.TypeDouble
case tipb.ScalarFuncSig_CastDecimalAsDecimal, tipb.ScalarFuncSig_CastIntAsDecimal, tipb.ScalarFuncSig_CastRealAsDecimal, tipb.ScalarFuncSig_CastTimeAsDecimal,
tipb.ScalarFuncSig_CastStringAsDecimal /*, tipb.ScalarFuncSig_CastDurationAsDecimal, tipb.ScalarFuncSig_CastJsonAsDecimal*/ :
return isValidTiFlashDecimalType(function.RetType)
case tipb.ScalarFuncSig_CastDecimalAsString, tipb.ScalarFuncSig_CastIntAsString, tipb.ScalarFuncSig_CastRealAsString, tipb.ScalarFuncSig_CastTimeAsString,
tipb.ScalarFuncSig_CastStringAsString /*, tipb.ScalarFuncSig_CastDurationAsString, tipb.ScalarFuncSig_CastJsonAsString*/ :
return true
case tipb.ScalarFuncSig_CastDecimalAsTime, tipb.ScalarFuncSig_CastIntAsTime, tipb.ScalarFuncSig_CastRealAsTime, tipb.ScalarFuncSig_CastTimeAsTime,
tipb.ScalarFuncSig_CastStringAsTime /*, tipb.ScalarFuncSig_CastDurationAsTime, tipb.ScalarFuncSig_CastJsonAsTime*/ :
// ban the function of casting year type as time type pushing down to tiflash because of https://github.com/pingcap/tidb/issues/26215
return function.GetArgs()[0].GetType().Tp != mysql.TypeYear
case tipb.ScalarFuncSig_CastIntAsInt, tipb.ScalarFuncSig_CastIntAsReal, tipb.ScalarFuncSig_CastIntAsDecimal, tipb.ScalarFuncSig_CastIntAsString,
tipb.ScalarFuncSig_CastRealAsInt, tipb.ScalarFuncSig_CastRealAsReal, tipb.ScalarFuncSig_CastRealAsDecimal, tipb.ScalarFuncSig_CastRealAsString, tipb.ScalarFuncSig_CastRealAsTime,
tipb.ScalarFuncSig_CastStringAsInt, tipb.ScalarFuncSig_CastStringAsReal, tipb.ScalarFuncSig_CastStringAsDecimal, tipb.ScalarFuncSig_CastStringAsString, tipb.ScalarFuncSig_CastStringAsTime,
tipb.ScalarFuncSig_CastDecimalAsInt /*, tipb.ScalarFuncSig_CastDecimalAsReal*/, tipb.ScalarFuncSig_CastDecimalAsDecimal, tipb.ScalarFuncSig_CastDecimalAsString, tipb.ScalarFuncSig_CastDecimalAsTime,
tipb.ScalarFuncSig_CastTimeAsInt /*, tipb.ScalarFuncSig_CastTimeAsReal*/, tipb.ScalarFuncSig_CastTimeAsDecimal, tipb.ScalarFuncSig_CastTimeAsTime, tipb.ScalarFuncSig_CastTimeAsString:
return true
}
case ast.DateAdd, ast.AddDate:
switch function.Function.PbCode() {
Expand Down Expand Up @@ -1168,7 +1186,7 @@ func canScalarFuncPushDown(scalarFunc *ScalarFunction, pc PbConverter, storeType
if storeType == kv.UnSpecified {
storageName = "storage layer"
}
pc.sc.AppendWarning(errors.New("Scalar function '" + scalarFunc.FuncName.L + "'(signature: " + scalarFunc.Function.PbCode().String() + ") can not be pushed to " + storageName))
pc.sc.AppendWarning(errors.New("Scalar function '" + scalarFunc.FuncName.L + "'(signature: " + scalarFunc.Function.PbCode().String() + ", return type: " + scalarFunc.RetType.CompactStr() + ") can not be pushed to " + storageName))
}
return false
}
Expand Down
8 changes: 8 additions & 0 deletions planner/core/testdata/enforce_mpp_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@
" └─TableFullScan_10 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo"
],
"Warn": [
<<<<<<< HEAD
"Scalar function 'md5'(signature: MD5) can not be pushed to tiflash",
"MPP mode may be blocked because groupByItems contain unsupported exprs",
"Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs",
Expand All @@ -360,6 +361,13 @@
"Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs",
"Scalar function 'md5'(signature: MD5) can not be pushed to tiflash",
"MPP mode may be blocked because groupByItems contain unsupported exprs",
=======
"Scalar function 'md5'(signature: MD5, return type: var_string(32)) can not be pushed to tiflash",
"Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs",
"Scalar function 'md5'(signature: MD5, return type: var_string(32)) can not be pushed to tiflash",
"Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs",
"Scalar function 'md5'(signature: MD5, return type: var_string(32)) can not be pushed to tiflash",
>>>>>>> 36d0b4067... expression: not push invalid cast to tiflash (#28458)
"Aggregation can not be pushed to tiflash because groupByItems contain unsupported exprs"
]
},
Expand Down
2 changes: 1 addition & 1 deletion planner/core/testdata/integration_serial_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "TestSelPushDownTiFlash",
"cases": [
"explain format = 'brief' select * from t where t.a > 1 and t.b = \"flash\" or t.a + 3 * t.a = 5",
"explain format = 'brief' select * from t where cast(t.a as float) + 3 = 5.1",
"explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1",
"explain format = 'brief' select * from t where b > 'a' order by convert(b, unsigned) limit 2",
"explain format = 'brief' select * from t where b > 'a' order by b limit 2"
]
Expand Down
4 changes: 2 additions & 2 deletions planner/core/testdata/integration_serial_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
]
},
{
"SQL": "explain format = 'brief' select * from t where cast(t.a as float) + 3 = 5.1",
"SQL": "explain format = 'brief' select * from t where cast(t.a as double) + 3 = 5.1",
"Plan": [
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tiflash] eq(plus(cast(test.t.a, float BINARY), 3), 5.1)",
"└─Selection 8000.00 cop[tiflash] eq(plus(cast(test.t.a, double BINARY), 3), 5.1)",
" └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo"
]
},
Expand Down
4 changes: 4 additions & 0 deletions planner/core/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -1508,7 +1508,11 @@
" └─IndexFullScan 1.00 cop[tikv] table:tn, index:a(a, b, c, d) keep order:true, stats:pseudo"
],
"Warning": [
<<<<<<< HEAD
"Scalar function 'mod'(signature: ModIntSignedSigned) can not be pushed to storage layer",
=======
"Scalar function 'intdiv'(signature: IntDivideInt, return type: bigint(20)) can not be pushed to storage layer",
>>>>>>> 36d0b4067... expression: not push invalid cast to tiflash (#28458)
"[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable"
]
},
Expand Down