Documentation ¶
Index ¶
- Constants
- Variables
- func Fingerprint(oneSql string, isCaseSensitive bool) (fingerprint string, err error)
- func HasOneInOptions(Options []*ast.ColumnOption, opTp ...ast.ColumnOptionType) bool
- func IsAllInOptions(Options []*ast.ColumnOption, opTp ...ast.ColumnOptionType) bool
- func IsMysqlReservedKeyword(name string) bool
- func LoadPtTemplateFromFile(fileName string) error
- func MysqlDataTypeIsBlob(tp byte) bool
- func Ping(entry *logrus.Entry, instance *model.Instance) error
- func RemoveArrayRepeat(input []string) (output []string)
- func ShowDatabases(entry *logrus.Entry, instance *model.Instance) ([]string, error)
- type BaseConn
- func (c *BaseConn) Close()
- func (c *BaseConn) Exec(query string) (driver.Result, error)
- func (c *BaseConn) Logger() *logrus.Entry
- func (c *BaseConn) Ping() error
- func (c *BaseConn) Query(query string, args ...interface{}) ([]map[string]sql.NullString, error)
- func (c *BaseConn) Transact(qs ...string) ([]driver.Result, error)
- type CapitalizeProcessor
- type Config
- type Context
- func (c *Context) AddExecutionPlan(sql string, records []*ExplainRecord)
- func (c *Context) AddSchema(name string)
- func (c *Context) AddSysVar(name, value string)
- func (c *Context) AddTable(schemaName, tableName string, table *TableInfo)
- func (c *Context) DelSchema(name string)
- func (c *Context) DelTable(schemaName, tableName string)
- func (c *Context) GetExecutionPlan(sql string) ([]*ExplainRecord, bool)
- func (c *Context) GetSchema(schemaName string) (*SchemaInfo, bool)
- func (c *Context) GetSysVar(name string) (string, bool)
- func (c *Context) GetTable(schemaName, tableName string) (*TableInfo, bool)
- func (c *Context) HasLoadSchemas() bool
- func (c *Context) HasLoadTables(schemaName string) (hasLoad bool)
- func (c *Context) HasSchema(schemaName string) (has bool)
- func (c *Context) HasTable(schemaName, tableName string) (has bool)
- func (c *Context) LoadSchemas(schemas []string)
- func (c *Context) LoadTables(schemaName string, tablesName []string)
- func (c *Context) SetSchemasLoad()
- func (c *Context) UseSchema(schema string)
- type Db
- type Executor
- func (c *Executor) Explain(query string) ([]*ExplainRecord, error)
- func (c *Executor) FetchMasterBinlogPos() (string, int64, error)
- func (c *Executor) ShowCreateTable(tableName string) (string, error)
- func (c *Executor) ShowDatabases(ignoreSysDatabase bool) ([]string, error)
- func (c *Executor) ShowDefaultConfiguration(sql, column string) (string, error)
- func (c *Executor) ShowMasterStatus() ([]map[string]sql.NullString, error)
- func (c *Executor) ShowSchemaTables(schema string) ([]string, error)
- func (c *Executor) ShowTableSizeMB(schema, table string) (float64, error)
- type ExplainRecord
- type FingerprintVisitor
- type Inspect
- func (i *Inspect) Audit(ctx context.Context, sql string) (*driver.AuditResult, error)
- func (i *Inspect) CheckInvalid(node ast.Node) error
- func (i *Inspect) CheckInvalidOffline(node ast.Node) error
- func (i *Inspect) Close(ctx context.Context)
- func (i *Inspect) CommitDDL(sql *model.BaseSQL) error
- func (i *Inspect) CommitDMLs(sqls []*model.BaseSQL) error
- func (i *Inspect) Context() *Context
- func (i *Inspect) Exec(ctx context.Context, query string) (_driver.Result, error)
- func (i *Inspect) GenRollbackSQL(ctx context.Context, sql string) (string, string, error)
- func (i *Inspect) GenerateDDLStmtRollbackSql(node ast.Node) (rollbackSql, unableRollbackReason string, err error)
- func (i *Inspect) GenerateDMLStmtRollbackSql(node ast.Node) (rollbackSql, unableRollbackReason string, err error)
- func (i *Inspect) GenerateRollbackSql(node ast.Node) (string, string, error)
- func (i *Inspect) GetAllRollbackSqlReversed(sqls []*model.RollbackSQL) []*model.RollbackSQL
- func (i *Inspect) IsOfflineAudit() bool
- func (i *Inspect) Logger() *logrus.Entry
- func (i *Inspect) Parse(ctx context.Context, sqlText string) ([]driver.Node, error)
- func (i *Inspect) ParseSql(sql string) ([]ast.Node, error)
- func (i *Inspect) Ping(ctx context.Context) error
- func (i *Inspect) Query(ctx context.Context, query string, args ...interface{}) ([]map[string]sql.NullString, error)
- func (i *Inspect) Schemas(ctx context.Context) ([]string, error)
- func (i *Inspect) Tx(ctx context.Context, queries ...string) ([]_driver.Result, error)
- type RuleHandler
- type SchemaInfo
- type TableChecker
- type TableInfo
Constants ¶
View Source
const ( SchemaNotExistMessage = "schema %s 不存在" SchemaExistMessage = "schema %s 已存在" TableNotExistMessage = "表 %s 不存在" TableExistMessage = "表 %s 已存在" ColumnNotExistMessage = "字段 %s 不存在" ColumnExistMessage = "字段 %s 已存在" ColumnIsAmbiguousMessage = "字段 %s 指代不明" IndexNotExistMessage = "索引 %s 不存在" IndexExistMessage = "索引 %s 已存在" DuplicateColumnsMessage = "字段名 %s 重复" DuplicateIndexesMessage = "索引名 %s 重复" MultiPrimaryKeyMessage = "主键只能设置一个" KeyedColumnNotExistMessage = "索引字段 %s 不存在" PrimaryKeyExistMessage = "已经存在主键,不能再添加" PrimaryKeyNotExistMessage = "当前没有主键,不能执行删除" ColumnsValuesNotMatchMessage = "指定的值列数与字段列数不匹配" DuplicatePrimaryKeyedColumnMessage = "主键字段 %s 重复" DuplicateIndexedColumnMessage = "索引 %s 字段 %s重复" )
View Source
const ( ExplainRecordExtraUsingFilesort = "Using filesort" ExplainRecordExtraUsingTemporary = "Using temporary" ExplainRecordAccessTypeAll = "ALL" )
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain_rows
View Source
const ( PTOSCNoUniqueIndexOrPrimaryKey = "至少要包含主键或者唯一键索引才能使用 pt-online-schema-change" PTOSCAvoidUniqueIndex = "" /* 127-byte string literal not displayed */ PTOSCAvoidRenameTable = "pt-online-schema-change 不支持使用rename table 来重命名表" PTOSCAvoidNoDefaultValueOnNotNullColumn = "非空字段必须设置默认值,不然 pt-online-schema-change 会执行失败" )
View Source
const ( NotSupportStatementRollback = "暂不支持回滚该类型的语句" NotSupportMultiTableStatementRollback = "暂不支持回滚多表的 DML 语句" NotSupportOnDuplicatStatementRollback = "暂不支持回滚 ON DUPLICATE 语句" NotSupportSubQueryStatementRollback = "暂不支持回滚带子查询的语句" NotSupportNoPrimaryKeyTableRollback = "不支持回滚没有主键的表的DML语句" NotSupportInsertWithoutPrimaryKeyRollback = "不支持回滚 INSERT 没有指定主键的语句" NotSupportExceedMaxRowsRollback = "预计影响行数超过配置的最大值,不生成回滚语句" )
View Source
const ( RuleTypeGlobalConfig = "全局配置" RuleTypeNamingConvention = "命名规范" RuleTypeIndexingConvention = "索引规范" RuleTypeDDLConvention = "DDL规范" RuleTypeDMLConvention = "DML规范" RuleTypeUsageSuggestion = "使用建议" )
rule type
View Source
const ( DDLCheckPKWithoutIfNotExists = "ddl_check_table_without_if_not_exists" DDLCheckObjectNameLength = "ddl_check_object_name_length" DDLCheckObjectNameUsingKeyword = "ddl_check_object_name_using_keyword" DDLCheckPKNotExist = "ddl_check_pk_not_exist" DDLCheckPKWithoutBigintUnsigned = "ddl_check_pk_without_bigint_unsigned" DDLCheckPKWithoutAutoIncrement = "ddl_check_pk_without_auto_increment" DDLCheckPKProhibitAutoIncrement = "ddl_check_pk_prohibit_auto_increment" DDLCheckColumnCharLength = "ddl_check_column_char_length" DDLDisableFK = "ddl_disable_fk" DDLCheckIndexCount = "ddl_check_index_count" DDLCheckCompositeIndexMax = "ddl_check_composite_index_max" DDLCheckTableWithoutInnoDBUTF8MB4 = "ddl_check_table_without_innodb_utf8mb4" DDLCheckIndexedColumnWithBolb = "ddl_check_index_column_with_blob" DDLCheckAlterTableNeedMerge = "ddl_check_alter_table_need_merge" DDLDisableDropStatement = "ddl_disable_drop_statement" DDLCheckTableWithoutComment = "ddl_check_table_without_comment" DDLCheckColumnWithoutComment = "ddl_check_column_without_comment" DDLCheckIndexPrefix = "ddl_check_index_prefix" DDLCheckUniqueIndexPrefix = "ddl_check_unique_index_prefix" DDLCheckUniqueIndex = "ddl_check_unique_index" DDLCheckColumnWithoutDefault = "ddl_check_column_without_default" DDLCheckColumnTimestampWitoutDefault = "ddl_check_column_timestamp_without_default" DDLCheckColumnBlobWithNotNull = "ddl_check_column_blob_with_not_null" DDLCheckColumnBlobDefaultIsNotNull = "ddl_check_column_blob_default_is_not_null" DDLCheckColumnEnumNotice = "ddl_check_column_enum_notice" DDLCheckColumnSetNitice = "ddl_check_column_set_notice" DDLCheckColumnBlobNotice = "ddl_check_column_blob_notice" DDLCheckIndexesExistBeforeCreateConstraints = "ddl_check_indexes_exist_before_creat_constraints" DDLCheckDatabaseCollation = "ddl_check_collation_database" DDLCheckDecimalTypeColumn = "ddl_check_decimal_type_column" DDLCheckDatabaseSuffix = "ddl_check_database_suffix" DDLCheckPKName = "ddl_check_pk_name" DDLCheckTransactionIsolationLevel = "ddl_check_transaction_isolation_level" DDLCheckTablePartition = "ddl_check_table_partition" DDLCheckIsExistLimitOffset = "ddl_check_is_exist_limit_offset" DDLCheckIndexOption = "ddl_check_index_option" DDLCheckOBjectNameUseCN = "ddl_check_object_name_using_cn" DDLCheckCreateView = "ddl_check_create_view" DDLCheckCreateTrigger = "ddl_check_create_trigger" DDLCheckCreateFunction = "ddl_check_create_function" DDLCheckCreateProcedure = "ddl_check_create_procedure" )
inspector DDL rules
View Source
const ( DMLCheckWithLimit = "dml_check_with_limit" DMLCheckWithOrderBy = "dml_check_with_order_by" DMLCheckWhereIsInvalid = "all_check_where_is_invalid" DMLDisableSelectAllColumn = "dml_disable_select_all_column" DMLCheckInsertColumnsExist = "dml_check_insert_columns_exist" DMLCheckBatchInsertListsMax = "dml_check_batch_insert_lists_max" DMLCheckWhereExistFunc = "dml_check_where_exist_func" DMLCheckWhereExistNot = "dml_check_where_exist_not" DMLCheckWhereExistImplicitConversion = "dml_check_where_exist_implicit_conversion" DMLCheckLimitMustExist = "dml_check_limit_must_exist" DMLCheckWhereExistScalarSubquery = "dml_check_where_exist_scalar_sub_queries" DMLWhereExistNull = "dml_check_where_exist_null" DMLCheckSelectForUpdate = "dml_check_select_for_update" DMLCheckNeedlessFunc = "dml_check_needless_func" DMLCheckFuzzySearch = "dml_check_fuzzy_search" DMLCheckNumberOfJoinTables = "dml_check_number_of_join_tables" DMLCheckIfAfterUnionDistinct = "dml_check_is_after_union_distinct" DMLCheckExplainAccessTypeAll = "dml_check_explain_access_type_all" DMLCheckExplainExtraUsingFilesort = "dml_check_explain_extra_using_filesort" DMLCheckExplainExtraUsingTemporary = "dml_check_explain_extra_using_temporary" )
inspector DML rules
View Source
const ( ConfigDMLRollbackMaxRows = "dml_rollback_max_rows" ConfigDDLOSCMinSize = "ddl_osc_min_size" ConfigDDLGhostMinSize = "ddl_ghost_min_size" )
inspector config code
View Source
const DAIL_TIMEOUT = 5 * time.Second
View Source
const (
SysVarLowerCaseTableNames = "lower_case_table_names"
)
Variables ¶
View Source
var ( RuleHandlerMap = map[string]RuleHandler{} // DefaultTemplateRules only use for unit test now. It should be removed later, // because Driver layer should not care about Rule template. TODO(@wy) DefaultTemplateRules = []model.Rule{} InitRules = []model.Rule{} )
View Source
var ColumnOptionMap = map[ast.ColumnOptionType]string{ ast.ColumnOptionNotNull: "NOT NULL", ast.ColumnOptionNull: "NULL", ast.ColumnOptionAutoIncrement: "AUTO_INCREMENT", ast.ColumnOptionPrimaryKey: "PRIMARY KEY", ast.ColumnOptionUniqKey: "UNIQUE KEY", }
View Source
var ReservedKeywords = map[string]struct{}{}/* 235 elements not displayed */
see https://dev.mysql.com/doc/refman/5.7/en/keywords.html
View Source
var RuleHandlers = []RuleHandler{ { Rule: model.Rule{ Name: ConfigDMLRollbackMaxRows, Desc: "在 DML 语句中预计影响行数超过指定值则不回滚", Value: "1000", Level: model.RuleLevelNotice, Typ: RuleTypeGlobalConfig, IsDefault: true, }, Func: nil, }, { Rule: model.Rule{ Name: ConfigDDLOSCMinSize, Desc: "改表时,表空间超过指定大小(MB)审核时输出osc改写建议", Value: "16", Level: model.RuleLevelNormal, Typ: RuleTypeGlobalConfig, IsDefault: true, }, Func: nil, }, { Rule: model.Rule{ Name: ConfigDDLGhostMinSize, Desc: "改表时,表空间超过指定大小(MB)时使用gh-ost上线", Value: "16", Level: model.RuleLevelNormal, Typ: RuleTypeGlobalConfig, IsDefault: true, }, Func: nil, }, { Rule: model.Rule{ Name: DDLCheckPKWithoutIfNotExists, Desc: "新建表必须加入if not exists create,保证重复执行不报错", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, IsDefault: true, }, Message: "新建表必须加入if not exists create,保证重复执行不报错", AllowOffline: true, Func: checkIfNotExist, }, { Rule: model.Rule{ Name: DDLCheckObjectNameLength, Desc: "表名、列名、索引名的长度不能大于64字节", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, IsDefault: true, }, Message: "表名、列名、索引名的长度不能大于64字节", AllowOffline: true, Func: checkNewObjectName, }, { Rule: model.Rule{ Name: DDLCheckPKNotExist, Desc: "表必须有主键", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "表必须有主键", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}}, Func: checkPrimaryKey, }, { Rule: model.Rule{ Name: DDLCheckPKWithoutAutoIncrement, Desc: "主键建议使用自增", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "主键建议使用自增", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}}, Func: checkPrimaryKey, }, { Rule: model.Rule{ Name: DDLCheckPKWithoutBigintUnsigned, Desc: "主键建议使用 bigint 无符号类型,即 bigint unsigned", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "主键建议使用 bigint 无符号类型,即 bigint unsigned", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}}, Func: checkPrimaryKey, }, { Rule: model.Rule{ Name: DDLCheckColumnCharLength, Desc: "char长度大于20时,必须使用varchar类型", Level: model.RuleLevelError, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "char长度大于20时,必须使用varchar类型", AllowOffline: true, Func: checkStringType, }, { Rule: model.Rule{ Name: DDLDisableFK, Desc: "禁止使用外键", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "禁止使用外键", AllowOffline: true, Func: checkForeignKey, }, { Rule: model.Rule{ Name: DDLCheckIndexCount, Desc: "索引个数建议不超过阈值", Level: model.RuleLevelNotice, Value: "5", Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "索引个数建议不超过%v个", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}, &ast.CreateIndexStmt{}}, Func: checkIndex, }, { Rule: model.Rule{ Name: DDLCheckCompositeIndexMax, Desc: "复合索引的列数量不建议超过阈值", Level: model.RuleLevelNotice, Value: "3", Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "复合索引的列数量不建议超过%v个", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}, &ast.CreateIndexStmt{}}, Func: checkIndex, }, { Rule: model.Rule{ Name: DDLCheckObjectNameUsingKeyword, Desc: "数据库对象命名禁止使用保留字", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, IsDefault: true, }, Message: "数据库对象命名禁止使用保留字 %s", AllowOffline: true, Func: checkNewObjectName, }, { Rule: model.Rule{ Name: DDLCheckOBjectNameUseCN, Desc: "数据库对象命名只能使用英文、下划线或数字,首字母必须是英文", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, IsDefault: true, }, Message: "数据库对象命名只能使用英文、下划线或数字,首字母必须是英文", AllowOffline: true, Func: checkNewObjectName, }, { Rule: model.Rule{ Name: DDLCheckTableWithoutInnoDBUTF8MB4, Desc: "建议使用Innodb引擎,utf8mb4字符集", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "建议使用Innodb引擎,utf8mb4字符集", AllowOffline: false, Func: checkEngineAndCharacterSet, }, { Rule: model.Rule{ Name: DDLCheckIndexedColumnWithBolb, Desc: "禁止将blob类型的列加入索引", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, IsDefault: true, }, Message: "禁止将blob类型的列加入索引", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}, &ast.CreateIndexStmt{}}, Func: disableAddIndexForColumnsTypeBlob, }, { Rule: model.Rule{ Name: DMLCheckWhereIsInvalid, Desc: "禁止使用没有where条件的sql语句或者使用where 1=1等变相没有条件的sql", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, IsDefault: true, }, Message: "禁止使用没有where条件的sql语句或者使用where 1=1等变相没有条件的sql", AllowOffline: true, Func: checkSelectWhere, }, { Rule: model.Rule{ Name: DDLCheckAlterTableNeedMerge, Desc: "存在多条对同一个表的修改语句,建议合并成一个ALTER语句", Level: model.RuleLevelNotice, Typ: RuleTypeUsageSuggestion, IsDefault: true, }, Message: "已存在对该表的修改语句,建议合并成一个ALTER语句", AllowOffline: false, Func: checkMergeAlterTable, }, { Rule: model.Rule{ Name: DMLDisableSelectAllColumn, Desc: "不建议使用select *", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, IsDefault: true, }, Message: "不建议使用select *", AllowOffline: true, Func: checkSelectAll, }, { Rule: model.Rule{ Name: DDLDisableDropStatement, Desc: "禁止除索引外的drop操作", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, IsDefault: true, }, Message: "禁止除索引外的drop操作", AllowOffline: true, Func: disableDropStmt, }, { Rule: model.Rule{ Name: DDLCheckTableWithoutComment, Desc: "表建议添加注释", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "表建议添加注释", AllowOffline: true, Func: checkTableWithoutComment, }, { Rule: model.Rule{ Name: DDLCheckColumnWithoutComment, Desc: "列建议添加注释", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "列建议添加注释", AllowOffline: true, Func: checkColumnWithoutComment, }, { Rule: model.Rule{ Name: DDLCheckIndexPrefix, Desc: "普通索引必须要以\"idx_\"为前缀", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, IsDefault: true, }, Message: "普通索引必须要以\"idx_\"为前缀", AllowOffline: true, Func: checkIndexPrefix, }, { Rule: model.Rule{ Name: DDLCheckUniqueIndexPrefix, Desc: "unique索引必须要以\"uniq_\"为前缀", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, IsDefault: true, }, Message: "unique索引必须要以\"uniq_\"为前缀", AllowOffline: true, Func: checkUniqIndexPrefix, }, { Rule: model.Rule{ Name: DDLCheckUniqueIndex, Desc: "unique索引名必须使用 IDX_UK_表名_字段名", Level: model.RuleLevelError, Typ: RuleTypeNamingConvention, }, Message: "unique索引名必须使用 IDX_UK_表名_字段名", AllowOffline: true, Func: checkUniqIndex, }, { Rule: model.Rule{ Name: DDLCheckColumnWithoutDefault, Desc: "除了自增列及大字段列之外,每个列都必须添加默认值", Level: model.RuleLevelError, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "除了自增列及大字段列之外,每个列都必须添加默认值", AllowOffline: true, Func: checkColumnWithoutDefault, }, { Rule: model.Rule{ Name: DDLCheckColumnTimestampWitoutDefault, Desc: "timestamp 类型的列必须添加默认值", Level: model.RuleLevelError, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "timestamp 类型的列必须添加默认值", AllowOffline: true, Func: checkColumnTimestampWithoutDefault, }, { Rule: model.Rule{ Name: DDLCheckColumnBlobWithNotNull, Desc: "BLOB 和 TEXT 类型的字段不建议设置为 NOT NULL", Level: model.RuleLevelError, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "BLOB 和 TEXT 类型的字段不建议设置为 NOT NULL", AllowOffline: true, Func: checkColumnBlobNotNull, }, { Rule: model.Rule{ Name: DDLCheckColumnBlobDefaultIsNotNull, Desc: "BLOB 和 TEXT 类型的字段不可指定非 NULL 的默认值", Level: model.RuleLevelError, Typ: RuleTypeDDLConvention, IsDefault: true, }, Message: "BLOB 和 TEXT 类型的字段不可指定非 NULL 的默认值", AllowOffline: true, Func: checkColumnBlobDefaultNull, }, { Rule: model.Rule{ Name: DMLCheckWithLimit, Desc: "delete/update 语句不能有limit条件", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, IsDefault: true, }, Message: "delete/update 语句不能有limit条件", AllowOffline: true, Func: checkDMLWithLimit, }, { Rule: model.Rule{ Name: DMLCheckWithOrderBy, Desc: "delete/update 语句不能有order by", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, IsDefault: true, }, Message: "delete/update 语句不能有order by", AllowOffline: true, Func: checkDMLWithOrderBy, }, { Rule: model.Rule{ Name: DMLCheckInsertColumnsExist, Desc: "insert 语句必须指定column", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, }, Message: "insert 语句必须指定column", AllowOffline: true, Func: checkDMLWithInsertColumnExist, }, { Rule: model.Rule{ Name: DMLCheckBatchInsertListsMax, Desc: "单条insert语句,建议批量插入不超过阈值", Level: model.RuleLevelNotice, Value: "5000", Typ: RuleTypeDMLConvention, }, Message: "单条insert语句,建议批量插入不超过%v条", AllowOffline: true, Func: checkDMLWithBatchInsertMaxLimits, }, { Rule: model.Rule{ Name: DDLCheckPKProhibitAutoIncrement, Desc: "主键禁止使用自增", Level: model.RuleLevelError, Typ: RuleTypeIndexingConvention, }, Message: "主键禁止使用自增", AllowOffline: true, NotAllowOfflineStmts: []ast.Node{&ast.AlterTableStmt{}}, Func: checkPrimaryKey, }, { Rule: model.Rule{ Name: DMLCheckWhereExistFunc, Desc: "避免对条件字段使用函数操作", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "避免对条件字段使用函数操作", AllowOffline: false, Func: checkWhereExistFunc, }, { Rule: model.Rule{ Name: DMLCheckWhereExistNot, Desc: "不建议对条件字段使用负向查询", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "不建议对条件字段使用负向查询", AllowOffline: true, Func: checkSelectWhere, }, { Rule: model.Rule{ Name: DMLWhereExistNull, Desc: "不建议对条件字段使用 NULL 值判断", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "不建议对条件字段使用 NULL 值判断", Func: checkWhereExistNull, AllowOffline: true, }, { Rule: model.Rule{ Name: DMLCheckWhereExistImplicitConversion, Desc: "条件字段存在数值和字符的隐式转换", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "条件字段存在数值和字符的隐式转换", Func: checkWhereColumnImplicitConversion, }, { Rule: model.Rule{ Name: DMLCheckLimitMustExist, Desc: "delete/update 语句必须有limit条件", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, }, Message: "delete/update 语句必须有limit条件", Func: checkDMLLimitExist, AllowOffline: true, }, { Rule: model.Rule{ Name: DMLCheckWhereExistScalarSubquery, Desc: "避免使用标量子查询", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "避免使用标量子查询", AllowOffline: true, Func: checkSelectWhere, }, { Rule: model.Rule{ Name: DDLCheckIndexesExistBeforeCreateConstraints, Desc: "建议创建约束前,先行创建索引", Level: model.RuleLevelNotice, Typ: RuleTypeIndexingConvention, }, Message: "建议创建约束前,先行创建索引", Func: checkIndexesExistBeforeCreatConstraints, }, { Rule: model.Rule{ Name: DMLCheckSelectForUpdate, Desc: "建议避免使用select for update", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "建议避免使用select for update", Func: checkDMLSelectForUpdate, AllowOffline: true, }, { Rule: model.Rule{ Name: DDLCheckDatabaseCollation, Desc: "建议使用规定的数据库排序规则", Level: model.RuleLevelNotice, Value: "utf8mb4_0900_ai_ci", Typ: RuleTypeDDLConvention, }, Message: "建议使用规定的数据库排序规则为%s", Func: checkCollationDatabase, }, { Rule: model.Rule{ Name: DDLCheckDecimalTypeColumn, Desc: "精确浮点数建议使用DECIMAL", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, }, Message: "精确浮点数建议使用DECIMAL", Func: checkDecimalTypeColumn, AllowOffline: true, }, { Rule: model.Rule{ Name: DMLCheckNeedlessFunc, Desc: "避免使用不必要的内置函数", Level: model.RuleLevelNotice, Value: "sha(),sqrt(),md5()", Typ: RuleTypeDMLConvention, }, Message: "避免使用不必要的内置函数[%v]", Func: checkNeedlessFunc, AllowOffline: true, }, { Rule: model.Rule{ Name: DDLCheckDatabaseSuffix, Desc: "数据库名称建议以\"_DB\"结尾", Level: model.RuleLevelNotice, Typ: RuleTypeNamingConvention, }, Message: "数据库名称建议以\"_DB\"结尾", Func: checkDatabaseSuffix, AllowOffline: true, }, { Rule: model.Rule{ Name: DDLCheckPKName, Desc: "建议主键命名为\"PK_表名\"", Level: model.RuleLevelNotice, Typ: RuleTypeNamingConvention, }, Message: "建议主键命名为\"PK_表名\"", Func: checkPKIndexName, AllowOffline: true, }, { Rule: model.Rule{ Name: DDLCheckTransactionIsolationLevel, Desc: "事物隔离级别建议设置成RC", Level: model.RuleLevelNotice, Typ: RuleTypeUsageSuggestion, }, Message: "事物隔离级别建议设置成RC", Func: checkTransactionIsolationLevel, AllowOffline: true, }, { Rule: model.Rule{ Name: DMLCheckFuzzySearch, Desc: "禁止使用全模糊搜索或左模糊搜索", Level: model.RuleLevelError, Typ: RuleTypeDMLConvention, }, Message: "禁止使用全模糊搜索或左模糊搜索", AllowOffline: true, Func: checkSelectWhere, }, { Rule: model.Rule{ Name: DDLCheckTablePartition, Desc: "不建议使用分区表相关功能", Level: model.RuleLevelNotice, Typ: RuleTypeUsageSuggestion, }, Message: "不建议使用分区表相关功能", AllowOffline: true, Func: checkTablePartition, }, { Rule: model.Rule{ Name: DMLCheckNumberOfJoinTables, Desc: "使用JOIN连接表查询建议不超过阈值", Level: model.RuleLevelNotice, Value: "3", Typ: RuleTypeDMLConvention, }, Message: "使用JOIN连接表查询建议不超过%v张", AllowOffline: true, Func: checkNumberOfJoinTables, }, { Rule: model.Rule{ Name: DMLCheckIfAfterUnionDistinct, Desc: "建议使用UNION ALL,替代UNION", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "建议使用UNION ALL,替代UNION", AllowOffline: true, Func: checkIsAfterUnionDistinct, }, { Rule: model.Rule{ Name: DDLCheckIsExistLimitOffset, Desc: "使用LIMIT分页时,避免使用LIMIT M,N", Level: model.RuleLevelNotice, Typ: RuleTypeDMLConvention, }, Message: "使用LIMIT分页时,避免使用LIMIT M,N", AllowOffline: true, Func: checkIsExistLimitOffset, }, { Rule: model.Rule{ Name: DDLCheckIndexOption, Desc: "建议选择可选性超过阈值字段作为索引", Level: model.RuleLevelNotice, Value: "0.7", Typ: RuleTypeDMLConvention, }, Message: "创建索引的字段可选性未超过阈值:%v", AllowOffline: false, Func: checkIndexOption, }, { Rule: model.Rule{ Name: DDLCheckColumnEnumNotice, Desc: "不建议使用 ENUM 类型", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, }, Message: "不建议使用 ENUM 类型", AllowOffline: true, Func: checkColumnEnumNotice, }, { Rule: model.Rule{ Name: DDLCheckColumnSetNitice, Desc: "不建议使用 SET 类型", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, }, Message: "不建议使用 SET 类型", AllowOffline: true, Func: checkColumnSetNotice, }, { Rule: model.Rule{ Name: DDLCheckColumnBlobNotice, Desc: "不建议使用 BLOB 或 TEXT 类型", Level: model.RuleLevelNotice, Typ: RuleTypeDDLConvention, }, Message: "不建议使用 BLOB 或 TEXT 类型", AllowOffline: true, Func: checkColumnBlobNotice, }, { Rule: model.Rule{ Name: DMLCheckExplainAccessTypeAll, Value: "10000", Desc: "查询的扫描不建议超过指定行数(默认值:10000)", Level: model.RuleLevelWarn, Typ: RuleTypeDMLConvention, }, Message: "该查询的扫描行数为%v", AllowOffline: false, Func: checkExplain, }, { Rule: model.Rule{ Name: DMLCheckExplainExtraUsingFilesort, Desc: "该查询使用了文件排序", Level: model.RuleLevelWarn, Typ: RuleTypeDMLConvention, }, Message: "该查询使用了文件排序", AllowOffline: false, Func: checkExplain, }, { Rule: model.Rule{ Name: DMLCheckExplainExtraUsingTemporary, Desc: "该查询使用了临时表", Level: model.RuleLevelWarn, Typ: RuleTypeDMLConvention, }, Message: "该查询使用了临时表", AllowOffline: false, Func: checkExplain, }, { Rule: model.Rule{ Name: DDLCheckCreateView, Desc: "禁止使用视图", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, }, Message: "禁止使用视图", AllowOffline: true, Func: checkCreateView, }, { Rule: model.Rule{ Name: DDLCheckCreateTrigger, Desc: "禁止使用触发器", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, }, Message: "禁止使用触发器", AllowOffline: true, Func: checkCreateTrigger, }, { Rule: model.Rule{ Name: DDLCheckCreateFunction, Desc: "禁止使用自定义函数", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, }, Message: "禁止使用自定义函数", AllowOffline: true, Func: checkCreateFunction, }, { Rule: model.Rule{ Name: DDLCheckCreateProcedure, Desc: "禁止使用存储过程", Level: model.RuleLevelError, Typ: RuleTypeUsageSuggestion, }, Message: "禁止使用存储过程", AllowOffline: true, Func: checkCreateProcedure, }, }
Functions ¶
func Fingerprint ¶
func HasOneInOptions ¶
func HasOneInOptions(Options []*ast.ColumnOption, opTp ...ast.ColumnOptionType) bool
func IsAllInOptions ¶
func IsAllInOptions(Options []*ast.ColumnOption, opTp ...ast.ColumnOptionType) bool
func IsMysqlReservedKeyword ¶
func LoadPtTemplateFromFile ¶
func MysqlDataTypeIsBlob ¶
func RemoveArrayRepeat ¶
Types ¶
type BaseConn ¶
type BaseConn struct {
// contains filtered or unexported fields
}
type CapitalizeProcessor ¶
type CapitalizeProcessor struct {
// contains filtered or unexported fields
}
CapitalizeProcessor capitalize identifiers as needed.
format.RestoreNameUppercase can not control name comparisons accurate. CASE: Database/Table/Table-alias names are case-insensitive when lower_case_table_names equals 1. Some identifiers, such as Tablespace names are case-sensitive which not affected by lower_case_table_names. ref: https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
func NewContext ¶
func (*Context) AddExecutionPlan ¶
func (c *Context) AddExecutionPlan(sql string, records []*ExplainRecord)
func (*Context) GetExecutionPlan ¶
func (c *Context) GetExecutionPlan(sql string) ([]*ExplainRecord, bool)
func (*Context) HasLoadSchemas ¶
func (*Context) HasLoadTables ¶
func (*Context) LoadSchemas ¶
func (*Context) LoadTables ¶
func (*Context) SetSchemasLoad ¶
func (c *Context) SetSchemasLoad()
type Executor ¶
type Executor struct { Db Db // contains filtered or unexported fields }
func NewExecutor ¶
func (*Executor) FetchMasterBinlogPos ¶
func (*Executor) ShowCreateTable ¶
func (*Executor) ShowDatabases ¶
func (*Executor) ShowDefaultConfiguration ¶
func (*Executor) ShowMasterStatus ¶
func (c *Executor) ShowMasterStatus() ([]map[string]sql.NullString, error)
func (*Executor) ShowSchemaTables ¶
type ExplainRecord ¶
type ExplainRecord struct { Id string `json:"id"` SelectType string `json:"select_type"` Table string `json:"table"` Partitions string `json:"partitions"` Type string `json:"type"` PossibleKeys string `json:"possible_keys"` Key string `json:"key"` KeyLen string `json:"key_len"` Ref string `json:"ref"` Rows int64 `json:"rows"` Filtered string `json:"filtered"` Extra string `json:"extra"` }
type Inspect ¶
type Inspect struct { // Ctx is SQL context. Ctx *Context // HasInvalidSql represent one of the commit sql base-validation failed. HasInvalidSql bool // contains filtered or unexported fields }
Inspect implements driver.Driver interface
func (*Inspect) GenRollbackSQL ¶
func (*Inspect) GenerateDDLStmtRollbackSql ¶
func (*Inspect) GenerateDMLStmtRollbackSql ¶
func (*Inspect) GenerateRollbackSql ¶
func (*Inspect) GetAllRollbackSqlReversed ¶
func (i *Inspect) GetAllRollbackSqlReversed(sqls []*model.RollbackSQL) []*model.RollbackSQL
func (*Inspect) IsOfflineAudit ¶
type RuleHandler ¶
type RuleHandler struct { Rule model.Rule Message string Func func(model.Rule, *Inspect, ast.Node) error AllowOffline bool NotAllowOfflineStmts []ast.Node }
func (*RuleHandler) IsAllowOfflineRule ¶
func (rh *RuleHandler) IsAllowOfflineRule(node ast.Node) bool
type SchemaInfo ¶
type TableChecker ¶
type TableChecker struct {
// contains filtered or unexported fields
}
type TableInfo ¶
type TableInfo struct { Size float64 // OriginalTable save parser object from db by query "show create table ..."; // using in inspect and generate rollback sql OriginalTable *ast.CreateTableStmt // MergedTable *ast.CreateTableStmt // save alter table parse object from input sql; AlterTables []*ast.AlterTableStmt // contains filtered or unexported fields }
Source Files ¶
Click to show internal directories.
Click to hide internal directories.