Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]fix: show tables #762

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions pkg/proto/rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,50 @@ func (ru *Rule) Range(f func(table string, vt *VTable) bool) {
}
}
}

// GetInvertedPhyTableMap returns the inverse relationship from physical table name to logical table name.
func (ru *Rule) GetInvertedPhyTableMap() map[string]string {
var invertedIndex map[string]string
for logicalTable, v := range ru.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)
}
invertedIndex[phyTable] = logicalTable
}
return true
})
}

return invertedIndex
}

// GetInvertedVTableMap returns the inverse relationship from logical table name to all physical table name.
// TODO: did we need an sorted version?
func (ru *Rule) GetInvertedVTableMap() map[string][]string {
var invertedIndex map[string][]string

vtables := ru.VTables()
if len(vtables) > 0 {
invertedIndex = make(map[string][]string)
}

for logicalTable, v := range vtables {
t := v.Topology()

_, tblLength := t.Len()
// memory allocation
invertedIndex[logicalTable] = make([]string, 0, tblLength)

t.Each(func(x, y int) bool {
if _, phyTable, ok := t.Render(x, y); ok {
invertedIndex[logicalTable] = append(invertedIndex[logicalTable], phyTable)
}
return true
})
}

return invertedIndex
}
52 changes: 39 additions & 13 deletions pkg/proto/rule/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package rule

import (
"fmt"
"sort"
"testing"
)

Expand All @@ -34,20 +35,27 @@ import (
)

