Files
tidb/pkg/meta/model/index.go

148 lines
4.7 KiB
Go

// Copyright 2024 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/parser/types"
)
// IndexInfo provides meta data describing a DB index.
// It corresponds to the statement `CREATE INDEX Name ON Table (Column);`
// See https://dev.mysql.com/doc/refman/5.7/en/create-index.html
type IndexInfo struct {
ID int64 `json:"id"`
Name model.CIStr `json:"idx_name"` // Index name.
Table model.CIStr `json:"tbl_name"` // Table name.
Columns []*IndexColumn `json:"idx_cols"` // Index columns.
State SchemaState `json:"state"`
BackfillState BackfillState `json:"backfill_state"`
Comment string `json:"comment"` // Comment
Tp model.IndexType `json:"index_type"` // Index type: Btree, Hash or Rtree
Unique bool `json:"is_unique"` // Whether the index is unique.
Primary bool `json:"is_primary"` // Whether the index is primary key.
Invisible bool `json:"is_invisible"` // Whether the index is invisible.
Global bool `json:"is_global"` // Whether the index is global.
MVIndex bool `json:"mv_index"` // Whether the index is multivalued index.
}
// Clone clones IndexInfo.
func (index *IndexInfo) Clone() *IndexInfo {
if index == nil {
return nil
}
ni := *index
ni.Columns = make([]*IndexColumn, len(index.Columns))
for i := range index.Columns {
ni.Columns[i] = index.Columns[i].Clone()
}
return &ni
}
// HasPrefixIndex returns whether any columns of this index uses prefix length.
func (index *IndexInfo) HasPrefixIndex() bool {
for _, ic := range index.Columns {
if ic.Length != types.UnspecifiedLength {
return true
}
}
return false
}
// HasColumnInIndexColumns checks whether the index contains the column with the specified ID.
func (index *IndexInfo) HasColumnInIndexColumns(tblInfo *TableInfo, colID int64) bool {
for _, ic := range index.Columns {
if tblInfo.Columns[ic.Offset].ID == colID {
return true
}
}
return false
}
// FindColumnByName finds the index column with the specified name.
func (index *IndexInfo) FindColumnByName(nameL string) *IndexColumn {
_, ret := FindIndexColumnByName(index.Columns, nameL)
return ret
}
// IsPublic checks if the index state is public
func (index *IndexInfo) IsPublic() bool {
return index.State == StatePublic
}
// FindIndexByColumns find IndexInfo in indices which is cover the specified columns.
func FindIndexByColumns(tbInfo *TableInfo, indices []*IndexInfo, cols ...model.CIStr) *IndexInfo {
for _, index := range indices {
if IsIndexPrefixCovered(tbInfo, index, cols...) {
return index
}
}
return nil
}
// IsIndexPrefixCovered checks the index's columns beginning with the cols.
func IsIndexPrefixCovered(tbInfo *TableInfo, index *IndexInfo, cols ...model.CIStr) bool {
if len(index.Columns) < len(cols) {
return false
}
for i := range cols {
if cols[i].L != index.Columns[i].Name.L ||
index.Columns[i].Offset >= len(tbInfo.Columns) {
return false
}
colInfo := tbInfo.Columns[index.Columns[i].Offset]
if index.Columns[i].Length != types.UnspecifiedLength && index.Columns[i].Length < colInfo.GetFlen() {
return false
}
}
return true
}
// FindIndexInfoByID finds IndexInfo in indices by id.
func FindIndexInfoByID(indices []*IndexInfo, id int64) *IndexInfo {
for _, idx := range indices {
if idx.ID == id {
return idx
}
}
return nil
}
// IndexColumn provides index column info.
type IndexColumn struct {
Name model.CIStr `json:"name"` // Index name
Offset int `json:"offset"` // Index offset
// Length of prefix when using column prefix
// for indexing;
// UnspecifedLength if not using prefix indexing
Length int `json:"length"`
}
// Clone clones IndexColumn.
func (i *IndexColumn) Clone() *IndexColumn {
ni := *i
return &ni
}
// FindIndexColumnByName finds IndexColumn by name. When IndexColumn is not found, returns (-1, nil).
func FindIndexColumnByName(indexCols []*IndexColumn, nameL string) (int, *IndexColumn) {
for i, ic := range indexCols {
if ic.Name.L == nameL {
return i, ic
}
}
return -1, nil
}