diff --git a/sqle/driver/mysql/audit_offline_test.go b/sqle/driver/mysql/audit_offline_test.go index 71903711c9..76657d59b4 100644 --- a/sqle/driver/mysql/audit_offline_test.go +++ b/sqle/driver/mysql/audit_offline_test.go @@ -3712,3 +3712,78 @@ func TestDMLAvoidWhereEqualNull(t *testing.T) { newTestResult()) }) } + +func TestDDLAvoidEvent(t *testing.T) { + rule := rulepkg.RuleHandlerMap[rulepkg.DDLAvoidEvent].Rule + t.Run(`create event`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + `create event my_event on schedule every 10 second do update schema.table set mycol = mycol + 1;`, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) + t.Run(`create event with DEFINER`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + `create DEFINER=user event my_event on schedule every 10 second do update schema.table set mycol = mycol + 1;`, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) + t.Run(`alter event`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + `ALTER EVENT your_event_name + ON SCHEDULE + EVERY 1 DAY + STARTS '2023-01-01 00:00:00' + DO + -- 修改事件的具体操作 + UPDATE your_table SET your_column = your_value WHERE your_condition; + `, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) + t.Run(`alter event with DEFINER`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + `ALTER DEFINER = user EVENT your_event_name + ON SCHEDULE + EVERY 1 DAY + STARTS '2023-01-01 00:00:00' + DO + -- 修改事件的具体操作 + UPDATE your_table SET your_column = your_value WHERE your_condition; + `, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) + t.Run(`create event with blank line`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + ` + + + create event my_event on schedule every 10 second do update schema.table set mycol = mycol + 1;`, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) + t.Run(`create event with space`, func(t *testing.T) { + runSingleRuleInspectCase( + rule, + t, + ``, + DefaultMysqlInspectOffline(), + ` create event my_event on schedule every 10 second do update schema.table set mycol = mycol + 1;`, + newTestResult().add(driverV2.RuleLevelWarn, "", "语法错误或者解析器不支持,请人工确认SQL正确性").addResult(rulepkg.DDLAvoidEvent)) + }) +} diff --git a/sqle/driver/mysql/rule/rule.go b/sqle/driver/mysql/rule/rule.go index bb68addfcb..db6c435055 100644 --- a/sqle/driver/mysql/rule/rule.go +++ b/sqle/driver/mysql/rule/rule.go @@ -120,6 +120,7 @@ const ( DDLAvoidText = "ddl_avoid_text" DDLAvoidFullText = "ddl_avoid_full_text" DDLAvoidGeometry = "ddl_avoid_geometry" + DDLAvoidEvent = "ddl_avoid_event" ) // inspector DML rules @@ -2389,6 +2390,18 @@ var RuleHandlers = []RuleHandler{ Message: "WHERE子句中禁止将NULL值与其他字段或值进行比较运算", Func: avoidWhereEqualNull, }, + { + Rule: driverV2.Rule{ + Name: DDLAvoidEvent, + Desc: "禁止使用event", + Annotation: "使用event会增加数据库的维护难度和依赖性,并且也会造成安全问题。", + Level: driverV2.RuleLevelError, + Category: RuleTypeUsageSuggestion, + }, + AllowOffline: true, + Message: "禁止使用event", + Func: avoidEvent, + }, } func checkMathComputationOrFuncOnIndex(input *RuleHandlerInput) error { @@ -7759,3 +7772,10 @@ func avoidWhereEqualNull(input *RuleHandlerInput) error { } return nil } + +func avoidEvent(input *RuleHandlerInput) error { + if util.IsEventSQL(input.Node.Text()) { + addResult(input.Res, input.Rule, input.Rule.Name) + } + return nil +} diff --git a/sqle/driver/mysql/util/util.go b/sqle/driver/mysql/util/util.go index 2dce569ec3..b3a687dc0d 100644 --- a/sqle/driver/mysql/util/util.go +++ b/sqle/driver/mysql/util/util.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "regexp" "strconv" "strings" @@ -249,3 +250,18 @@ func IsGeometryColumn(col *ast.ColumnDef) bool { } return false } + +// TODO: 暂时使用正则表达式匹配event,后续会修改语法树进行匹配event +func IsEventSQL(sql string) bool { + createPattern := `^CREATE\s+(DEFINER\s?=.+?)?EVENT` + createRe := regexp.MustCompile(createPattern) + alterPattern := `^ALTER\s+(DEFINER\s?=.+?)?EVENT` + alterRe := regexp.MustCompile(alterPattern) + + sql = strings.ToUpper(strings.TrimSpace(sql)) + if createRe.MatchString(sql) { + return true + } else { + return alterRe.MatchString(sql) + } +}