From 025fbd6200d691d5b2361d0c5d82cf2027e8f2e6 Mon Sep 17 00:00:00 2001 From: xufei Date: Sat, 20 Feb 2021 10:41:57 +0800 Subject: [PATCH 1/2] cherry pick #22713 to release-4.0 Signed-off-by: ti-srebot --- executor/show_test.go | 10 ++++++++++ expression/expression.go | 10 ++++++++++ planner/core/physical_plan_test.go | 17 +++++++++++------ planner/core/task.go | 8 ++++++++ planner/core/testdata/plan_suite_out.json | 21 +++++++++++++++++++-- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/executor/show_test.go b/executor/show_test.go index 19c65fc8e6159..38c8e0ee85837 100644 --- a/executor/show_test.go +++ b/executor/show_test.go @@ -144,6 +144,16 @@ func (s *testSuite5) TestShowErrors(c *C) { tk.MustQuery("show errors").Check(testutil.RowsWithSep("|", "Error|1050|Table 'test.show_errors' already exists")) } +func (s *testSuite5) TestShowWarningsForExprPushdown(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + testSQL := `create table if not exists show_warnings_expr_pushdown (a int, value date)` + 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")) +} + func (s *testSuite5) TestShowGrantsPrivilege(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("create user show_grants") diff --git a/expression/expression.go b/expression/expression.go index f5fcbbf44d95f..602383d1e76c1 100644 --- a/expression/expression.go +++ b/expression/expression.go @@ -1143,6 +1143,13 @@ func canScalarFuncPushDown(scalarFunc *ScalarFunction, pc PbConverter, storeType // Check whether this function can be pushed. if !canFuncBePushed(scalarFunc, storeType) { + if pc.sc.InExplainStmt { + storageName := storeType.Name() + 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)) + } return false } @@ -1166,6 +1173,9 @@ func canScalarFuncPushDown(scalarFunc *ScalarFunction, pc PbConverter, storeType func canExprPushDown(expr Expression, pc PbConverter, storeType kv.StoreType) bool { if storeType == kv.TiFlash && expr.GetType().Tp == mysql.TypeDuration { + if pc.sc.InExplainStmt { + pc.sc.AppendWarning(errors.New("Expr '" + expr.String() + "' can not be pushed to TiFlash because it contains Duration type")) + } return false } switch x := expr.(type) { diff --git a/planner/core/physical_plan_test.go b/planner/core/physical_plan_test.go index 4f3fa07e0cc27..91a1cff9a420f 100644 --- a/planner/core/physical_plan_test.go +++ b/planner/core/physical_plan_test.go @@ -880,7 +880,7 @@ func (s *testPlanSuite) TestLimitToCopHint(c *C) { output []struct { SQL string Plan []string - Warning string + Warning []string } ) @@ -897,15 +897,20 @@ func (s *testPlanSuite) TestLimitToCopHint(c *C) { warnings := tk.Se.GetSessionVars().StmtCtx.GetWarnings() s.testData.OnRecord(func() { if len(warnings) > 0 { - output[i].Warning = warnings[0].Err.Error() + output[i].Warning = make([]string, len(warnings)) + for j, warning := range warnings { + output[i].Warning[j] = warning.Err.Error() + } } }) - if output[i].Warning == "" { + if len(output[i].Warning) == 0 { c.Assert(len(warnings), Equals, 0, comment) } else { - c.Assert(len(warnings), Equals, 1, comment) - c.Assert(warnings[0].Level, Equals, stmtctx.WarnLevelWarning, comment) - c.Assert(warnings[0].Err.Error(), Equals, output[i].Warning, comment) + c.Assert(len(warnings), Equals, len(output[i].Warning), comment) + for j, warning := range warnings { + c.Assert(warning.Level, Equals, stmtctx.WarnLevelWarning, comment) + c.Assert(warning.Err.Error(), Equals, output[i].Warning[j], comment) + } } } } diff --git a/planner/core/task.go b/planner/core/task.go index f4ba96cc9e0e2..93ba40e83e30d 100644 --- a/planner/core/task.go +++ b/planner/core/task.go @@ -16,6 +16,7 @@ package core import ( "math" + "github.com/pingcap/errors" "github.com/pingcap/parser/ast" "github.com/pingcap/parser/charset" "github.com/pingcap/parser/mysql" @@ -1043,6 +1044,13 @@ func CheckAggCanPushCop(sctx sessionctx.Context, aggFuncs []*aggregation.AggFunc return false } if !aggregation.CheckAggPushDown(aggFunc, storeType) { + if sc.InExplainStmt { + storageName := storeType.Name() + if storeType == kv.UnSpecified { + storageName = "storage layer" + } + sc.AppendWarning(errors.New("Agg function '" + aggFunc.Name + "' can not be pushed to " + storageName)) + } return false } if !expression.CanExprsPushDown(sc, aggFunc.Args, client, storeType) { diff --git a/planner/core/testdata/plan_suite_out.json b/planner/core/testdata/plan_suite_out.json index f16a5af4324d8..66290395bd4d9 100644 --- a/planner/core/testdata/plan_suite_out.json +++ b/planner/core/testdata/plan_suite_out.json @@ -1456,7 +1456,7 @@ " └─Selection_13 0.83 cop[tikv] gt(test.tn.c, 50)", " └─IndexRangeScan_12 2.50 cop[tikv] table:tn, index:a(a, b, c, d) range:(1 10,1 20), keep order:false, stats:pseudo" ], - "Warning": "" + "Warning": null }, { "SQL": "select * from tn where a = 1 and b > 10 and b < 20 and c > 50 order by d limit 1", @@ -1466,7 +1466,7 @@ " └─Selection_19 0.83 cop[tikv] gt(test.tn.c, 50)", " └─IndexRangeScan_18 2.50 cop[tikv] table:tn, index:a(a, b, c, d) range:(1 10,1 20), keep order:false, stats:pseudo" ], - "Warning": "" + "Warning": null }, { "SQL": "select /*+ LIMIT_TO_COP() */ a from tn where mod(a, 2) order by a limit 1", @@ -1476,7 +1476,24 @@ " └─IndexReader_21 1.00 root index:IndexFullScan_20", " └─IndexFullScan_20 1.00 cop[tikv] table:tn, index:a(a, b, c, d) keep order:true, stats:pseudo" ], +<<<<<<< HEAD "Warning": "[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable" +======= + "Warning": [ + "Scalar function 'mod'(signature: ModInt) can not be pushed to storage layer", + "[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable" + ] + }, + { + "SQL": "select /*+ LIMIT_TO_COP() */ a from tn where a > 10 limit 1", + "Plan": [ + "Limit_8 1.00 root offset:0, count:1", + "└─IndexReader_12 1.00 root index:Limit_11", + " └─Limit_11 1.00 cop[tikv] offset:0, count:1", + " └─IndexRangeScan_10 1.00 cop[tikv] table:tn, index:a(a, b, c, d) range:(10,+inf], keep order:false, stats:pseudo" + ], + "Warning": null +>>>>>>> 3ad7f4014... expression: Add warning info for exprs that can not be pushed to storage layer (#22713) } ] }, From f65fc7cb871cceaf881c37a1ec5cad471a2dc7ca Mon Sep 17 00:00:00 2001 From: xufei Date: Mon, 1 Mar 2021 15:31:49 +0800 Subject: [PATCH 2/2] resolve merge conflict --- planner/core/testdata/plan_suite_out.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/planner/core/testdata/plan_suite_out.json b/planner/core/testdata/plan_suite_out.json index 66290395bd4d9..df5494298bdc2 100644 --- a/planner/core/testdata/plan_suite_out.json +++ b/planner/core/testdata/plan_suite_out.json @@ -1476,24 +1476,10 @@ " └─IndexReader_21 1.00 root index:IndexFullScan_20", " └─IndexFullScan_20 1.00 cop[tikv] table:tn, index:a(a, b, c, d) keep order:true, stats:pseudo" ], -<<<<<<< HEAD - "Warning": "[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable" -======= "Warning": [ "Scalar function 'mod'(signature: ModInt) can not be pushed to storage layer", "[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable" ] - }, - { - "SQL": "select /*+ LIMIT_TO_COP() */ a from tn where a > 10 limit 1", - "Plan": [ - "Limit_8 1.00 root offset:0, count:1", - "└─IndexReader_12 1.00 root index:Limit_11", - " └─Limit_11 1.00 cop[tikv] offset:0, count:1", - " └─IndexRangeScan_10 1.00 cop[tikv] table:tn, index:a(a, b, c, d) range:(10,+inf], keep order:false, stats:pseudo" - ], - "Warning": null ->>>>>>> 3ad7f4014... expression: Add warning info for exprs that can not be pushed to storage layer (#22713) } ] },