Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

infoschema: show information about table partitions in information_schema.PARTITIONS #14347 #14849

Merged
merged 3 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,107 @@ func dataForPseudoProfiling() [][]types.Datum {
return rows
}

func dataForPartitions(ctx sessionctx.Context, schemas []*model.DBInfo) ([][]types.Datum, error) {
tableRowsMap, colLengthMap, err := tableStatsCache.get(ctx)
if err != nil {
return nil, err
}
checker := privilege.GetPrivilegeManager(ctx)
var rows [][]types.Datum
// createTimeTp := partitionsCols[18].tp
for _, schema := range schemas {
for _, table := range schema.Tables {
if checker != nil && !checker.RequestVerification(ctx.GetSessionVars().ActiveRoles, schema.Name.L, table.Name.L, "", mysql.SelectPriv) {
continue
}
createTime := types.Time{Time: types.FromGoTime(table.GetUpdateTime()), Type: mysql.TypeDatetime}

var rowCount, dataLength, indexLength uint64
if table.GetPartitionInfo() == nil {
rowCount = tableRowsMap[table.ID]
dataLength, indexLength = getDataAndIndexLength(table, table.ID, rowCount, colLengthMap)
avgRowLength := uint64(0)
if rowCount != 0 {
avgRowLength = dataLength / rowCount
}
record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
nil, // PARTITION_NAME
nil, // SUBPARTITION_NAME
nil, // PARTITION_ORDINAL_POSITION
nil, // SUBPARTITION_ORDINAL_POSITION
nil, // PARTITION_METHOD
nil, // SUBPARTITION_METHOD
nil, // PARTITION_EXPRESSION
nil, // SUBPARTITION_EXPRESSION
nil, // PARTITION_DESCRIPTION
rowCount, // TABLE_ROWS
avgRowLength, // AVG_ROW_LENGTH
dataLength, // DATA_LENGTH
nil, // MAX_DATA_LENGTH
indexLength, // INDEX_LENGTH
nil, // DATA_FREE
createTime, // CREATE_TIME
nil, // UPDATE_TIME
nil, // CHECK_TIME
nil, // CHECKSUM
nil, // PARTITION_COMMENT
nil, // NODEGROUP
nil, // TABLESPACE_NAME
)
rows = append(rows, record)
} else {
for i, pi := range table.GetPartitionInfo().Definitions {
rowCount = tableRowsMap[pi.ID]
dataLength, indexLength = getDataAndIndexLength(table, pi.ID, tableRowsMap[pi.ID], colLengthMap)

avgRowLength := uint64(0)
if rowCount != 0 {
avgRowLength = dataLength / rowCount
}

var partitionDesc string
if table.Partition.Type == model.PartitionTypeRange {
partitionDesc = pi.LessThan[0]
}

record := types.MakeDatums(
catalogVal, // TABLE_CATALOG
schema.Name.O, // TABLE_SCHEMA
table.Name.O, // TABLE_NAME
pi.Name.O, // PARTITION_NAME
nil, // SUBPARTITION_NAME
i+1, // PARTITION_ORDINAL_POSITION
nil, // SUBPARTITION_ORDINAL_POSITION
table.Partition.Type.String(), // PARTITION_METHOD
nil, // SUBPARTITION_METHOD
table.Partition.Expr, // PARTITION_EXPRESSION
nil, // SUBPARTITION_EXPRESSION
partitionDesc, // PARTITION_DESCRIPTION
rowCount, // TABLE_ROWS
avgRowLength, // AVG_ROW_LENGTH
dataLength, // DATA_LENGTH
uint64(0), // MAX_DATA_LENGTH
indexLength, // INDEX_LENGTH
uint64(0), // DATA_FREE
createTime, // CREATE_TIME
nil, // UPDATE_TIME
nil, // CHECK_TIME
nil, // CHECKSUM
pi.Comment, // PARTITION_COMMENT
nil, // NODEGROUP
nil, // TABLESPACE_NAME
)
rows = append(rows, record)
}
}
}
}
return rows, nil
}

func dataForKeyColumnUsage(schemas []*model.DBInfo) [][]types.Datum {
rows := make([][]types.Datum, 0, len(schemas)) // The capacity is not accurate, but it is not a big problem.
for _, schema := range schemas {
Expand Down Expand Up @@ -1823,6 +1924,7 @@ func (it *infoschemaTable) getRows(ctx sessionctx.Context, cols []*table.Column)
fullRows = dataForPseudoProfiling()
}
case tablePartitions:
fullRows, err = dataForPartitions(ctx, dbs)
case tableKeyColumm:
fullRows = dataForKeyColumnUsage(dbs)
case tableReferConst:
Expand Down
46 changes: 46 additions & 0 deletions infoschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,49 @@ func (s *testTableSuite) TestReloadDropDatabase(c *C) {
_, ok := is.TableByID(t2.Meta().ID)
c.Assert(ok, IsFalse)
}

func (s *testTableSuite) TestPartitionsTable(c *C) {
oldExpiryTime := infoschema.TableStatsCacheExpiry
infoschema.TableStatsCacheExpiry = 0
defer func() { infoschema.TableStatsCacheExpiry = oldExpiryTime }()

do := s.dom
h := do.StatsHandle()
h.Clear()

tk := testkit.NewTestKit(c, s.store)

tk.MustExec("USE test;")
tk.MustExec("DROP TABLE IF EXISTS `test_partitions`;")
tk.MustExec(`CREATE TABLE test_partitions (a int, b int, c varchar(5), primary key(a), index idx(c)) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16));`)
tk.MustExec(`insert into test_partitions(a, b, c) values(1, 2, "c"), (7, 3, "d"), (12, 4, "e");`)

tk.MustQuery("select PARTITION_NAME, PARTITION_DESCRIPTION from information_schema.PARTITIONS where table_name='test_partitions';").Check(
testkit.Rows("" +
"p0 6]\n" +
"[p1 11]\n" +
"[p2 16"))

tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.PARTITIONS where table_name='test_partitions';").Check(
testkit.Rows("" +
"0 0 0 0]\n" +
"[0 0 0 0]\n" +
"[0 0 0 0"))

tk.MustExec("analyze table test_partitions;")
tk.MustQuery("select table_rows, avg_row_length, data_length, index_length from information_schema.PARTITIONS where table_name='test_partitions';").Check(
testkit.Rows("" +
"1 18 18 2]\n" +
"[1 18 18 2]\n" +
"[1 18 18 2"))

// Test for table has no partitions.
tk.MustExec("DROP TABLE IF EXISTS `test_partitions_1`;")
tk.MustExec(`CREATE TABLE test_partitions_1 (a int, b int, c varchar(5), primary key(a), index idx(c));`)
tk.MustExec(`insert into test_partitions_1(a, b, c) values(1, 2, "c"), (7, 3, "d"), (12, 4, "e");`)
tk.MustExec("analyze table test_partitions_1;")
tk.MustQuery("select PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, INDEX_LENGTH from information_schema.PARTITIONS where table_name='test_partitions_1';").Check(
testkit.Rows("<nil> 3 18 54 6"))

tk.MustExec("DROP TABLE `test_partitions`;")
}