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

*: add TestLocalTemporaryTableInfoSchema to store local temporary table schemas #25518

Merged
merged 14 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from 13 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
155 changes: 155 additions & 0 deletions infoschema/infoschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,158 @@ func GetBundle(h InfoSchema, ids []int64) *placement.Bundle {
}
return &placement.Bundle{ID: placement.GroupID(id), Rules: newRules}
}

type schemaLocalTempSchemaTables struct {
tables map[string]table.Table
}

// LocalTemporaryTables store local temporary tables
type LocalTemporaryTables struct {
schemaMap map[string]*schemaLocalTempSchemaTables
idx2table map[int64]table.Table
}

// NewLocalTemporaryTableInfoSchema creates a new LocalTemporaryTableInfoSchema object
func NewLocalTemporaryTableInfoSchema() *LocalTemporaryTables {
return &LocalTemporaryTables{
schemaMap: make(map[string]*schemaLocalTempSchemaTables),
idx2table: make(map[int64]table.Table),
}
}

// TableByName get table by name
func (is *LocalTemporaryTables) TableByName(schema, table model.CIStr) (table.Table, bool) {
if tbNames, ok := is.schemaMap[schema.L]; ok {
if t, ok := tbNames.tables[table.L]; ok {
return t, true
}
}
return nil, false
}

// TableExists check if table with the name exists
func (is *LocalTemporaryTables) TableExists(schema, table model.CIStr) (ok bool) {
_, ok = is.TableByName(schema, table)
return
}

// TableByID get table by table id
func (is *LocalTemporaryTables) TableByID(id int64) (tbl table.Table, ok bool) {
tbl, ok = is.idx2table[id]
return
}

// AddTable add a table
func (is *LocalTemporaryTables) AddTable(schema *model.DBInfo, tbl table.Table) error {
schemaTables := is.ensureSchema(schema.Name)

tblMeta := tbl.Meta()
if _, ok := schemaTables.tables[tblMeta.Name.L]; ok {
return ErrTableExists.GenWithStackByArgs(tblMeta.Name)
}

if _, ok := is.idx2table[tblMeta.ID]; ok {
return ErrTableExists.GenWithStackByArgs(tblMeta.Name)
}

schemaTables.tables[tblMeta.Name.L] = tbl
is.idx2table[tblMeta.ID] = tbl

return nil
}

// RemoveTable remove a table
func (is *LocalTemporaryTables) RemoveTable(schema, table model.CIStr) (exist bool) {
tbls := is.schemaTables(schema)
if tbls == nil {
return false
}

oldTable, exist := tbls.tables[table.L]
if !exist {
return false
}

delete(tbls.tables, table.L)
delete(is.idx2table, oldTable.Meta().ID)
return true
}

// SchemaByTable get a table's schema name
func (is *LocalTemporaryTables) SchemaByTable(tableInfo *model.TableInfo) (string, bool) {
if tableInfo == nil {
return "", false
}

for schema, v := range is.schemaMap {
if tbl, ok := v.tables[tableInfo.Name.L]; ok {
if tbl.Meta().ID == tableInfo.ID {
return schema, true
}
}
}

return "", false
}

func (is *LocalTemporaryTables) ensureSchema(schema model.CIStr) *schemaLocalTempSchemaTables {
if tbls, ok := is.schemaMap[schema.L]; ok {
return tbls
}

tbls := &schemaLocalTempSchemaTables{tables: make(map[string]table.Table)}
is.schemaMap[schema.L] = tbls
return tbls
}

func (is *LocalTemporaryTables) schemaTables(schema model.CIStr) *schemaLocalTempSchemaTables {
if is.schemaMap == nil {
return nil
}

if tbls, ok := is.schemaMap[schema.L]; ok {
return tbls
}

return nil
}

// TemporaryTableAttachedInfoSchema implements InfoSchema
// Local temporary table has a loose relationship with database.
// So when a database is dropped, its temporary tables still exist and can be return by TableByName/TableByID.
// However SchemaByTable will return nil if database is dropped.
type TemporaryTableAttachedInfoSchema struct {
InfoSchema
LocalTemporaryTables *LocalTemporaryTables
}

// TableByName implements InfoSchema.TableByName
func (ts *TemporaryTableAttachedInfoSchema) TableByName(schema, table model.CIStr) (table.Table, error) {
if tbl, ok := ts.LocalTemporaryTables.TableByName(schema, table); ok {
return tbl, nil
}

return ts.InfoSchema.TableByName(schema, table)
}

// TableByID implements InfoSchema.TableByID
func (ts *TemporaryTableAttachedInfoSchema) TableByID(id int64) (table.Table, bool) {
if tbl, ok := ts.LocalTemporaryTables.TableByID(id); ok {
return tbl, true
}

return ts.InfoSchema.TableByID(id)
}

// SchemaByTable implements InfoSchema.SchemaByTable
func (ts *TemporaryTableAttachedInfoSchema) SchemaByTable(tableInfo *model.TableInfo) (*model.DBInfo, bool) {
if tableInfo == nil {
return nil, false
}

if schemaName, ok := ts.LocalTemporaryTables.SchemaByTable(tableInfo); ok {
return ts.SchemaByName(model.NewCIStr(schemaName))
}

return ts.InfoSchema.SchemaByTable(tableInfo)
}
Loading