From 2d804ea26290b73854d5c2cd06c65ea3c6ce437e Mon Sep 17 00:00:00 2001 From: Ewan Chou Date: Fri, 31 Aug 2018 21:26:16 +0800 Subject: [PATCH 1/4] plan: use point get plan for UPDATE statement --- cmd/explaintest/r/explain_easy.result | 3 +- cmd/explaintest/r/explain_easy_stats.result | 3 +- plan/point_get_plan.go | 51 +++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/cmd/explaintest/r/explain_easy.result b/cmd/explaintest/r/explain_easy.result index ff0e9159abeaa..a1226b7693363 100644 --- a/cmd/explaintest/r/explain_easy.result +++ b/cmd/explaintest/r/explain_easy.result @@ -50,8 +50,7 @@ IndexJoin_11 4166.67 root left outer join, inner:IndexLookUp_10, outer key:test. └─TableScan_9 10.00 cop table:t2, keep order:false, stats:pseudo explain update t1 set t1.c2 = 2 where t1.c1 = 1; id count task operator info -TableReader_5 1.00 root data:TableScan_4 -└─TableScan_4 1.00 cop table:t1, range:[1,1], keep order:false, stats:pseudo +Point_Get_1 1.00 root table:t1, handle:1 explain delete from t1 where t1.c2 = 1; id count task operator info IndexLookUp_9 10.00 root diff --git a/cmd/explaintest/r/explain_easy_stats.result b/cmd/explaintest/r/explain_easy_stats.result index 7aec0dda5f6fe..8d8e90e0b94d8 100644 --- a/cmd/explaintest/r/explain_easy_stats.result +++ b/cmd/explaintest/r/explain_easy_stats.result @@ -56,8 +56,7 @@ Projection_6 2481.25 root test.t1.c1, test.t1.c2, test.t1.c3, test.t2.c1, test.t └─TableScan_20 1985.00 cop table:t2, keep order:false explain update t1 set t1.c2 = 2 where t1.c1 = 1; id count task operator info -TableReader_5 1.00 root data:TableScan_4 -└─TableScan_4 1.00 cop table:t1, range:[1,1], keep order:false +Point_Get_1 1.00 root table:t1, handle:1 explain delete from t1 where t1.c2 = 1; id count task operator info IndexLookUp_9 0.00 root diff --git a/plan/point_get_plan.go b/plan/point_get_plan.go index b74eb5995e542..eed4bf8392666 100644 --- a/plan/point_get_plan.go +++ b/plan/point_get_plan.go @@ -127,6 +127,8 @@ func tryFastPlan(ctx sessionctx.Context, node ast.Node) Plan { } return fp } + case *ast.UpdateStmt: + return tryUpdatePointPlan(ctx, x) case *ast.DeleteStmt: return tryDeletePointPlan(ctx, x) } @@ -382,6 +384,55 @@ func findInPairs(colName string, pairs []nameValuePair) int { return -1 } +func tryUpdatePointPlan(ctx sessionctx.Context, updateStmt *ast.UpdateStmt) Plan { + selStmt := &ast.SelectStmt{ + Fields: &ast.FieldList{}, + From: updateStmt.TableRefs, + Where: updateStmt.Where, + OrderBy: updateStmt.Order, + Limit: updateStmt.Limit, + } + fastSelect := tryPointGetPlan(ctx, selStmt) + if fastSelect == nil { + return nil + } + checkFastPlanPrivilege(ctx, fastSelect, mysql.SelectPriv, mysql.UpdatePriv) + orderedList := buildOrderedList(ctx, fastSelect, updateStmt.List) + if orderedList == nil { + return nil + } + updatePlan := &Update{ + SelectPlan: fastSelect, + OrderedList: orderedList, + } + updatePlan.SetSchema(fastSelect.schema) + return updatePlan +} + +func buildOrderedList(ctx sessionctx.Context, fastSelect *PointGetPlan, list []*ast.Assignment) []*expression.Assignment { + orderedList := make([]*expression.Assignment, 0, len(list)) + for _, assign := range list { + col, err := fastSelect.schema.FindColumn(assign.Column) + if err != nil { + return nil + } + if col == nil { + return nil + } + newAssign := &expression.Assignment{ + Col: col, + } + expr, err := expression.RewriteSimpleExprWithSchema(ctx, assign.Expr, fastSelect.schema) + if err != nil { + return nil + } + expr = expression.BuildCastFunction(ctx, expr, col.GetType()) + newAssign.Expr = expr.ResolveIndices(fastSelect.schema) + orderedList = append(orderedList, newAssign) + } + return orderedList +} + func tryDeletePointPlan(ctx sessionctx.Context, delStmt *ast.DeleteStmt) Plan { if delStmt.IsMultiTable { return nil From 78f4d7b8de4078bf534d1bced1748ba023837129 Mon Sep 17 00:00:00 2001 From: Ewan Chou Date: Mon, 3 Sep 2018 13:01:48 +0800 Subject: [PATCH 2/4] domain: fix leak test --- domain/schema_validator_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/domain/schema_validator_test.go b/domain/schema_validator_test.go index a120dd95db214..2fc2ffd4955af 100644 --- a/domain/schema_validator_test.go +++ b/domain/schema_validator_test.go @@ -95,6 +95,7 @@ func (*testSuite) TestSchemaValidator(c *C) { c.Assert(valid, Equals, ResultUnknown) close(exit) + time.Sleep(time.Millisecond) } func reload(validator SchemaValidator, leaseGrantCh chan leaseGrantItem, ids ...int64) int64 { From 6beafe9beca547e452550a634386ad45ccc7ebbc Mon Sep 17 00:00:00 2001 From: Ewan Chou Date: Mon, 3 Sep 2018 16:11:44 +0800 Subject: [PATCH 3/4] simple rewrite supports param marker --- expression/simple_rewriter.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/expression/simple_rewriter.go b/expression/simple_rewriter.go index f5d7386e74f54..c1da52783e344 100644 --- a/expression/simple_rewriter.go +++ b/expression/simple_rewriter.go @@ -137,6 +137,11 @@ func (sr *simpleRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok boo if v.Sel == nil { sr.inToExpression(len(v.List), v.Not, &v.Type) } + case *ast.ParamMarkerExpr: + tp := types.NewFieldType(mysql.TypeUnspecified) + types.DefaultParamTypeForValue(v.GetValue(), tp) + value := &Constant{Value: v.Datum, RetType: tp} + sr.push(value) case *ast.RowExpr: sr.rowToScalarFunc(v) case *ast.ParenthesesExpr: From 5edbe57f1b3122ce9943eb9a87580ccffa7f8842 Mon Sep 17 00:00:00 2001 From: Ewan Chou Date: Mon, 3 Sep 2018 18:49:52 +0800 Subject: [PATCH 4/4] check error --- plan/point_get_plan.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plan/point_get_plan.go b/plan/point_get_plan.go index eed4bf8392666..404a3888ed8f4 100644 --- a/plan/point_get_plan.go +++ b/plan/point_get_plan.go @@ -396,7 +396,9 @@ func tryUpdatePointPlan(ctx sessionctx.Context, updateStmt *ast.UpdateStmt) Plan if fastSelect == nil { return nil } - checkFastPlanPrivilege(ctx, fastSelect, mysql.SelectPriv, mysql.UpdatePriv) + if checkFastPlanPrivilege(ctx, fastSelect, mysql.SelectPriv, mysql.UpdatePriv) != nil { + return nil + } orderedList := buildOrderedList(ctx, fastSelect, updateStmt.List) if orderedList == nil { return nil