diff --git a/controllers/inspect/traverse_create.go b/controllers/inspect/traverse_create.go index 9f0a8bd..a40a5a8 100644 --- a/controllers/inspect/traverse_create.go +++ b/controllers/inspect/traverse_create.go @@ -482,7 +482,7 @@ func (c *TraverseCreateTableRedundantIndexes) Enter(in ast.Node) (ast.Node, bool for _, v := range cons.Keys { idxColsMap = append(idxColsMap, v.Column.Name.L) } - c.Redundant.IndexesCols = append(c.Redundant.IndexesCols, process.IndexColsMap{Index: cons.Name, Cols: idxColsMap}) + c.Redundant.IndexesCols = append(c.Redundant.IndexesCols, process.IndexColsMap{Index: cons.Name, Cols: idxColsMap, Tag: "is_meta"}) } } } diff --git a/controllers/process/index.go b/controllers/process/index.go index 0af77b1..e38e454 100644 --- a/controllers/process/index.go +++ b/controllers/process/index.go @@ -128,9 +128,10 @@ func (i *IndexNumber) CheckPrimaryKeyColsNum() error { } // 检查冗余索引 +// is_drop:drop操作,is_add:add操作,is_meta:原表表结构 type IndexColsMap struct { Index string // 索引 - Tag string // 标记,值:is_drop/is_add + Tag string // 标记,值:is_drop/is_add/is_meta Cols []string // 组成索引的列 } type RedundantIndex struct { @@ -161,22 +162,69 @@ func (r *RedundantIndex) CheckRepeatCols() error { } func (r *RedundantIndex) CheckRepeatColsWithDiffIndexes() error { - // 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写 + // 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写 // KEY idx_a_b (col1,col2), // KEY idx_b (col1,col2), - idxCols := make(map[string]bool) + // 获取is_add + var isAddIdxCols []string + // 获取is_drop + var isDropIdxCols []string + // 获取is_meta + isMetaIdxCols := make(map[string]string) for _, item := range r.IndexesCols { - // 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写 - // KEY idx_a_b (col1,col2), - // KEY idx_b (col1,col2), + if item.Tag == "is_add" { + isAddIdxCols = append(isAddIdxCols, item.Index) + } if item.Tag == "is_drop" { - continue + isDropIdxCols = append(isDropIdxCols, item.Index) } - valueJoin := strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)) - if !idxCols[valueJoin] { - idxCols[valueJoin] = true - } else { - return fmt.Errorf("表`%s`发现了重复定义的索引`%s`,已经存在定义列相同索引`%s`", r.Table, item.Index, strings.Join(item.Cols, ",")) + if item.Tag == "is_meta" { + isMetaIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)) + } + } + // 从is_meta数据中删除is_drop的数据 + for _, item := range isDropIdxCols { + delete(isMetaIdxCols, item) + } + // 为create table语句 + if len(isDropIdxCols) == 0 && len(isAddIdxCols) == 0 { + // 对map中的键进行分组 + groups := make(map[string][]string) + for key, value := range isMetaIdxCols { + groups[value] = append(groups[value], key) + } + var result []string + for _, keys := range groups { + if len(keys) > 1 { + result = append(result, strings.Join(keys, "/")) + } + } + if len(result) > 0 { + return fmt.Errorf("表`%s`发现了重复定义的索引:%s", r.Table, strings.Join(result, ";")) + } + } else { + // 为alter table xxx add / drop index + for _, item := range r.IndexesCols { + // 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写 + // KEY idx_a_b (col1,col2), + // KEY idx_b (col1,col2), + if item.Tag == "is_add" { + found := false + var foundKey string + valueJoin := strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)) + for key, value := range isMetaIdxCols { + if value == valueJoin { + found = true + foundKey = key + break + } + } + if !found { + isMetaIdxCols[item.Index] = valueJoin + } else { + return fmt.Errorf("表`%s`发现了重复定义的索引:%s(%s),请检查原始表结构", r.Table, foundKey, strings.Join(item.Cols, ", ")) + } + } } } return nil @@ -184,7 +232,7 @@ func (r *RedundantIndex) CheckRepeatColsWithDiffIndexes() error { func (r *RedundantIndex) CheckRedundantColsWithDiffIndexes() error { /* - 查找冗余的索引,即索引名不一样,但是定义的列冗余,不区分大小写 + 查找冗余的索引,即索引名不一样,但是定义的列冗余,不区分大小写 KEY idx_a (col1), KEY idx_b (col1,col2), KEY idx_c (col1,col2,col3) @@ -198,7 +246,7 @@ func (r *RedundantIndex) CheckRedundantColsWithDiffIndexes() error { {IDX_STATUS_UPDATETIME [i_status d_update_time]} ] */ - var idxCols []string + // idxCols := make(map[string]string) /* 解决冗余索引时,当指定drop冗余索引时,允许通过 @@ -206,34 +254,58 @@ func (r *RedundantIndex) CheckRedundantColsWithDiffIndexes() error { 添加索引: ALTER TABLE `tbl1` ADD UNIQUE uniq_bb(`a`,`b`,`c`),DROP INDEX `idx_aa`; */ - var IsDropIndexes []string - // 找出is_drop的索引操作 + // 获取is_drop + var isDropIdxCols []string + // 获取is_meta + isMetaIdxCols := make(map[string]string) + isAddIdxCols := make(map[string]string) + for _, item := range r.IndexesCols { + if item.Tag == "is_add" { + isAddIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)) + } if item.Tag == "is_drop" { - IsDropIndexes = append(IsDropIndexes, item.Index) + isDropIdxCols = append(isDropIdxCols, item.Index) } - } - // 从r.IndexesCols中移除is_drop的索引名 - for _, item := range r.IndexesCols { - if utils.IsContain(IsDropIndexes, item.Index) { - break + if item.Tag == "is_meta" { + isMetaIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)) } - idxCols = append(idxCols, strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))) } - // 检查是否存在冗余索引 - for _, k := range idxCols { - for _, k1 := range idxCols { - if k == k1 { - continue + // 从is_meta数据中删除is_drop的数据 + for _, item := range isDropIdxCols { + delete(isMetaIdxCols, item) + } + + // 为create table语句 + if len(isDropIdxCols) == 0 && len(isAddIdxCols) == 0 { + var result []string + for k, v := range isMetaIdxCols { + for k1, v1 := range isMetaIdxCols { + if v != v1 { + if strings.HasPrefix(v, v1) && utils.IsSubKey(v, v1) { + result = append(result, strings.Join([]string{k, k1}, "/")) + } + } } - if strings.HasPrefix(k, k1) && utils.IsSubKey(k, k1) { - return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为(%s)/(%s)【您可以增加一个drop原冗余索引的操作】", - r.Table, - strings.Replace(k, utils.KeyJoinChar, ",", -1), - strings.Replace(k1, utils.KeyJoinChar, ",", -1), - ) + } + if len(result) > 0 { + return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为%s", r.Table, strings.Join(result, ", ")) + } + } else { + // 为alter table xxx add / drop index + var result []string + for k, v := range isAddIdxCols { + for k1, v1 := range isMetaIdxCols { + if v != v1 { + if strings.HasPrefix(v, v1) && utils.IsSubKey(v, v1) { + result = append(result, strings.Join([]string{k, k1}, "/")) + } + } } } + if len(result) > 0 { + return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为%s", r.Table, strings.Join(result, ", ")) + } } return nil }