github.com/pingcap/tidb/parser@v0.0.0-20231013125129-93a834a6bf8d/model/model.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package model 15 16 import ( 17 "bytes" 18 "cmp" 19 "encoding/json" 20 "fmt" 21 "strconv" 22 "strings" 23 "time" 24 "unsafe" 25 26 "github.com/pingcap/errors" 27 "github.com/pingcap/tidb/parser/auth" 28 "github.com/pingcap/tidb/parser/charset" 29 "github.com/pingcap/tidb/parser/duration" 30 "github.com/pingcap/tidb/parser/mysql" 31 "github.com/pingcap/tidb/parser/types" 32 ) 33 34 // SchemaState is the state for schema elements. 35 type SchemaState byte 36 37 const ( 38 // StateNone means this schema element is absent and can't be used. 39 StateNone SchemaState = iota 40 // StateDeleteOnly means we can only delete items for this schema element. 41 StateDeleteOnly 42 // StateWriteOnly means we can use any write operation on this schema element, 43 // but outer can't read the changed data. 44 StateWriteOnly 45 // StateWriteReorganization means we are re-organizing whole data after write only state. 46 StateWriteReorganization 47 // StateDeleteReorganization means we are re-organizing whole data after delete only state. 48 StateDeleteReorganization 49 // StatePublic means this schema element is ok for all write and read operations. 50 StatePublic 51 // StateReplicaOnly means we're waiting tiflash replica to be finished. 52 StateReplicaOnly 53 // StateGlobalTxnOnly means we can only use global txn for operator on this schema element 54 StateGlobalTxnOnly 55 /* 56 * Please add the new state at the end to keep the values consistent across versions. 57 */ 58 ) 59 60 // String implements fmt.Stringer interface. 61 func (s SchemaState) String() string { 62 switch s { 63 case StateDeleteOnly: 64 return "delete only" 65 case StateWriteOnly: 66 return "write only" 67 case StateWriteReorganization: 68 return "write reorganization" 69 case StateDeleteReorganization: 70 return "delete reorganization" 71 case StatePublic: 72 return "public" 73 case StateReplicaOnly: 74 return "replica only" 75 case StateGlobalTxnOnly: 76 return "global txn only" 77 default: 78 return "none" 79 } 80 } 81 82 const ( 83 // ColumnInfoVersion0 means the column info version is 0. 84 ColumnInfoVersion0 = uint64(0) 85 // ColumnInfoVersion1 means the column info version is 1. 86 ColumnInfoVersion1 = uint64(1) 87 // ColumnInfoVersion2 means the column info version is 2. 88 // This is for v2.1.7 to Compatible with older versions charset problem. 89 // Old version such as v2.0.8 treat utf8 as utf8mb4, because there is no UTF8 check in v2.0.8. 90 // 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. 91 // This is not compatibility for user. Then we try to fix this in PR #9820, and increase the version number. 92 ColumnInfoVersion2 = uint64(2) 93 94 // CurrLatestColumnInfoVersion means the latest column info in the current TiDB. 95 CurrLatestColumnInfoVersion = ColumnInfoVersion2 96 ) 97 98 // ChangeStateInfo is used for recording the information of schema changing. 99 type ChangeStateInfo struct { 100 // DependencyColumnOffset is the changing column offset that the current column depends on when executing modify/change column. 101 DependencyColumnOffset int `json:"relative_col_offset"` 102 } 103 104 // ColumnInfo provides meta data describing of a table column. 105 type ColumnInfo struct { 106 ID int64 `json:"id"` 107 Name CIStr `json:"name"` 108 Offset int `json:"offset"` 109 OriginDefaultValue interface{} `json:"origin_default"` 110 OriginDefaultValueBit []byte `json:"origin_default_bit"` 111 DefaultValue interface{} `json:"default"` 112 DefaultValueBit []byte `json:"default_bit"` 113 // DefaultIsExpr is indicates the default value string is expr. 114 DefaultIsExpr bool `json:"default_is_expr"` 115 GeneratedExprString string `json:"generated_expr_string"` 116 GeneratedStored bool `json:"generated_stored"` 117 Dependences map[string]struct{} `json:"dependences"` 118 FieldType types.FieldType `json:"type"` 119 State SchemaState `json:"state"` 120 Comment string `json:"comment"` 121 // A hidden column is used internally(expression index) and are not accessible by users. 122 Hidden bool `json:"hidden"` 123 *ChangeStateInfo `json:"change_state_info"` 124 // Version means the version of the column info. 125 // Version = 0: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in system time zone. 126 // That is a bug if multiple TiDB servers in different system time zone. 127 // Version = 1: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in UTC time zone. 128 // This will fix bug in version 0. For compatibility with version 0, we add version field in column info struct. 129 Version uint64 `json:"version"` 130 } 131 132 // IsVirtualGenerated checks the column if it is virtual. 133 func (c *ColumnInfo) IsVirtualGenerated() bool { 134 return c.IsGenerated() && !c.GeneratedStored 135 } 136 137 // Clone clones ColumnInfo. 138 func (c *ColumnInfo) Clone() *ColumnInfo { 139 if c == nil { 140 return nil 141 } 142 nc := *c 143 return &nc 144 } 145 146 // GetType returns the type of ColumnInfo. 147 func (c *ColumnInfo) GetType() byte { 148 return c.FieldType.GetType() 149 } 150 151 // GetFlag returns the flag of ColumnInfo. 152 func (c *ColumnInfo) GetFlag() uint { 153 return c.FieldType.GetFlag() 154 } 155 156 // GetFlen returns the flen of ColumnInfo. 157 func (c *ColumnInfo) GetFlen() int { 158 return c.FieldType.GetFlen() 159 } 160 161 // GetDecimal returns the decimal of ColumnInfo. 162 func (c *ColumnInfo) GetDecimal() int { 163 return c.FieldType.GetDecimal() 164 } 165 166 // GetCharset returns the charset of ColumnInfo. 167 func (c *ColumnInfo) GetCharset() string { 168 return c.FieldType.GetCharset() 169 } 170 171 // GetCollate returns the collation of ColumnInfo. 172 func (c *ColumnInfo) GetCollate() string { 173 return c.FieldType.GetCollate() 174 } 175 176 // GetElems returns the elems of ColumnInfo. 177 func (c *ColumnInfo) GetElems() []string { 178 return c.FieldType.GetElems() 179 } 180 181 // SetType set the type of ColumnInfo. 182 func (c *ColumnInfo) SetType(tp byte) { 183 c.FieldType.SetType(tp) 184 } 185 186 // SetFlag set the flag of ColumnInfo. 187 func (c *ColumnInfo) SetFlag(flag uint) { 188 c.FieldType.SetFlag(flag) 189 } 190 191 // AddFlag adds the flag of ColumnInfo. 192 func (c *ColumnInfo) AddFlag(flag uint) { 193 c.FieldType.AddFlag(flag) 194 } 195 196 // AndFlag adds a flag to the column. 197 func (c *ColumnInfo) AndFlag(flag uint) { 198 c.FieldType.AndFlag(flag) 199 } 200 201 // ToggleFlag flips the flag according to the value. 202 func (c *ColumnInfo) ToggleFlag(flag uint) { 203 c.FieldType.ToggleFlag(flag) 204 } 205 206 // DelFlag removes the flag from the column's flag. 207 func (c *ColumnInfo) DelFlag(flag uint) { 208 c.FieldType.DelFlag(flag) 209 } 210 211 // SetFlen sets the flen of ColumnInfo. 212 func (c *ColumnInfo) SetFlen(flen int) { 213 c.FieldType.SetFlen(flen) 214 } 215 216 // SetDecimal sets the decimal of ColumnInfo. 217 func (c *ColumnInfo) SetDecimal(decimal int) { 218 c.FieldType.SetDecimal(decimal) 219 } 220 221 // SetCharset sets charset of the ColumnInfo 222 func (c *ColumnInfo) SetCharset(charset string) { 223 c.FieldType.SetCharset(charset) 224 } 225 226 // SetCollate sets the collation of the column. 227 func (c *ColumnInfo) SetCollate(collate string) { 228 c.FieldType.SetCollate(collate) 229 } 230 231 // SetElems set the elements of enum column. 232 func (c *ColumnInfo) SetElems(elems []string) { 233 c.FieldType.SetElems(elems) 234 } 235 236 // IsGenerated returns true if the column is generated column. 237 func (c *ColumnInfo) IsGenerated() bool { 238 return len(c.GeneratedExprString) != 0 239 } 240 241 // SetOriginDefaultValue sets the origin default value. 242 // For mysql.TypeBit type, the default value storage format must be a string. 243 // Other value such as int must convert to string format first. 244 // The mysql.TypeBit type supports the null default value. 245 func (c *ColumnInfo) SetOriginDefaultValue(value interface{}) error { 246 c.OriginDefaultValue = value 247 if c.GetType() == mysql.TypeBit { 248 if value == nil { 249 return nil 250 } 251 if v, ok := value.(string); ok { 252 c.OriginDefaultValueBit = []byte(v) 253 return nil 254 } 255 return types.ErrInvalidDefault.GenWithStackByArgs(c.Name) 256 } 257 return nil 258 } 259 260 // GetOriginDefaultValue gets the origin default value. 261 func (c *ColumnInfo) GetOriginDefaultValue() interface{} { 262 if c.GetType() == mysql.TypeBit && c.OriginDefaultValueBit != nil { 263 // If the column type is BIT, both `OriginDefaultValue` and `DefaultValue` of ColumnInfo are corrupted, 264 // because the content before json.Marshal is INCONSISTENT with the content after json.Unmarshal. 265 return string(c.OriginDefaultValueBit) 266 } 267 return c.OriginDefaultValue 268 } 269 270 // SetDefaultValue sets the default value. 271 func (c *ColumnInfo) SetDefaultValue(value interface{}) error { 272 c.DefaultValue = value 273 if c.GetType() == mysql.TypeBit { 274 // For mysql.TypeBit type, the default value storage format must be a string. 275 // Other value such as int must convert to string format first. 276 // The mysql.TypeBit type supports the null default value. 277 if value == nil { 278 return nil 279 } 280 if v, ok := value.(string); ok { 281 c.DefaultValueBit = []byte(v) 282 return nil 283 } 284 return types.ErrInvalidDefault.GenWithStackByArgs(c.Name) 285 } 286 return nil 287 } 288 289 // GetDefaultValue gets the default value of the column. 290 // Default value use to stored in DefaultValue field, but now, 291 // bit type default value will store in DefaultValueBit for fix bit default value decode/encode bug. 292 func (c *ColumnInfo) GetDefaultValue() interface{} { 293 if c.GetType() == mysql.TypeBit && c.DefaultValueBit != nil { 294 return string(c.DefaultValueBit) 295 } 296 return c.DefaultValue 297 } 298 299 // GetTypeDesc gets the description for column type. 300 func (c *ColumnInfo) GetTypeDesc() string { 301 desc := c.FieldType.CompactStr() 302 if mysql.HasUnsignedFlag(c.GetFlag()) && c.GetType() != mysql.TypeBit && c.GetType() != mysql.TypeYear { 303 desc += " unsigned" 304 } 305 if mysql.HasZerofillFlag(c.GetFlag()) && c.GetType() != mysql.TypeYear { 306 desc += " zerofill" 307 } 308 return desc 309 } 310 311 // EmptyColumnInfoSize is the memory usage of ColumnInfoSize 312 const EmptyColumnInfoSize = int64(unsafe.Sizeof(ColumnInfo{})) 313 314 // FindColumnInfo finds ColumnInfo in cols by name. 315 func FindColumnInfo(cols []*ColumnInfo, name string) *ColumnInfo { 316 name = strings.ToLower(name) 317 for _, col := range cols { 318 if col.Name.L == name { 319 return col 320 } 321 } 322 return nil 323 } 324 325 // FindColumnInfoByID finds ColumnInfo in cols by id. 326 func FindColumnInfoByID(cols []*ColumnInfo, id int64) *ColumnInfo { 327 for _, col := range cols { 328 if col.ID == id { 329 return col 330 } 331 } 332 return nil 333 } 334 335 // FindIndexInfoByID finds IndexInfo in indices by id. 336 func FindIndexInfoByID(indices []*IndexInfo, id int64) *IndexInfo { 337 for _, idx := range indices { 338 if idx.ID == id { 339 return idx 340 } 341 } 342 return nil 343 } 344 345 // FindFKInfoByName finds FKInfo in fks by lowercase name. 346 func FindFKInfoByName(fks []*FKInfo, name string) *FKInfo { 347 for _, fk := range fks { 348 if fk.Name.L == name { 349 return fk 350 } 351 } 352 return nil 353 } 354 355 // FindIndexByColumns find IndexInfo in indices which is cover the specified columns. 356 func FindIndexByColumns(tbInfo *TableInfo, indices []*IndexInfo, cols ...CIStr) *IndexInfo { 357 for _, index := range indices { 358 if IsIndexPrefixCovered(tbInfo, index, cols...) { 359 return index 360 } 361 } 362 return nil 363 } 364 365 // IsIndexPrefixCovered checks the index's columns beginning with the cols. 366 func IsIndexPrefixCovered(tbInfo *TableInfo, index *IndexInfo, cols ...CIStr) bool { 367 if len(index.Columns) < len(cols) { 368 return false 369 } 370 for i := range cols { 371 if cols[i].L != index.Columns[i].Name.L || 372 index.Columns[i].Offset >= len(tbInfo.Columns) { 373 return false 374 } 375 colInfo := tbInfo.Columns[index.Columns[i].Offset] 376 if index.Columns[i].Length != types.UnspecifiedLength && index.Columns[i].Length < colInfo.GetFlen() { 377 return false 378 } 379 } 380 return true 381 } 382 383 // ExtraHandleID is the column ID of column which we need to append to schema to occupy the handle's position 384 // for use of execution phase. 385 const ExtraHandleID = -1 386 387 // ExtraPidColID is the column ID of column which store the partitionID decoded in global index values. 388 const ExtraPidColID = -2 389 390 // ExtraPhysTblID is the column ID of column that should be filled in with the physical table id. 391 // Primarily used for table partition dynamic prune mode, to return which partition (physical table id) the row came from. 392 // Using a dedicated id for this, since in the future ExtraPidColID and ExtraPhysTblID may be used for the same request. 393 // Must be after ExtraPidColID! 394 const ExtraPhysTblID = -3 395 396 // ExtraRowChecksumID is the column ID of column which holds the row checksum info. 397 const ExtraRowChecksumID = -4 398 399 const ( 400 // TableInfoVersion0 means the table info version is 0. 401 // Upgrade from v2.1.1 or v2.1.2 to v2.1.3 and later, and then execute a "change/modify column" statement 402 // that does not specify a charset value for column. Then the following error may be reported: 403 // ERROR 1105 (HY000): unsupported modify charset from utf8mb4 to utf8. 404 // To eliminate this error, we will not modify the charset of this column 405 // when executing a change/modify column statement that does not specify a charset value for column. 406 // This behavior is not compatible with MySQL. 407 TableInfoVersion0 = uint16(0) 408 // TableInfoVersion1 means the table info version is 1. 409 // When we execute a change/modify column statement that does not specify a charset value for column, 410 // we set the charset of this column to the charset of table. This behavior is compatible with MySQL. 411 TableInfoVersion1 = uint16(1) 412 // TableInfoVersion2 means the table info version is 2. 413 // This is for v2.1.7 to Compatible with older versions charset problem. 414 // Old version such as v2.0.8 treat utf8 as utf8mb4, because there is no UTF8 check in v2.0.8. 415 // 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. 416 // This is not compatibility for user. Then we try to fix this in PR #9820, and increase the version number. 417 TableInfoVersion2 = uint16(2) 418 // TableInfoVersion3 means the table info version is 3. 419 // This version aims to deal with upper-cased charset name in TableInfo stored by versions prior to TiDB v2.1.9: 420 // TiDB always suppose all charsets / collations as lower-cased and try to convert them if they're not. 421 // However, the convert is missed in some scenarios before v2.1.9, so for all those tables prior to TableInfoVersion3, their 422 // charsets / collations will be converted to lower-case while loading from the storage. 423 TableInfoVersion3 = uint16(3) 424 // TableInfoVersion4 is not used. 425 TableInfoVersion4 = uint16(4) 426 // TableInfoVersion5 indicates that the auto_increment allocator in TiDB has been separated from 427 // _tidb_rowid allocator when AUTO_ID_CACHE is 1. This version is introduced to preserve the compatibility of old tables: 428 // the tables with version <= TableInfoVersion4 still use a single allocator for auto_increment and _tidb_rowid. 429 // Also see https://github.com/pingcap/tidb/issues/982. 430 TableInfoVersion5 = uint16(5) 431 432 // CurrLatestTableInfoVersion means the latest table info in the current TiDB. 433 CurrLatestTableInfoVersion = TableInfoVersion5 434 ) 435 436 // ExtraHandleName is the name of ExtraHandle Column. 437 var ExtraHandleName = NewCIStr("_tidb_rowid") 438 439 // ExtraPartitionIdName is the name of ExtraPartitionId Column. 440 var ExtraPartitionIdName = NewCIStr("_tidb_pid") //nolint:revive 441 442 // ExtraPhysTblIdName is the name of ExtraPhysTblID Column. 443 var ExtraPhysTblIdName = NewCIStr("_tidb_tid") //nolint:revive 444 445 // TableInfo provides meta data describing a DB table. 446 type TableInfo struct { 447 ID int64 `json:"id"` 448 Name CIStr `json:"name"` 449 Charset string `json:"charset"` 450 Collate string `json:"collate"` 451 // Columns are listed in the order in which they appear in the schema. 452 Columns []*ColumnInfo `json:"cols"` 453 Indices []*IndexInfo `json:"index_info"` 454 Constraints []*ConstraintInfo `json:"constraint_info"` 455 ForeignKeys []*FKInfo `json:"fk_info"` 456 State SchemaState `json:"state"` 457 // PKIsHandle is true when primary key is a single integer column. 458 PKIsHandle bool `json:"pk_is_handle"` 459 // IsCommonHandle is true when clustered index feature is 460 // enabled and the primary key is not a single integer column. 461 IsCommonHandle bool `json:"is_common_handle"` 462 // CommonHandleVersion is the version of the clustered index. 463 // 0 for the clustered index created == 5.0.0 RC. 464 // 1 for the clustered index created > 5.0.0 RC. 465 CommonHandleVersion uint16 `json:"common_handle_version"` 466 467 Comment string `json:"comment"` 468 AutoIncID int64 `json:"auto_inc_id"` 469 470 // Only used by BR when: 471 // 1. SepAutoInc() is true 472 // 2. The table is nonclustered and has auto_increment column. 473 // In that case, both auto_increment_id and tidb_rowid need to be backup & recover. 474 // See also https://github.com/pingcap/tidb/issues/46093 475 // 476 // It should have been named TiDBRowID, but for historial reasons, we do not use separate meta key for _tidb_rowid and auto_increment_id, 477 // and field `AutoIncID` is used to serve both _tidb_rowid and auto_increment_id. 478 // If we introduce a TiDBRowID here, it could make furthur misunderstanding: 479 // in most cases, AutoIncID is _tidb_rowid and TiDBRowID is null 480 // but in some cases, AutoIncID is auto_increment_id and TiDBRowID is _tidb_rowid 481 // So let's just use another name AutoIncIDExtra to avoid misconception. 482 AutoIncIDExtra int64 `json:"auto_inc_id_extra,omitempty"` 483 484 AutoIdCache int64 `json:"auto_id_cache"` //nolint:revive 485 AutoRandID int64 `json:"auto_rand_id"` 486 MaxColumnID int64 `json:"max_col_id"` 487 MaxIndexID int64 `json:"max_idx_id"` 488 MaxForeignKeyID int64 `json:"max_fk_id"` 489 MaxConstraintID int64 `json:"max_cst_id"` 490 // UpdateTS is used to record the timestamp of updating the table's schema information. 491 // These changing schema operations don't include 'truncate table' and 'rename table'. 492 UpdateTS uint64 `json:"update_timestamp"` 493 // OldSchemaID : 494 // Because auto increment ID has schemaID as prefix, 495 // We need to save original schemaID to keep autoID unchanged 496 // while renaming a table from one database to another. 497 // TODO: Remove it. 498 // Now it only uses for compatibility with the old version that already uses this field. 499 OldSchemaID int64 `json:"old_schema_id,omitempty"` 500 501 // ShardRowIDBits specify if the implicit row ID is sharded. 502 ShardRowIDBits uint64 503 // MaxShardRowIDBits uses to record the max ShardRowIDBits be used so far. 504 MaxShardRowIDBits uint64 `json:"max_shard_row_id_bits"` 505 // AutoRandomBits is used to set the bit number to shard automatically when PKIsHandle. 506 AutoRandomBits uint64 `json:"auto_random_bits"` 507 // AutoRandomRangeBits represents the bit number of the int primary key that will be used by TiDB. 508 AutoRandomRangeBits uint64 `json:"auto_random_range_bits"` 509 // PreSplitRegions specify the pre-split region when create table. 510 // The pre-split region num is 2^(PreSplitRegions-1). 511 // And the PreSplitRegions should less than or equal to ShardRowIDBits. 512 PreSplitRegions uint64 `json:"pre_split_regions"` 513 514 Partition *PartitionInfo `json:"partition"` 515 516 Compression string `json:"compression"` 517 518 View *ViewInfo `json:"view"` 519 520 Sequence *SequenceInfo `json:"sequence"` 521 522 // Lock represent the table lock info. 523 Lock *TableLockInfo `json:"Lock"` 524 525 // Version means the version of the table info. 526 Version uint16 `json:"version"` 527 528 // TiFlashReplica means the TiFlash replica info. 529 TiFlashReplica *TiFlashReplicaInfo `json:"tiflash_replica"` 530 531 // IsColumnar means the table is column-oriented. 532 // It's true when the engine of the table is TiFlash only. 533 IsColumnar bool `json:"is_columnar"` 534 535 TempTableType `json:"temp_table_type"` 536 TableCacheStatusType `json:"cache_table_status"` 537 PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` 538 539 // StatsOptions is used when do analyze/auto-analyze for each table 540 StatsOptions *StatsOptions `json:"stats_options"` 541 542 ExchangePartitionInfo *ExchangePartitionInfo `json:"exchange_partition_info"` 543 544 TTLInfo *TTLInfo `json:"ttl_info"` 545 } 546 547 // SepAutoInc decides whether _rowid and auto_increment id use separate allocator. 548 func (t *TableInfo) SepAutoInc() bool { 549 return t.Version >= TableInfoVersion5 && t.AutoIdCache == 1 550 } 551 552 // TableCacheStatusType is the type of the table cache status 553 type TableCacheStatusType int 554 555 //revive:disable:exported 556 const ( 557 TableCacheStatusDisable TableCacheStatusType = iota 558 TableCacheStatusEnable 559 TableCacheStatusSwitching 560 ) 561 562 //revive:enable:exported 563 564 func (t TableCacheStatusType) String() string { 565 switch t { 566 case TableCacheStatusDisable: 567 return "disable" 568 case TableCacheStatusEnable: 569 return "enable" 570 case TableCacheStatusSwitching: 571 return "switching" 572 default: 573 return "" 574 } 575 } 576 577 // TempTableType is the type of the temp table 578 type TempTableType byte 579 580 //revive:disable:exported 581 const ( 582 TempTableNone TempTableType = iota 583 TempTableGlobal 584 TempTableLocal 585 ) 586 587 //revive:enable:exported 588 589 func (t TempTableType) String() string { 590 switch t { 591 case TempTableGlobal: 592 return "global" 593 case TempTableLocal: 594 return "local" 595 default: 596 return "" 597 } 598 } 599 600 // TableLockInfo provides meta data describing a table lock. 601 type TableLockInfo struct { 602 Tp TableLockType 603 // Use array because there may be multiple sessions holding the same read lock. 604 Sessions []SessionInfo 605 State TableLockState 606 // TS is used to record the timestamp this table lock been locked. 607 TS uint64 608 } 609 610 // SessionInfo contain the session ID and the server ID. 611 type SessionInfo struct { 612 ServerID string 613 SessionID uint64 614 } 615 616 func (s SessionInfo) String() string { 617 return "server: " + s.ServerID + "_session: " + strconv.FormatUint(s.SessionID, 10) 618 } 619 620 // TableLockTpInfo is composed by schema ID, table ID and table lock type. 621 type TableLockTpInfo struct { 622 SchemaID int64 623 TableID int64 624 Tp TableLockType 625 } 626 627 // TableLockState is the state for table lock. 628 type TableLockState byte 629 630 const ( 631 // TableLockStateNone means this table lock is absent. 632 TableLockStateNone TableLockState = iota 633 // 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. 634 TableLockStatePreLock 635 // TableLockStatePublic means this table lock is public state. 636 TableLockStatePublic 637 ) 638 639 // String implements fmt.Stringer interface. 640 func (t TableLockState) String() string { 641 switch t { 642 case TableLockStatePreLock: 643 return "pre-lock" 644 case TableLockStatePublic: 645 return "public" 646 default: 647 return "none" 648 } 649 } 650 651 // TableLockType is the type of the table lock. 652 type TableLockType byte 653 654 const ( 655 // TableLockNone means this table lock is absent. 656 TableLockNone TableLockType = iota 657 // TableLockRead means the session with this lock can read the table (but not write it). 658 // Multiple sessions can acquire a READ lock for the table at the same time. 659 // Other sessions can read the table without explicitly acquiring a READ lock. 660 TableLockRead 661 // TableLockReadLocal is not supported. 662 TableLockReadLocal 663 // TableLockReadOnly is used to set a table into read-only status, 664 // when the session exits, it will not release its lock automatically. 665 TableLockReadOnly 666 // TableLockWrite means only the session with this lock has write/read permission. 667 // Only the session that holds the lock can access the table. No other session can access it until the lock is released. 668 TableLockWrite 669 // TableLockWriteLocal means the session with this lock has write/read permission, and the other session still has read permission. 670 TableLockWriteLocal 671 ) 672 673 func (t TableLockType) String() string { 674 switch t { 675 case TableLockNone: 676 return "NONE" 677 case TableLockRead: 678 return "READ" 679 case TableLockReadLocal: 680 return "READ LOCAL" 681 case TableLockReadOnly: 682 return "READ ONLY" 683 case TableLockWriteLocal: 684 return "WRITE LOCAL" 685 case TableLockWrite: 686 return "WRITE" 687 } 688 return "" 689 } 690 691 // TiFlashReplicaInfo means the flash replica info. 692 type TiFlashReplicaInfo struct { 693 Count uint64 694 LocationLabels []string 695 Available bool 696 AvailablePartitionIDs []int64 697 } 698 699 // IsPartitionAvailable checks whether the partition table replica was available. 700 func (tr *TiFlashReplicaInfo) IsPartitionAvailable(pid int64) bool { 701 for _, id := range tr.AvailablePartitionIDs { 702 if id == pid { 703 return true 704 } 705 } 706 return false 707 } 708 709 // GetPartitionInfo returns the partition information. 710 func (t *TableInfo) GetPartitionInfo() *PartitionInfo { 711 if t.Partition != nil && t.Partition.Enable { 712 return t.Partition 713 } 714 return nil 715 } 716 717 // GetUpdateTime gets the table's updating time. 718 func (t *TableInfo) GetUpdateTime() time.Time { 719 return TSConvert2Time(t.UpdateTS) 720 } 721 722 // GetDBID returns the schema ID that is used to create an allocator. 723 // TODO: Remove it after removing OldSchemaID. 724 func (t *TableInfo) GetDBID(dbID int64) int64 { 725 if t.OldSchemaID != 0 { 726 return t.OldSchemaID 727 } 728 return dbID 729 } 730 731 // Clone clones TableInfo. 732 func (t *TableInfo) Clone() *TableInfo { 733 nt := *t 734 nt.Columns = make([]*ColumnInfo, len(t.Columns)) 735 nt.Indices = make([]*IndexInfo, len(t.Indices)) 736 nt.ForeignKeys = make([]*FKInfo, len(t.ForeignKeys)) 737 738 for i := range t.Columns { 739 nt.Columns[i] = t.Columns[i].Clone() 740 } 741 742 for i := range t.Indices { 743 nt.Indices[i] = t.Indices[i].Clone() 744 } 745 746 for i := range t.ForeignKeys { 747 nt.ForeignKeys[i] = t.ForeignKeys[i].Clone() 748 } 749 750 if t.Partition != nil { 751 nt.Partition = t.Partition.Clone() 752 } 753 if t.TTLInfo != nil { 754 nt.TTLInfo = t.TTLInfo.Clone() 755 } 756 757 return &nt 758 } 759 760 // GetPkName will return the pk name if pk exists. 761 func (t *TableInfo) GetPkName() CIStr { 762 for _, colInfo := range t.Columns { 763 if mysql.HasPriKeyFlag(colInfo.GetFlag()) { 764 return colInfo.Name 765 } 766 } 767 return CIStr{} 768 } 769 770 // GetPkColInfo gets the ColumnInfo of pk if exists. 771 // Make sure PkIsHandle checked before call this method. 772 func (t *TableInfo) GetPkColInfo() *ColumnInfo { 773 for _, colInfo := range t.Columns { 774 if mysql.HasPriKeyFlag(colInfo.GetFlag()) { 775 return colInfo 776 } 777 } 778 return nil 779 } 780 781 // GetAutoIncrementColInfo gets the ColumnInfo of auto_increment column if exists. 782 func (t *TableInfo) GetAutoIncrementColInfo() *ColumnInfo { 783 for _, colInfo := range t.Columns { 784 if mysql.HasAutoIncrementFlag(colInfo.GetFlag()) { 785 return colInfo 786 } 787 } 788 return nil 789 } 790 791 // IsAutoIncColUnsigned checks whether the auto increment column is unsigned. 792 func (t *TableInfo) IsAutoIncColUnsigned() bool { 793 col := t.GetAutoIncrementColInfo() 794 if col == nil { 795 return false 796 } 797 return mysql.HasUnsignedFlag(col.GetFlag()) 798 } 799 800 // ContainsAutoRandomBits indicates whether a table contains auto_random column. 801 func (t *TableInfo) ContainsAutoRandomBits() bool { 802 return t.AutoRandomBits != 0 803 } 804 805 // IsAutoRandomBitColUnsigned indicates whether the auto_random column is unsigned. Make sure the table contains auto_random before calling this method. 806 func (t *TableInfo) IsAutoRandomBitColUnsigned() bool { 807 if !t.PKIsHandle || t.AutoRandomBits == 0 { 808 return false 809 } 810 return mysql.HasUnsignedFlag(t.GetPkColInfo().GetFlag()) 811 } 812 813 // Cols returns the columns of the table in public state. 814 func (t *TableInfo) Cols() []*ColumnInfo { 815 publicColumns := make([]*ColumnInfo, len(t.Columns)) 816 maxOffset := -1 817 for _, col := range t.Columns { 818 if col.State != StatePublic { 819 continue 820 } 821 publicColumns[col.Offset] = col 822 if maxOffset < col.Offset { 823 maxOffset = col.Offset 824 } 825 } 826 return publicColumns[0 : maxOffset+1] 827 } 828 829 // FindIndexByName finds index by name. 830 func (t *TableInfo) FindIndexByName(idxName string) *IndexInfo { 831 for _, idx := range t.Indices { 832 if idx.Name.L == idxName { 833 return idx 834 } 835 } 836 return nil 837 } 838 839 // FindPublicColumnByName finds the public column by name. 840 func (t *TableInfo) FindPublicColumnByName(colNameL string) *ColumnInfo { 841 for _, col := range t.Cols() { 842 if col.Name.L == colNameL { 843 return col 844 } 845 } 846 return nil 847 } 848 849 // IsLocked checks whether the table was locked. 850 func (t *TableInfo) IsLocked() bool { 851 return t.Lock != nil && len(t.Lock.Sessions) > 0 852 } 853 854 // MoveColumnInfo moves a column to another offset. It maintains the offsets of all affects columns and index columns, 855 func (t *TableInfo) MoveColumnInfo(from, to int) { 856 if from == to { 857 return 858 } 859 updatedOffsets := make(map[int]int) 860 src := t.Columns[from] 861 if from < to { 862 for i := from; i < to; i++ { 863 t.Columns[i] = t.Columns[i+1] 864 t.Columns[i].Offset = i 865 updatedOffsets[i+1] = i 866 } 867 } else if from > to { 868 for i := from; i > to; i-- { 869 t.Columns[i] = t.Columns[i-1] 870 t.Columns[i].Offset = i 871 updatedOffsets[i-1] = i 872 } 873 } 874 t.Columns[to] = src 875 t.Columns[to].Offset = to 876 updatedOffsets[from] = to 877 for _, idx := range t.Indices { 878 for _, idxCol := range idx.Columns { 879 newOffset, ok := updatedOffsets[idxCol.Offset] 880 if ok { 881 idxCol.Offset = newOffset 882 } 883 } 884 } 885 } 886 887 // ClearPlacement clears all table and partitions' placement settings 888 func (t *TableInfo) ClearPlacement() { 889 t.PlacementPolicyRef = nil 890 if t.Partition != nil { 891 for i := range t.Partition.Definitions { 892 def := &t.Partition.Definitions[i] 893 def.PlacementPolicyRef = nil 894 } 895 } 896 } 897 898 // NewExtraHandleColInfo mocks a column info for extra handle column. 899 func NewExtraHandleColInfo() *ColumnInfo { 900 colInfo := &ColumnInfo{ 901 ID: ExtraHandleID, 902 Name: ExtraHandleName, 903 } 904 905 colInfo.SetFlag(mysql.PriKeyFlag | mysql.NotNullFlag) 906 colInfo.SetType(mysql.TypeLonglong) 907 908 flen, decimal := mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong) 909 colInfo.SetFlen(flen) 910 colInfo.SetDecimal(decimal) 911 912 colInfo.SetCharset(charset.CharsetBin) 913 colInfo.SetCollate(charset.CollationBin) 914 return colInfo 915 } 916 917 // NewExtraPartitionIDColInfo mocks a column info for extra partition id column. 918 func NewExtraPartitionIDColInfo() *ColumnInfo { 919 colInfo := &ColumnInfo{ 920 ID: ExtraPidColID, 921 Name: ExtraPartitionIdName, 922 } 923 colInfo.SetType(mysql.TypeLonglong) 924 flen, decimal := mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong) 925 colInfo.SetFlen(flen) 926 colInfo.SetDecimal(decimal) 927 colInfo.SetCharset(charset.CharsetBin) 928 colInfo.SetCollate(charset.CollationBin) 929 return colInfo 930 } 931 932 // NewExtraPhysTblIDColInfo mocks a column info for extra partition id column. 933 func NewExtraPhysTblIDColInfo() *ColumnInfo { 934 colInfo := &ColumnInfo{ 935 ID: ExtraPhysTblID, 936 Name: ExtraPhysTblIdName, 937 } 938 colInfo.SetType(mysql.TypeLonglong) 939 flen, decimal := mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong) 940 colInfo.SetFlen(flen) 941 colInfo.SetDecimal(decimal) 942 colInfo.SetCharset(charset.CharsetBin) 943 colInfo.SetCollate(charset.CollationBin) 944 return colInfo 945 } 946 947 // GetPrimaryKey extract the primary key in a table and return `IndexInfo` 948 // The returned primary key could be explicit or implicit. 949 // If there is no explicit primary key in table, 950 // the first UNIQUE INDEX on NOT NULL columns will be the implicit primary key. 951 // For more information about implicit primary key, see 952 // https://dev.mysql.com/doc/refman/8.0/en/invisible-indexes.html 953 func (t *TableInfo) GetPrimaryKey() *IndexInfo { 954 var implicitPK *IndexInfo 955 956 for _, key := range t.Indices { 957 if key.Primary { 958 // table has explicit primary key 959 return key 960 } 961 // The case index without any columns should never happen, but still do a check here 962 if len(key.Columns) == 0 { 963 continue 964 } 965 // find the first unique key with NOT NULL columns 966 if implicitPK == nil && key.Unique { 967 // ensure all columns in unique key have NOT NULL flag 968 allColNotNull := true 969 skip := false 970 for _, idxCol := range key.Columns { 971 col := FindColumnInfo(t.Cols(), idxCol.Name.L) 972 // This index has a column in DeleteOnly state, 973 // or it is expression index (it defined on a hidden column), 974 // it can not be implicit PK, go to next index iterator 975 if col == nil || col.Hidden { 976 skip = true 977 break 978 } 979 if !mysql.HasNotNullFlag(col.GetFlag()) { 980 allColNotNull = false 981 break 982 } 983 } 984 if skip { 985 continue 986 } 987 if allColNotNull { 988 implicitPK = key 989 } 990 } 991 } 992 return implicitPK 993 } 994 995 // ColumnIsInIndex checks whether c is included in any indices of t. 996 func (t *TableInfo) ColumnIsInIndex(c *ColumnInfo) bool { 997 for _, index := range t.Indices { 998 for _, column := range index.Columns { 999 if column.Name.L == c.Name.L { 1000 return true 1001 } 1002 } 1003 } 1004 return false 1005 } 1006 1007 // HasClusteredIndex checks whether the table has a clustered index. 1008 func (t *TableInfo) HasClusteredIndex() bool { 1009 return t.PKIsHandle || t.IsCommonHandle 1010 } 1011 1012 // IsView checks if TableInfo is a view. 1013 func (t *TableInfo) IsView() bool { 1014 return t.View != nil 1015 } 1016 1017 // IsSequence checks if TableInfo is a sequence. 1018 func (t *TableInfo) IsSequence() bool { 1019 return t.Sequence != nil 1020 } 1021 1022 // IsBaseTable checks to see the table is neither a view or a sequence. 1023 func (t *TableInfo) IsBaseTable() bool { 1024 return t.Sequence == nil && t.View == nil 1025 } 1026 1027 // ViewAlgorithm is VIEW's SQL ALGORITHM characteristic. 1028 // See https://dev.mysql.com/doc/refman/5.7/en/view-algorithms.html 1029 type ViewAlgorithm int 1030 1031 //revive:disable:exported 1032 const ( 1033 AlgorithmUndefined ViewAlgorithm = iota 1034 AlgorithmMerge 1035 AlgorithmTemptable 1036 ) 1037 1038 //revive:enable:exported 1039 1040 func (v *ViewAlgorithm) String() string { 1041 switch *v { 1042 case AlgorithmMerge: 1043 return "MERGE" 1044 case AlgorithmTemptable: 1045 return "TEMPTABLE" 1046 case AlgorithmUndefined: 1047 return "UNDEFINED" 1048 default: 1049 return "UNDEFINED" 1050 } 1051 } 1052 1053 // ViewSecurity is VIEW's SQL SECURITY characteristic. 1054 // See https://dev.mysql.com/doc/refman/5.7/en/create-view.html 1055 type ViewSecurity int 1056 1057 //revive:disable:exported 1058 const ( 1059 SecurityDefiner ViewSecurity = iota 1060 SecurityInvoker 1061 ) 1062 1063 //revive:enable:exported 1064 1065 func (v *ViewSecurity) String() string { 1066 switch *v { 1067 case SecurityInvoker: 1068 return "INVOKER" 1069 case SecurityDefiner: 1070 return "DEFINER" 1071 default: 1072 return "DEFINER" 1073 } 1074 } 1075 1076 // ViewCheckOption is VIEW's WITH CHECK OPTION clause part. 1077 // See https://dev.mysql.com/doc/refman/5.7/en/view-check-option.html 1078 type ViewCheckOption int 1079 1080 //revive:disable:exported 1081 const ( 1082 CheckOptionLocal ViewCheckOption = iota 1083 CheckOptionCascaded 1084 ) 1085 1086 //revive:enable:exported 1087 1088 func (v *ViewCheckOption) String() string { 1089 switch *v { 1090 case CheckOptionLocal: 1091 return "LOCAL" 1092 case CheckOptionCascaded: 1093 return "CASCADED" 1094 default: 1095 return "CASCADED" 1096 } 1097 } 1098 1099 // ViewInfo provides meta data describing a DB view. 1100 // 1101 //revive:disable:exported 1102 type ViewInfo struct { 1103 Algorithm ViewAlgorithm `json:"view_algorithm"` 1104 Definer *auth.UserIdentity `json:"view_definer"` 1105 Security ViewSecurity `json:"view_security"` 1106 SelectStmt string `json:"view_select"` 1107 CheckOption ViewCheckOption `json:"view_checkoption"` 1108 Cols []CIStr `json:"view_cols"` 1109 } 1110 1111 const ( 1112 DefaultSequenceCacheBool = true 1113 DefaultSequenceCycleBool = false 1114 DefaultSequenceOrderBool = false 1115 DefaultSequenceCacheValue = int64(1000) 1116 DefaultSequenceIncrementValue = int64(1) 1117 DefaultPositiveSequenceStartValue = int64(1) 1118 DefaultNegativeSequenceStartValue = int64(-1) 1119 DefaultPositiveSequenceMinValue = int64(1) 1120 DefaultPositiveSequenceMaxValue = int64(9223372036854775806) 1121 DefaultNegativeSequenceMaxValue = int64(-1) 1122 DefaultNegativeSequenceMinValue = int64(-9223372036854775807) 1123 ) 1124 1125 // SequenceInfo provide meta data describing a DB sequence. 1126 type SequenceInfo struct { 1127 Start int64 `json:"sequence_start"` 1128 Cache bool `json:"sequence_cache"` 1129 Cycle bool `json:"sequence_cycle"` 1130 MinValue int64 `json:"sequence_min_value"` 1131 MaxValue int64 `json:"sequence_max_value"` 1132 Increment int64 `json:"sequence_increment"` 1133 CacheValue int64 `json:"sequence_cache_value"` 1134 Comment string `json:"sequence_comment"` 1135 } 1136 1137 //revive:enable:exported 1138 1139 // PartitionType is the type for PartitionInfo 1140 type PartitionType int 1141 1142 // Partition types. 1143 const ( 1144 // Actually non-partitioned, but during DDL keeping the table as 1145 // a single partition 1146 PartitionTypeNone PartitionType = 0 1147 1148 PartitionTypeRange PartitionType = 1 1149 PartitionTypeHash PartitionType = 2 1150 PartitionTypeList PartitionType = 3 1151 PartitionTypeKey PartitionType = 4 1152 PartitionTypeSystemTime PartitionType = 5 1153 ) 1154 1155 func (p PartitionType) String() string { 1156 switch p { 1157 case PartitionTypeRange: 1158 return "RANGE" 1159 case PartitionTypeHash: 1160 return "HASH" 1161 case PartitionTypeList: 1162 return "LIST" 1163 case PartitionTypeKey: 1164 return "KEY" 1165 case PartitionTypeSystemTime: 1166 return "SYSTEM_TIME" 1167 case PartitionTypeNone: 1168 return "NONE" 1169 default: 1170 return "" 1171 } 1172 } 1173 1174 // ExchangePartitionInfo provides exchange partition info. 1175 type ExchangePartitionInfo struct { 1176 // It is nt tableID when table which has the info is a partition table, else pt tableID. 1177 ExchangePartitionTableID int64 `json:"exchange_partition_id"` 1178 ExchangePartitionDefID int64 `json:"exchange_partition_def_id"` 1179 // Deprecated, not used 1180 XXXExchangePartitionFlag bool `json:"exchange_partition_flag"` 1181 } 1182 1183 // PartitionInfo provides table partition info. 1184 type PartitionInfo struct { 1185 Type PartitionType `json:"type"` 1186 Expr string `json:"expr"` 1187 Columns []CIStr `json:"columns"` 1188 1189 // User may already create table with partition but table partition is not 1190 // yet supported back then. When Enable is true, write/read need use tid 1191 // rather than pid. 1192 Enable bool `json:"enable"` 1193 1194 Definitions []PartitionDefinition `json:"definitions"` 1195 // AddingDefinitions is filled when adding partitions that is in the mid state. 1196 AddingDefinitions []PartitionDefinition `json:"adding_definitions"` 1197 // DroppingDefinitions is filled when dropping/truncating partitions that is in the mid state. 1198 DroppingDefinitions []PartitionDefinition `json:"dropping_definitions"` 1199 // NewPartitionIDs is filled when truncating partitions that is in the mid state. 1200 NewPartitionIDs []int64 1201 1202 States []PartitionState `json:"states"` 1203 Num uint64 `json:"num"` 1204 // Only used during ReorganizePartition so far 1205 DDLState SchemaState `json:"ddl_state"` 1206 // Set during ALTER TABLE ... if the table id needs to change 1207 // like if there is a global index or going between non-partitioned 1208 // and partitioned table, to make the data dropping / range delete 1209 // optimized. 1210 NewTableID int64 `json:"new_table_id"` 1211 // Set during ALTER TABLE ... PARTITION BY ... 1212 // First as the new partition scheme, then in StateDeleteReorg as the old 1213 DDLType PartitionType `json:"ddl_type"` 1214 DDLExpr string `json:"ddl_expr"` 1215 DDLColumns []CIStr `json:"ddl_columns"` 1216 } 1217 1218 // Clone clones itself. 1219 func (pi *PartitionInfo) Clone() *PartitionInfo { 1220 newPi := *pi 1221 newPi.Columns = make([]CIStr, len(pi.Columns)) 1222 copy(newPi.Columns, pi.Columns) 1223 1224 newPi.Definitions = make([]PartitionDefinition, len(pi.Definitions)) 1225 for i := range pi.Definitions { 1226 newPi.Definitions[i] = pi.Definitions[i].Clone() 1227 } 1228 1229 newPi.AddingDefinitions = make([]PartitionDefinition, len(pi.AddingDefinitions)) 1230 for i := range pi.AddingDefinitions { 1231 newPi.AddingDefinitions[i] = pi.AddingDefinitions[i].Clone() 1232 } 1233 1234 newPi.DroppingDefinitions = make([]PartitionDefinition, len(pi.DroppingDefinitions)) 1235 for i := range pi.DroppingDefinitions { 1236 newPi.DroppingDefinitions[i] = pi.DroppingDefinitions[i].Clone() 1237 } 1238 1239 return &newPi 1240 } 1241 1242 // GetNameByID gets the partition name by ID. 1243 func (pi *PartitionInfo) GetNameByID(id int64) string { 1244 definitions := pi.Definitions 1245 // do not convert this loop to `for _, def := range definitions`. 1246 // see https://github.com/pingcap/parser/pull/1072 for the benchmark. 1247 for i := range definitions { 1248 if id == definitions[i].ID { 1249 return definitions[i].Name.O 1250 } 1251 } 1252 return "" 1253 } 1254 1255 // GetStateByID gets the partition state by ID. 1256 func (pi *PartitionInfo) GetStateByID(id int64) SchemaState { 1257 for _, pstate := range pi.States { 1258 if pstate.ID == id { 1259 return pstate.State 1260 } 1261 } 1262 return StatePublic 1263 } 1264 1265 // SetStateByID sets the state of the partition by ID. 1266 func (pi *PartitionInfo) SetStateByID(id int64, state SchemaState) { 1267 newState := PartitionState{ID: id, State: state} 1268 for i, pstate := range pi.States { 1269 if pstate.ID == id { 1270 pi.States[i] = newState 1271 return 1272 } 1273 } 1274 if pi.States == nil { 1275 pi.States = make([]PartitionState, 0, 1) 1276 } 1277 pi.States = append(pi.States, newState) 1278 } 1279 1280 // GCPartitionStates cleans up the partition state. 1281 func (pi *PartitionInfo) GCPartitionStates() { 1282 if len(pi.States) < 1 { 1283 return 1284 } 1285 newStates := make([]PartitionState, 0, len(pi.Definitions)) 1286 for _, state := range pi.States { 1287 found := false 1288 for _, def := range pi.Definitions { 1289 if def.ID == state.ID { 1290 found = true 1291 break 1292 } 1293 } 1294 if found { 1295 newStates = append(newStates, state) 1296 } 1297 } 1298 pi.States = newStates 1299 } 1300 1301 // HasTruncatingPartitionID checks whether the pid is truncating. 1302 func (pi *PartitionInfo) HasTruncatingPartitionID(pid int64) bool { 1303 for i := range pi.NewPartitionIDs { 1304 if pi.NewPartitionIDs[i] == pid { 1305 return true 1306 } 1307 } 1308 return false 1309 } 1310 1311 // PartitionState is the state of the partition. 1312 type PartitionState struct { 1313 ID int64 `json:"id"` 1314 State SchemaState `json:"state"` 1315 } 1316 1317 // PartitionDefinition defines a single partition. 1318 type PartitionDefinition struct { 1319 ID int64 `json:"id"` 1320 Name CIStr `json:"name"` 1321 LessThan []string `json:"less_than"` 1322 InValues [][]string `json:"in_values"` 1323 PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` 1324 Comment string `json:"comment,omitempty"` 1325 } 1326 1327 // Clone clones ConstraintInfo. 1328 func (ci *PartitionDefinition) Clone() PartitionDefinition { 1329 nci := *ci 1330 nci.LessThan = make([]string, len(ci.LessThan)) 1331 copy(nci.LessThan, ci.LessThan) 1332 return nci 1333 } 1334 1335 const emptyPartitionDefinitionSize = int64(unsafe.Sizeof(PartitionState{})) 1336 1337 // MemoryUsage return the memory usage of PartitionDefinition 1338 func (ci *PartitionDefinition) MemoryUsage() (sum int64) { 1339 if ci == nil { 1340 return 1341 } 1342 1343 sum = emptyPartitionDefinitionSize + ci.Name.MemoryUsage() 1344 if ci.PlacementPolicyRef != nil { 1345 sum += int64(unsafe.Sizeof(ci.PlacementPolicyRef.ID)) + ci.PlacementPolicyRef.Name.MemoryUsage() 1346 } 1347 1348 for _, str := range ci.LessThan { 1349 sum += int64(len(str)) 1350 } 1351 for _, strs := range ci.InValues { 1352 for _, str := range strs { 1353 sum += int64(len(str)) 1354 } 1355 } 1356 return 1357 } 1358 1359 // FindPartitionDefinitionByName finds PartitionDefinition by name. 1360 func (pi *PartitionInfo) FindPartitionDefinitionByName(partitionDefinitionName string) int { 1361 lowConstrName := strings.ToLower(partitionDefinitionName) 1362 definitions := pi.Definitions 1363 for i := range definitions { 1364 if definitions[i].Name.L == lowConstrName { 1365 return i 1366 } 1367 } 1368 return -1 1369 } 1370 1371 // GetPartitionIDByName gets the partition ID by name. 1372 func (pi *PartitionInfo) GetPartitionIDByName(partitionDefinitionName string) int64 { 1373 lowConstrName := strings.ToLower(partitionDefinitionName) 1374 for _, definition := range pi.Definitions { 1375 if definition.Name.L == lowConstrName { 1376 return definition.ID 1377 } 1378 } 1379 return -1 1380 } 1381 1382 // IndexColumn provides index column info. 1383 type IndexColumn struct { 1384 Name CIStr `json:"name"` // Index name 1385 Offset int `json:"offset"` // Index offset 1386 // Length of prefix when using column prefix 1387 // for indexing; 1388 // UnspecifedLength if not using prefix indexing 1389 Length int `json:"length"` 1390 } 1391 1392 // Clone clones IndexColumn. 1393 func (i *IndexColumn) Clone() *IndexColumn { 1394 ni := *i 1395 return &ni 1396 } 1397 1398 // PrimaryKeyType is the type of primary key. 1399 // Available values are "clustered", "nonclustered", and ""(default). 1400 type PrimaryKeyType int8 1401 1402 func (p PrimaryKeyType) String() string { 1403 switch p { 1404 case PrimaryKeyTypeClustered: 1405 return "CLUSTERED" 1406 case PrimaryKeyTypeNonClustered: 1407 return "NONCLUSTERED" 1408 default: 1409 return "" 1410 } 1411 } 1412 1413 //revive:disable:exported 1414 const ( 1415 PrimaryKeyTypeDefault PrimaryKeyType = iota 1416 PrimaryKeyTypeClustered 1417 PrimaryKeyTypeNonClustered 1418 ) 1419 1420 //revive:enable:exported 1421 1422 // IndexType is the type of index 1423 type IndexType int 1424 1425 // String implements Stringer interface. 1426 func (t IndexType) String() string { 1427 switch t { 1428 case IndexTypeBtree: 1429 return "BTREE" 1430 case IndexTypeHash: 1431 return "HASH" 1432 case IndexTypeRtree: 1433 return "RTREE" 1434 case IndexTypeHypo: 1435 return "HYPO" 1436 default: 1437 return "" 1438 } 1439 } 1440 1441 // IndexTypes 1442 const ( 1443 IndexTypeInvalid IndexType = iota 1444 IndexTypeBtree 1445 IndexTypeHash 1446 IndexTypeRtree 1447 IndexTypeHypo 1448 ) 1449 1450 // IndexInfo provides meta data describing a DB index. 1451 // It corresponds to the statement `CREATE INDEX Name ON Table (Column);` 1452 // See https://dev.mysql.com/doc/refman/5.7/en/create-index.html 1453 type IndexInfo struct { 1454 ID int64 `json:"id"` 1455 Name CIStr `json:"idx_name"` // Index name. 1456 Table CIStr `json:"tbl_name"` // Table name. 1457 Columns []*IndexColumn `json:"idx_cols"` // Index columns. 1458 State SchemaState `json:"state"` 1459 BackfillState BackfillState `json:"backfill_state"` 1460 Comment string `json:"comment"` // Comment 1461 Tp IndexType `json:"index_type"` // Index type: Btree, Hash or Rtree 1462 Unique bool `json:"is_unique"` // Whether the index is unique. 1463 Primary bool `json:"is_primary"` // Whether the index is primary key. 1464 Invisible bool `json:"is_invisible"` // Whether the index is invisible. 1465 Global bool `json:"is_global"` // Whether the index is global. 1466 MVIndex bool `json:"mv_index"` // Whether the index is multivalued index. 1467 } 1468 1469 // Clone clones IndexInfo. 1470 func (index *IndexInfo) Clone() *IndexInfo { 1471 if index == nil { 1472 return nil 1473 } 1474 ni := *index 1475 ni.Columns = make([]*IndexColumn, len(index.Columns)) 1476 for i := range index.Columns { 1477 ni.Columns[i] = index.Columns[i].Clone() 1478 } 1479 return &ni 1480 } 1481 1482 // HasPrefixIndex returns whether any columns of this index uses prefix length. 1483 func (index *IndexInfo) HasPrefixIndex() bool { 1484 for _, ic := range index.Columns { 1485 if ic.Length != types.UnspecifiedLength { 1486 return true 1487 } 1488 } 1489 return false 1490 } 1491 1492 // HasColumnInIndexColumns checks whether the index contains the column with the specified ID. 1493 func (index *IndexInfo) HasColumnInIndexColumns(tblInfo *TableInfo, colID int64) bool { 1494 for _, ic := range index.Columns { 1495 if tblInfo.Columns[ic.Offset].ID == colID { 1496 return true 1497 } 1498 } 1499 return false 1500 } 1501 1502 // FindColumnByName finds the index column with the specified name. 1503 func (index *IndexInfo) FindColumnByName(nameL string) *IndexColumn { 1504 _, ret := FindIndexColumnByName(index.Columns, nameL) 1505 return ret 1506 } 1507 1508 // IsPublic checks if the index state is public 1509 func (index *IndexInfo) IsPublic() bool { 1510 return index.State == StatePublic 1511 } 1512 1513 // FindIndexColumnByName finds IndexColumn by name. When IndexColumn is not found, returns (-1, nil). 1514 func FindIndexColumnByName(indexCols []*IndexColumn, nameL string) (int, *IndexColumn) { 1515 for i, ic := range indexCols { 1516 if ic.Name.L == nameL { 1517 return i, ic 1518 } 1519 } 1520 return -1, nil 1521 } 1522 1523 // ConstraintInfo provides meta data describing check-expression constraint. 1524 type ConstraintInfo struct { 1525 ID int64 `json:"id"` 1526 Name CIStr `json:"constraint_name"` 1527 Table CIStr `json:"tbl_name"` // Table name. 1528 ConstraintCols []CIStr `json:"constraint_cols"` // Depended column names. 1529 Enforced bool `json:"enforced"` 1530 InColumn bool `json:"in_column"` // Indicate whether the constraint is column type check. 1531 ExprString string `json:"expr_string"` 1532 State SchemaState `json:"state"` 1533 } 1534 1535 // Clone clones ConstraintInfo. 1536 func (ci *ConstraintInfo) Clone() *ConstraintInfo { 1537 nci := *ci 1538 1539 nci.ConstraintCols = make([]CIStr, len(ci.ConstraintCols)) 1540 copy(nci.ConstraintCols, ci.ConstraintCols) 1541 return &nci 1542 } 1543 1544 // FindConstraintInfoByName finds constraintInfo by name. 1545 func (t *TableInfo) FindConstraintInfoByName(constrName string) *ConstraintInfo { 1546 lowConstrName := strings.ToLower(constrName) 1547 for _, chk := range t.Constraints { 1548 if chk.Name.L == lowConstrName { 1549 return chk 1550 } 1551 } 1552 return nil 1553 } 1554 1555 // FindIndexNameByID finds index name by id. 1556 func (t *TableInfo) FindIndexNameByID(id int64) string { 1557 indexInfo := FindIndexInfoByID(t.Indices, id) 1558 if indexInfo != nil { 1559 return indexInfo.Name.L 1560 } 1561 return "" 1562 } 1563 1564 // FindColumnNameByID finds column name by id. 1565 func (t *TableInfo) FindColumnNameByID(id int64) string { 1566 colInfo := FindColumnInfoByID(t.Columns, id) 1567 if colInfo != nil { 1568 return colInfo.Name.L 1569 } 1570 return "" 1571 } 1572 1573 // FKInfo provides meta data describing a foreign key constraint. 1574 type FKInfo struct { 1575 ID int64 `json:"id"` 1576 Name CIStr `json:"fk_name"` 1577 RefSchema CIStr `json:"ref_schema"` 1578 RefTable CIStr `json:"ref_table"` 1579 RefCols []CIStr `json:"ref_cols"` 1580 Cols []CIStr `json:"cols"` 1581 OnDelete int `json:"on_delete"` 1582 OnUpdate int `json:"on_update"` 1583 State SchemaState `json:"state"` 1584 Version int `json:"version"` 1585 } 1586 1587 const ( 1588 // FKVersion0 indicate the FKInfo version is 0. 1589 // In FKVersion0, TiDB only supported syntax of foreign key, but the foreign key constraint doesn't take effect. 1590 FKVersion0 = 0 1591 // FKVersion1 indicate the FKInfo version is 1. 1592 // In FKVersion1, TiDB supports the foreign key constraint. 1593 FKVersion1 = 1 1594 ) 1595 1596 // ReferredFKInfo provides the cited foreign key in the child table. 1597 type ReferredFKInfo struct { 1598 Cols []CIStr `json:"cols"` 1599 ChildSchema CIStr `json:"child_schema"` 1600 ChildTable CIStr `json:"child_table"` 1601 ChildFKName CIStr `json:"child_fk_name"` 1602 } 1603 1604 // ReferOptionType is the type for refer options. 1605 type ReferOptionType int 1606 1607 // Refer option types. 1608 const ( 1609 ReferOptionNoOption ReferOptionType = iota 1610 ReferOptionRestrict 1611 ReferOptionCascade 1612 ReferOptionSetNull 1613 ReferOptionNoAction 1614 ReferOptionSetDefault 1615 ) 1616 1617 // String implements fmt.Stringer interface. 1618 func (r ReferOptionType) String() string { 1619 switch r { 1620 case ReferOptionRestrict: 1621 return "RESTRICT" 1622 case ReferOptionCascade: 1623 return "CASCADE" 1624 case ReferOptionSetNull: 1625 return "SET NULL" 1626 case ReferOptionNoAction: 1627 return "NO ACTION" 1628 case ReferOptionSetDefault: 1629 return "SET DEFAULT" 1630 } 1631 return "" 1632 } 1633 1634 func (fk *FKInfo) String(db, tb string) string { 1635 buf := bytes.Buffer{} 1636 buf.WriteString("`" + db + "`.`") 1637 buf.WriteString(tb + "`, CONSTRAINT `") 1638 buf.WriteString(fk.Name.O + "` FOREIGN KEY (") 1639 for i, col := range fk.Cols { 1640 if i > 0 { 1641 buf.WriteString(", ") 1642 } 1643 buf.WriteString("`" + col.O + "`") 1644 } 1645 buf.WriteString(") REFERENCES `") 1646 if fk.RefSchema.L != db { 1647 buf.WriteString(fk.RefSchema.L) 1648 buf.WriteString("`.`") 1649 } 1650 buf.WriteString(fk.RefTable.L) 1651 buf.WriteString("` (") 1652 for i, col := range fk.RefCols { 1653 if i > 0 { 1654 buf.WriteString(", ") 1655 } 1656 buf.WriteString("`" + col.O + "`") 1657 } 1658 buf.WriteString(")") 1659 if onDelete := ReferOptionType(fk.OnDelete); onDelete != ReferOptionNoOption { 1660 buf.WriteString(" ON DELETE ") 1661 buf.WriteString(onDelete.String()) 1662 } 1663 if onUpdate := ReferOptionType(fk.OnUpdate); onUpdate != ReferOptionNoOption { 1664 buf.WriteString(" ON UPDATE ") 1665 buf.WriteString(onUpdate.String()) 1666 } 1667 return buf.String() 1668 } 1669 1670 // Clone clones FKInfo. 1671 func (fk *FKInfo) Clone() *FKInfo { 1672 nfk := *fk 1673 1674 nfk.RefCols = make([]CIStr, len(fk.RefCols)) 1675 nfk.Cols = make([]CIStr, len(fk.Cols)) 1676 copy(nfk.RefCols, fk.RefCols) 1677 copy(nfk.Cols, fk.Cols) 1678 1679 return &nfk 1680 } 1681 1682 // DBInfo provides meta data describing a DB. 1683 type DBInfo struct { 1684 ID int64 `json:"id"` // Database ID 1685 Name CIStr `json:"db_name"` // DB name. 1686 Charset string `json:"charset"` 1687 Collate string `json:"collate"` 1688 Tables []*TableInfo `json:"-"` // Tables in the DB. 1689 State SchemaState `json:"state"` 1690 PlacementPolicyRef *PolicyRefInfo `json:"policy_ref_info"` 1691 } 1692 1693 // Clone clones DBInfo. 1694 func (db *DBInfo) Clone() *DBInfo { 1695 newInfo := *db 1696 newInfo.Tables = make([]*TableInfo, len(db.Tables)) 1697 for i := range db.Tables { 1698 newInfo.Tables[i] = db.Tables[i].Clone() 1699 } 1700 return &newInfo 1701 } 1702 1703 // Copy shallow copies DBInfo. 1704 func (db *DBInfo) Copy() *DBInfo { 1705 newInfo := *db 1706 newInfo.Tables = make([]*TableInfo, len(db.Tables)) 1707 copy(newInfo.Tables, db.Tables) 1708 return &newInfo 1709 } 1710 1711 // LessDBInfo is used for sorting DBInfo by DBInfo.Name. 1712 func LessDBInfo(a *DBInfo, b *DBInfo) int { 1713 return cmp.Compare(a.Name.L, b.Name.L) 1714 } 1715 1716 // CIStr is case insensitive string. 1717 type CIStr struct { 1718 O string `json:"O"` // Original string. 1719 L string `json:"L"` // Lower case string. 1720 } 1721 1722 // String implements fmt.Stringer interface. 1723 func (cis CIStr) String() string { 1724 return cis.O 1725 } 1726 1727 // NewCIStr creates a new CIStr. 1728 func NewCIStr(s string) (cs CIStr) { 1729 cs.O = s 1730 cs.L = strings.ToLower(s) 1731 return 1732 } 1733 1734 // UnmarshalJSON implements the user defined unmarshal method. 1735 // CIStr can be unmarshaled from a single string, so PartitionDefinition.Name 1736 // in this change https://github.com/pingcap/tidb/pull/6460/files would be 1737 // compatible during TiDB upgrading. 1738 func (cis *CIStr) UnmarshalJSON(b []byte) error { 1739 type T CIStr 1740 if err := json.Unmarshal(b, (*T)(cis)); err == nil { 1741 return nil 1742 } 1743 1744 // Unmarshal CIStr from a single string. 1745 err := json.Unmarshal(b, &cis.O) 1746 if err != nil { 1747 return errors.Trace(err) 1748 } 1749 cis.L = strings.ToLower(cis.O) 1750 return nil 1751 } 1752 1753 // MemoryUsage return the memory usage of CIStr 1754 func (cis *CIStr) MemoryUsage() (sum int64) { 1755 if cis == nil { 1756 return 1757 } 1758 1759 return int64(unsafe.Sizeof(cis.O))*2 + int64(len(cis.O)+len(cis.L)) 1760 } 1761 1762 // TableItemID is composed by table ID and column/index ID 1763 type TableItemID struct { 1764 TableID int64 1765 ID int64 1766 IsIndex bool 1767 } 1768 1769 // PolicyRefInfo is the struct to refer the placement policy. 1770 type PolicyRefInfo struct { 1771 ID int64 `json:"id"` 1772 Name CIStr `json:"name"` 1773 } 1774 1775 // PlacementSettings is the settings of the placement 1776 type PlacementSettings struct { 1777 PrimaryRegion string `json:"primary_region"` 1778 Regions string `json:"regions"` 1779 Learners uint64 `json:"learners"` 1780 Followers uint64 `json:"followers"` 1781 Voters uint64 `json:"voters"` 1782 Schedule string `json:"schedule"` 1783 Constraints string `json:"constraints"` 1784 LeaderConstraints string `json:"leader_constraints"` 1785 LearnerConstraints string `json:"learner_constraints"` 1786 FollowerConstraints string `json:"follower_constraints"` 1787 VoterConstraints string `json:"voter_constraints"` 1788 SurvivalPreferences string `json:"survival_preferences"` 1789 } 1790 1791 // PolicyInfo is the struct to store the placement policy. 1792 type PolicyInfo struct { 1793 *PlacementSettings 1794 ID int64 `json:"id"` 1795 Name CIStr `json:"name"` 1796 State SchemaState `json:"state"` 1797 } 1798 1799 // Clone clones PolicyInfo. 1800 func (p *PolicyInfo) Clone() *PolicyInfo { 1801 cloned := *p 1802 cloned.PlacementSettings = p.PlacementSettings.Clone() 1803 return &cloned 1804 } 1805 1806 // DefaultJobInterval sets the default interval between TTL jobs 1807 const DefaultJobInterval = time.Hour 1808 1809 // TTLInfo records the TTL config 1810 type TTLInfo struct { 1811 ColumnName CIStr `json:"column"` 1812 IntervalExprStr string `json:"interval_expr"` 1813 // `IntervalTimeUnit` is actually ast.TimeUnitType. Use `int` to avoid cycle dependency 1814 IntervalTimeUnit int `json:"interval_time_unit"` 1815 Enable bool `json:"enable"` 1816 // JobInterval is the interval between two TTL scan jobs. 1817 // It's suggested to get a duration with `(*TTLInfo).GetJobInterval` 1818 JobInterval string `json:"job_interval"` 1819 } 1820 1821 // Clone clones TTLInfo 1822 func (t *TTLInfo) Clone() *TTLInfo { 1823 cloned := *t 1824 return &cloned 1825 } 1826 1827 // GetJobInterval parses the job interval and return 1828 // if the job interval is an empty string, the "1h" will be returned, to keep compatible with 6.5 (in which 1829 // TTL_JOB_INTERVAL attribute doesn't exist) 1830 // Didn't set TTL_JOB_INTERVAL during upgrade and bootstrap because setting default value here is much simpler 1831 // and could avoid bugs blocking users from upgrading or bootstrapping the cluster. 1832 func (t *TTLInfo) GetJobInterval() (time.Duration, error) { 1833 if len(t.JobInterval) == 0 { 1834 return DefaultJobInterval, nil 1835 } 1836 1837 return duration.ParseDuration(t.JobInterval) 1838 } 1839 1840 func writeSettingItemToBuilder(sb *strings.Builder, item string, separatorFns ...func()) { 1841 if sb.Len() != 0 { 1842 for _, fn := range separatorFns { 1843 fn() 1844 } 1845 if len(separatorFns) == 0 { 1846 sb.WriteString(" ") 1847 } 1848 } 1849 sb.WriteString(item) 1850 } 1851 func writeSettingStringToBuilder(sb *strings.Builder, item string, value string, separatorFns ...func()) { 1852 writeSettingItemToBuilder(sb, fmt.Sprintf("%s=\"%s\"", item, strings.ReplaceAll(value, "\"", "\\\"")), separatorFns...) 1853 } 1854 func writeSettingIntegerToBuilder(sb *strings.Builder, item string, value uint64, separatorFns ...func()) { 1855 writeSettingItemToBuilder(sb, fmt.Sprintf("%s=%d", item, value), separatorFns...) 1856 } 1857 1858 func writeSettingDurationToBuilder(sb *strings.Builder, item string, dur time.Duration, separatorFns ...func()) { 1859 writeSettingStringToBuilder(sb, item, dur.String(), separatorFns...) 1860 } 1861 1862 func (p *PlacementSettings) String() string { 1863 sb := new(strings.Builder) 1864 if len(p.PrimaryRegion) > 0 { 1865 writeSettingStringToBuilder(sb, "PRIMARY_REGION", p.PrimaryRegion) 1866 } 1867 1868 if len(p.Regions) > 0 { 1869 writeSettingStringToBuilder(sb, "REGIONS", p.Regions) 1870 } 1871 1872 if len(p.Schedule) > 0 { 1873 writeSettingStringToBuilder(sb, "SCHEDULE", p.Schedule) 1874 } 1875 1876 if len(p.Constraints) > 0 { 1877 writeSettingStringToBuilder(sb, "CONSTRAINTS", p.Constraints) 1878 } 1879 1880 if len(p.LeaderConstraints) > 0 { 1881 writeSettingStringToBuilder(sb, "LEADER_CONSTRAINTS", p.LeaderConstraints) 1882 } 1883 1884 if p.Voters > 0 { 1885 writeSettingIntegerToBuilder(sb, "VOTERS", p.Voters) 1886 } 1887 1888 if len(p.VoterConstraints) > 0 { 1889 writeSettingStringToBuilder(sb, "VOTER_CONSTRAINTS", p.VoterConstraints) 1890 } 1891 1892 if p.Followers > 0 { 1893 writeSettingIntegerToBuilder(sb, "FOLLOWERS", p.Followers) 1894 } 1895 1896 if len(p.FollowerConstraints) > 0 { 1897 writeSettingStringToBuilder(sb, "FOLLOWER_CONSTRAINTS", p.FollowerConstraints) 1898 } 1899 1900 if p.Learners > 0 { 1901 writeSettingIntegerToBuilder(sb, "LEARNERS", p.Learners) 1902 } 1903 1904 if len(p.LearnerConstraints) > 0 { 1905 writeSettingStringToBuilder(sb, "LEARNER_CONSTRAINTS", p.LearnerConstraints) 1906 } 1907 1908 return sb.String() 1909 } 1910 1911 // Clone clones the placement settings. 1912 func (p *PlacementSettings) Clone() *PlacementSettings { 1913 cloned := *p 1914 return &cloned 1915 } 1916 1917 // RunawayActionType is the type of runaway action. 1918 type RunawayActionType int32 1919 1920 //revive:disable:exported 1921 const ( 1922 RunawayActionNone RunawayActionType = iota 1923 RunawayActionDryRun 1924 RunawayActionCooldown 1925 RunawayActionKill 1926 ) 1927 1928 // RunawayWatchType is the type of runaway watch. 1929 type RunawayWatchType int32 1930 1931 //revive:disable:exported 1932 const ( 1933 WatchNone RunawayWatchType = iota 1934 WatchExact 1935 WatchSimilar 1936 WatchPlan 1937 ) 1938 1939 func (t RunawayWatchType) String() string { 1940 switch t { 1941 case WatchExact: 1942 return "EXACT" 1943 case WatchSimilar: 1944 return "SIMILAR" 1945 case WatchPlan: 1946 return "PLAN" 1947 default: 1948 return "NONE" 1949 } 1950 } 1951 1952 // RunawayOptionType is the runaway's option type. 1953 type RunawayOptionType int 1954 1955 //revive:disable:exported 1956 const ( 1957 RunawayRule RunawayOptionType = iota 1958 RunawayAction 1959 RunawayWatch 1960 ) 1961 1962 func (t RunawayActionType) String() string { 1963 switch t { 1964 case RunawayActionDryRun: 1965 return "DRYRUN" 1966 case RunawayActionCooldown: 1967 return "COOLDOWN" 1968 case RunawayActionKill: 1969 return "KILL" 1970 default: 1971 return "DRYRUN" 1972 } 1973 } 1974 1975 // ResourceGroupRefInfo is the struct to refer the resource group. 1976 type ResourceGroupRefInfo struct { 1977 ID int64 `json:"id"` 1978 Name CIStr `json:"name"` 1979 } 1980 1981 // ResourceGroupRunawaySettings is the runaway settings of the resource group 1982 type ResourceGroupRunawaySettings struct { 1983 ExecElapsedTimeMs uint64 `json:"exec_elapsed_time_ms"` 1984 Action RunawayActionType `json:"action"` 1985 WatchType RunawayWatchType `json:"watch_type"` 1986 WatchDurationMs int64 `json:"watch_duration_ms"` 1987 } 1988 1989 type ResourceGroupBackgroundSettings struct { 1990 JobTypes []string `json:"job_types"` 1991 } 1992 1993 // ResourceGroupSettings is the settings of the resource group 1994 type ResourceGroupSettings struct { 1995 RURate uint64 `json:"ru_per_sec"` 1996 Priority uint64 `json:"priority"` 1997 CPULimiter string `json:"cpu_limit"` 1998 IOReadBandwidth string `json:"io_read_bandwidth"` 1999 IOWriteBandwidth string `json:"io_write_bandwidth"` 2000 BurstLimit int64 `json:"burst_limit"` 2001 Runaway *ResourceGroupRunawaySettings `json:"runaway"` 2002 Background *ResourceGroupBackgroundSettings `json:"background"` 2003 } 2004 2005 // NewResourceGroupSettings creates a new ResourceGroupSettings. 2006 func NewResourceGroupSettings() *ResourceGroupSettings { 2007 return &ResourceGroupSettings{ 2008 RURate: 0, 2009 Priority: MediumPriorityValue, 2010 CPULimiter: "", 2011 IOReadBandwidth: "", 2012 IOWriteBandwidth: "", 2013 BurstLimit: 0, 2014 } 2015 } 2016 2017 // PriorityValueToName converts the priority value to corresponding name 2018 func PriorityValueToName(value uint64) string { 2019 switch value { 2020 case LowPriorityValue: 2021 return "LOW" 2022 case MediumPriorityValue: 2023 return "MEDIUM" 2024 case HighPriorityValue: 2025 return "HIGH" 2026 default: 2027 return "MEDIUM" 2028 } 2029 } 2030 2031 //revive:disable:exported 2032 const ( 2033 LowPriorityValue = 1 2034 MediumPriorityValue = 8 2035 HighPriorityValue = 16 2036 ) 2037 2038 func (p *ResourceGroupSettings) String() string { 2039 sb := new(strings.Builder) 2040 separatorFn := func() { 2041 sb.WriteString(", ") 2042 } 2043 if p.RURate != 0 { 2044 writeSettingIntegerToBuilder(sb, "RU_PER_SEC", p.RURate, separatorFn) 2045 } 2046 writeSettingItemToBuilder(sb, "PRIORITY="+PriorityValueToName(p.Priority), separatorFn) 2047 if len(p.CPULimiter) > 0 { 2048 writeSettingStringToBuilder(sb, "CPU", p.CPULimiter, separatorFn) 2049 } 2050 if len(p.IOReadBandwidth) > 0 { 2051 writeSettingStringToBuilder(sb, "IO_READ_BANDWIDTH", p.IOReadBandwidth, separatorFn) 2052 } 2053 if len(p.IOWriteBandwidth) > 0 { 2054 writeSettingStringToBuilder(sb, "IO_WRITE_BANDWIDTH", p.IOWriteBandwidth, separatorFn) 2055 } 2056 // Once burst limit is negative, meaning allow burst with unlimit. 2057 if p.BurstLimit < 0 { 2058 writeSettingItemToBuilder(sb, "BURSTABLE", separatorFn) 2059 } 2060 if p.Runaway != nil { 2061 writeSettingDurationToBuilder(sb, "QUERY_LIMIT=(EXEC_ELAPSED", time.Duration(p.Runaway.ExecElapsedTimeMs)*time.Millisecond, separatorFn) 2062 writeSettingItemToBuilder(sb, "ACTION="+p.Runaway.Action.String()) 2063 if p.Runaway.WatchType != WatchNone { 2064 writeSettingItemToBuilder(sb, "WATCH="+p.Runaway.WatchType.String()) 2065 if p.Runaway.WatchDurationMs > 0 { 2066 writeSettingDurationToBuilder(sb, "DURATION", time.Duration(p.Runaway.WatchDurationMs)*time.Millisecond) 2067 } else { 2068 writeSettingItemToBuilder(sb, "DURATION=UNLIMITED") 2069 } 2070 } 2071 sb.WriteString(")") 2072 } 2073 if p.Background != nil { 2074 fmt.Fprintf(sb, ", BACKGROUND=(TASK_TYPES='%s')", strings.Join(p.Background.JobTypes, ",")) 2075 } 2076 2077 return sb.String() 2078 } 2079 2080 // Adjust adjusts the resource group settings. 2081 func (p *ResourceGroupSettings) Adjust() { 2082 // Curretly we only support ru_per_sec sytanx, so BurstLimit(capicity) is always same as ru_per_sec. 2083 if p.BurstLimit == 0 { 2084 p.BurstLimit = int64(p.RURate) 2085 } 2086 } 2087 2088 // Clone clones the resource group settings. 2089 func (p *ResourceGroupSettings) Clone() *ResourceGroupSettings { 2090 cloned := *p 2091 return &cloned 2092 } 2093 2094 // ResourceGroupInfo is the struct to store the resource group. 2095 type ResourceGroupInfo struct { 2096 *ResourceGroupSettings 2097 ID int64 `json:"id"` 2098 Name CIStr `json:"name"` 2099 State SchemaState `json:"state"` 2100 } 2101 2102 // Clone clones the ResourceGroupInfo. 2103 func (p *ResourceGroupInfo) Clone() *ResourceGroupInfo { 2104 cloned := *p 2105 cloned.ResourceGroupSettings = p.ResourceGroupSettings.Clone() 2106 return &cloned 2107 } 2108 2109 // StatsOptions is the struct to store the stats options. 2110 type StatsOptions struct { 2111 *StatsWindowSettings 2112 AutoRecalc bool `json:"auto_recalc"` 2113 ColumnChoice ColumnChoice `json:"column_choice"` 2114 ColumnList []CIStr `json:"column_list"` 2115 SampleNum uint64 `json:"sample_num"` 2116 SampleRate float64 `json:"sample_rate"` 2117 Buckets uint64 `json:"buckets"` 2118 TopN uint64 `json:"topn"` 2119 Concurrency uint `json:"concurrency"` 2120 } 2121 2122 // NewStatsOptions creates a new StatsOptions. 2123 func NewStatsOptions() *StatsOptions { 2124 return &StatsOptions{ 2125 AutoRecalc: true, 2126 ColumnChoice: DefaultChoice, 2127 ColumnList: []CIStr{}, 2128 SampleNum: uint64(0), 2129 SampleRate: 0.0, 2130 Buckets: uint64(0), 2131 TopN: uint64(0), 2132 Concurrency: uint(0), 2133 } 2134 } 2135 2136 // ColumnChoice is the type of the column choice. 2137 type ColumnChoice byte 2138 2139 //revive:disable:exported 2140 const ( 2141 DefaultChoice ColumnChoice = iota 2142 AllColumns 2143 PredicateColumns 2144 ColumnList 2145 ) 2146 2147 //revive:enable:exported 2148 2149 func (s ColumnChoice) String() string { 2150 switch s { 2151 case AllColumns: 2152 return "ALL" 2153 case PredicateColumns: 2154 return "PREDICATE" 2155 case ColumnList: 2156 return "LIST" 2157 default: 2158 return "DEFAULT" 2159 } 2160 } 2161 2162 // StatsWindowSettings is the settings of the stats window. 2163 type StatsWindowSettings struct { 2164 WindowStart time.Time `json:"window_start"` 2165 WindowEnd time.Time `json:"window_end"` 2166 RepeatType WindowRepeatType `json:"repeat_type"` 2167 RepeatInterval uint `json:"repeat_interval"` 2168 } 2169 2170 // WindowRepeatType is the type of the window repeat. 2171 type WindowRepeatType byte 2172 2173 //revive:disable:exported 2174 const ( 2175 Never WindowRepeatType = iota 2176 Day 2177 Week 2178 Month 2179 ) 2180 2181 //revive:enable:exported 2182 2183 func (s WindowRepeatType) String() string { 2184 switch s { 2185 case Never: 2186 return "Never" 2187 case Day: 2188 return "Day" 2189 case Week: 2190 return "Week" 2191 case Month: 2192 return "Month" 2193 default: 2194 return "" 2195 } 2196 } 2197 2198 // TraceInfo is the information for trace. 2199 type TraceInfo struct { 2200 // ConnectionID is the id of the connection 2201 ConnectionID uint64 `json:"connection_id"` 2202 // SessionAlias is the alias of session 2203 SessionAlias string `json:"session_alias"` 2204 }