From 7698b7598e3c3e50808c075b037c5d1e546342a3 Mon Sep 17 00:00:00 2001 From: gufengwyx8 <466144425@qq.com> Date: Wed, 7 Feb 2024 01:03:58 +0800 Subject: [PATCH 1/3] fix: optimize show open tables xxx statment (#676) --- pkg/runtime/ast/show.go | 4 +++ pkg/runtime/optimize/dal/show_open_tables.go | 31 ++++++++++++++++---- pkg/runtime/plan/dal/show_open_tables.go | 17 ++++++++--- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/pkg/runtime/ast/show.go b/pkg/runtime/ast/show.go index b5376a97..dcc85237 100644 --- a/pkg/runtime/ast/show.go +++ b/pkg/runtime/ast/show.go @@ -64,6 +64,10 @@ type BaseShow struct { filter interface{} // ExpressionNode or string } +func NewBaseShow(filter string) BaseShow { + return BaseShow{filter: filter} +} + func (bs *BaseShow) Restore(flag RestoreFlag, sb *strings.Builder, args *[]int) error { switch val := bs.filter.(type) { case string: diff --git a/pkg/runtime/optimize/dal/show_open_tables.go b/pkg/runtime/optimize/dal/show_open_tables.go index 51ec124c..56fde854 100644 --- a/pkg/runtime/optimize/dal/show_open_tables.go +++ b/pkg/runtime/optimize/dal/show_open_tables.go @@ -37,15 +37,15 @@ func init() { } func optimizeShowOpenTables(ctx context.Context, o *optimize.Optimizer) (proto.Plan, error) { - var invertedIndex map[string]string + var invertedShards map[string]string for logicalTable, v := range o.Rule.VTables() { t := v.Topology() t.Each(func(x, y int) bool { if _, phyTable, ok := t.Render(x, y); ok { - if invertedIndex == nil { - invertedIndex = make(map[string]string) + if invertedShards == nil { + invertedShards = make(map[string]string) } - invertedIndex[phyTable] = logicalTable + invertedShards[phyTable] = logicalTable } return true }) @@ -55,15 +55,34 @@ func optimizeShowOpenTables(ctx context.Context, o *optimize.Optimizer) (proto.P tenant := rcontext.Tenant(ctx) clusters := security.DefaultTenantManager().GetClusters(tenant) + + invertedDatabases := make(map[string]string) + for _, cluster := range clusters { + ns := namespace.Load(tenant, cluster) + for _, d := range ns.DBGroups() { + invertedDatabases[d] = cluster + } + } + plans := make([]proto.Plan, 0, len(clusters)) for _, cluster := range clusters { ns := namespace.Load(tenant, cluster) // 配置里原子库 都需要执行一次 groups := ns.DBGroups() for i := 0; i < len(groups); i++ { - ret := dal.NewShowOpenTablesPlan(stmt) + var ret *dal.ShowOpenTablesPlan + if db, ok := stmt.Like(); ok && db == cluster { + // filter in cluster + show := ast.NewBaseShow(groups[i]) + stmtCopy := ast.ShowOpenTables{BaseShow: &show} + ret = dal.NewShowOpenTablesPlan(&stmtCopy) + } else { + // no filter or can't match any group + ret = dal.NewShowOpenTablesPlan(stmt) + } ret.BindArgs(o.Args) - ret.SetInvertedShards(invertedIndex) + ret.SetInvertedShards(invertedShards) + ret.SetInvertedDatabases(invertedDatabases) ret.SetDatabase(groups[i]) plans = append(plans, ret) } diff --git a/pkg/runtime/plan/dal/show_open_tables.go b/pkg/runtime/plan/dal/show_open_tables.go index ca10e17a..aeb2e2df 100644 --- a/pkg/runtime/plan/dal/show_open_tables.go +++ b/pkg/runtime/plan/dal/show_open_tables.go @@ -40,10 +40,11 @@ var _ proto.Plan = (*ShowOpenTablesPlan)(nil) type ShowOpenTablesPlan struct { plan.BasePlan - Database string - Conn proto.DB - Stmt *ast.ShowOpenTables - invertedShards map[string]string // phy table name -> logical table name + Database string + Conn proto.DB + Stmt *ast.ShowOpenTables + invertedShards map[string]string // phy table name -> logical table name + invertedDatabases map[string]string // phy database name -> logical database name } // NewShowOpenTablesPlan create ShowTables Plan @@ -97,6 +98,10 @@ func (st *ShowOpenTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (pro return next, nil } + if logicDatabaseName, ok := st.invertedDatabases[dest[0].String()]; ok { + dest[0] = proto.NewValueString(logicDatabaseName) + } + if logicalTableName, ok := st.invertedShards[dest[1].String()]; ok { dest[1] = proto.NewValueString(logicalTableName) } @@ -135,3 +140,7 @@ func (st *ShowOpenTablesPlan) SetDatabase(database string) { func (st *ShowOpenTablesPlan) SetInvertedShards(m map[string]string) { st.invertedShards = m } + +func (st *ShowOpenTablesPlan) SetInvertedDatabases(m map[string]string) { + st.invertedDatabases = m +} From aa7f09eaf3255838cee27ce429b62aa78f86e3aa Mon Sep 17 00:00:00 2001 From: gufengwyx8 <466144425@qq.com> Date: Wed, 7 Feb 2024 09:48:40 +0800 Subject: [PATCH 2/3] fix: convert english comments (#676) --- pkg/runtime/optimize/dal/show_open_tables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/runtime/optimize/dal/show_open_tables.go b/pkg/runtime/optimize/dal/show_open_tables.go index 56fde854..7931233d 100644 --- a/pkg/runtime/optimize/dal/show_open_tables.go +++ b/pkg/runtime/optimize/dal/show_open_tables.go @@ -67,7 +67,7 @@ func optimizeShowOpenTables(ctx context.Context, o *optimize.Optimizer) (proto.P plans := make([]proto.Plan, 0, len(clusters)) for _, cluster := range clusters { ns := namespace.Load(tenant, cluster) - // 配置里原子库 都需要执行一次 + // check every group from namespace groups := ns.DBGroups() for i := 0; i < len(groups); i++ { var ret *dal.ShowOpenTablesPlan From 89c8bd15ac83db1c7b80719a4289cca547f14f19 Mon Sep 17 00:00:00 2001 From: gufengwyx8 <466144425@qq.com> Date: Wed, 10 Apr 2024 23:20:11 +0800 Subject: [PATCH 3/3] fix: fix bug can't match any group (#676) --- pkg/mysql/thead/thead.go | 7 ++++ pkg/runtime/optimize/dal/show_open_tables.go | 36 ++++++++++++-------- pkg/runtime/plan/dal/show_open_tables.go | 32 ++++++++++++----- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/pkg/mysql/thead/thead.go b/pkg/mysql/thead/thead.go index 6dcdc034..a1273417 100644 --- a/pkg/mysql/thead/thead.go +++ b/pkg/mysql/thead/thead.go @@ -78,6 +78,13 @@ var ( Col{Name: "expr", FieldType: consts.FieldTypeVarString}, Col{Name: "step", FieldType: consts.FieldTypeVarString}, } + + OpenTables = Thead{ + Col{Name: "Database", FieldType: consts.FieldTypeVarString}, + Col{Name: "Table", FieldType: consts.FieldTypeVarString}, + Col{Name: "In_use", FieldType: consts.FieldTypeInt24}, + Col{Name: "Name_locked", FieldType: consts.FieldTypeInt24}, + } ) type Col struct { diff --git a/pkg/runtime/optimize/dal/show_open_tables.go b/pkg/runtime/optimize/dal/show_open_tables.go index 7931233d..375d014f 100644 --- a/pkg/runtime/optimize/dal/show_open_tables.go +++ b/pkg/runtime/optimize/dal/show_open_tables.go @@ -64,29 +64,37 @@ func optimizeShowOpenTables(ctx context.Context, o *optimize.Optimizer) (proto.P } } + duplicates := make(map[string]struct{}) + plans := make([]proto.Plan, 0, len(clusters)) for _, cluster := range clusters { ns := namespace.Load(tenant, cluster) // check every group from namespace groups := ns.DBGroups() for i := 0; i < len(groups); i++ { - var ret *dal.ShowOpenTablesPlan - if db, ok := stmt.Like(); ok && db == cluster { - // filter in cluster - show := ast.NewBaseShow(groups[i]) - stmtCopy := ast.ShowOpenTables{BaseShow: &show} - ret = dal.NewShowOpenTablesPlan(&stmtCopy) - } else { - // no filter or can't match any group - ret = dal.NewShowOpenTablesPlan(stmt) + if db, ok := stmt.Like(); !ok || db == cluster { + var ret *dal.ShowOpenTablesPlan + if ok { + // filter in cluster + show := ast.NewBaseShow(groups[i]) + stmtCopy := ast.ShowOpenTables{BaseShow: &show} + ret = dal.NewShowOpenTablesPlan(&stmtCopy, duplicates, false) + } else { + // no filter + ret = dal.NewShowOpenTablesPlan(stmt, duplicates, false) + } + ret.BindArgs(o.Args) + ret.SetInvertedShards(invertedShards) + ret.SetInvertedDatabases(invertedDatabases) + ret.SetDatabase(groups[i]) + plans = append(plans, ret) } - ret.BindArgs(o.Args) - ret.SetInvertedShards(invertedShards) - ret.SetInvertedDatabases(invertedDatabases) - ret.SetDatabase(groups[i]) - plans = append(plans, ret) } } + if len(plans) == 0 { + // can't match any group + return dal.NewShowOpenTablesPlan(stmt, duplicates, true), nil + } return &dml.CompositePlan{ Plans: plans, diff --git a/pkg/runtime/plan/dal/show_open_tables.go b/pkg/runtime/plan/dal/show_open_tables.go index aeb2e2df..749288c9 100644 --- a/pkg/runtime/plan/dal/show_open_tables.go +++ b/pkg/runtime/plan/dal/show_open_tables.go @@ -19,6 +19,7 @@ package dal import ( "context" + "github.com/arana-db/arana/pkg/mysql/thead" "strings" ) @@ -43,14 +44,18 @@ type ShowOpenTablesPlan struct { Database string Conn proto.DB Stmt *ast.ShowOpenTables - invertedShards map[string]string // phy table name -> logical table name - invertedDatabases map[string]string // phy database name -> logical database name + invertedShards map[string]string // phy table name -> logical table name + invertedDatabases map[string]string // phy database name -> logical database name + duplicates map[string]struct{} // filter duplicates + empty bool // if can't match any group, return empty result } // NewShowOpenTablesPlan create ShowTables Plan -func NewShowOpenTablesPlan(stmt *ast.ShowOpenTables) *ShowOpenTablesPlan { +func NewShowOpenTablesPlan(stmt *ast.ShowOpenTables, duplicates map[string]struct{}, empty bool) *ShowOpenTablesPlan { return &ShowOpenTablesPlan{ - Stmt: stmt, + Stmt: stmt, + duplicates: duplicates, + empty: empty, } } @@ -66,6 +71,10 @@ func (st *ShowOpenTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (pro err error ) + if st.empty { + return emptyRs(), nil + } + if err = st.Stmt.Restore(ast.RestoreDefault, &sb, &indexes); err != nil { return nil, errors.WithStack(err) } @@ -86,9 +95,6 @@ func (st *ShowOpenTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (pro fields, _ := ds.Fields() - // filter duplicates - duplicates := make(map[string]struct{}) - // 1. convert to logical table name // 2. filter duplicated table name ds = dataset.Pipe(ds, @@ -123,16 +129,24 @@ func (st *ShowOpenTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (pro } tableName := vr.Values()[1].String() - if _, ok := duplicates[tableName]; ok { + if _, ok := st.duplicates[tableName]; ok { return false } - duplicates[tableName] = struct{}{} + st.duplicates[tableName] = struct{}{} return true }), ) return resultx.New(resultx.WithDataset(ds)), nil } +func emptyRs() proto.Result { + columns := thead.OpenTables.ToFields() + ds := &dataset.VirtualDataset{ + Columns: columns, + } + return resultx.New(resultx.WithDataset(ds)) +} + func (st *ShowOpenTablesPlan) SetDatabase(database string) { st.Database = database }