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

*: add a new I_S table and support show create for resource groups #40665

Merged
merged 6 commits into from
Jan 17, 2023
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
33 changes: 31 additions & 2 deletions ddl/resource_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package ddl_test

import (
"context"
"strconv"
"testing"

"github.com/pingcap/tidb/ddl"
Expand All @@ -29,7 +30,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestResourceGroupBaisc(t *testing.T) {
func TestResourceGroupBasic(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
Expand Down Expand Up @@ -90,6 +91,8 @@ func TestResourceGroupBaisc(t *testing.T) {
re.Equal(uint64(2000), g.RRURate)
re.Equal(uint64(3000), g.WRURate)

tk.MustQuery("select * from information_schema.resource_groups where group_name = 'x'").Check(testkit.Rows(strconv.FormatInt(g.ID, 10) + " x 2000 3000"))

tk.MustExec("drop resource group x")
g = testResourceGroupNameFromIS(t, tk.Session(), "x")
re.Nil(g)
Expand Down Expand Up @@ -129,7 +132,33 @@ func TestResourceGroupBaisc(t *testing.T) {
groups, err := infosync.GetAllResourceGroups(context.TODO())
require.Equal(t, 0, len(groups))
require.NoError(t, err)
// TODO: privilege check & constraint syntax check.

// Check information schema table information_schema.resource_groups
tk.MustExec("create resource group x " +
"RRU_PER_SEC=1000 " +
"WRU_PER_SEC=2000")
g1 := testResourceGroupNameFromIS(t, tk.Session(), "x")
tk.MustQuery("select * from information_schema.resource_groups where group_name = 'x'").Check(testkit.Rows(strconv.FormatInt(g1.ID, 10) + " x 1000 2000"))
tk.MustQuery("show create resource group x").Check(testkit.Rows("x CREATE RESOURCE GROUP `x` RRU_PER_SEC=1000 WRU_PER_SEC=2000"))

tk.MustExec("create resource group y " +
"RRU_PER_SEC=2000 " +
"WRU_PER_SEC=3000")
g2 := testResourceGroupNameFromIS(t, tk.Session(), "y")
tk.MustQuery("select * from information_schema.resource_groups where group_name = 'y'").Check(testkit.Rows(strconv.FormatInt(g2.ID, 10) + " y 2000 3000"))
tk.MustQuery("show create resource group y").Check(testkit.Rows("y CREATE RESOURCE GROUP `y` RRU_PER_SEC=2000 WRU_PER_SEC=3000"))

tk.MustExec("alter resource group y " +
"RRU_PER_SEC=4000 " +
"WRU_PER_SEC=2000")

g2 = testResourceGroupNameFromIS(t, tk.Session(), "y")
tk.MustQuery("select * from information_schema.resource_groups where group_name = 'y'").Check(testkit.Rows(strconv.FormatInt(g2.ID, 10) + " y 4000 2000"))
tk.MustQuery("show create resource group y").Check(testkit.Rows("y CREATE RESOURCE GROUP `y` RRU_PER_SEC=4000 WRU_PER_SEC=2000"))

tk.MustGetErrCode("create user usr_fail resource group nil_group", mysql.ErrResourceGroupNotExists)
tk.MustExec("create user user2")
tk.MustGetErrCode("alter user user2 resource group nil_group", mysql.ErrResourceGroupNotExists)
}

func testResourceGroupNameFromIS(t *testing.T, ctx sessionctx.Context, name string) *model.ResourceGroupInfo {
Expand Down
4 changes: 3 additions & 1 deletion executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ func (b *executorBuilder) buildShow(v *plannercore.PhysicalShow) Executor {
Partition: v.Partition,
Column: v.Column,
IndexName: v.IndexName,
ResourceGroupName: model.NewCIStr(v.ResourceGroupName),
Flag: v.Flag,
Roles: v.Roles,
User: v.User,
Expand Down Expand Up @@ -1930,7 +1931,8 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo
strings.ToLower(infoschema.TableMemoryUsage),
strings.ToLower(infoschema.TableMemoryUsageOpsHistory),
strings.ToLower(infoschema.ClusterTableMemoryUsage),
strings.ToLower(infoschema.ClusterTableMemoryUsageOpsHistory):
strings.ToLower(infoschema.ClusterTableMemoryUsageOpsHistory),
strings.ToLower(infoschema.TableResourceGroups):
return &MemTableReaderExec{
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ID()),
table: v.Table,
Expand Down
19 changes: 19 additions & 0 deletions executor/infoschema_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex
err = e.setDataForMemoryUsageOpsHistory(sctx)
case infoschema.ClusterTableMemoryUsageOpsHistory:
err = e.setDataForClusterMemoryUsageOpsHistory(sctx)
case infoschema.TableResourceGroups:
err = e.setDataFromResourceGroups(sctx)
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -3386,6 +3388,23 @@ func (e *memtableRetriever) setDataFromPlacementPolicies(sctx sessionctx.Context
return nil
}

func (e *memtableRetriever) setDataFromResourceGroups(sctx sessionctx.Context) error {
is := sessiontxn.GetTxnManager(sctx).GetTxnInfoSchema()
resourceGroups := is.AllResourceGroups()
rows := make([][]types.Datum, 0, len(resourceGroups))
for _, group := range resourceGroups {
row := types.MakeDatums(
group.ID,
group.Name.O,
group.RRURate,
group.WRURate,
)
rows = append(rows, row)
}
e.rows = rows
return nil
}

func checkRule(rule *label.Rule) (dbName, tableName string, partitionName string, err error) {
s := strings.Split(rule.ID, "/")
if len(s) < 3 {
Expand Down
39 changes: 29 additions & 10 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,17 @@ var etcdDialTimeout = 5 * time.Second
type ShowExec struct {
baseExecutor

Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName model.CIStr
Table *ast.TableName // Used for showing columns.
Partition model.CIStr // Used for showing partition
Column *ast.ColumnName // Used for `desc table column`.
IndexName model.CIStr // Used for show table regions.
Flag int // Some flag parsed from sql, such as FULL.
Roles []*auth.RoleIdentity // Used for show grants.
User *auth.UserIdentity // Used by show grants, show create user.
Extractor plannercore.ShowPredicateExtractor
Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName model.CIStr
Table *ast.TableName // Used for showing columns.
Partition model.CIStr // Used for showing partition
Column *ast.ColumnName // Used for `desc table column`.
IndexName model.CIStr // Used for show table regions.
ResourceGroupName model.CIStr // Used for showing resource group
Flag int // Some flag parsed from sql, such as FULL.
Roles []*auth.RoleIdentity // Used for show grants.
User *auth.UserIdentity // Used by show grants, show create user.
Extractor plannercore.ShowPredicateExtractor

is infoschema.InfoSchema

Expand Down Expand Up @@ -182,6 +183,8 @@ func (e *ShowExec) fetchAll(ctx context.Context) error {
return e.fetchShowCreateDatabase()
case ast.ShowCreatePlacementPolicy:
return e.fetchShowCreatePlacementPolicy()
case ast.ShowCreateResourceGroup:
return e.fetchShowCreateResourceGroup()
case ast.ShowDatabases:
return e.fetchShowDatabases()
case ast.ShowDrainerStatus:
Expand Down Expand Up @@ -1452,6 +1455,11 @@ func ConstructResultOfShowCreatePlacementPolicy(policyInfo *model.PolicyInfo) st
return fmt.Sprintf("CREATE PLACEMENT POLICY `%s` %s", policyInfo.Name.O, policyInfo.PlacementSettings.String())
}

// constructResultOfShowCreateResourceGroup constructs the result for show create resource group.
func constructResultOfShowCreateResourceGroup(resourceGroup *model.ResourceGroupInfo) string {
return fmt.Sprintf("CREATE RESOURCE GROUP `%s` %s", resourceGroup.Name.O, resourceGroup.ResourceGroupSettings.String())
}

// fetchShowCreateDatabase composes show create database result.
func (e *ShowExec) fetchShowCreateDatabase() error {
checker := privilege.GetPrivilegeManager(e.ctx)
Expand Down Expand Up @@ -1485,6 +1493,17 @@ func (e *ShowExec) fetchShowCreatePlacementPolicy() error {
return nil
}

// fetchShowCreateResourceGroup composes show create resource group result.
func (e *ShowExec) fetchShowCreateResourceGroup() error {
group, found := e.is.ResourceGroupByName(e.ResourceGroupName)
if !found {
return infoschema.ErrResourceGroupNotExists.GenWithStackByArgs(e.ResourceGroupName.O)
}
showCreate := constructResultOfShowCreateResourceGroup(group)
e.appendRow([]interface{}{e.ResourceGroupName.O, showCreate})
return nil
}

func (e *ShowExec) fetchShowCollation() error {
var (
fieldPatternsLike collate.WildcardPattern
Expand Down
17 changes: 17 additions & 0 deletions executor/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,14 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm
if s.ResourceGroupNameOption.Type == ast.UserResourceGroupName {
resourceGroupName = s.ResourceGroupNameOption.Value
}

// check if specified resource group exists
if resourceGroupName != "default" && resourceGroupName != "" {
_, exists := e.is.ResourceGroupByName(model.NewCIStr(resourceGroupName))
if !exists {
return infoschema.ErrResourceGroupNotExists
}
}
}
userAttributes = append(userAttributes, fmt.Sprintf("\"resource_group\": \"%s\"", resourceGroupName))
// If FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME are both specified to 0, a string of 0 length is generated.
Expand Down Expand Up @@ -1900,6 +1908,15 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt)
if !variable.EnableResourceControl.Load() {
return infoschema.ErrResourceGroupSupportDisabled
}

// check if specified resource group exists
if s.ResourceGroupNameOption.Value != "default" && s.ResourceGroupNameOption.Value != "" {
_, exists := e.is.ResourceGroupByName(model.NewCIStr(s.ResourceGroupNameOption.Value))
if !exists {
return infoschema.ErrResourceGroupNotExists
}
}

newAttributes = append(newAttributes, fmt.Sprintf(`"resource_group": "%s"`, s.ResourceGroupNameOption.Value))
}
if passwordLockingStr != "" {
Expand Down
1 change: 1 addition & 0 deletions executor/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func TestUserAttributes(t *testing.T) {
rootTK.MustExec("alter user usr1 comment 'comment1'")
rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "default"}`))
rootTK.MustExec("set global tidb_enable_resource_control = 'on'")
rootTK.MustExec("CREATE RESOURCE GROUP rg1 rru_per_sec = 100 wru_per_sec = 200")
rootTK.MustExec("alter user usr1 resource group rg1")
rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "rg1"}`))
}
1 change: 1 addition & 0 deletions infoschema/infoschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ func TestInfoTables(t *testing.T) {
"DEADLOCKS",
"PLACEMENT_POLICIES",
"TRX_SUMMARY",
"RESOURCE_GROUPS",
}
for _, tbl := range infoTables {
tb, err1 := is.TableByName(util.InformationSchemaName, model.NewCIStr(tbl))
Expand Down
12 changes: 12 additions & 0 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ const (
TableMemoryUsage = "MEMORY_USAGE"
// TableMemoryUsageOpsHistory is the memory control operators history.
TableMemoryUsageOpsHistory = "MEMORY_USAGE_OPS_HISTORY"
// TableResourceGroups is the metadata of resource groups.
TableResourceGroups = "RESOURCE_GROUPS"
)

const (
Expand Down Expand Up @@ -304,6 +306,7 @@ var tableIDMap = map[string]int64{
TableMemoryUsageOpsHistory: autoid.InformationSchemaDBID + 85,
ClusterTableMemoryUsage: autoid.InformationSchemaDBID + 86,
ClusterTableMemoryUsageOpsHistory: autoid.InformationSchemaDBID + 87,
TableResourceGroups: autoid.InformationSchemaDBID + 88,
}

// columnInfo represents the basic column information of all kinds of INFORMATION_SCHEMA tables
Expand Down Expand Up @@ -1586,6 +1589,14 @@ var tableMemoryUsageOpsHistoryCols = []columnInfo{
{name: "SQL_TEXT", tp: mysql.TypeVarchar, size: 256},
}

var tableResourceGroupsCols = []columnInfo{
{name: "GROUP_ID", tp: mysql.TypeLonglong, size: 64, flag: mysql.NotNullFlag},
BornChanger marked this conversation as resolved.
Show resolved Hide resolved
{name: "GROUP_NAME", tp: mysql.TypeVarchar, size: 512, flag: mysql.NotNullFlag},
{name: "RRU_PER_SECOND", tp: mysql.TypeLonglong, size: 64},
{name: "WRU_PER_SECOND", tp: mysql.TypeLonglong, size: 64},
// {name: "BURSTABLE", tp: mysql.TypeVarchar, size: 10},
}

// GetShardingInfo returns a nil or description string for the sharding information of given TableInfo.
// The returned description string may be:
// - "NOT_SHARDED": for tables that SHARD_ROW_ID_BITS is not specified.
Expand Down Expand Up @@ -2048,6 +2059,7 @@ var tableNameToColumns = map[string][]columnInfo{
TableUserAttributes: tableUserAttributesCols,
TableMemoryUsage: tableMemoryUsageCols,
TableMemoryUsageOpsHistory: tableMemoryUsageOpsHistoryCols,
TableResourceGroups: tableResourceGroupsCols,
}

func createInfoSchemaTable(_ autoid.Allocators, meta *model.TableInfo) (table.Table, error) {
Expand Down
31 changes: 18 additions & 13 deletions parser/ast/dml.go
Original file line number Diff line number Diff line change
Expand Up @@ -2771,6 +2771,7 @@ const (
ShowPlacementForPartition
ShowPlacementLabels
ShowSessionStates
ShowCreateResourceGroup
)

const (
Expand All @@ -2791,19 +2792,20 @@ const (
type ShowStmt struct {
dmlNode

Tp ShowStmtType // Databases/Tables/Columns/....
DBName string
Table *TableName // Used for showing columns.
Partition model.CIStr // Used for showing partition.
Column *ColumnName // Used for `desc table column`.
IndexName model.CIStr
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants/create user.
Roles []*auth.RoleIdentity // Used for show grants .. using
IfNotExists bool // Used for `show create database if not exists`
Extended bool // Used for `show extended columns from ...`
Limit *Limit // Used for partial Show STMTs to limit Result Set row numbers.
Tp ShowStmtType // Databases/Tables/Columns/....
DBName string
Table *TableName // Used for showing columns.
Partition model.CIStr // Used for showing partition.
Column *ColumnName // Used for `desc table column`.
IndexName model.CIStr
ResourceGroupName string // used for showing resource group
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants/create user.
Roles []*auth.RoleIdentity // Used for show grants .. using
IfNotExists bool // Used for `show create database if not exists`
Extended bool // Used for `show extended columns from ...`
Limit *Limit // Used for partial Show STMTs to limit Result Set row numbers.

CountWarningsOrErrors bool // Used for showing count(*) warnings | errors

Expand Down Expand Up @@ -2879,6 +2881,9 @@ func (n *ShowStmt) Restore(ctx *format.RestoreCtx) error {
case ShowCreatePlacementPolicy:
ctx.WriteKeyWord("CREATE PLACEMENT POLICY ")
ctx.WriteName(n.DBName)
case ShowCreateResourceGroup:
ctx.WriteKeyWord("CREATE RESOURCE GROUP ")
ctx.WriteName(n.ResourceGroupName)
case ShowCreateUser:
ctx.WriteKeyWord("CREATE USER ")
if err := n.User.Restore(ctx); err != nil {
Expand Down
Loading