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/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..375d014f 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,19 +55,46 @@ 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 + } + } + + 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++ { - ret := dal.NewShowOpenTablesPlan(stmt) - ret.BindArgs(o.Args) - ret.SetInvertedShards(invertedIndex) - ret.SetDatabase(groups[i]) - plans = append(plans, ret) + 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) + } } } + 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 ca10e17a..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" ) @@ -40,16 +41,21 @@ 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 + 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, } } @@ -65,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) } @@ -85,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, @@ -97,6 +104,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) } @@ -118,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 } @@ -135,3 +154,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 +}