-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
174 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,88 @@ | ||
package ai | ||
|
||
import ( | ||
"fmt" | ||
|
||
rulepkg "github.com/actiontech/sqle/sqle/driver/mysql/rule" | ||
util "github.com/actiontech/sqle/sqle/driver/mysql/rule/ai/util" | ||
driverV2 "github.com/actiontech/sqle/sqle/driver/v2" | ||
"github.com/actiontech/sqle/sqle/pkg/params" | ||
"github.com/pingcap/parser/ast" | ||
|
||
"github.com/actiontech/sqle/sqle/driver/mysql/plocale" | ||
) | ||
|
||
const ( | ||
SQLE00023 = "SQLE00023" | ||
) | ||
|
||
func init() { | ||
rh := rulepkg.SourceHandler{ | ||
Rule: rulepkg.SourceRule{ | ||
Name: SQLE00023, | ||
Desc: plocale.Rule00023Desc, | ||
Annotation: plocale.Rule00023Annotation, | ||
Category: plocale.RuleTypeDDLConvention, | ||
Level: driverV2.RuleLevelWarn, | ||
Params: []*rulepkg.SourceParam{{ | ||
Key: rulepkg.DefaultSingleParamKeyName, | ||
Value: "2", | ||
Desc: plocale.Rule00023Params1, | ||
Type: params.ParamTypeInt, | ||
Enums: nil, | ||
}}, | ||
Knowledge: driverV2.RuleKnowledge{}, | ||
AllowOffline: true, | ||
}, | ||
Message: plocale.Rule00023Message, | ||
Func: RuleSQLE00023, | ||
} | ||
sourceRuleHandlers = append(sourceRuleHandlers, &rh) | ||
} | ||
|
||
/* | ||
==== Prompt start ==== | ||
In MySQL, you should check if the SQL violate the rule(SQLE00023): "In table definition, the number of columns in a primary key should be kept within the threshold", the threshold should be a parameter whose default value is 2. | ||
You should follow the following logic: | ||
1. For "create table ..." statement, if the primary key constraint has columns more than threshold, report a violation | ||
2. For "alter table ... add primary key ..." statement, if the primary key constraint has columns more than threshold, report a violation | ||
==== Prompt end ==== | ||
*/ | ||
|
||
// ==== Rule code start ==== | ||
func RuleSQLE00023(input *rulepkg.RuleHandlerInput) error { | ||
// get expected param value | ||
param := input.Rule.Params.GetParam(rulepkg.DefaultSingleParamKeyName) | ||
if param == nil { | ||
return fmt.Errorf("param %s not found", rulepkg.DefaultSingleParamKeyName) | ||
} | ||
maxColumnCount := param.Int() | ||
|
||
switch stmt := input.Node.(type) { | ||
case *ast.CreateTableStmt: | ||
// "create table ..." | ||
constraint := util.GetTableConstraint(stmt.Constraints, ast.ConstraintPrimaryKey) | ||
if nil != constraint { | ||
//this is a table primary key definition | ||
if len(constraint.Keys) > maxColumnCount { | ||
rulepkg.AddResult(input.Res, input.Rule, SQLE00023, maxColumnCount) | ||
} | ||
} | ||
case *ast.AlterTableStmt: | ||
// "alter table" | ||
for _, spec := range util.GetAlterTableCommandsByTypes(stmt, ast.AlterTableAddConstraint) { | ||
// "alter table ... add constraint..." | ||
constraint := spec.Constraint | ||
if nil != spec.Constraint && spec.Constraint.Tp == ast.ConstraintPrimaryKey { | ||
//"alter table ... add primary key ..." | ||
if len(constraint.Keys) > maxColumnCount { | ||
rulepkg.AddResult(input.Res, input.Rule, SQLE00023, maxColumnCount) | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ==== Rule code end ==== | ||
// | ||
//import ( | ||
// "fmt" | ||
// | ||
// rulepkg "github.com/actiontech/sqle/sqle/driver/mysql/rule" | ||
// util "github.com/actiontech/sqle/sqle/driver/mysql/rule/ai/util" | ||
// driverV2 "github.com/actiontech/sqle/sqle/driver/v2" | ||
// "github.com/actiontech/sqle/sqle/pkg/params" | ||
// "github.com/pingcap/parser/ast" | ||
// | ||
// "github.com/actiontech/sqle/sqle/driver/mysql/plocale" | ||
//) | ||
// | ||
//const ( | ||
// SQLE00023 = "SQLE00023" | ||
//) | ||
// | ||
//func init() { | ||
// rh := rulepkg.SourceHandler{ | ||
// Rule: rulepkg.SourceRule{ | ||
// Name: SQLE00023, | ||
// Desc: plocale.Rule00023Desc, | ||
// Annotation: plocale.Rule00023Annotation, | ||
// Category: plocale.RuleTypeDDLConvention, | ||
// Level: driverV2.RuleLevelWarn, | ||
// Params: []*rulepkg.SourceParam{{ | ||
// Key: rulepkg.DefaultSingleParamKeyName, | ||
// Value: "2", | ||
// Desc: plocale.Rule00023Params1, | ||
// Type: params.ParamTypeInt, | ||
// Enums: nil, | ||
// }}, | ||
// Knowledge: driverV2.RuleKnowledge{}, | ||
// AllowOffline: true, | ||
// }, | ||
// Message: plocale.Rule00023Message, | ||
// Func: RuleSQLE00023, | ||
// } | ||
// sourceRuleHandlers = append(sourceRuleHandlers, &rh) | ||
//} | ||
// | ||
///* | ||
//==== Prompt start ==== | ||
//In MySQL, you should check if the SQL violate the rule(SQLE00023): "In table definition, the number of columns in a primary key should be kept within the threshold", the threshold should be a parameter whose default value is 2. | ||
//You should follow the following logic: | ||
//1. For "create table ..." statement, if the primary key constraint has columns more than threshold, report a violation | ||
//2. For "alter table ... add primary key ..." statement, if the primary key constraint has columns more than threshold, report a violation | ||
//==== Prompt end ==== | ||
//*/ | ||
// | ||
//// ==== Rule code start ==== | ||
//func RuleSQLE00023(input *rulepkg.RuleHandlerInput) error { | ||
// // get expected param value | ||
// param := input.Rule.Params.GetParam(rulepkg.DefaultSingleParamKeyName) | ||
// if param == nil { | ||
// return fmt.Errorf("param %s not found", rulepkg.DefaultSingleParamKeyName) | ||
// } | ||
// maxColumnCount := param.Int() | ||
// | ||
// switch stmt := input.Node.(type) { | ||
// case *ast.CreateTableStmt: | ||
// // "create table ..." | ||
// constraint := util.GetTableConstraint(stmt.Constraints, ast.ConstraintPrimaryKey) | ||
// if nil != constraint { | ||
// //this is a table primary key definition | ||
// if len(constraint.Keys) > maxColumnCount { | ||
// rulepkg.AddResult(input.Res, input.Rule, SQLE00023, maxColumnCount) | ||
// } | ||
// } | ||
// case *ast.AlterTableStmt: | ||
// // "alter table" | ||
// for _, spec := range util.GetAlterTableCommandsByTypes(stmt, ast.AlterTableAddConstraint) { | ||
// // "alter table ... add constraint..." | ||
// constraint := spec.Constraint | ||
// if nil != spec.Constraint && spec.Constraint.Tp == ast.ConstraintPrimaryKey { | ||
// //"alter table ... add primary key ..." | ||
// if len(constraint.Keys) > maxColumnCount { | ||
// rulepkg.AddResult(input.Res, input.Rule, SQLE00023, maxColumnCount) | ||
// } | ||
// } | ||
// } | ||
// } | ||
// return nil | ||
//} | ||
// | ||
//// ==== Rule code end ==== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,90 @@ | ||
package ai | ||
|
||
import ( | ||
"strings" | ||
|
||
rulepkg "github.com/actiontech/sqle/sqle/driver/mysql/rule" | ||
util "github.com/actiontech/sqle/sqle/driver/mysql/rule/ai/util" | ||
driverV2 "github.com/actiontech/sqle/sqle/driver/v2" | ||
"github.com/actiontech/sqle/sqle/pkg/params" | ||
"github.com/pingcap/parser/ast" | ||
"github.com/pingcap/parser/mysql" | ||
|
||
"github.com/actiontech/sqle/sqle/driver/mysql/plocale" | ||
) | ||
|
||
const ( | ||
SQLE00171 = "SQLE00171" | ||
) | ||
|
||
func init() { | ||
rh := rulepkg.SourceHandler{ | ||
Rule: rulepkg.SourceRule{ | ||
Name: SQLE00171, | ||
Desc: plocale.Rule00171Desc, | ||
Annotation: plocale.Rule00171Annotation, | ||
Category: plocale.RuleTypeDDLConvention, | ||
Level: driverV2.RuleLevelWarn, | ||
Params: []*rulepkg.SourceParam{{ | ||
Key: rulepkg.DefaultSingleParamKeyName, | ||
Value: "CREATE_TIME", | ||
Desc: plocale.Rule00171Params1, | ||
Type: params.ParamTypeString, | ||
Enums: nil, | ||
}}, | ||
Knowledge: driverV2.RuleKnowledge{}, | ||
AllowOffline: false, | ||
}, | ||
Message: plocale.Rule00171Message, | ||
Func: RuleSQLE00171, | ||
} | ||
sourceRuleHandlers = append(sourceRuleHandlers, &rh) | ||
} | ||
|
||
/* | ||
==== Prompt start ==== | ||
In MySQL, you should check if the SQL violate the rule(SQLE00171): "In DDL, when creating table, table should have a field about create-timestamp, whose DEFAULT value should be 'CURRENT_TIMESTAMP'", the create-timestamp column name is a parameter whose default value is 'CREATE_TIME'. | ||
You should follow the following logic: | ||
For "create table ..." statement, check the following conditions, report violation if any condition is violated: | ||
1. The table should have a create-timestamp column whose type is datetime or timestamp, and column name is same as the parameter | ||
2. The create-timestamp column's DEFAULT value should be configured as 'CURRENT_TIMESTAMP' | ||
==== Prompt end ==== | ||
*/ | ||
|
||
// ==== Rule code start ==== | ||
func RuleSQLE00171(input *rulepkg.RuleHandlerInput) error { | ||
// get expected create_time field name in config | ||
createTimeFieldName := input.Rule.Params.GetParam(rulepkg.DefaultSingleParamKeyName).String() | ||
found := false | ||
|
||
switch stmt := input.Node.(type) { | ||
case *ast.CreateTableStmt: | ||
// "create table" | ||
for _, col := range stmt.Cols { | ||
if strings.EqualFold(util.GetColumnName(col), createTimeFieldName) { | ||
// the column is create_time column | ||
if util.IsColumnTypeEqual(col, mysql.TypeTimestamp) || util.IsColumnTypeEqual(col, mysql.TypeDatetime) { | ||
// the column is Timestamp-type or Datetime-type | ||
if c := util.GetColumnOption(col, ast.ColumnOptionDefaultValue); nil != c { | ||
// the column has "DEFAULT" option | ||
if util.IsOptionFuncCall(c, "current_timestamp") { | ||
// the "DEFAULT" value is current_timestamp | ||
found = true | ||
} | ||
} | ||
} | ||
} | ||
} | ||
default: | ||
return nil | ||
} | ||
|
||
if !found { | ||
rulepkg.AddResult(input.Res, input.Rule, SQLE00024, createTimeFieldName) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ==== Rule code end ==== | ||
// | ||
//import ( | ||
// "strings" | ||
// | ||
// rulepkg "github.com/actiontech/sqle/sqle/driver/mysql/rule" | ||
// util "github.com/actiontech/sqle/sqle/driver/mysql/rule/ai/util" | ||
// driverV2 "github.com/actiontech/sqle/sqle/driver/v2" | ||
// "github.com/actiontech/sqle/sqle/pkg/params" | ||
// "github.com/pingcap/parser/ast" | ||
// "github.com/pingcap/parser/mysql" | ||
// | ||
// "github.com/actiontech/sqle/sqle/driver/mysql/plocale" | ||
//) | ||
// | ||
//const ( | ||
// SQLE00171 = "SQLE00171" | ||
//) | ||
// | ||
//func init() { | ||
// rh := rulepkg.SourceHandler{ | ||
// Rule: rulepkg.SourceRule{ | ||
// Name: SQLE00171, | ||
// Desc: plocale.Rule00171Desc, | ||
// Annotation: plocale.Rule00171Annotation, | ||
// Category: plocale.RuleTypeDDLConvention, | ||
// Level: driverV2.RuleLevelWarn, | ||
// Params: []*rulepkg.SourceParam{{ | ||
// Key: rulepkg.DefaultSingleParamKeyName, | ||
// Value: "CREATE_TIME", | ||
// Desc: plocale.Rule00171Params1, | ||
// Type: params.ParamTypeString, | ||
// Enums: nil, | ||
// }}, | ||
// Knowledge: driverV2.RuleKnowledge{}, | ||
// AllowOffline: false, | ||
// }, | ||
// Message: plocale.Rule00171Message, | ||
// Func: RuleSQLE00171, | ||
// } | ||
// sourceRuleHandlers = append(sourceRuleHandlers, &rh) | ||
//} | ||
// | ||
///* | ||
//==== Prompt start ==== | ||
//In MySQL, you should check if the SQL violate the rule(SQLE00171): "In DDL, when creating table, table should have a field about create-timestamp, whose DEFAULT value should be 'CURRENT_TIMESTAMP'", the create-timestamp column name is a parameter whose default value is 'CREATE_TIME'. | ||
//You should follow the following logic: | ||
//For "create table ..." statement, check the following conditions, report violation if any condition is violated: | ||
//1. The table should have a create-timestamp column whose type is datetime or timestamp, and column name is same as the parameter | ||
//2. The create-timestamp column's DEFAULT value should be configured as 'CURRENT_TIMESTAMP' | ||
//==== Prompt end ==== | ||
//*/ | ||
// | ||
//// ==== Rule code start ==== | ||
//func RuleSQLE00171(input *rulepkg.RuleHandlerInput) error { | ||
// // get expected create_time field name in config | ||
// createTimeFieldName := input.Rule.Params.GetParam(rulepkg.DefaultSingleParamKeyName).String() | ||
// found := false | ||
// | ||
// switch stmt := input.Node.(type) { | ||
// case *ast.CreateTableStmt: | ||
// // "create table" | ||
// for _, col := range stmt.Cols { | ||
// if strings.EqualFold(util.GetColumnName(col), createTimeFieldName) { | ||
// // the column is create_time column | ||
// if util.IsColumnTypeEqual(col, mysql.TypeTimestamp) || util.IsColumnTypeEqual(col, mysql.TypeDatetime) { | ||
// // the column is Timestamp-type or Datetime-type | ||
// if c := util.GetColumnOption(col, ast.ColumnOptionDefaultValue); nil != c { | ||
// // the column has "DEFAULT" option | ||
// if util.IsOptionFuncCall(c, "current_timestamp") { | ||
// // the "DEFAULT" value is current_timestamp | ||
// found = true | ||
// } | ||
// } | ||
// } | ||
// } | ||
// } | ||
// default: | ||
// return nil | ||
// } | ||
// | ||
// if !found { | ||
// rulepkg.AddResult(input.Res, input.Rule, SQLE00024, createTimeFieldName) | ||
// } | ||
// | ||
// return nil | ||
//} | ||
// | ||
//// ==== Rule code end ==== |