Documentation
¶
Overview ¶
Package lint provides a framework for static analysis of MySQL schema definitions and DDL statements. It enables validation and best-practice enforcement beyond the runtime checks provided by the check package.
The linter framework operates on parsed CREATE TABLE statements rather than live database connections.
Basic Usage ¶
Linters are registered via init() functions and executed via RunLinters():
package naming
func init() {
lint.Register(TableNameLinter{})
}
// Later, run all linters:
violations := lint.RunLinters(tables, stmts, config)
Creating a Linter ¶
To create a custom linter, implement the Linter interface:
type MyLinter struct{}
func (l *MyLinter) Name() string { return "my_linter" }
func (l *MyLinter) Category() string { return "custom" }
func (l *MyLinter) Description() string { return "My custom linter" }
func (l *MyLinter) Lint(createTables []*statement.CreateTable, statements []*statement.AbstractStatement) []lint.Violation {
// Perform linting logic
return violations
}
Configuration ¶
Linters can be enabled/disabled via the Config.Enabled map:
config := lint.Config{
Enabled: map[string]bool{
"table_name": true,
"column_name": false,
},
}
Configurable linters can implement the ConfigurableLinter interface to accept custom settings via Config.Settings. Settings must be provided as map[string]string:
config := lint.Config{
Settings: map[string]map[string]string{
"my_linter": {
"option1": "value1",
"option2": "value2",
},
},
}
Index ¶
- func AlterTableTypeToString(tp ast.AlterTableType) string
- func ConfigBool(value string, key string) (bool, error)
- func CreateTableStatements(statements ...any) iter.Seq[*statement.CreateTable]
- func Disable(names ...string) error
- func Enable(names ...string) error
- func Enabled(name string) bool
- func GetConfigBool(c map[string]string, key string) bool
- func HasErrors(violations []Violation) bool
- func HasWarnings(violations []Violation) bool
- func List() []string
- func Register(l Linter)
- func Reset()
- func Stringer(l Linter) string
- type AllowCharset
- func (l *AllowCharset) Configure(config map[string]string) error
- func (l *AllowCharset) DefaultConfig() map[string]string
- func (l *AllowCharset) Description() string
- func (l *AllowCharset) Lint(createTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
- func (l *AllowCharset) Name() string
- func (l *AllowCharset) String() string
- type AllowEngine
- func (l *AllowEngine) Configure(config map[string]string) error
- func (l *AllowEngine) DefaultConfig() map[string]string
- func (l *AllowEngine) Description() string
- func (l *AllowEngine) Lint(existingTables []*statement.CreateTable, ...) (violations []Violation)
- func (l *AllowEngine) Name() string
- func (l *AllowEngine) String() string
- type AutoIncCapacityLinter
- func (l *AutoIncCapacityLinter) Configure(config map[string]string) error
- func (l *AutoIncCapacityLinter) DefaultConfig() map[string]string
- func (l *AutoIncCapacityLinter) Description() string
- func (l *AutoIncCapacityLinter) Lint(existingTables []*statement.CreateTable, ...) (violations []Violation)
- func (l *AutoIncCapacityLinter) Name() string
- func (l *AutoIncCapacityLinter) String() string
- type Config
- type ConfigurableLinter
- type HasFKLinter
- type HasFloatLinter
- type InvisibleIndexBeforeDropLinter
- func (l *InvisibleIndexBeforeDropLinter) Configure(config map[string]string) error
- func (l *InvisibleIndexBeforeDropLinter) DefaultConfig() map[string]string
- func (l *InvisibleIndexBeforeDropLinter) Description() string
- func (l *InvisibleIndexBeforeDropLinter) Lint(existingTables []*statement.CreateTable, ...) []Violation
- func (l *InvisibleIndexBeforeDropLinter) Name() string
- func (l *InvisibleIndexBeforeDropLinter) String() string
- type Linter
- type Location
- type MultipleAlterTableLinter
- type NameCaseLinter
- type PrimaryKeyLinter
- func (l *PrimaryKeyLinter) Configure(config map[string]string) error
- func (l *PrimaryKeyLinter) DefaultConfig() map[string]string
- func (l *PrimaryKeyLinter) Description() string
- func (l *PrimaryKeyLinter) Lint(existingTables []*statement.CreateTable, ...) (violations []Violation)
- func (l *PrimaryKeyLinter) Name() string
- func (l *PrimaryKeyLinter) String() string
- type RedundantIndexLinter
- type ReservedWordsLinter
- type Severity
- type UnsafeLinter
- func (l *UnsafeLinter) Configure(config map[string]string) error
- func (l *UnsafeLinter) DefaultConfig() map[string]string
- func (l *UnsafeLinter) Description() string
- func (l *UnsafeLinter) Lint(_ []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
- func (l *UnsafeLinter) Name() string
- func (l *UnsafeLinter) String() string
- type Violation
- type ZeroDateLinter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AlterTableTypeToString ¶
func AlterTableTypeToString(tp ast.AlterTableType) string
AlterTableTypeToString converts an AlterTableType constant to a human-readable string
func ConfigBool ¶
ConfigBool parses a boolean configuration value from a string. It accepts "true" or "false" (case-insensitive) and returns an error for invalid values. The key parameter is used in error messages to provide context.
func CreateTableStatements ¶
func CreateTableStatements(statements ...any) iter.Seq[*statement.CreateTable]
CreateTableStatements returns an iterator over all CREATE TABLE statements, combining those from the existing schema state and those included in incoming changes.
func Disable ¶
Disable disables specific linters by name. Returns an error if the linter is not found.
func Enabled ¶
Enabled returns whether a specific linter is enabled. Returns an error if the linter is not found.
func HasWarnings ¶
HasWarnings returns true if any violations have WARNING severity.
func Register ¶
func Register(l Linter)
Register registers a linter with the global registry. This should be called from init() functions in linter implementations. Linters are enabled by default when registered.
Types ¶
type AllowCharset ¶
type AllowCharset struct {
// contains filtered or unexported fields
}
func (*AllowCharset) DefaultConfig ¶
func (l *AllowCharset) DefaultConfig() map[string]string
func (*AllowCharset) Description ¶
func (l *AllowCharset) Description() string
func (*AllowCharset) Lint ¶
func (l *AllowCharset) Lint(createTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*AllowCharset) Name ¶
func (l *AllowCharset) Name() string
func (*AllowCharset) String ¶
func (l *AllowCharset) String() string
type AllowEngine ¶
type AllowEngine struct {
// contains filtered or unexported fields
}
func (*AllowEngine) DefaultConfig ¶
func (l *AllowEngine) DefaultConfig() map[string]string
func (*AllowEngine) Description ¶
func (l *AllowEngine) Description() string
func (*AllowEngine) Lint ¶
func (l *AllowEngine) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*AllowEngine) Name ¶
func (l *AllowEngine) Name() string
func (*AllowEngine) String ¶
func (l *AllowEngine) String() string
type AutoIncCapacityLinter ¶
type AutoIncCapacityLinter struct {
// contains filtered or unexported fields
}
func (*AutoIncCapacityLinter) Configure ¶
func (l *AutoIncCapacityLinter) Configure(config map[string]string) error
func (*AutoIncCapacityLinter) DefaultConfig ¶
func (l *AutoIncCapacityLinter) DefaultConfig() map[string]string
func (*AutoIncCapacityLinter) Description ¶
func (l *AutoIncCapacityLinter) Description() string
func (*AutoIncCapacityLinter) Lint ¶
func (l *AutoIncCapacityLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*AutoIncCapacityLinter) Name ¶
func (l *AutoIncCapacityLinter) Name() string
func (*AutoIncCapacityLinter) String ¶
func (l *AutoIncCapacityLinter) String() string
type Config ¶
type Config struct {
// Enabled maps linter names to whether they are enabled
// If a linter is not in this map, it uses its default enabled state
Enabled map[string]bool
// Settings maps linter names to their configuration as map[string]string
// Each linter's settings are provided as key-value string pairs
Settings map[string]map[string]string
// LintOnlyChanges indicates whether to lint only the changes
// or all of the existing schema plus the changes.
LintOnlyChanges bool
// IgnoreTables can be used to discard violations for specific tables
IgnoreTables map[string]bool
}
Config holds linter configuration
type ConfigurableLinter ¶
type ConfigurableLinter interface {
Linter
// Configure applies configuration to the linter
// Configuration is provided as a map of string keys to string values
Configure(config map[string]string) error
// DefaultConfig returns the default configuration for this linter
DefaultConfig() map[string]string
}
ConfigurableLinter is an optional interface for linters that support configuration
type HasFKLinter ¶
type HasFKLinter struct{}
func (*HasFKLinter) Description ¶
func (l *HasFKLinter) Description() string
func (*HasFKLinter) Lint ¶
func (l *HasFKLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*HasFKLinter) Name ¶
func (l *HasFKLinter) Name() string
func (*HasFKLinter) String ¶
func (l *HasFKLinter) String() string
type HasFloatLinter ¶
type HasFloatLinter struct{}
func (*HasFloatLinter) Description ¶
func (l *HasFloatLinter) Description() string
func (*HasFloatLinter) Lint ¶
func (l *HasFloatLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*HasFloatLinter) Name ¶
func (l *HasFloatLinter) Name() string
func (*HasFloatLinter) String ¶
func (l *HasFloatLinter) String() string
type InvisibleIndexBeforeDropLinter ¶
type InvisibleIndexBeforeDropLinter struct {
// contains filtered or unexported fields
}
InvisibleIndexBeforeDropLinter checks that indexes are made invisible before dropping. This is a safety practice to ensure the index is not needed before permanently removing it.
func (*InvisibleIndexBeforeDropLinter) Configure ¶
func (l *InvisibleIndexBeforeDropLinter) Configure(config map[string]string) error
func (*InvisibleIndexBeforeDropLinter) DefaultConfig ¶
func (l *InvisibleIndexBeforeDropLinter) DefaultConfig() map[string]string
func (*InvisibleIndexBeforeDropLinter) Description ¶
func (l *InvisibleIndexBeforeDropLinter) Description() string
func (*InvisibleIndexBeforeDropLinter) Lint ¶
func (l *InvisibleIndexBeforeDropLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) []Violation
func (*InvisibleIndexBeforeDropLinter) Name ¶
func (l *InvisibleIndexBeforeDropLinter) Name() string
func (*InvisibleIndexBeforeDropLinter) String ¶
func (l *InvisibleIndexBeforeDropLinter) String() string
type Linter ¶
type Linter interface {
// Name returns the unique name of this linter
Name() string
// Description returns a human-readable description of what this linter checks
Description() string
// Lint performs the actual linting and returns any violations found.
// Linters can use either or both of the parameters as needed.
Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
// String returns a string representation of the linter
String() string
}
Linter is the interface that all linters must implement
type Location ¶
type Location struct {
// Table is the name of the table where the violation occurred
Table string
// Column is the name of the column (if applicable)
Column *string
// Index is the name of the index (if applicable)
Index *string
// Constraint is the name of the constraint (if applicable)
Constraint *string
}
Location provides information about where a violation occurred
type MultipleAlterTableLinter ¶
type MultipleAlterTableLinter struct{}
MultipleAlterTableLinter checks for multiple ALTER TABLE statements affecting the same table. Multiple ALTER TABLE statements on the same table should be combined into a single statement for better performance, fewer table rebuilds, and decreased danger of bad intermediate state.
func (*MultipleAlterTableLinter) Description ¶
func (l *MultipleAlterTableLinter) Description() string
func (*MultipleAlterTableLinter) Lint ¶
func (l *MultipleAlterTableLinter) Lint(_ []*statement.CreateTable, changes []*statement.AbstractStatement) []Violation
func (*MultipleAlterTableLinter) Name ¶
func (l *MultipleAlterTableLinter) Name() string
func (*MultipleAlterTableLinter) String ¶
func (l *MultipleAlterTableLinter) String() string
type NameCaseLinter ¶
type NameCaseLinter struct{}
func (*NameCaseLinter) Description ¶
func (l *NameCaseLinter) Description() string
func (*NameCaseLinter) Lint ¶
func (l *NameCaseLinter) Lint(createTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*NameCaseLinter) Name ¶
func (*NameCaseLinter) Name() string
func (*NameCaseLinter) String ¶
func (l *NameCaseLinter) String() string
type PrimaryKeyLinter ¶
type PrimaryKeyLinter struct {
// contains filtered or unexported fields
}
PrimaryKeyLinter checks that primary keys are defined and use appropriate data types. Primary keys should be BIGINT (preferably UNSIGNED) or BINARY/VARBINARY, but the linter can be configured to allow other types. Missing PK and other types are flagged as errors, and signed int types are flagged as a warning.
func (*PrimaryKeyLinter) Configure ¶
func (l *PrimaryKeyLinter) Configure(config map[string]string) error
func (*PrimaryKeyLinter) DefaultConfig ¶
func (l *PrimaryKeyLinter) DefaultConfig() map[string]string
func (*PrimaryKeyLinter) Description ¶
func (l *PrimaryKeyLinter) Description() string
func (*PrimaryKeyLinter) Lint ¶
func (l *PrimaryKeyLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*PrimaryKeyLinter) Name ¶
func (l *PrimaryKeyLinter) Name() string
func (*PrimaryKeyLinter) String ¶
func (l *PrimaryKeyLinter) String() string
type RedundantIndexLinter ¶
type RedundantIndexLinter struct{}
RedundantIndexLinter checks for redundant indexes in tables. An index is considered redundant if: 1. Its columns are a prefix of the PRIMARY KEY columns 2. Another index's column list starts with this index's columns (prefix match) 3. Another index has exactly the same columns in the same order (duplicate) 4. The index ends with PRIMARY KEY columns (suffix redundancy)
In InnoDB, secondary indexes automatically include PRIMARY KEY columns as a suffix, making certain index patterns redundant and wasteful.
func (*RedundantIndexLinter) Description ¶
func (l *RedundantIndexLinter) Description() string
func (*RedundantIndexLinter) Lint ¶
func (l *RedundantIndexLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) []Violation
func (*RedundantIndexLinter) Name ¶
func (l *RedundantIndexLinter) Name() string
func (*RedundantIndexLinter) String ¶
func (l *RedundantIndexLinter) String() string
type ReservedWordsLinter ¶
type ReservedWordsLinter struct{}
ReservedWordsLinter checks for usage of MySQL reserved words in table and column names. Using reserved words as identifiers can cause syntax errors and requires quoting.
func (*ReservedWordsLinter) Description ¶
func (l *ReservedWordsLinter) Description() string
func (*ReservedWordsLinter) Lint ¶
func (l *ReservedWordsLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*ReservedWordsLinter) Name ¶
func (l *ReservedWordsLinter) Name() string
func (*ReservedWordsLinter) String ¶
func (l *ReservedWordsLinter) String() string
type Severity ¶
type Severity int
Severity represents the severity level of a linting violation
const ( // SeverityInfo indicates a suggestion or style preference // This is the default value if no explicit Severity is given SeverityInfo Severity = iota // SeverityWarning indicates a best practice violation or potential issue SeverityWarning // SeverityError indicates a violation that will cause actual problems // (syntax errors, MySQL limitations, etc.) SeverityError )
type UnsafeLinter ¶
type UnsafeLinter struct {
// contains filtered or unexported fields
}
func (*UnsafeLinter) DefaultConfig ¶
func (l *UnsafeLinter) DefaultConfig() map[string]string
func (*UnsafeLinter) Description ¶
func (l *UnsafeLinter) Description() string
func (*UnsafeLinter) Lint ¶
func (l *UnsafeLinter) Lint(_ []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*UnsafeLinter) Name ¶
func (l *UnsafeLinter) Name() string
func (*UnsafeLinter) String ¶
func (l *UnsafeLinter) String() string
type Violation ¶
type Violation struct {
// Linter is the linter that produced this violation
Linter Linter
// Severity is the severity level of the violation
Severity Severity
// Message is a human-readable description of the violation
Message string
// Location provides information about where the violation occurred
Location *Location
// Suggestion is an optional suggestion for fixing the violation
Suggestion *string
// Context provides additional context-specific information
Context map[string]any
}
Violation represents a linting violation found during analysis
func FilterByLinter ¶
FilterByLinter returns only violations from the specified linter.
func FilterBySeverity ¶
FilterBySeverity returns only violations with the specified severity.
func RunLinters ¶
func RunLinters(existingSchema []*statement.CreateTable, changes []*statement.AbstractStatement, config Config) ([]Violation, error)
RunLinters runs all enabled linters and returns any violations found. Linters are executed in an undefined order.
A linter is executed if:
- It is enabled by default (set during Register), AND
- It is not explicitly disabled in config.Enabled
OR:
- It is explicitly enabled in config.Enabled
If a linter implements ConfigurableLinter and has settings in config.Settings, those settings are applied before running the linter.
type ZeroDateLinter ¶
type ZeroDateLinter struct{}
func (*ZeroDateLinter) Description ¶
func (l *ZeroDateLinter) Description() string
func (*ZeroDateLinter) Lint ¶
func (l *ZeroDateLinter) Lint(existingTables []*statement.CreateTable, changes []*statement.AbstractStatement) (violations []Violation)
func (*ZeroDateLinter) Name ¶
func (l *ZeroDateLinter) Name() string
func (*ZeroDateLinter) String ¶
func (l *ZeroDateLinter) String() string
Source Files
¶
- lint.go
- lint_allow_charset.go
- lint_allow_engine.go
- lint_auto_inc_capacity.go
- lint_has_fk.go
- lint_has_float.go
- lint_invisible_index.go
- lint_multiple_alter.go
- lint_name_case.go
- lint_primary_key_type.go
- lint_redundant_indexes.go
- lint_reserved_words.go
- lint_unsafe.go
- lint_zero_date.go
- linter.go
- registry.go
- violation.go