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 INFORMATION_SCHEMA.USER_PRIVILEGES table #2963

Merged
merged 4 commits into from
Mar 30, 2017
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
2 changes: 1 addition & 1 deletion executor/aggregate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func (s *testSuite) TestAggregation(c *C) {

result = tk.MustQuery("select count(*) from information_schema.columns")
// When adding new memory table in information_schema, please update this variable.
columnCountOfAllInformationSchemaTables := "576"
columnCountOfAllInformationSchemaTables := "580"
result.Check(testkit.Rows(columnCountOfAllInformationSchemaTables))

tk.MustExec("drop table if exists t1")
Expand Down
1 change: 1 addition & 0 deletions infoschema/infoschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ func (*testSuite) TestInfoTables(c *C) {
"PLUGINS",
"TABLE_CONSTRAINTS",
"TRIGGERS",
"USER_PRIVILEGES",
}
for _, t := range info_tables {
tb, err1 := is.TableByName(model.NewCIStr(infoschema.Name), model.NewCIStr(t))
Expand Down
79 changes: 48 additions & 31 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/pingcap/tidb/meta/autoid"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/privilege"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/sessionctx/varsutil"
"github.com/pingcap/tidb/table"
Expand All @@ -31,22 +32,23 @@ import (
)

const (
tableSchemata = "SCHEMATA"
tableTables = "TABLES"
tableColumns = "COLUMNS"
tableStatistics = "STATISTICS"
tableCharacterSets = "CHARACTER_SETS"
tableCollations = "COLLATIONS"
tableFiles = "FILES"
catalogVal = "def"
tableProfiling = "PROFILING"
tablePartitions = "PARTITIONS"
tableKeyColumm = "KEY_COLUMN_USAGE"
tableReferConst = "REFERENTIAL_CONSTRAINTS"
tableSessionVar = "SESSION_VARIABLES"
tablePlugins = "PLUGINS"
tableConstraints = "TABLE_CONSTRAINTS"
tableTriggers = "TRIGGERS"
tableSchemata = "SCHEMATA"
tableTables = "TABLES"
tableColumns = "COLUMNS"
tableStatistics = "STATISTICS"
tableCharacterSets = "CHARACTER_SETS"
tableCollations = "COLLATIONS"
tableFiles = "FILES"
catalogVal = "def"
tableProfiling = "PROFILING"
tablePartitions = "PARTITIONS"
tableKeyColumm = "KEY_COLUMN_USAGE"
tableReferConst = "REFERENTIAL_CONSTRAINTS"
tableSessionVar = "SESSION_VARIABLES"
tablePlugins = "PLUGINS"
tableConstraints = "TABLE_CONSTRAINTS"
tableTriggers = "TRIGGERS"
tableUserPrivileges = "USER_PRIVILEGES"
)

type columnInfo struct {
Expand Down Expand Up @@ -322,6 +324,13 @@ var tableTriggersCols = []columnInfo{
{"DATABASE_COLLATION", mysql.TypeVarchar, 32, 0, nil, nil},
}

var tableUserPrivilegesCols = []columnInfo{
{"GRANTEE", mysql.TypeVarchar, 81, 0, nil, nil},
{"TABLE_CATALOG", mysql.TypeVarchar, 512, 0, nil, nil},
{"PRIVILEGE_TYPE", mysql.TypeVarchar, 64, 0, nil, nil},
{"IS_GRANTABLE", mysql.TypeVarchar, 3, 0, nil, nil},
}

func dataForCharacterSets() (records [][]types.Datum) {
records = append(records,
types.MakeDatums("ascii", "ascii_general_ci", "US ASCII", 1),
Expand Down Expand Up @@ -358,6 +367,11 @@ func dataForSessionVar(ctx context.Context) (records [][]types.Datum, err error)
return
}

func dataForUserPrivileges(ctx context.Context) [][]types.Datum {
checker := privilege.GetPrivilegeChecker(ctx)
return checker.UserPrivilegesTable()
}

var filesCols = []columnInfo{
{"FILE_ID", mysql.TypeLonglong, 4, 0, nil, nil},
{"FILE_NAME", mysql.TypeVarchar, 64, 0, nil, nil},
Expand Down Expand Up @@ -630,21 +644,22 @@ func dataForTableConstraints(schemas []*model.DBInfo) [][]types.Datum {
}

var tableNameToColumns = map[string]([]columnInfo){
tableSchemata: schemataCols,
tableTables: tablesCols,
tableColumns: columnsCols,
tableStatistics: statisticsCols,
tableCharacterSets: charsetCols,
tableCollations: collationsCols,
tableFiles: filesCols,
tableProfiling: profilingCols,
tablePartitions: partitionsCols,
tableKeyColumm: keyColumnUsageCols,
tableReferConst: referConstCols,
tableSessionVar: sessionVarCols,
tablePlugins: pluginsCols,
tableConstraints: tableConstraintsCols,
tableTriggers: tableTriggersCols,
tableSchemata: schemataCols,
tableTables: tablesCols,
tableColumns: columnsCols,
tableStatistics: statisticsCols,
tableCharacterSets: charsetCols,
tableCollations: collationsCols,
tableFiles: filesCols,
tableProfiling: profilingCols,
tablePartitions: partitionsCols,
tableKeyColumm: keyColumnUsageCols,
tableReferConst: referConstCols,
tableSessionVar: sessionVarCols,
tablePlugins: pluginsCols,
tableConstraints: tableConstraintsCols,
tableTriggers: tableTriggersCols,
tableUserPrivileges: tableUserPrivilegesCols,
}

func createInfoSchemaTable(handle *Handle, meta *model.TableInfo) *infoschemaTable {
Expand Down Expand Up @@ -708,6 +723,8 @@ func (it *infoschemaTable) getRows(ctx context.Context, cols []*table.Column) (f
case tableKeyColumm:
case tableReferConst:
case tablePlugins, tableTriggers:
case tableUserPrivileges:
fullRows = dataForUserPrivileges(ctx)
}
if err != nil {
return nil, errors.Trace(err)
Expand Down
4 changes: 4 additions & 0 deletions privilege/privilege.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/util/types"
)

type keyType int
Expand All @@ -41,6 +42,9 @@ type Checker interface {

// DBIsVisible returns true is the database is visible to current user.
DBIsVisible(db string) bool

// UserPrivilegesTable provide data for INFORMATION_SCHEMA.USERS_PRIVILEGE table.
UserPrivilegesTable() [][]types.Datum
}

const key keyType = 0
Expand Down
36 changes: 36 additions & 0 deletions privilege/privileges/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package privileges

import (
"fmt"
"strings"
"sync/atomic"
"time"
Expand Down Expand Up @@ -455,6 +456,41 @@ func (p *MySQLPrivilege) DBIsVisible(user, host, db string) bool {
return false
}

// UserPrivilegesTable provide data for INFORMATION_SCHEMA.USERS_PRIVILEGE table.
func (p *MySQLPrivilege) UserPrivilegesTable() [][]types.Datum {
var rows [][]types.Datum
for _, user := range p.User {
rows = appendUserPrivilegesTableRow(rows, user)
}
return rows
}

func appendUserPrivilegesTableRow(rows [][]types.Datum, user userRecord) [][]types.Datum {
var isGrantable string
if user.Privileges&mysql.GrantPriv > 0 {
isGrantable = "YES"
} else {
isGrantable = "NO"
}
gurantee := fmt.Sprintf("'%s'@'%s'", user.User, user.Host)

for _, priv := range mysql.AllGlobalPrivs {
if priv == mysql.GrantPriv {
continue
}
if user.Privileges&priv > 0 {
privilegeType := mysql.Priv2Str[priv]
// +---------------------------+---------------+-------------------------+--------------+
// | GRANTEE | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE |
// +---------------------------+---------------+-------------------------+--------------+
// | 'root'@'localhost' | def | SELECT | YES |
record := types.MakeDatums(gurantee, "def", privilegeType, isGrantable)
rows = append(rows, record)
}
}
return rows
}

// Handle wraps MySQLPrivilege providing thread safe access.
type Handle struct {
ctx context.Context
Expand Down
6 changes: 6 additions & 0 deletions privilege/privileges/privileges.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ func (p *UserPrivileges) DBIsVisible(db string) bool {
return mysqlPriv.DBIsVisible(user, host, db)
}

// UserPrivilegesTable implements the Checker interface.
func (p *UserPrivileges) UserPrivilegesTable() [][]types.Datum {
mysqlPriv := p.Handle.Get()
return mysqlPriv.UserPrivilegesTable()
}

// Check implements Checker.Check interface.
func (p *UserPrivileges) Check(ctx context.Context, db *model.DBInfo, tbl *model.TableInfo, privilege mysql.PrivilegeType) (bool, error) {
if p.privs == nil {
Expand Down