From 03c401199829fbfd5d456c5e1e6a96c97b5ac447 Mon Sep 17 00:00:00 2001 From: exialin Date: Tue, 12 Feb 2019 15:36:55 +0800 Subject: [PATCH] parser: implement Restore for PrivElem, GrantStmt and RevokeStmt (#198) --- ast/misc.go | 152 ++++++++++++++++++++++++++++++++++++++++++++++++- parser.y | 2 +- parser_test.go | 44 +++++++------- 3 files changed, 172 insertions(+), 26 deletions(-) diff --git a/ast/misc.go b/ast/misc.go index 7bbc36af0..c068cbbcd 100755 --- a/ast/misc.go +++ b/ast/misc.go @@ -1220,7 +1220,65 @@ type PrivElem struct { // Restore implements Node interface. func (n *PrivElem) Restore(ctx *RestoreCtx) error { - return errors.New("Not implemented") + switch n.Priv { + case 0: + // Do nothing for types that have no effect. + // Actually this should not happen since there is no way to determine its type. + return errors.New("Cannot determine privilege type") + case mysql.AllPriv: + ctx.WriteKeyWord("ALL") + case mysql.AlterPriv: + ctx.WriteKeyWord("ALTER") + case mysql.CreatePriv: + ctx.WriteKeyWord("CREATE") + case mysql.CreateUserPriv: + ctx.WriteKeyWord("CREATE USER") + case mysql.TriggerPriv: + ctx.WriteKeyWord("TRIGGER") + case mysql.DeletePriv: + ctx.WriteKeyWord("DELETE") + case mysql.DropPriv: + ctx.WriteKeyWord("DROP") + case mysql.ProcessPriv: + ctx.WriteKeyWord("PROCESS") + case mysql.ExecutePriv: + ctx.WriteKeyWord("EXECUTE") + case mysql.IndexPriv: + ctx.WriteKeyWord("INDEX") + case mysql.InsertPriv: + ctx.WriteKeyWord("INSERT") + case mysql.SelectPriv: + ctx.WriteKeyWord("SELECT") + case mysql.SuperPriv: + ctx.WriteKeyWord("SUPER") + case mysql.ShowDBPriv: + ctx.WriteKeyWord("SHOW DATABASES") + case mysql.UpdatePriv: + ctx.WriteKeyWord("UPDATE") + case mysql.GrantPriv: + ctx.WriteKeyWord("GRANT OPTION") + case mysql.ReferencesPriv: + ctx.WriteKeyWord("REFERENCES") + case mysql.CreateViewPriv: + ctx.WriteKeyWord("CREATE VIEW") + case mysql.ShowViewPriv: + ctx.WriteKeyWord("SHOW VIEW") + default: + return errors.New("Unsupported privilege type") + } + if n.Cols != nil { + ctx.WritePlain(" (") + for i, v := range n.Cols { + if i != 0 { + ctx.WritePlain(",") + } + if err := v.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore PrivElem.Cols[%d]", i) + } + } + ctx.WritePlain(")") + } + return nil } // Accept implements Node Accept interface. @@ -1250,6 +1308,19 @@ const ( ObjectTypeTable ) +// Restore implements Node interface. +func (n ObjectTypeType) Restore(ctx *RestoreCtx) error { + switch n { + case ObjectTypeNone: + // do nothing + case ObjectTypeTable: + ctx.WriteKeyWord("TABLE ") + default: + return errors.New("Unsupported object type") + } + return nil +} + // GrantLevelType is the type for grant level. type GrantLevelType int @@ -1271,6 +1342,28 @@ type GrantLevel struct { TableName string } +// Restore implements Node interface. +func (n *GrantLevel) Restore(ctx *RestoreCtx) error { + switch n.Level { + case GrantLevelDB: + if n.DBName == "" { + ctx.WritePlain("*") + } else { + ctx.WriteName(n.DBName) + ctx.WritePlain(".*") + } + case GrantLevelGlobal: + ctx.WritePlain("*.*") + case GrantLevelTable: + if n.DBName != "" { + ctx.WriteName(n.DBName) + ctx.WritePlain(".") + } + ctx.WriteName(n.TableName) + } + return nil +} + // RevokeStmt is the struct for REVOKE statement. type RevokeStmt struct { stmtNode @@ -1283,7 +1376,32 @@ type RevokeStmt struct { // Restore implements Node interface. func (n *RevokeStmt) Restore(ctx *RestoreCtx) error { - return errors.New("Not implemented") + ctx.WriteKeyWord("REVOKE ") + for i, v := range n.Privs { + if i != 0 { + ctx.WritePlain(", ") + } + if err := v.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Privs[%d]", i) + } + } + ctx.WriteKeyWord(" ON ") + if err := n.ObjectType.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType") + } + if err := n.Level.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore RevokeStmt.Level") + } + ctx.WriteKeyWord(" FROM ") + for i, v := range n.Users { + if i != 0 { + ctx.WritePlain(", ") + } + if err := v.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Users[%d]", i) + } + } + return nil } // Accept implements Node Accept interface. @@ -1316,7 +1434,35 @@ type GrantStmt struct { // Restore implements Node interface. func (n *GrantStmt) Restore(ctx *RestoreCtx) error { - return errors.New("Not implemented") + ctx.WriteKeyWord("GRANT ") + for i, v := range n.Privs { + if i != 0 { + ctx.WritePlain(", ") + } + if err := v.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore GrantStmt.Privs[%d]", i) + } + } + ctx.WriteKeyWord(" ON ") + if err := n.ObjectType.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType") + } + if err := n.Level.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore GrantStmt.Level") + } + ctx.WriteKeyWord(" TO ") + for i, v := range n.Users { + if i != 0 { + ctx.WritePlain(", ") + } + if err := v.Restore(ctx); err != nil { + return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i) + } + } + if n.WithGrant { + ctx.WriteKeyWord(" WITH GRANT OPTION") + } + return nil } // SecureText implements SensitiveStatement interface. diff --git a/parser.y b/parser.y index f4442efdd..e8e8c1ec7 100644 --- a/parser.y +++ b/parser.y @@ -5804,7 +5804,7 @@ AdminStmt: $$ = &ast.AdminStmt{ Tp: ast.AdminRestoreTable, Tables: []*ast.TableName{$4.(*ast.TableName)}, - JobNumber: $5.(int64), + JobNumber: $5.(int64), } } | "ADMIN" "CLEANUP" "INDEX" TableName Identifier diff --git a/parser_test.go b/parser_test.go index 571beb4a8..1395b9bbe 100755 --- a/parser_test.go +++ b/parser_test.go @@ -2102,32 +2102,32 @@ func (s *testParserSuite) TestPrivilege(c *C) { {`DROP USER IF EXISTS 'root'@'localhost'`, true, "DROP USER IF EXISTS `root`@`localhost`"}, // for grant statement - {"GRANT ALL ON db1.* TO 'jeffrey'@'localhost';", true, ""}, - {"GRANT ALL ON db1.* TO 'jeffrey'@'localhost' WITH GRANT OPTION;", true, ""}, - {"GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost';", true, ""}, - {"GRANT ALL ON *.* TO 'someuser'@'somehost';", true, ""}, - {"GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';", true, ""}, - {"GRANT ALL ON mydb.* TO 'someuser'@'somehost';", true, ""}, - {"GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';", true, ""}, - {"GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost';", true, ""}, - {"GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';", true, ""}, - {"GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';", true, ""}, - {"grant all privileges on zabbix.* to 'zabbix'@'localhost' identified by 'password';", true, ""}, - {"GRANT SELECT ON test.* to 'test'", true, ""}, // For issue 2654. + {"GRANT ALL ON db1.* TO 'jeffrey'@'localhost';", true, "GRANT ALL ON `db1`.* TO `jeffrey`@`localhost`"}, + {"GRANT ALL ON db1.* TO 'jeffrey'@'localhost' WITH GRANT OPTION;", true, "GRANT ALL ON `db1`.* TO `jeffrey`@`localhost` WITH GRANT OPTION"}, + {"GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost';", true, "GRANT SELECT ON `db2`.`invoice` TO `jeffrey`@`localhost`"}, + {"GRANT ALL ON *.* TO 'someuser'@'somehost';", true, "GRANT ALL ON *.* TO `someuser`@`somehost`"}, + {"GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';", true, "GRANT SELECT, INSERT ON *.* TO `someuser`@`somehost`"}, + {"GRANT ALL ON mydb.* TO 'someuser'@'somehost';", true, "GRANT ALL ON `mydb`.* TO `someuser`@`somehost`"}, + {"GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';", true, "GRANT SELECT, INSERT ON `mydb`.* TO `someuser`@`somehost`"}, + {"GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost';", true, "GRANT ALL ON `mydb`.`mytbl` TO `someuser`@`somehost`"}, + {"GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';", true, "GRANT SELECT, INSERT ON `mydb`.`mytbl` TO `someuser`@`somehost`"}, + {"GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';", true, "GRANT SELECT (`col1`), INSERT (`col1`,`col2`) ON `mydb`.`mytbl` TO `someuser`@`somehost`"}, + {"grant all privileges on zabbix.* to 'zabbix'@'localhost' identified by 'password';", true, "GRANT ALL ON `zabbix`.* TO `zabbix`@`localhost` IDENTIFIED BY 'password'"}, + {"GRANT SELECT ON test.* to 'test'", true, "GRANT SELECT ON `test`.* TO `test`@`%`"}, // For issue 2654. {"grant PROCESS,usage, REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'xxxxxxxxxx'@'%' identified by password 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'", true, ""}, // For issue 4865 {"/* rds internal mark */ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, RELOAD, PROCESS, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER on *.* to 'root2'@'%' identified by password '*sdsadsdsadssadsadsadsadsada' with grant option", true, ""}, // for revoke statement - {"REVOKE ALL ON db1.* FROM 'jeffrey'@'localhost';", true, ""}, - {"REVOKE SELECT ON db2.invoice FROM 'jeffrey'@'localhost';", true, ""}, - {"REVOKE ALL ON *.* FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE SELECT, INSERT ON *.* FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE ALL ON mydb.* FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE SELECT, INSERT ON mydb.* FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE ALL ON mydb.mytbl FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE SELECT, INSERT ON mydb.mytbl FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE SELECT (col1), INSERT (col1,col2) ON mydb.mytbl FROM 'someuser'@'somehost';", true, ""}, - {"REVOKE all privileges on zabbix.* FROM 'zabbix'@'localhost' identified by 'password';", true, ""}, + {"REVOKE ALL ON db1.* FROM 'jeffrey'@'localhost';", true, "REVOKE ALL ON `db1`.* FROM `jeffrey`@`localhost`"}, + {"REVOKE SELECT ON db2.invoice FROM 'jeffrey'@'localhost';", true, "REVOKE SELECT ON `db2`.`invoice` FROM `jeffrey`@`localhost`"}, + {"REVOKE ALL ON *.* FROM 'someuser'@'somehost';", true, "REVOKE ALL ON *.* FROM `someuser`@`somehost`"}, + {"REVOKE SELECT, INSERT ON *.* FROM 'someuser'@'somehost';", true, "REVOKE SELECT, INSERT ON *.* FROM `someuser`@`somehost`"}, + {"REVOKE ALL ON mydb.* FROM 'someuser'@'somehost';", true, "REVOKE ALL ON `mydb`.* FROM `someuser`@`somehost`"}, + {"REVOKE SELECT, INSERT ON mydb.* FROM 'someuser'@'somehost';", true, "REVOKE SELECT, INSERT ON `mydb`.* FROM `someuser`@`somehost`"}, + {"REVOKE ALL ON mydb.mytbl FROM 'someuser'@'somehost';", true, "REVOKE ALL ON `mydb`.`mytbl` FROM `someuser`@`somehost`"}, + {"REVOKE SELECT, INSERT ON mydb.mytbl FROM 'someuser'@'somehost';", true, "REVOKE SELECT, INSERT ON `mydb`.`mytbl` FROM `someuser`@`somehost`"}, + {"REVOKE SELECT (col1), INSERT (col1,col2) ON mydb.mytbl FROM 'someuser'@'somehost';", true, "REVOKE SELECT (`col1`), INSERT (`col1`,`col2`) ON `mydb`.`mytbl` FROM `someuser`@`somehost`"}, + {"REVOKE all privileges on zabbix.* FROM 'zabbix'@'localhost' identified by 'password';", true, "REVOKE ALL ON `zabbix`.* FROM `zabbix`@`localhost` IDENTIFIED BY 'password'"}, } s.RunTest(c, table) }