func TestRule(t *testing.T) {
m := make(map[int][]int)
const (
shardDBSize = 4
logicalVtableSize = 16
stepperSize = 1
)

for i := 0; i < 16; i++ {
m[i%4] = append(m[i%4], i%16)
topologyStatus := make(map[int][]int)

// table topology: 4 databases, 16 tables
for i := 0; i < logicalVtableSize; i++ {
topologyStatus[i%shardDBSize] = append(topologyStatus[i%shardDBSize], i%logicalVtableSize)
}

t.Log(m)
t.Log("topology: ", topologyStatus)

buildRule := func(c1, c2 ShardComputer) *Rule {
var (
ru Rule
vtab VTable
stepper = Stepper{
N: 1,
N: stepperSize,
U: Unum,
}
)
Expand Down Expand Up @@ -75,10 +83,10 @@ func TestRule(t *testing.T) {

// table topology: 4 databases, 16 tables
var topo Topology
topo.SetTopology(0, 0, 4, 8, 12)
topo.SetTopology(1, 1, 5, 9, 13)
topo.SetTopology(2, 2, 6, 10, 14)
topo.SetTopology(3, 3, 7, 11, 15)
for i := 0; i < logicalVtableSize; i++ {
topo.SetTopology(i%shardDBSize, topologyStatus[i%shardDBSize]...)
}

topo.SetRender(func(i int) string {
return fmt.Sprintf("school_%04d", i)
}, func(i int) string {
Expand All @@ -99,7 +107,7 @@ func TestRule(t *testing.T) {
Compute(gomock.Any()).
DoAndReturn(func(value proto.Value) (int, error) {
x, _ := value.Int64()
return int(x) % 16 / 4, nil
return int(x) % logicalVtableSize / shardDBSize, nil
}).
MinTimes(1)
c1.EXPECT().Variables().Return([]string{"uid"}).MinTimes(1)
Expand All @@ -109,7 +117,7 @@ func TestRule(t *testing.T) {
Compute(gomock.Any()).
DoAndReturn(func(value proto.Value) (int, error) {
x, _ := value.Int64()
return int(x % 16), nil
return int(x % logicalVtableSize), nil
}).
MinTimes(1)
c2.EXPECT().Variables().Return([]string{"uid"}).MinTimes(1)
Expand All @@ -130,8 +138,8 @@ func TestRule(t *testing.T) {
"uid": proto.NewValueInt64(42),
})
assert.NoError(t, err)
assert.Equal(t, uint32(2), dbIdx)
assert.Equal(t, uint32(10), tblIdx)
assert.Equal(t, uint32(42/logicalVtableSize), dbIdx)
assert.Equal(t, uint32(42%logicalVtableSize), tblIdx)

db, tbl, ok := vtab.Topology().Render(int(dbIdx), int(tblIdx))
assert.True(t, ok)
Expand All @@ -145,6 +153,24 @@ func TestRule(t *testing.T) {
})
assert.Error(t, err)

// test table name invert functions
phy2VtableMap := ru.GetInvertedPhyTableMap()
expectedPhy2VtableMap := make(map[string]string, logicalVtableSize)
for i := 0; i < logicalVtableSize; i++ {
expectedPhy2VtableMap[fmt.Sprintf("student_%04d", i)] = "student"
}
assert.Equal(t, expectedPhy2VtableMap, phy2VtableMap)

vtable2PhyMap := ru.GetInvertedVTableMap()
expectedVtable2PhyMap := make(map[string][]string)
for i := 0; i < logicalVtableSize; i++ {
expectedVtable2PhyMap["student"] = append(expectedVtable2PhyMap["student"], fmt.Sprintf("student_%04d", i))
}
for tblName := range vtable2PhyMap {
sort.Strings(vtable2PhyMap[tblName])
}
assert.Equal(t, expectedPhy2VtableMap, phy2VtableMap)

ru.RemoveVTable("student")
assert.False(t, ru.Has("student"))
assert.False(t, (*Rule)(nil).Has("student"))
Expand Down
12 changes: 7 additions & 5 deletions pkg/runtime/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,12 +735,14 @@ func (cc *convCtx) convShowStmt(node *ast.ShowStmt) Statement {
case ast.ShowShardingTable:
return &ShowShardingTable{BaseShow: toBaseShow()}
case ast.ShowTables:
var pattern sql.NullString
if like, ok := toLike(node); ok {
pattern.Valid = true
pattern.String = like
ret := &ShowTables{BaseShow: toBaseShow()}
if node.Extended {
ret.flag |= stFlagExtended
}
if node.Full {
ret.flag |= stFlagFull
}
return &ShowTables{BaseShowWithSingleColumn: &BaseShowWithSingleColumn{toBaseShow(), pattern}}
return ret
case ast.ShowReplicas:
return &ShowReplicas{BaseShow: toBaseShow()}
case ast.ShowMasterStatus:
Expand Down
32 changes: 29 additions & 3 deletions pkg/runtime/ast/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,19 +179,45 @@ func (s ShowCollation) Restore(flag RestoreFlag, sb *strings.Builder, args *[]in
return nil
}

type showTablesFlag int8

const (
stFlagFull showTablesFlag = 0x01 << iota
stFlagExtended
)

type ShowTables struct {
*BaseShowWithSingleColumn
*BaseShow
flag showTablesFlag
}

func (st *ShowTables) Mode() SQLType {
return SQLTypeShowTables
}

func (st *ShowTables) IsFull() bool {
return st.flag&stFlagFull != 0
}

func (st *ShowTables) IsExtended() bool {
return st.flag&stFlagExtended != 0
}

func (st *ShowTables) Restore(flag RestoreFlag, sb *strings.Builder, args *[]int) error {
sb.WriteString("SHOW TABLES")
if err := st.BaseShowWithSingleColumn.Restore(flag, sb, args); err != nil {
sb.WriteString("SHOW ")

if st.IsExtended() {
sb.WriteString("EXTENDED ")
}
if st.IsFull() {
sb.WriteString("FULL ")
}

sb.WriteString("TABLES")
if err := st.BaseShow.Restore(flag, sb, args); err != nil {
return errors.WithStack(err)
}

return nil
}

Expand Down
45 changes: 28 additions & 17 deletions pkg/runtime/optimize/dal/show_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,43 @@ import (
import (
"github.com/arana-db/arana/pkg/proto"
"github.com/arana-db/arana/pkg/runtime/ast"
rcontext "github.com/arana-db/arana/pkg/runtime/context"
"github.com/arana-db/arana/pkg/runtime/namespace"
"github.com/arana-db/arana/pkg/runtime/optimize"
"github.com/arana-db/arana/pkg/runtime/plan/dal"
"github.com/arana-db/arana/pkg/runtime/plan/dml"
"github.com/arana-db/arana/pkg/security"
)

func init() {
optimize.Register(ast.SQLTypeShowTables, optimizeShowTables)
}

func optimizeShowTables(_ context.Context, o *optimize.Optimizer) (proto.Plan, error) {
func optimizeShowTables(ctx context.Context, o *optimize.Optimizer) (proto.Plan, error) {
stmt := o.Stmt.(*ast.ShowTables)
var invertedIndex 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)
}
invertedIndex[phyTable] = logicalTable
}
return true
})
// construct table
invertedIndex := o.Rule.GetInvertedPhyTableMap()
// filter duplicates
duplicates := make(map[string]struct{})

tenant := rcontext.Tenant(ctx)
clusters := security.DefaultTenantManager().GetClusters(tenant)
plans := make([]proto.Plan, 0, len(clusters))
for _, cluster := range clusters {
ns := namespace.Load(tenant, cluster)
// execute query to all dbs
groups := ns.DBGroups()
for i := 0; i < len(groups); i++ {
ret := dal.NewShowTablesPlan(stmt)
ret.BindArgs(o.Args)
ret.SetInvertedShards(invertedIndex)
ret.SetDatabase(groups[i])
ret.SetDuplicates(duplicates)
plans = append(plans, ret)
}
}

ret := dal.NewShowTablesPlan(stmt)
ret.BindArgs(o.Args)
ret.SetInvertedShards(invertedIndex)
return ret, nil
return &dml.CompositePlan{
Plans: plans,
}, nil
}
14 changes: 8 additions & 6 deletions pkg/runtime/plan/dal/show_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ type ShowTablesPlan struct {
plan.BasePlan
Database string
Stmt *ast.ShowTables
invertedShards map[string]string // phy table name -> logical table name
invertedShards map[string]string // phy table name -> logical table name
duplicates map[string]struct{} // filter duplicates
}

// NewShowTablesPlan create ShowTables Plan
Expand Down Expand Up @@ -91,9 +92,6 @@ func (st *ShowTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (proto.R

fields[0] = mysql.NewField(headerPrefix+rcontext.Schema(ctx), constant.FieldTypeVarString)

// filter duplicates
duplicates := make(map[string]struct{})

// 1. convert to logical table name
// 2. filter duplicated table name
// 3. if pattern exists, then filter table name that matches with the pattern
Expand Down Expand Up @@ -128,10 +126,10 @@ func (st *ShowTablesPlan) ExecIn(ctx context.Context, conn proto.VConn) (proto.R
}

tableName := vr.Values()[0].String()
if _, ok := duplicates[tableName]; ok {
if _, ok := st.duplicates[tableName]; ok {
return false
}
duplicates[tableName] = struct{}{}
st.duplicates[tableName] = struct{}{}
return true
}, systemTablePrefix),
dataset.Filter(st.Stmt.Filter()),
Expand All @@ -147,3 +145,7 @@ func (st *ShowTablesPlan) SetDatabase(db string) {
func (st *ShowTablesPlan) SetInvertedShards(m map[string]string) {
st.invertedShards = m
}

func (st *ShowTablesPlan) SetDuplicates(m map[string]struct{}) {
st.duplicates = m
}
Loading