diff --git a/ast/misc.go b/ast/misc.go index 76f264987..ce08629c3 100755 --- a/ast/misc.go +++ b/ast/misc.go @@ -42,6 +42,7 @@ var ( _ StmtNode = &RollbackStmt{} _ StmtNode = &SetPwdStmt{} _ StmtNode = &SetRoleStmt{} + _ StmtNode = &SetDefaultRoleStmt{} _ StmtNode = &SetStmt{} _ StmtNode = &UseStmt{} _ StmtNode = &FlushStmt{} @@ -847,6 +848,58 @@ func (n *SetRoleStmt) Accept(v Visitor) (Node, bool) { return v.Leave(n) } +type SetDefaultRoleStmt struct { + stmtNode + + SetRoleOpt SetRoleStmtType + RoleList []*auth.RoleIdentity + UserList []*auth.UserIdentity +} + +func (n *SetDefaultRoleStmt) Restore(ctx *RestoreCtx) error { + ctx.WriteKeyWord("SET DEFAULT ROLE") + switch n.SetRoleOpt { + case SetRoleNone: + ctx.WriteKeyWord(" NONE") + case SetRoleAll: + ctx.WriteKeyWord(" ALL") + default: + ctx.WriteKeyWord("") + } + for i, role := range n.RoleList { + ctx.WritePlain(" ") + err := role.Restore(ctx) + if err != nil { + return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.RoleList") + } + if i != len(n.RoleList)-1 { + ctx.WritePlain(",") + } + } + ctx.WritePlain(" TO") + for i, user := range n.UserList { + ctx.WritePlain(" ") + err := user.Restore(ctx) + if err != nil { + return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.UserList") + } + if i != len(n.UserList)-1 { + ctx.WritePlain(",") + } + } + return nil +} + +// Accept implements Node Accept interface. +func (n *SetDefaultRoleStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SetDefaultRoleStmt) + return v.Leave(n) +} + // UserSpec is used for parsing create user statement. type UserSpec struct { User *auth.UserIdentity diff --git a/parser.go b/parser.go index be06a19dc..4c3a6c89f 100644 --- a/parser.go +++ b/parser.go @@ -11357,6 +11357,15 @@ yynewstate: { parser.yyVAL.statement = yyS[yypt-0].item.(*ast.SetRoleStmt) } + case 1058: + { + tmp := yyS[yypt-2].item.(*ast.SetRoleStmt) + parser.yyVAL.statement = &ast.SetDefaultRoleStmt{ + SetRoleOpt: tmp.SetRoleOpt, + RoleList: tmp.RoleList, + UserList: yyS[yypt-0].item.([]*auth.UserIdentity), + } + } case 1059: { parser.yyVAL.item = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleNone, RoleList: nil} diff --git a/parser.y b/parser.y index 2c9ba1d97..793a1ecd8 100644 --- a/parser.y +++ b/parser.y @@ -5680,6 +5680,12 @@ SetRoleStmt: SetDefaultRoleStmt: "SET" "DEFAULT" "ROLE" SetDefaultRoleOpt "TO" UsernameList { + tmp := $4.(*ast.SetRoleStmt) + $$ = &ast.SetDefaultRoleStmt{ + SetRoleOpt: tmp.SetRoleOpt, + RoleList: tmp.RoleList, + UserList: $6.([]*auth.UserIdentity), + } } SetDefaultRoleOpt: diff --git a/parser_test.go b/parser_test.go index 52d6fc086..b41a2f857 100755 --- a/parser_test.go +++ b/parser_test.go @@ -771,7 +771,7 @@ func (s *testParserSuite) TestDBAStmt(c *C) { {"SET ROLE DEFAULT", true, "SET ROLE DEFAULT"}, {"SET ROLE ALL", true, "SET ROLE ALL"}, {"SET ROLE ALL EXCEPT `role1`, `role2`", true, "SET ROLE ALL EXCEPT `role1`@`%`, `role2`@`%`"}, - {"SET DEFAULT ROLE administrator, developer TO 'joe'@'10.0.0.1'", true, ""}, + {"SET DEFAULT ROLE administrator, developer TO `joe`@`10.0.0.1`", true, "SET DEFAULT ROLE `administrator`@`%`, `developer`@`%` TO `joe`@`10.0.0.1`"}, // for set names and set vars {"set names utf8, @@session.sql_mode=1;", true, "SET NAMES 'utf8', @@SESSION.`sql_mode`=1"}, {"set @@session.sql_mode=1, names utf8, charset utf8;", true, "SET @@SESSION.`sql_mode`=1, NAMES 'utf8', NAMES 'utf8'"},