Skip to content

Commit

Permalink
*: upgrade mysql.user table schema (pingcap#2849)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiancaiamao authored and coocood committed Mar 20, 2017
1 parent 52100cb commit d0ddbaa
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 67 deletions.
74 changes: 70 additions & 4 deletions bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,40 @@ const (
Delete_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Create_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Drop_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Reload_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Shutdown_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Process_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
File_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Grant_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
References_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Index_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Alter_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Show_db_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Super_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Create_tmp_table_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Lock_tables_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Execute_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Index_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Repl_slave_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Repl_client_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Create_view_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Show_view_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Create_routine_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Alter_routine_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Create_user_priv ENUM('N','Y') NOT NULL DEFAULT 'N',
Event_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Trigger_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
Create_tablespace_priv enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
ssl_type enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '',
ssl_cipher blob NOT NULL DEFAULT "ssl_cipher",
x509_issuer blob NOT NULL DEFAULT "x509_issuer",
x509_subject blob NOT NULL DEFAULT "x509_subject",
max_questions int(11) unsigned NOT NULL DEFAULT '0',
max_updates int(11) unsigned NOT NULL DEFAULT '0',
max_connections int(11) unsigned NOT NULL DEFAULT '0',
max_user_connections int(11) unsigned NOT NULL DEFAULT '0',
plugin char(64) COLLATE utf8_bin DEFAULT 'mysql_native_password',
authentication_string text COLLATE utf8_bin,
password_expired enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
PRIMARY KEY (Host, User));`
// CreateDBPrivTable is the SQL statement creates DB scope privilege table in system db.
CreateDBPrivTable = `CREATE TABLE if not exists mysql.db (
Expand Down Expand Up @@ -153,6 +181,7 @@ const (
version2 = 2
version3 = 3
version4 = 4
version5 = 5
)

func checkBootstrapped(s Session) (bool, error) {
Expand Down Expand Up @@ -217,14 +246,16 @@ func upgrade(s Session) {
// Do upgrade works then update bootstrap version.
if ver < version2 {
upgradeToVer2(s)
ver = version2
}
if ver < version3 {
upgradeToVer3(s)
}
if ver < version4 {
upgradeToVer4(s)
}
if ver < version5 {
upgradeToVer5(s)
}

updateBootstrapVer(s)
_, err = s.Execute("COMMIT")
Expand Down Expand Up @@ -279,6 +310,42 @@ func upgradeToVer4(s Session) {
mustExecute(s, sql)
}

// Update to version 5.
func upgradeToVer5(s Session) {
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT ''")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `ssl_cipher` blob NOT NULL")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `x509_issuer` blob NOT NULL")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `x509_subject` blob NOT NULL")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `max_questions` int(11) unsigned NOT NULL DEFAULT '0'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `max_updates` int(11) unsigned NOT NULL DEFAULT '0'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `max_connections` int(11) unsigned NOT NULL DEFAULT '0'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `max_user_connections` int(11) unsigned NOT NULL DEFAULT '0'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `plugin` char(64) COLLATE utf8_bin DEFAULT 'mysql_native_password'")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `authentication_string` text COLLATE utf8_bin")
s.Execute("ALTER TABLE mysql.user ADD COLUMN `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N'")

// For reasons of compatibility, set the non-exists privilege column value to 'Y', as TiDB doesn't check them in older versions.
s.Execute("UPDATE mysql.user SET Reload_priv='Y', Shutdown_priv='Y', Process_priv='Y', File_priv='Y', References_priv='Y', Super_priv='Y', Create_tmp_table_priv='Y', Lock_tables_priv='Y', Execute_priv='Y', Repl_slave_priv='Y', Repl_client_priv='Y', Create_view_priv='Y', Show_view_priv='Y', Create_routine_priv='Y', Alter_routine_priv='Y', Event_priv='Y', Trigger_priv='Y', Create_tablespace_priv='Y'")
}

// Update boostrap version variable in mysql.TiDB table.
func updateBootstrapVer(s Session) {
// Update bootstrap version.
Expand Down Expand Up @@ -327,8 +394,7 @@ func doDMLWorks(s Session) {
mustExecute(s, "BEGIN")

// Insert a default user with empty password.
mustExecute(s, `INSERT INTO mysql.user VALUES
("%", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y")`)
mustExecute(s, `INSERT INTO mysql.user VALUES ("%", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "", "", "", "", 0, 0, 0, 0, "mysql_native_password", "", "N")`)

// Init global system variables table.
values := make([]string, 0, len(variable.SysVars))
Expand Down
2 changes: 1 addition & 1 deletion bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *testBootstrapSuite) TestBootstrap(c *C) {
row, err := r.Next()
c.Assert(err, IsNil)
c.Assert(row, NotNil)
match(c, row.Data, []byte("%"), []byte("root"), []byte(""), "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y")
match(c, row.Data, []byte("%"), []byte("root"), []byte(""), "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "", []byte(""), []byte(""), []byte(""), 0, 0, 0, 0, []byte("mysql_native_password"), []byte(""), "N")

c.Assert(se.Auth("root@anyhost", []byte(""), []byte("")), IsTrue)
mustExecSQL(c, se, "USE test;")
Expand Down
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 := "561"
columnCountOfAllInformationSchemaTables := "589"
result.Check(testkit.Rows(columnCountOfAllInformationSchemaTables))

tk.MustExec("drop table if exists t1")
Expand Down
4 changes: 2 additions & 2 deletions executor/grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func (e *GrantExec) Next() (*Row, error) {
}
}

user := fmt.Sprintf(`("%s", "%s", "%s")`, host, userName, pwd)
sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, Password) VALUES %s;`, mysql.SystemDB, mysql.UserTable, user)
item := fmt.Sprintf(`("%s", "%s", "%s", "", "", "")`, host, userName, pwd)
sql := fmt.Sprintf(`INSERT INTO %s.%s (Host, User, Password, ssl_cipher, x509_issuer, x509_subject) VALUES %s;`, mysql.SystemDB, mysql.UserTable, item)
_, err := e.ctx.(sqlexec.SQLExecutor).Execute(sql)
if err != nil {
return nil, errors.Trace(err)
Expand Down
197 changes: 145 additions & 52 deletions mysql/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ const (
)

// PrivilegeType privilege
type PrivilegeType uint32
type PrivilegeType uint64

const (
_ PrivilegeType = 1 << iota
Expand Down Expand Up @@ -178,87 +178,180 @@ const (
ExecutePriv
// IndexPriv is the privilege to create/drop index.
IndexPriv
// ReloadPriv enables use of the FLUSH statement.
ReloadPriv
// ShutdownPriv enables use of the SHUTDOWN statement.
ShutdownPriv
// ProcessPriv can be used to view the plain text of currently executing statements, including statements that set or change passwords.
ProcessPriv
// FilePriv can be abused to read into a database table any files that the MySQL server can read on the server host.
FilePriv
// ReferencesPriv is required for creation of a foreign key constraint.
ReferencesPriv
// SuperPriv enables many operations and server behaviors.
SuperPriv
// CreateTMPTablePriv enables the creation of temporary tables using the CREATE TEMPORARY TABLE statement.
CreateTMPTablePriv
// LockTablesPriv enables the use of explicit LOCK TABLES statements to lock tables.
LockTablesPriv
// ReplSlavePriv should be granted to accounts that are used by slave servers to connect to the current server as their master.
ReplSlavePriv
// ReplClientPriv enables the use of SHOW MASTER STATUS, SHOW SLAVE STATUS, and SHOW BINARY LOGS.
ReplClientPriv
// CreateViewPriv enables use of CREATE VIEW.
CreateViewPriv
// ShowViewPriv enables use of SHOW CREATE VIEW.
ShowViewPriv
// CreateRoutinePriv is needed to create stored routines (procedures and functions).
CreateRoutinePriv
// AlterRoutinePriv is needed to alter or drop stored routines (procedures and functions).
AlterRoutinePriv
// EventPriv is required to create, alter, drop, or see events for the Event Scheduler.
EventPriv
// TriggerPriv enables trigger operations. You must have this privilege for a table to create, drop, execute, or display triggers for that table.
TriggerPriv
// CreateTablespacePriv is needed to create, alter, or drop tablespaces and log file groups.
CreateTablespacePriv
// AllPriv is the privilege for all actions.
AllPriv
)

// Priv2UserCol is the privilege to mysql.user table column name.
var Priv2UserCol = map[PrivilegeType]string{
CreatePriv: "Create_priv",
SelectPriv: "Select_priv",
InsertPriv: "Insert_priv",
UpdatePriv: "Update_priv",
DeletePriv: "Delete_priv",
ShowDBPriv: "Show_db_priv",
CreateUserPriv: "Create_user_priv",
DropPriv: "Drop_priv",
GrantPriv: "Grant_priv",
AlterPriv: "Alter_priv",
ExecutePriv: "Execute_priv",
IndexPriv: "Index_priv",
CreatePriv: "Create_priv",
SelectPriv: "Select_priv",
InsertPriv: "Insert_priv",
UpdatePriv: "Update_priv",
DeletePriv: "Delete_priv",
ShowDBPriv: "Show_db_priv",
CreateUserPriv: "Create_user_priv",
DropPriv: "Drop_priv",
GrantPriv: "Grant_priv",
AlterPriv: "Alter_priv",
ExecutePriv: "Execute_priv",
IndexPriv: "Index_priv",
ReloadPriv: "Reload_priv",
ShutdownPriv: "Shutdown_priv",
ProcessPriv: "Process_priv",
FilePriv: "File_priv",
ReferencesPriv: "References_priv",
SuperPriv: "Super_priv",
CreateTMPTablePriv: "Create_tmp_table_priv",
LockTablesPriv: "Lock_tables_priv",
ReplSlavePriv: "Repl_slave_priv",
ReplClientPriv: "Repl_client_priv",
CreateViewPriv: "Create_view_priv",
ShowViewPriv: "Show_view_priv",
CreateRoutinePriv: "Create_routine_priv",
AlterRoutinePriv: "Alter_routine_priv",
EventPriv: "Event_priv",
TriggerPriv: "Trigger_priv",
CreateTablespacePriv: "Create_tablespace_priv",
}

// Col2PrivType is the privilege tables column name to privilege type.
var Col2PrivType = map[string]PrivilegeType{
"Create_priv": CreatePriv,
"Select_priv": SelectPriv,
"Insert_priv": InsertPriv,
"Update_priv": UpdatePriv,
"Delete_priv": DeletePriv,
"Show_db_priv": ShowDBPriv,
"Create_user_priv": CreateUserPriv,
"Drop_priv": DropPriv,
"Grant_priv": GrantPriv,
"Alter_priv": AlterPriv,
"Execute_priv": ExecutePriv,
"Index_priv": IndexPriv,
"Create_priv": CreatePriv,
"Select_priv": SelectPriv,
"Insert_priv": InsertPriv,
"Update_priv": UpdatePriv,
"Delete_priv": DeletePriv,
"Show_db_priv": ShowDBPriv,
"Create_user_priv": CreateUserPriv,
"Drop_priv": DropPriv,
"Grant_priv": GrantPriv,
"Alter_priv": AlterPriv,
"Execute_priv": ExecutePriv,
"Index_priv": IndexPriv,
"Reload_priv": ReloadPriv,
"Shutdown_priv": ShutdownPriv,
"Process_priv": ProcessPriv,
"File_priv": FilePriv,
"References_priv": ReferencesPriv,
"Super_priv": SuperPriv,
"Create_tmp_table_priv": CreateTMPTablePriv,
"Lock_tables_priv": LockTablesPriv,
"Repl_slave_priv": ReplSlavePriv,
"Repl_client_priv": ReplClientPriv,
"Create_view_priv": CreateViewPriv,
"Show_view_priv": ShowViewPriv,
"Create_routine_priv": CreateRoutinePriv,
"Alter_routine_priv": AlterRoutinePriv,
"Event_priv": EventPriv,
"Trigger_priv": TriggerPriv,
"Create_tablespace_priv": CreateTablespacePriv,
}

// AllGlobalPrivs is all the privileges in global scope.
var AllGlobalPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, ShowDBPriv, ExecutePriv, IndexPriv, CreateUserPriv}

// Priv2Str is the map for privilege to string.
var Priv2Str = map[PrivilegeType]string{
CreatePriv: "Create",
SelectPriv: "Select",
InsertPriv: "Insert",
UpdatePriv: "Update",
DeletePriv: "Delete",
ShowDBPriv: "Show Databases",
CreateUserPriv: "Create User",
DropPriv: "Drop",
GrantPriv: "Grant Option",
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
ReloadPriv: "Reload",
ShutdownPriv: "Shutdown",
ProcessPriv: "Process",
FilePriv: "File",
ReferencesPriv: "References",
SuperPriv: "Super",
CreateTMPTablePriv: "Create Temporary Tables",
LockTablesPriv: "Lock Tables",
ReplSlavePriv: "Replication Slave",
ReplClientPriv: "Replication Client",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
CreateRoutinePriv: "Create Routine",
AlterRoutinePriv: "Alter Routine",
EventPriv: "Event",
TriggerPriv: "Trigger",
CreateTablespacePriv: "Create Tablespace",
}

// Priv2SetStr is the map for privilege type to privilege set string.
var Priv2SetStr = map[PrivilegeType]string{
CreatePriv: "Create",
SelectPriv: "Select",
InsertPriv: "Insert",
UpdatePriv: "Update",
DeletePriv: "Delete",
ShowDBPriv: "Show Databases",
CreateUserPriv: "Create User",
DropPriv: "Drop",
GrantPriv: "Grant Option",
GrantPriv: "Grant",
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
}

// Priv2SetStr is the map for privilege to string.
var Priv2SetStr = map[PrivilegeType]string{
CreatePriv: "Create",
SelectPriv: "Select",
InsertPriv: "Insert",
UpdatePriv: "Update",
DeletePriv: "Delete",
DropPriv: "Drop",
GrantPriv: "Grant",
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
ReferencesPriv: "References",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
TriggerPriv: "Trigger",
}

// SetStr2Priv is the map for privilege set string to privilege type.
var SetStr2Priv = map[string]PrivilegeType{
"Create": CreatePriv,
"Select": SelectPriv,
"Insert": InsertPriv,
"Update": UpdatePriv,
"Delete": DeletePriv,
"Drop": DropPriv,
"Grant": GrantPriv,
"Alter": AlterPriv,
"Execute": ExecutePriv,
"Index": IndexPriv,
"Create": CreatePriv,
"Select": SelectPriv,
"Insert": InsertPriv,
"Update": UpdatePriv,
"Delete": DeletePriv,
"Drop": DropPriv,
"Grant": GrantPriv,
"Alter": AlterPriv,
"Execute": ExecutePriv,
"Index": IndexPriv,
"References": ReferencesPriv,
"Create View": CreateViewPriv,
"Show View": ShowViewPriv,
"Trigger": TriggerPriv,
}

// AllDBPrivs is all the privileges in database scope.
Expand Down
Loading

0 comments on commit d0ddbaa

Please sign in to comment.