mirror of
1
Fork 0
forgejo/vendor/github.com/pingcap/tidb/infoschema/tables.go

459 lines
16 KiB
Go
Raw Normal View History

// Copyright 2016 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 infoschema
import (
"fmt"
"sort"
"github.com/pingcap/tidb/column"
"github.com/pingcap/tidb/meta/autoid"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/table/tables"
"github.com/pingcap/tidb/util/charset"
"github.com/pingcap/tidb/util/types"
)
const (
tableSchemata = "SCHEMATA"
tableTables = "TABLES"
tableColumns = "COLUMNS"
tableStatistics = "STATISTICS"
tableCharacterSets = "CHARACTER_SETS"
tableCollations = "COLLATIONS"
tableFiles = "FILES"
catalogVal = "def"
tableProfiling = "PROFILING"
)
type columnInfo struct {
name string
tp byte
size int
flag uint
deflt interface{}
elems []string
}
func buildColumnInfo(tableName string, col columnInfo) *model.ColumnInfo {
mCharset := charset.CharsetBin
mCollation := charset.CharsetBin
mFlag := mysql.UnsignedFlag
if col.tp == mysql.TypeVarchar || col.tp == mysql.TypeBlob {
mCharset = mysql.DefaultCharset
mCollation = mysql.DefaultCollationName
mFlag = 0
}
fieldType := types.FieldType{
Charset: mCharset,
Collate: mCollation,
Tp: col.tp,
Flen: col.size,
Flag: uint(mFlag),
}
return &model.ColumnInfo{
Name: model.NewCIStr(col.name),
FieldType: fieldType,
State: model.StatePublic,
}
}
func buildTableMeta(tableName string, cs []columnInfo) *model.TableInfo {
cols := make([]*model.ColumnInfo, 0, len(cs))
for _, c := range cs {
cols = append(cols, buildColumnInfo(tableName, c))
}
for i, col := range cols {
col.Offset = i
}
return &model.TableInfo{
Name: model.NewCIStr(tableName),
Columns: cols,
State: model.StatePublic,
}
}
var schemataCols = []columnInfo{
{"CATALOG_NAME", mysql.TypeVarchar, 512, 0, nil, nil},
{"SCHEMA_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"DEFAULT_CHARACTER_SET_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"DEFAULT_COLLATION_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"SQL_PATH", mysql.TypeVarchar, 512, 0, nil, nil},
}
var tablesCols = []columnInfo{
{"TABLE_CATALOG", mysql.TypeVarchar, 512, 0, nil, nil},
{"TABLE_SCHEMA", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_TYPE", mysql.TypeVarchar, 64, 0, nil, nil},
{"ENGINE", mysql.TypeVarchar, 64, 0, nil, nil},
{"VERSION", mysql.TypeLonglong, 21, 0, nil, nil},
{"ROW_FORMAT", mysql.TypeVarchar, 10, 0, nil, nil},
{"TABLE_ROWS", mysql.TypeLonglong, 21, 0, nil, nil},
{"AVG_ROW_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"DATA_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"MAX_DATA_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"INDEX_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"DATA_FREE", mysql.TypeLonglong, 21, 0, nil, nil},
{"AUTO_INCREMENT", mysql.TypeLonglong, 21, 0, nil, nil},
{"CREATE_TIME", mysql.TypeDatetime, 19, 0, nil, nil},
{"UPDATE_TIME", mysql.TypeDatetime, 19, 0, nil, nil},
{"CHECK_TIME", mysql.TypeDatetime, 19, 0, nil, nil},
{"TABLE_COLLATION", mysql.TypeVarchar, 32, 0, nil, nil},
{"CHECK_SUM", mysql.TypeLonglong, 21, 0, nil, nil},
{"CREATE_OPTIONS", mysql.TypeVarchar, 255, 0, nil, nil},
{"TABLE_COMMENT", mysql.TypeVarchar, 2048, 0, nil, nil},
}
var columnsCols = []columnInfo{
{"TABLE_CATALOG", mysql.TypeVarchar, 512, 0, nil, nil},
{"TABLE_SCHEMA", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"COLUMN_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"ORIGINAL_POSITION", mysql.TypeLonglong, 64, 0, nil, nil},
{"COLUMN_DEFAULT", mysql.TypeBlob, 196606, 0, nil, nil},
{"IS_NULLABLE", mysql.TypeVarchar, 3, 0, nil, nil},
{"DATA_TYPE", mysql.TypeVarchar, 64, 0, nil, nil},
{"CHARACTER_MAXIMUM_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"CHARACTOR_OCTET_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"NUMERIC_PRECISION", mysql.TypeLonglong, 21, 0, nil, nil},
{"NUMERIC_SCALE", mysql.TypeLonglong, 21, 0, nil, nil},
{"DATETIME_PRECISION", mysql.TypeLonglong, 21, 0, nil, nil},
{"CHARACTER_SET_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"COLLATION_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"COLUMN_TYPE", mysql.TypeBlob, 196606, 0, nil, nil},
{"COLUMN_KEY", mysql.TypeVarchar, 3, 0, nil, nil},
{"EXTRA", mysql.TypeVarchar, 30, 0, nil, nil},
{"PRIVILEGES", mysql.TypeVarchar, 80, 0, nil, nil},
{"COLUMN_COMMENT", mysql.TypeVarchar, 1024, 0, nil, nil},
}
var statisticsCols = []columnInfo{
{"TABLE_CATALOG", mysql.TypeVarchar, 512, 0, nil, nil},
{"TABLE_SCHEMA", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"NON_UNIQUE", mysql.TypeVarchar, 1, 0, nil, nil},
{"INDEX_SCHEMA", mysql.TypeVarchar, 64, 0, nil, nil},
{"INDEX_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"SEQ_IN_INDEX", mysql.TypeLonglong, 2, 0, nil, nil},
{"COLUMN_NAME", mysql.TypeVarchar, 21, 0, nil, nil},
{"COLLATION", mysql.TypeVarchar, 1, 0, nil, nil},
{"CARDINALITY", mysql.TypeLonglong, 21, 0, nil, nil},
{"SUB_PART", mysql.TypeLonglong, 3, 0, nil, nil},
{"PACKED", mysql.TypeVarchar, 10, 0, nil, nil},
{"NULLABLE", mysql.TypeVarchar, 3, 0, nil, nil},
{"INDEX_TYPE", mysql.TypeVarchar, 16, 0, nil, nil},
{"COMMENT", mysql.TypeVarchar, 16, 0, nil, nil},
{"INDEX_COMMENT", mysql.TypeVarchar, 1024, 0, nil, nil},
}
var profilingCols = []columnInfo{
{"QUERY_ID", mysql.TypeLong, 20, 0, nil, nil},
{"SEQ", mysql.TypeLong, 20, 0, nil, nil},
{"STATE", mysql.TypeVarchar, 30, 0, nil, nil},
{"DURATION", mysql.TypeNewDecimal, 9, 0, nil, nil},
{"CPU_USER", mysql.TypeNewDecimal, 9, 0, nil, nil},
{"CPU_SYSTEM", mysql.TypeNewDecimal, 9, 0, nil, nil},
{"CONTEXT_VOLUNTARY", mysql.TypeLong, 20, 0, nil, nil},
{"CONTEXT_INVOLUNTARY", mysql.TypeLong, 20, 0, nil, nil},
{"BLOCK_OPS_IN", mysql.TypeLong, 20, 0, nil, nil},
{"BLOCK_OPS_OUT", mysql.TypeLong, 20, 0, nil, nil},
{"MESSAGES_SENT", mysql.TypeLong, 20, 0, nil, nil},
{"MESSAGES_RECEIVED", mysql.TypeLong, 20, 0, nil, nil},
{"PAGE_FAULTS_MAJOR", mysql.TypeLong, 20, 0, nil, nil},
{"PAGE_FAULTS_MINOR", mysql.TypeLong, 20, 0, nil, nil},
{"SWAPS", mysql.TypeLong, 20, 0, nil, nil},
{"SOURCE_FUNCTION", mysql.TypeVarchar, 30, 0, nil, nil},
{"SOURCE_FILE", mysql.TypeVarchar, 20, 0, nil, nil},
{"SOURCE_LINE", mysql.TypeLong, 20, 0, nil, nil},
}
var charsetCols = []columnInfo{
{"CHARACTER_SET_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"DEFAULT_COLLATE_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"DESCRIPTION", mysql.TypeVarchar, 60, 0, nil, nil},
{"MAXLEN", mysql.TypeLonglong, 3, 0, nil, nil},
}
var collationsCols = []columnInfo{
{"COLLATION_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"CHARACTER_SET_NAME", mysql.TypeVarchar, 32, 0, nil, nil},
{"ID", mysql.TypeLonglong, 11, 0, nil, nil},
{"IS_DEFAULT", mysql.TypeVarchar, 3, 0, nil, nil},
{"IS_COMPILED", mysql.TypeVarchar, 3, 0, nil, nil},
{"SORTLEN", mysql.TypeLonglong, 3, 0, nil, nil},
}
func dataForCharacterSets() (records [][]types.Datum) {
records = append(records,
types.MakeDatums("ascii", "ascii_general_ci", "US ASCII", 1),
types.MakeDatums("binary", "binary", "Binary pseudo charset", 1),
types.MakeDatums("latin1", "latin1_swedish_ci", "cp1252 West European", 1),
types.MakeDatums("utf8", "utf8_general_ci", "UTF-8 Unicode", 3),
types.MakeDatums("utf8mb4", "utf8mb4_general_ci", "UTF-8 Unicode", 4),
)
return records
}
func dataForColltions() (records [][]types.Datum) {
records = append(records,
types.MakeDatums("ascii_general_ci", "ascii", 1, "Yes", "Yes", 1),
types.MakeDatums("binary", "binary", 2, "Yes", "Yes", 1),
types.MakeDatums("latin1_swedish_ci", "latin1", 3, "Yes", "Yes", 1),
types.MakeDatums("utf8_general_ci", "utf8", 4, "Yes", "Yes", 1),
types.MakeDatums("utf8mb4_general_ci", "utf8mb4", 5, "Yes", "Yes", 1),
)
return records
}
var filesCols = []columnInfo{
{"FILE_ID", mysql.TypeLonglong, 4, 0, nil, nil},
{"FILE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLESPACE_NAME", mysql.TypeVarchar, 20, 0, nil, nil},
{"TABLE_CATALOG", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_SCHEMA", mysql.TypeVarchar, 64, 0, nil, nil},
{"TABLE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"LOGFILE_GROUP_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
{"LOGFILE_GROUP_NUMBER", mysql.TypeLonglong, 32, 0, nil, nil},
{"ENGINE", mysql.TypeVarchar, 64, 0, nil, nil},
{"FULLTEXT_KEYS", mysql.TypeVarchar, 64, 0, nil, nil},
{"DELETED_ROWS", mysql.TypeLonglong, 4, 0, nil, nil},
{"UPDATE_COUNT", mysql.TypeLonglong, 4, 0, nil, nil},
{"FREE_EXTENTS", mysql.TypeLonglong, 4, 0, nil, nil},
{"TOTAL_EXTENTS", mysql.TypeLonglong, 4, 0, nil, nil},
{"EXTENT_SIZE", mysql.TypeLonglong, 4, 0, nil, nil},
{"INITIAL_SIZE", mysql.TypeLonglong, 21, 0, nil, nil},
{"MAXIMUM_SIZE", mysql.TypeLonglong, 21, 0, nil, nil},
{"AUTOEXTEND_SIZE", mysql.TypeLonglong, 21, 0, nil, nil},
{"CREATION_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"LAST_UPDATE_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"LAST_ACCESS_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"RECOVER_TIME", mysql.TypeLonglong, 4, 0, nil, nil},
{"TRANSACTION_COUNTER", mysql.TypeLonglong, 4, 0, nil, nil},
{"VERSION", mysql.TypeLonglong, 21, 0, nil, nil},
{"ROW_FORMAT", mysql.TypeVarchar, 21, 0, nil, nil},
{"TABLE_ROWS", mysql.TypeLonglong, 21, 0, nil, nil},
{"AVG_ROW_LENGTH", mysql.TypeLonglong, 21, 0, nil, nil},
{"DATA_FREE", mysql.TypeLonglong, 21, 0, nil, nil},
{"CREATE_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"UPDATE_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"CHECK_TIME", mysql.TypeDatetime, -1, 0, nil, nil},
{"CHECKSUM", mysql.TypeLonglong, 21, 0, nil, nil},
{"STATUS", mysql.TypeVarchar, 20, 0, nil, nil},
{"EXTRA", mysql.TypeVarchar, 255, 0, nil, nil},
}
func dataForSchemata(schemas []string) [][]types.Datum {
sort.Strings(schemas)
rows := [][]types.Datum{}
for _, schema := range schemas {
record := types.MakeDatums(
catalogVal, // CATALOG_NAME
schema, // SCHEMA_NAME
mysql.DefaultCharset, // DEFAULT_CHARACTER_SET_NAME
mysql.DefaultCollationName, // DEFAULT_COLLATION_NAME
nil,
)
rows = append(rows, record)
}
return rows
}
func dataForTables(schemas []*model.DBInfo) [][]types.Datum {
rows := [][]types.Datum{}
for _, schema := range schemas {
for _, table := range schema.Tables {
record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
"BASE_TABLE", // TABLE_TYPE
"InnoDB", // ENGINE
uint64(10), // VERSION
"Compact", // ROW_FORMAT
uint64(0), // TABLE_ROWS
uint64(0), // AVG_ROW_LENGTH
uint64(16384), // DATA_LENGTH
uint64(0), // MAX_DATA_LENGTH
uint64(0), // INDEX_LENGTH
uint64(0), // DATA_FREE
nil, // AUTO_INCREMENT
nil, // CREATE_TIME
nil, // UPDATE_TIME
nil, // CHECK_TIME
"latin1_swedish_ci", // TABLE_COLLATION
nil, // CHECKSUM
"", // CREATE_OPTIONS
"", // TABLE_COMMENT
)
rows = append(rows, record)
}
}
return rows
}
func dataForColumns(schemas []*model.DBInfo) [][]types.Datum {
rows := [][]types.Datum{}
for _, schema := range schemas {
for _, table := range schema.Tables {
rs := dataForColumnsInTable(schema, table)
for _, r := range rs {
rows = append(rows, r)
}
}
}
return rows
}
func dataForColumnsInTable(schema *model.DBInfo, table *model.TableInfo) [][]types.Datum {
rows := [][]types.Datum{}
for i, col := range table.Columns {
colLen := col.Flen
if colLen == types.UnspecifiedLength {
colLen = mysql.GetDefaultFieldLength(col.Tp)
}
decimal := col.Decimal
if decimal == types.UnspecifiedLength {
decimal = 0
}
columnType := col.FieldType.CompactStr()
columnDesc := column.NewColDesc(&column.Col{ColumnInfo: *col})
var columnDefault interface{}
if columnDesc.DefaultValue != nil {
columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue)
}
record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
col.Name.O, // COLUMN_NAME
i+1, // ORIGINAL_POSITION
columnDefault, // COLUMN_DEFAULT
columnDesc.Null, // IS_NULLABLE
types.TypeToStr(col.Tp, col.Charset), // DATA_TYPE
colLen, // CHARACTER_MAXIMUM_LENGTH
colLen, // CHARACTOR_OCTET_LENGTH
decimal, // NUMERIC_PRECISION
0, // NUMERIC_SCALE
0, // DATETIME_PRECISION
col.Charset, // CHARACTER_SET_NAME
col.Collate, // COLLATION_NAME
columnType, // COLUMN_TYPE
columnDesc.Key, // COLUMN_KEY
columnDesc.Extra, // EXTRA
"select,insert,update,references", // PRIVILEGES
"", // COLUMN_COMMENT
)
rows = append(rows, record)
}
return rows
}
func dataForStatistics(schemas []*model.DBInfo) [][]types.Datum {
rows := [][]types.Datum{}
for _, schema := range schemas {
for _, table := range schema.Tables {
rs := dataForStatisticsInTable(schema, table)
for _, r := range rs {
rows = append(rows, r)
}
}
}
return rows
}
func dataForStatisticsInTable(schema *model.DBInfo, table *model.TableInfo) [][]types.Datum {
rows := [][]types.Datum{}
if table.PKIsHandle {
for _, col := range table.Columns {
if mysql.HasPriKeyFlag(col.Flag) {
record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
"0", // NON_UNIQUE
schema.Name.O, // INDEX_SCHEMA
"PRIMARY", // INDEX_NAME
1, // SEQ_IN_INDEX
col.Name.O, // COLUMN_NAME
"A", // COLLATION
0, // CARDINALITY
nil, // SUB_PART
nil, // PACKED
"", // NULLABLE
"BTREE", // INDEX_TYPE
"", // COMMENT
"", // INDEX_COMMENT
)
rows = append(rows, record)
}
}
}
nameToCol := make(map[string]*model.ColumnInfo, len(table.Columns))
for _, c := range table.Columns {
nameToCol[c.Name.L] = c
}
for _, index := range table.Indices {
nonUnique := "1"
if index.Unique {
nonUnique = "0"
}
for i, key := range index.Columns {
col := nameToCol[key.Name.L]
nullable := "YES"
if mysql.HasNotNullFlag(col.Flag) {
nullable = ""
}
record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
nonUnique, // NON_UNIQUE
schema.Name.O, // INDEX_SCHEMA
index.Name.O, // INDEX_NAME
i+1, // SEQ_IN_INDEX
key.Name.O, // COLUMN_NAME
"A", // COLLATION
0, // CARDINALITY
nil, // SUB_PART
nil, // PACKED
nullable, // NULLABLE
"BTREE", // INDEX_TYPE
"", // COMMENT
"", // INDEX_COMMENT
)
rows = append(rows, record)
}
}
return rows
}
var tableNameToColumns = map[string]([]columnInfo){
tableSchemata: schemataCols,
tableTables: tablesCols,
tableColumns: columnsCols,
tableStatistics: statisticsCols,
tableCharacterSets: charsetCols,
tableCollations: collationsCols,
tableFiles: filesCols,
tableProfiling: profilingCols,
}
func createMemoryTable(meta *model.TableInfo, alloc autoid.Allocator) (table.Table, error) {
tbl, _ := tables.MemoryTableFromMeta(alloc, meta)
return tbl, nil
}