1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- // Copyright 2015 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,
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package model
- import (
- "encoding/json"
- "strconv"
- "strings"
- "time"
- "github.com/pingcap/errors"
- "github.com/pingcap/parser/auth"
- "github.com/pingcap/parser/mysql"
- "github.com/pingcap/parser/types"
- )
- // SchemaState is the state for schema elements.
- type SchemaState byte
- const (
- // StateNone means this schema element is absent and can't be used.
- StateNone SchemaState = iota
- // StateDeleteOnly means we can only delete items for this schema element.
- StateDeleteOnly
- // StateWriteOnly means we can use any write operation on this schema element,
- // but outer can't read the changed data.
- StateWriteOnly
- // StateWriteReorganization means we are re-organizing whole data after write only state.
- StateWriteReorganization
- // StateDeleteReorganization means we are re-organizing whole data after delete only state.
- StateDeleteReorganization
- // StatePublic means this schema element is ok for all write and read operations.
- StatePublic
- // StateReplica means we're waiting tiflash replica to be finished.
- StateReplicaOnly
- // StateGlobalTxnOnly means we can only use global txn for operator on this schema element
- StateGlobalTxnOnly
- /*
- * Please add the new state at the end to keep the values consistent across versions.
- */
- )
- // String implements fmt.Stringer interface.
- func (s SchemaState) String() string {
- switch s {
- case StateDeleteOnly:
- return "delete only"
- case StateWriteOnly:
- return "write only"
- case StateWriteReorganization:
- return "write reorganization"
- case StateDeleteReorganization:
- return "delete reorganization"
- case StatePublic:
- return "public"
- case StateReplicaOnly:
- return "replica only"
- case StateGlobalTxnOnly:
- return "global txn only"
- default:
- return "none"
- }
- }
- const (
- // ColumnInfoVersion0 means the column info version is 0.
- ColumnInfoVersion0 = uint64(0)
- // ColumnInfoVersion1 means the column info version is 1.
- ColumnInfoVersion1 = uint64(1)
- // ColumnInfoVersion2 means the column info version is 2.
- // This is for v2.1.7 to Compatible with older versions charset problem.
- // Old version such as v2.0.8 treat utf8 as utf8mb4, because there is no UTF8 check in v2.0.8.
- // After version V2.1.2 (PR#8738) , TiDB add UTF8 check, then the user upgrade from v2.0.8 insert some UTF8MB4 characters will got error.
- // This is not compatibility for user. Then we try to fix this in PR #9820, and increase the version number.
- ColumnInfoVersion2 = uint64(2)
- // CurrLatestColumnInfoVersion means the latest column info in the current TiDB.
- CurrLatestColumnInfoVersion = ColumnInfoVersion2
- )
- // ChangeStateInfo is used for recording the information of schema changing.
- type ChangeStateInfo struct {
- // DependencyColumnOffset is the changing column offset that the current column depends on when executing modify/change column.
- DependencyColumnOffset int `json:"relative_col_offset"`
- }
- // ColumnInfo provides meta data describing of a table column.
- type ColumnInfo struct {
- ID int64 `json:"id"`
- Name CIStr `json:"name"`
- Offset int `json:"offset"`
- OriginDefaultValue interface{} `json:"origin_default"`
- OriginDefaultValueBit []byte `json:"origin_default_bit"`
- DefaultValue interface{} `json:"default"`
- DefaultValueBit []byte `json:"default_bit"`
- // DefaultIsExpr is indicates the default value string is expr.
- DefaultIsExpr bool `json:"default_is_expr"`
- GeneratedExprString string `json:"generated_expr_string"`
- GeneratedStored bool `json:"generated_stored"`
- Dependences map[string]struct{} `json:"dependences"`
- types.FieldType `json:"type"`
- State SchemaState `json:"state"`
- Comment string `json:"comment"`
- // A hidden column is used internally(expression index) and are not accessible by users.
- Hidden bool `json:"hidden"`
- *ChangeStateInfo `json:"change_state_info"`
- // Version means the version of the column info.
- // Version = 0: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in system time zone.
- // That is a bug if multiple TiDB servers in different system time zone.
- // Version = 1: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in UTC time zone.
- // This will fix bug in version 0. For compatibility with version 0, we add version field in column info struct.
- Version uint64 `json:"version"`
- }
- // Clone clones ColumnInfo.
- func (c *ColumnInfo) Clone() *ColumnInfo {
- nc := *c
- return &nc
- }
- // IsGenerated returns true if the column is generated column.
- func (c *ColumnInfo) IsGenerated() bool {
- return len(c.GeneratedExprString) != 0
- }
- // SetOriginalDefaultValue sets the origin default value.
- // For mysql.TypeBit type, the default value storage format must be a string.
- // Other value such as int must convert to string format first.
- // The mysql.TypeBit type supports the null default value.
- func (c *ColumnInfo) SetOriginDefaultValue(value interface{}) error {
- c.OriginDefaultValue = value
- if c.Tp == mysql.TypeBit {
- if value == nil {
- return nil
- }
- if v, ok := value.(string); ok {
- c.OriginDefaultValueBit = []byte(v)
- return nil
- }
- return types.ErrInvalidDefault.GenWithStackByArgs(c.Name)
- }
- return nil
- }
- // GetOriginalDefaultValue gets the origin default value.
- func (c *ColumnInfo) GetOriginDefaultValue() interface{} {
- if c.Tp == mysql.TypeBit && c.OriginDefaultValueBit != nil {
- // If the column type is BIT, both `OriginDefaultValue` and `DefaultValue` of ColumnInfo are corrupted,
- // because the content before json.Marshal is INCONSISTENT with the content after json.Unmarshal.
- return string(c.OriginDefaultValueBit)
- }
- return c.OriginDefaultValue
- }
- // SetDefaultValue sets the default value.
- func (c *ColumnInfo) SetDefaultValue(value interface{}) error {
- c.DefaultValue = value
- if c.Tp == mysql.TypeBit {
- // For mysql.TypeBit type, the default value storage format must be a string.
- // Other value such as int must convert to string format first.
- // The mysql.TypeBit type supports the null default value.
- if value == nil {
- return nil
- }
- if v, ok := value.(string); ok {
- c.DefaultValueBit = []byte(v)
- return nil
- }
- return types.ErrInvalidDefault.GenWithStackByArgs(c.Name)
- }
- return nil
- }
- // GetDefaultValue gets the default value of the column.
- // Default value use to stored in DefaultValue field, but now,
- // bit type default value will store in DefaultValueBit for fix bit default value decode/encode bug.
- func (c *ColumnInfo) GetDefaultValue() interface{} {
- if c.Tp == mysql.TypeBit && c.DefaultValueBit != nil {
- return string(c.DefaultValueBit)
- }
- return c.DefaultValue
- }
- // GetTypeDesc gets the description for column type.
- func (c *ColumnInfo) GetTypeDesc() string {
- desc := c.FieldType.CompactStr()
- if mysql.HasUnsignedFlag(c.Flag) && c.Tp != mysql.TypeBit && c.Tp != mysql.TypeYear {
- desc += " unsigned"
- }
- if mysql.HasZerofillFlag(c.Flag) && c.Tp != mysql.TypeYear {
- desc += " zerofill"
- }
- return desc
- }
- // FindColumnInfo finds ColumnInfo in cols by name.
- func FindColumnInfo(cols []*ColumnInfo, name string) *ColumnInfo {
- name = strings.ToLower(name)
- for _, col := range cols {
- if col.Name.L == name {
- return col
- }
- }
- return nil
- }
- // ExtraHandleID is the column ID of column which we need to append to schema to occupy the handle's position
- // for use of execution phase.
- const ExtraHandleID = -1
- // ExtraPartitionID is the column ID of column which store the partitionID decoded in global index values.
- const ExtraPidColID = -2
- const (
- // TableInfoVersion0 means the table info version is 0.
- // Upgrade from v2.1.1 or v2.1.2 to v2.1.3 and later, and then execute a "change/modify column" statement
- // that does not specify a charset value for column. Then the following error may be reported:
- // ERROR 1105 (HY000): unsupported modify charset from utf8mb4 to utf8.
- // To eliminate this error, we will not modify the charset of this column
- // when executing a change/modify column statement that does not specify a charset value for column.
- // This behavior is not compatible with MySQL.
- TableInfoVersion0 = uint16(0)
- // TableInfoVersion1 means the table info version is 1.
- // When we execute a change/modify column statement that does not specify a charset value for column,
- // we set the charset of this column to the charset of table. This behavior is compatible with MySQL.
- TableInfoVersion1 = uint16(1)
- // TableInfoVersion2 means the table info version is 2.
- // This is for v2.1.7 to Compatible with older versions charset problem.
- // Old version such as v2.0.8 treat utf8 as utf8mb4, because there is no UTF8 check in v2.0.8.
- // After version V2.1.2 (PR#8738) , TiDB add UTF8 check, then the user upgrade from v2.0.8 insert some UTF8MB4 characters will got error.
- // This is not compatibility for user. Then we try to fix this in PR #9820, and increase the version number.
- TableInfoVersion2 = uint16(2)
- // TableInfoVersion3 means the table info version is 3.
- // This version aims to deal with upper-cased charset name in TableInfo stored by versions prior to TiDB v2.1.9:
- // TiDB always suppose all charsets / collations as lower-cased and try to convert them if they're not.
- // However, the convert is missed in some scenarios before v2.1.9, so for all those tables prior to TableInfoVersion3, their
- // charsets / collations will be converted to lower-case while loading from the storage.
- TableInfoVersion3 = uint16(3)
- // TableInfoVersion4 indicates that the auto_increment allocator in TiDB has been separated from
- // _tidb_rowid allocator. This version is introduced to preserve the compatibility of old tables:
- // the tables with version < TableInfoVersion4 still use a single allocator for auto_increment and _tidb_rowid.
- // Also see https://github.com/pingcap/tidb/issues/982.
- TableInfoVersion4 = uint16(4)
- // CurrLatestTableInfoVersion means the latest table info in the current TiDB.
- CurrLatestTableInfoVersion = TableInfoVersion4
- )
- // ExtraHandleName is the name of ExtraHandle Column.
- var ExtraHandleName = NewCIStr("_tidb_rowid")
- // ExtraPartitionIdName is the name of ExtraPartitionId Column.
- var ExtraPartitionIdName = NewCIStr("_tidb_pid")
- // TableInfo provides meta data describing a DB table.
- type TableInfo struct {
- ID int64 `json:"id"`
- Name CIStr `json:"name"`
- Charset string `json:"charset"`
- Collate string `json:"collate"`
- // Columns are listed in the order in which they appear in the schema.
- Columns []*ColumnInfo `json:"cols"`
- Indices []*IndexInfo `json:"index_info"`
- Constraints []*ConstraintInfo `json:"constraint_info"`
- ForeignKeys []*FKInfo `json:"fk_info"`
- State SchemaState `json:"state"`
- // PKIsHandle is true when primary key is a single integer column.
- PKIsHandle bool `json:"pk_is_handle"`
- // IsCommonHandle is true when clustered index feature is
- // enabled and the primary key is not a single integer column.
- IsCommonHandle bool `json:"is_common_handle"`
- // CommonHandleVersion is the version of the clustered index.
- // 0 for the clustered index created == 5.0.0 RC.
- // 1 for the clustered index created > 5.0.0 RC.
- CommonHandleVersion uint16 `json:"common_handle_version"`
- Comment string `json:"comment"`
- AutoIncID int64 `json:"auto_inc_id"`
- AutoIdCache int64 `json:"auto_id_cache"`
- AutoRandID int64 `json:"auto_rand_id"`
- MaxColumnID int64 `json:"max_col_id"`
- MaxIndexID int64 `json:"max_idx_id"`
- MaxConstraintID int64 `json:"max_cst_id"`
- // UpdateTS is used to record the timestamp of updating the table's schema information.
- // These changing schema operations don't include 'truncate table' and 'rename table'.
- UpdateTS uint64 `json:"update_timestamp"`
- // OldSchemaID :
- // Because auto increment ID has schemaID as prefix,
- // We need to save original schemaID to keep autoID unchanged
- // while renaming a table from one database to another.
- // TODO: Remove it.
- // Now it only uses for compatibility with the old version that already uses this field.
- OldSchemaID int64 `json:"old_schema_id,omitempty"`
- // ShardRowIDBits specify if the implicit row ID is sharded.
- ShardRowIDBits uint64
- // MaxShardRowIDBits uses to record the max ShardRowIDBits be used so far.
- MaxShardRowIDBits uint64 `json:"max_shard_row_id_bits"`
- // AutoRandomBits is used to set the bit number to shard automatically when PKIsHandle.
- AutoRandomBits uint64 `json:"auto_random_bits"`
- // PreSplitRegions specify the pre-split region when create table.
- // The pre-split region num is 2^(PreSplitRegions-1).
- // And the PreSplitRegions should less than or equal to ShardRowIDBits.
- PreSplitRegions uint64 `json:"pre_split_regions"`
- Partition *PartitionInfo `json:"partition"`
- Compression string `json:"compression"`
- View *ViewInfo `json:"view"`
- Sequence *SequenceInfo `json:"sequence"`
- // Lock represent the table lock info.
- Lock *TableLockInfo `json:"Lock"`
- // Version means the version of the table info.
- Version uint16 `json:"version"`
- // TiFlashReplica means the TiFlash replica info.
- TiFlashReplica *TiFlashReplicaInfo `json:"tiflash_replica"`
- // IsColumnar means the table is column-oriented.
- // It's true when the engine of the table is TiFlash only.
- IsColumnar bool `json:"is_columnar"`
- }
- // TableLockInfo provides meta data describing a table lock.
- type TableLockInfo struct {
- Tp TableLockType
- // Use array because there may be multiple sessions holding the same read lock.
- Sessions []SessionInfo
- State TableLockState
- // TS is used to record the timestamp this table lock been locked.
- TS uint64
- }
- // SessionInfo contain the session ID and the server ID.
- type SessionInfo struct {
- ServerID string
- SessionID uint64
- }
- func (s SessionInfo) String() string {
- return "server: " + s.ServerID + "_session: " + strconv.FormatUint(s.SessionID, 10)
- }
- // TableLockTpInfo is composed by schema ID, table ID and table lock type.
- type TableLockTpInfo struct {
- SchemaID int64
- TableID int64
- Tp TableLockType
- }
- // TableLockState is the state for table lock.
- type TableLockState byte
- const (
- // TableLockStateNone means this table lock is absent.
- TableLockStateNone TableLockState = iota
- // TableLockStatePreLock means this table lock is pre-lock state. Other session doesn't hold this lock should't do corresponding operation according to the lock type.
- TableLockStatePreLock
- // TableLockStatePublic means this table lock is public state.
- TableLockStatePublic
- )
- // String implements fmt.Stringer interface.
- func (t TableLockState) String() string {
- switch t {
- case TableLockStatePreLock:
- return "pre-lock"
- case TableLockStatePublic:
- return "public"
- default:
- return "none"
- }
- }
- // TableLockType is the type of the table lock.
- type TableLockType byte
- const (
- TableLockNone TableLockType = iota
- // TableLockRead means the session with this lock can read the table (but not write it).
- // Multiple sessions can acquire a READ lock for the table at the same time.
- // Other sessions can read the table without explicitly acquiring a READ lock.
- TableLockRead
- // TableLockReadLocal is not supported.
- TableLockReadLocal
- // TableLockReadOnly is used to set a table into read-only status,
- // when the session exits, it will not release its lock automatically.
- TableLockReadOnly
- // TableLockWrite means only the session with this lock has write/read permission.
- // Only the session that holds the lock can access the table. No other session can access it until the lock is released.
- TableLockWrite
- // TableLockWriteLocal means the session with this lock has write/read permission, and the other session still has read permission.
- TableLockWriteLocal
- )
- func (t TableLockType) String() string {
- switch t {
- case TableLockNone:
- return "NONE"
- case TableLockRead:
- return "READ"
- case TableLockReadLocal:
- return "READ LOCAL"
- case TableLockReadOnly:
- return "READ ONLY"
- case TableLockWriteLocal:
- return "WRITE LOCAL"
- case TableLockWrite:
- return "WRITE"
- }
- return ""
- }
- // TiFlashReplicaInfo means the flash replica info.
- type TiFlashReplicaInfo struct {
- Count uint64
- LocationLabels []string
- Available bool
- AvailablePartitionIDs []int64
- }
- // IsPartitionAvailable checks whether the partition table replica was available.
- func (tr *TiFlashReplicaInfo) IsPartitionAvailable(pid int64) bool {
- for _, id := range tr.AvailablePartitionIDs {
- if id == pid {
- return true
- }
- }
- return false
- }
- // GetPartitionInfo returns the partition information.
- func (t *TableInfo) GetPartitionInfo() *PartitionInfo {
- if t.Partition != nil && t.Partition.Enable {
- return t.Partition
- }
- return nil
- }
- // GetUpdateTime gets the table's updating time.
- func (t *TableInfo) GetUpdateTime() time.Time {
- return TSConvert2Time(t.UpdateTS)
- }
- // GetDBID returns the schema ID that is used to create an allocator.
- // TODO: Remove it after removing OldSchemaID.
- func (t *TableInfo) GetDBID(dbID int64) int64 {
- if t.OldSchemaID != 0 {
- return t.OldSchemaID
- }
- return dbID
- }
- // Clone clones TableInfo.
- func (t *TableInfo) Clone() *TableInfo {
- nt := *t
- nt.Columns = make([]*ColumnInfo, len(t.Columns))
- nt.Indices = make([]*IndexInfo, len(t.Indices))
- nt.ForeignKeys = make([]*FKInfo, len(t.ForeignKeys))
- for i := range t.Columns {
- nt.Columns[i] = t.Columns[i].Clone()
- }
- for i := range t.Indices {
- nt.Indices[i] = t.Indices[i].Clone()
- }
- for i := range t.ForeignKeys {
- nt.ForeignKeys[i] = t.ForeignKeys[i].Clone()
- }
- return &nt
- }
- // GetPkName will return the pk name if pk exists.
- func (t *TableInfo) GetPkName() CIStr {
- for _, colInfo := range t.Columns {
- if mysql.HasPriKeyFlag(colInfo.Flag) {
- return colInfo.Name
- }
- }
- return CIStr{}
- }
- // GetPkColInfo gets the ColumnInfo of pk if exists.
- // Make sure PkIsHandle checked before call this method.
- func (t *TableInfo) GetPkColInfo() *ColumnInfo {
- for _, colInfo := range t.Columns {
- if mysql.HasPriKeyFlag(colInfo.Flag) {
- return colInfo
- }
- }
- return nil
- }
- func (t *TableInfo) GetAutoIncrementColInfo() *ColumnInfo {
- for _, colInfo := range t.Columns {
- if mysql.HasAutoIncrementFlag(colInfo.Flag) {
- return colInfo
- }
- }
- return nil
- }
- func (t *TableInfo) IsAutoIncColUnsigned() bool {
- col := t.GetAutoIncrementColInfo()
- if col == nil {
- return false
- }
- return mysql.HasUnsignedFlag(col.Flag)
- }
- // ContainsAutoRandomBits indicates whether a table contains auto_random column.
- func (t *TableInfo) ContainsAutoRandomBits() bool {
- return t.AutoRandomBits != 0
- }
- // IsAutoRandomBitColUnsigned indicates whether the auto_random column is unsigned. Make sure the table contains auto_random before calling this method.
- func (t *TableInfo) IsAutoRandomBitColUnsigned() bool {
- if !t.PKIsHandle || t.AutoRandomBits == 0 {
- return false
- }
- return mysql.HasUnsignedFlag(t.GetPkColInfo().Flag)
- }
- // Cols returns the columns of the table in public state.
- func (t *TableInfo) Cols() []*ColumnInfo {
- publicColumns := make([]*ColumnInfo, len(t.Columns))
- maxOffset := -1
- for _, col := range t.Columns {
- if col.State != StatePublic {
- continue
- }
- publicColumns[col.Offset] = col
- if maxOffset < col.Offset {
- maxOffset = col.Offset
- }
- }
- return publicColumns[0 : maxOffset+1]
- }
- // FindIndexByName finds index by name.
- func (t *TableInfo) FindIndexByName(idxName string) *IndexInfo {
- for _, idx := range t.Indices {
- if idx.Name.L == idxName {
- return idx
- }
- }
- return nil
- }
- // IsLocked checks whether the table was locked.
- func (t *TableInfo) IsLocked() bool {
- return t.Lock != nil && len(t.Lock.Sessions) > 0
- }
- // NewExtraHandleColInfo mocks a column info for extra handle column.
- func NewExtraHandleColInfo() *ColumnInfo {
- colInfo := &ColumnInfo{
- ID: ExtraHandleID,
- Name: ExtraHandleName,
- }
- colInfo.Flag = mysql.PriKeyFlag | mysql.NotNullFlag
- colInfo.Tp = mysql.TypeLonglong
- colInfo.Flen, colInfo.Decimal = mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong)
- return colInfo
- }
- // NewExtraPartitionIDColInfo mocks a column info for extra partition id column.
- func NewExtraPartitionIDColInfo() *ColumnInfo {
- colInfo := &ColumnInfo{
- ID: ExtraPidColID,
- Name: ExtraPartitionIdName,
- }
- colInfo.Tp = mysql.TypeLonglong
- colInfo.Flen, colInfo.Decimal = mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong)
- return colInfo
- }
- // ColumnIsInIndex checks whether c is included in any indices of t.
- func (t *TableInfo) ColumnIsInIndex(c *ColumnInfo) bool {
- for _, index := range t.Indices {
- for _, column := range index.Columns {
- if column.Name.L == c.Name.L {
- return true
- }
- }
- }
- return false
- }
- // IsView checks if TableInfo is a view.
- func (t *TableInfo) IsView() bool {
- return t.View != nil
- }
- // IsSequence checks if TableInfo is a sequence.
- func (t *TableInfo) IsSequence() bool {
- return t.Sequence != nil
- }
- // IsBaseTable checks to see the table is neither a view or a sequence.
- func (t *TableInfo) IsBaseTable() bool {
- return t.Sequence == nil && t.View == nil
- }
- // ViewAlgorithm is VIEW's SQL AlGORITHM characteristic.
- // See https://dev.mysql.com/doc/refman/5.7/en/view-algorithms.html
- type ViewAlgorithm int
- const (
- AlgorithmUndefined ViewAlgorithm = iota
- AlgorithmMerge
- AlgorithmTemptable
- )
- func (v *ViewAlgorithm) String() string {
- switch *v {
- case AlgorithmMerge:
- return "MERGE"
- case AlgorithmTemptable:
- return "TEMPTABLE"
- case AlgorithmUndefined:
- return "UNDEFINED"
- default:
- return "UNDEFINED"
- }
- }
- // ViewSecurity is VIEW's SQL SECURITY characteristic.
- // See https://dev.mysql.com/doc/refman/5.7/en/create-view.html
- type ViewSecurity int
- const (
- SecurityDefiner ViewSecurity = iota
- SecurityInvoker
- )
- func (v *ViewSecurity) String() string {
- switch *v {
- case SecurityInvoker:
- return "INVOKER"
- case SecurityDefiner:
- return "DEFINER"
- default:
- return "DEFINER"
- }
- }
- // ViewCheckOption is VIEW's WITH CHECK OPTION clause part.
- // See https://dev.mysql.com/doc/refman/5.7/en/view-check-option.html
- type ViewCheckOption int
- const (
- CheckOptionLocal ViewCheckOption = iota
- CheckOptionCascaded
- )
- func (v *ViewCheckOption) String() string {
- switch *v {
- case CheckOptionLocal:
- return "LOCAL"
- case CheckOptionCascaded:
- return "CASCADED"
- default:
- return "CASCADED"
- }
- }
- // ViewInfo provides meta data describing a DB view.
- type ViewInfo struct {
- Algorithm ViewAlgorithm `json:"view_algorithm"`
- Definer *auth.UserIdentity `json:"view_definer"`
- Security ViewSecurity `json:"view_security"`
- SelectStmt string `json:"view_select"`
- CheckOption ViewCheckOption `json:"view_checkoption"`
- Cols []CIStr `json:"view_cols"`
- }
- const (
- DefaultSequenceCacheBool = true
- DefaultSequenceCycleBool = false
- DefaultSequenceOrderBool = false
- DefaultSequenceCacheValue = int64(1000)
- DefaultSequenceIncrementValue = int64(1)
- DefaultPositiveSequenceStartValue = int64(1)
- DefaultNegativeSequenceStartValue = int64(-1)
- DefaultPositiveSequenceMinValue = int64(1)
- DefaultPositiveSequenceMaxValue = int64(9223372036854775806)
- DefaultNegativeSequenceMaxValue = int64(-1)
- DefaultNegativeSequenceMinValue = int64(-9223372036854775807)
- )
- // SequenceInfo provide meta data describing a DB sequence.
- type SequenceInfo struct {
- Start int64 `json:"sequence_start"`
- Cache bool `json:"sequence_cache"`
- Cycle bool `json:"sequence_cycle"`
- MinValue int64 `json:"sequence_min_value"`
- MaxValue int64 `json:"sequence_max_value"`
- Increment int64 `json:"sequence_increment"`
- CacheValue int64 `json:"sequence_cache_value"`
- Comment string `json:"sequence_comment"`
- }
- // PartitionType is the type for PartitionInfo
- type PartitionType int
- // Partition types.
- const (
- PartitionTypeRange PartitionType = 1
- PartitionTypeHash PartitionType = 2
- PartitionTypeList PartitionType = 3
- PartitionTypeKey PartitionType = 4
- PartitionTypeSystemTime PartitionType = 5
- )
- func (p PartitionType) String() string {
- switch p {
- case PartitionTypeRange:
- return "RANGE"
- case PartitionTypeHash:
- return "HASH"
- case PartitionTypeList:
- return "LIST"
- case PartitionTypeKey:
- return "KEY"
- case PartitionTypeSystemTime:
- return "SYSTEM_TIME"
- default:
- return ""
- }
- }
- // PartitionInfo provides table partition info.
- type PartitionInfo struct {
- Type PartitionType `json:"type"`
- Expr string `json:"expr"`
- Columns []CIStr `json:"columns"`
- // User may already creates table with partition but table partition is not
- // yet supported back then. When Enable is true, write/read need use tid
- // rather than pid.
- Enable bool `json:"enable"`
- Definitions []PartitionDefinition `json:"definitions"`
- // AddingDefinitions is filled when adding a partition that is in the mid state.
- AddingDefinitions []PartitionDefinition `json:"adding_definitions"`
- // DroppingDefinitions is filled when dropping a partition that is in the mid state.
- DroppingDefinitions []PartitionDefinition `json:"dropping_definitions"`
- States []PartitionState `json:"states"`
- Num uint64 `json:"num"`
- }
- // GetNameByID gets the partition name by ID.
- func (pi *PartitionInfo) GetNameByID(id int64) string {
- definitions := pi.Definitions
- // do not convert this loop to `for _, def := range definitions`.
- // see https://github.com/pingcap/parser/pull/1072 for the benchmark.
- for i := range definitions {
- if id == definitions[i].ID {
- return definitions[i].Name.L
- }
- }
- return ""
- }
- func (pi *PartitionInfo) GetStateByID(id int64) SchemaState {
- for _, pstate := range pi.States {
- if pstate.ID == id {
- return pstate.State
- }
- }
- return StatePublic
- }
- func (pi *PartitionInfo) SetStateByID(id int64, state SchemaState) {
- newState := PartitionState{ID: id, State: state}
- for i, pstate := range pi.States {
- if pstate.ID == id {
- pi.States[i] = newState
- return
- }
- }
- if pi.States == nil {
- pi.States = make([]PartitionState, 0, 1)
- }
- pi.States = append(pi.States, newState)
- }
- func (pi *PartitionInfo) GCPartitionStates() {
- if len(pi.States) < 1 {
- return
- }
- newStates := make([]PartitionState, 0, len(pi.Definitions))
- for _, state := range pi.States {
- found := false
- for _, def := range pi.Definitions {
- if def.ID == state.ID {
- found = true
- break
- }
- }
- if found {
- newStates = append(newStates, state)
- }
- }
- pi.States = newStates
- }
- type PartitionState struct {
- ID int64 `json:"id"`
- State SchemaState `json:"state"`
- }
- // PartitionDefinition defines a single partition.
- type PartitionDefinition struct {
- ID int64 `json:"id"`
- Name CIStr `json:"name"`
- LessThan []string `json:"less_than"`
- InValues [][]string `json:"in_values"`
- Comment string `json:"comment,omitempty"`
- }
- // Clone clones ConstraintInfo.
- func (ci *PartitionDefinition) Clone() PartitionDefinition {
- nci := *ci
- nci.LessThan = make([]string, len(ci.LessThan))
- copy(nci.LessThan, ci.LessThan)
- return nci
- }
- // FindPartitionDefinitionByName finds PartitionDefinition by name.
- func (t *TableInfo) FindPartitionDefinitionByName(partitionDefinitionName string) *PartitionDefinition {
- lowConstrName := strings.ToLower(partitionDefinitionName)
- definitions := t.Partition.Definitions
- for i := range definitions {
- if definitions[i].Name.L == lowConstrName {
- return &t.Partition.Definitions[i]
- }
- }
- return nil
- }
- // IndexColumn provides index column info.
- type IndexColumn struct {
- Name 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
- }
- // PrimaryKeyType is the type of primary key.
- // Available values are 'clustered', 'nonclustered', and ''(default).
- type PrimaryKeyType int8
- func (p PrimaryKeyType) String() string {
- switch p {
- case PrimaryKeyTypeClustered:
- return "CLUSTERED"
- case PrimaryKeyTypeNonClustered:
- return "NONCLUSTERED"
- default:
- return ""
- }
- }
- const (
- PrimaryKeyTypeDefault PrimaryKeyType = iota
- PrimaryKeyTypeClustered
- PrimaryKeyTypeNonClustered
- )
- // IndexType is the type of index
- type IndexType int
- // String implements Stringer interface.
- func (t IndexType) String() string {
- switch t {
- case IndexTypeBtree:
- return "BTREE"
- case IndexTypeHash:
- return "HASH"
- case IndexTypeRtree:
- return "RTREE"
- default:
- return ""
- }
- }
- // IndexTypes
- const (
- IndexTypeInvalid IndexType = iota
- IndexTypeBtree
- IndexTypeHash
- IndexTypeRtree
- )
- // 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 CIStr `json:"idx_name"` // Index name.
- Table CIStr `json:"tbl_name"` // Table name.
- Columns []*IndexColumn `json:"idx_cols"` // Index columns.
- State SchemaState `json:"state"`
- Comment string `json:"comment"` // Comment
- Tp 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.
- }
- // Clone clones IndexInfo.
- func (index *IndexInfo) Clone() *IndexInfo {
- 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
- }
- // ConstraintInfo provides meta data describing check-expression constraint.
- type ConstraintInfo struct {
- ID int64 `json:"id"`
- Name CIStr `json:"constraint_name"`
- Table CIStr `json:"tbl_name"` // Table name.
- ConstraintCols []CIStr `json:"constraint_cols"` // Depended column names.
- Enforced bool `json:"enforced"`
- InColumn bool `json:"in_column"` // Indicate whether the constraint is column type check.
- ExprString string `json:"expr_string"`
- State SchemaState `json:"state"`
- }
- // Clone clones ConstraintInfo.
- func (ci *ConstraintInfo) Clone() *ConstraintInfo {
- nci := *ci
- nci.ConstraintCols = make([]CIStr, len(ci.ConstraintCols))
- copy(nci.ConstraintCols, ci.ConstraintCols)
- return &nci
- }
- // FindConstraintInfoByName finds constraintInfo by name.
- func (t *TableInfo) FindConstraintInfoByName(constrName string) *ConstraintInfo {
- lowConstrName := strings.ToLower(constrName)
- for _, chk := range t.Constraints {
- if chk.Name.L == lowConstrName {
- return chk
- }
- }
- return nil
- }
- // FKInfo provides meta data describing a foreign key constraint.
- type FKInfo struct {
- ID int64 `json:"id"`
- Name CIStr `json:"fk_name"`
- RefTable CIStr `json:"ref_table"`
- RefCols []CIStr `json:"ref_cols"`
- Cols []CIStr `json:"cols"`
- OnDelete int `json:"on_delete"`
- OnUpdate int `json:"on_update"`
- State SchemaState `json:"state"`
- }
- // Clone clones FKInfo.
- func (fk *FKInfo) Clone() *FKInfo {
- nfk := *fk
- nfk.RefCols = make([]CIStr, len(fk.RefCols))
- nfk.Cols = make([]CIStr, len(fk.Cols))
- copy(nfk.RefCols, fk.RefCols)
- copy(nfk.Cols, fk.Cols)
- return &nfk
- }
- // DBInfo provides meta data describing a DB.
- type DBInfo struct {
- ID int64 `json:"id"` // Database ID
- Name CIStr `json:"db_name"` // DB name.
- Charset string `json:"charset"`
- Collate string `json:"collate"`
- Tables []*TableInfo `json:"-"` // Tables in the DB.
- State SchemaState `json:"state"`
- }
- // Clone clones DBInfo.
- func (db *DBInfo) Clone() *DBInfo {
- newInfo := *db
- newInfo.Tables = make([]*TableInfo, len(db.Tables))
- for i := range db.Tables {
- newInfo.Tables[i] = db.Tables[i].Clone()
- }
- return &newInfo
- }
- // Copy shallow copies DBInfo.
- func (db *DBInfo) Copy() *DBInfo {
- newInfo := *db
- newInfo.Tables = make([]*TableInfo, len(db.Tables))
- copy(newInfo.Tables, db.Tables)
- return &newInfo
- }
- // CIStr is case insensitive string.
- type CIStr struct {
- O string `json:"O"` // Original string.
- L string `json:"L"` // Lower case string.
- }
- // String implements fmt.Stringer interface.
- func (cis CIStr) String() string {
- return cis.O
- }
- // NewCIStr creates a new CIStr.
- func NewCIStr(s string) (cs CIStr) {
- cs.O = s
- cs.L = strings.ToLower(s)
- return
- }
- // UnmarshalJSON implements the user defined unmarshal method.
- // CIStr can be unmarshaled from a single string, so PartitionDefinition.Name
- // in this change https://github.com/pingcap/tidb/pull/6460/files would be
- // compatible during TiDB upgrading.
- func (cis *CIStr) UnmarshalJSON(b []byte) error {
- type T CIStr
- if err := json.Unmarshal(b, (*T)(cis)); err == nil {
- return nil
- }
- // Unmarshal CIStr from a single string.
- err := json.Unmarshal(b, &cis.O)
- if err != nil {
- return errors.Trace(err)
- }
- cis.L = strings.ToLower(cis.O)
- return nil
- }
- // TableColumnID is composed by table ID and column ID.
- type TableColumnID struct {
- TableID int64
- ColumnID int64
- }
|