From 6beb6cdf16f6e1d9e6ae5ef68beb328b4b219044 Mon Sep 17 00:00:00 2001 From: HuaiyuXu <391585975@qq.com> Date: Tue, 4 Jun 2019 14:31:10 +0800 Subject: [PATCH] planner, executor: return TableDual when tryFastPlan is promised to be false (#10676) --- executor/executor_test.go | 41 +++++++++++++++++++++++++++++ executor/point_get.go | 1 - planner/core/common_plans.go | 3 ++- planner/core/point_get_plan.go | 41 ++++++++++++++++++++++------- planner/core/point_get_plan_test.go | 2 +- 5 files changed, 75 insertions(+), 13 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 84bc61af04429..7bce3ca10e929 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -3799,6 +3799,47 @@ func (s *testSuite) TestSplitIndexRegion(c *C) { c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.WarnDataTruncated)) } +func (s *testSuite) TestIssue10448(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int1 primary key)") + tk.MustExec("insert into t values(125)") + tk.MustQuery("desc select * from t where pk = 9223372036854775807").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 18446744073709551616").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 9223372036854775808").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 18446744073709551615").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 128").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int8 primary key)") + tk.MustExec("insert into t values(9223372036854775807)") + tk.MustQuery("select * from t where pk = 9223372036854775807").Check(testkit.Rows("9223372036854775807")) + tk.MustQuery("desc select * from t where pk = 9223372036854775807").Check(testkit.Rows("Point_Get_1 1.00 root table:t, handle:9223372036854775807")) + tk.MustQuery("desc select * from t where pk = 18446744073709551616").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 9223372036854775808").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 18446744073709551615").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int1 unsigned primary key)") + tk.MustExec("insert into t values(255)") + tk.MustQuery("select * from t where pk = 255").Check(testkit.Rows("255")) + tk.MustQuery("desc select * from t where pk = 256").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 9223372036854775807").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 18446744073709551616").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 9223372036854775808").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 18446744073709551615").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(pk int8 unsigned primary key)") + tk.MustExec("insert into t value(18446744073709551615)") + tk.MustQuery("desc select * from t where pk = 18446744073709551615").Check(testkit.Rows("Point_Get_1 1.00 root table:t, handle:18446744073709551615")) + tk.MustQuery("select * from t where pk = 18446744073709551615").Check(testkit.Rows("18446744073709551615")) + tk.MustQuery("desc select * from t where pk = 9223372036854775807").Check(testkit.Rows("Point_Get_1 1.00 root table:t, handle:9223372036854775807")) + tk.MustQuery("desc select * from t where pk = 18446744073709551616").Check(testkit.Rows("TableDual_2 0.00 root rows:0")) + tk.MustQuery("desc select * from t where pk = 9223372036854775808").Check(testkit.Rows("Point_Get_1 1.00 root table:t, handle:9223372036854775808")) +} + func (s *testSuite) TestUnsignedFeedback(c *C) { tk := testkit.NewTestKit(c, s.store) oriProbability := statistics.FeedbackProbability.Load() diff --git a/executor/point_get.go b/executor/point_get.go index bf3ff62de8231..e9063386fbe0c 100644 --- a/executor/point_get.go +++ b/executor/point_get.go @@ -46,7 +46,6 @@ func (b *executorBuilder) buildPointGet(p *plannercore.PointGetPlan) Executor { idxVals: p.IndexValues, handle: p.Handle, startTS: startTS, - done: p.UnsignedHandle && p.Handle < 0, } } diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index ed0ad362ac43e..bbb9b3497c270 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -220,7 +220,8 @@ func (e *Execute) getPhysicalPlan(ctx sessionctx.Context, is infoschema.InfoSche if err != nil { return nil, err } - if prepared.UseCache { + _, isTableDual := p.(*PhysicalTableDual) + if !isTableDual && prepared.UseCache { ctx.PreparedPlanCache().Put(cacheKey, NewPSTMTPlanCacheValue(p)) } return p, err diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index 0be899e4fb87e..b6966932d2f85 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/opcode" + "github.com/pingcap/parser/terror" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/planner/property" "github.com/pingcap/tidb/privilege" @@ -46,6 +47,7 @@ type PointGetPlan struct { IndexValueParams []*driver.ParamMarkerExpr expr expression.Expression ctx sessionctx.Context + IsTableDual bool } type nameValuePair struct { @@ -84,7 +86,11 @@ func (p *PointGetPlan) ExplainInfo() string { } } } else { - fmt.Fprintf(buffer, ", handle:%d", p.Handle) + if p.UnsignedHandle { + fmt.Fprintf(buffer, ", handle:%d", uint64(p.Handle)) + } else { + fmt.Fprintf(buffer, ", handle:%d", p.Handle) + } } return buffer.String() } @@ -130,6 +136,11 @@ func TryFastPlan(ctx sessionctx.Context, node ast.Node) Plan { if checkFastPlanPrivilege(ctx, fp, mysql.SelectPriv) != nil { return nil } + if fp.IsTableDual { + tableDual := PhysicalTableDual{} + tableDual.SetSchema(fp.Schema()) + return tableDual.Init(ctx, &property.StatsInfo{}) + } return fp } case *ast.UpdateStmt: @@ -186,19 +197,23 @@ func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt) *PointGetP if pairs == nil { return nil } - handlePair, unsigned := findPKHandle(tbl, pairs) + handlePair, fieldType := findPKHandle(tbl, pairs) if handlePair.value.Kind() != types.KindNull && len(pairs) == 1 { schema := buildSchemaFromFields(ctx, tblName.Schema, tbl, selStmt.Fields.Fields) if schema == nil { return nil } p := newPointGetPlan(ctx, schema, tbl) - var err error - p.Handle, err = handlePair.value.ToInt64(ctx.GetSessionVars().StmtCtx) + intDatum, err := handlePair.value.ConvertTo(ctx.GetSessionVars().StmtCtx, fieldType) if err != nil { + if terror.ErrorEqual(types.ErrOverflow, err) { + p.IsTableDual = true + return p + } return nil } - p.UnsignedHandle = unsigned + p.Handle = intDatum.GetInt64() + p.UnsignedHandle = mysql.HasUnsignedFlag(fieldType.Flag) p.HandleParam = handlePair.param return p } @@ -364,20 +379,20 @@ func getNameValuePairs(nvPairs []nameValuePair, expr ast.ExprNode) []nameValuePa return nil } -func findPKHandle(tblInfo *model.TableInfo, pairs []nameValuePair) (handlePair nameValuePair, unsigned bool) { +func findPKHandle(tblInfo *model.TableInfo, pairs []nameValuePair) (handlePair nameValuePair, fieldType *types.FieldType) { if !tblInfo.PKIsHandle { - return handlePair, unsigned + return handlePair, nil } for _, col := range tblInfo.Columns { if mysql.HasPriKeyFlag(col.Flag) { i := findInPairs(col.Name.L, pairs) if i == -1 { - return handlePair, unsigned + return handlePair, nil } - return pairs[i], mysql.HasUnsignedFlag(col.Flag) + return pairs[i], &col.FieldType } } - return handlePair, unsigned + return handlePair, nil } func getIndexValues(idxInfo *model.IndexInfo, pairs []nameValuePair) ([]types.Datum, []*driver.ParamMarkerExpr) { @@ -427,6 +442,9 @@ func tryUpdatePointPlan(ctx sessionctx.Context, updateStmt *ast.UpdateStmt) Plan if checkFastPlanPrivilege(ctx, fastSelect, mysql.SelectPriv, mysql.UpdatePriv) != nil { return nil } + if fastSelect.IsTableDual { + return PhysicalTableDual{}.Init(ctx, &property.StatsInfo{}) + } orderedList := buildOrderedList(ctx, fastSelect, updateStmt.List) if orderedList == nil { return nil @@ -484,6 +502,9 @@ func tryDeletePointPlan(ctx sessionctx.Context, delStmt *ast.DeleteStmt) Plan { if checkFastPlanPrivilege(ctx, fastSelect, mysql.SelectPriv, mysql.DeletePriv) != nil { return nil } + if fastSelect.IsTableDual { + return PhysicalTableDual{}.Init(ctx, &property.StatsInfo{}) + } delPlan := Delete{ SelectPlan: fastSelect, }.Init(ctx) diff --git a/planner/core/point_get_plan_test.go b/planner/core/point_get_plan_test.go index 7d8eece9df1f8..eac7937801fbc 100644 --- a/planner/core/point_get_plan_test.go +++ b/planner/core/point_get_plan_test.go @@ -150,5 +150,5 @@ func (s *testPointGetSuite) TestPointGetPlanCache(c *C) { tk.MustQuery("execute stmt7 using @p2").Check(testkit.Rows("1")) counter.Write(pb) hit = pb.GetCounter().GetValue() - c.Check(hit, Equals, float64(3)) + c.Check(hit, Equals, float64(2)) }