dsl

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package dsl provides a domain-specific language for defining custom SQL analysis rules.

Index

Constants

This section is empty.

Variables

View Source
var BuiltinFunctions = map[string]interface{}{

	"contains":   strings.Contains,
	"hasPrefix":  strings.HasPrefix,
	"hasSuffix":  strings.HasSuffix,
	"toLower":    strings.ToLower,
	"toUpper":    strings.ToUpper,
	"trim":       strings.TrimSpace,
	"startsWith": strings.HasPrefix,
	"endsWith":   strings.HasSuffix,

	"matches":    matchesRegex,
	"notMatches": notMatchesRegex,

	"isSystemTable": isSystemTable,
	"isAggregate":   isAggregate,
	"isTempTable":   isTempTable,

	"len":          length,
	"any":          anyMatch,
	"all":          allMatch,
	"contains_any": containsAny,
}

BuiltinFunctions provides functions available in DSL conditions. These are registered with expr-lang for use in "when" expressions.

View Source
var SQLKeywords = []string{
	"SELECT", "FROM", "WHERE", "JOIN", "LEFT", "RIGHT", "INNER", "OUTER",
	"ON", "AND", "OR", "NOT", "IN", "EXISTS", "BETWEEN", "LIKE", "IS",
	"NULL", "ORDER", "BY", "GROUP", "HAVING", "LIMIT", "OFFSET",
	"INSERT", "INTO", "VALUES", "UPDATE", "SET", "DELETE",
	"CREATE", "ALTER", "DROP", "TABLE", "INDEX", "VIEW",
	"UNION", "INTERSECT", "EXCEPT", "ALL", "DISTINCT",
	"AS", "ASC", "DESC", "CASE", "WHEN", "THEN", "ELSE", "END",
}

SQLKeywords contains common SQL keywords for pattern matching.

Functions

func BuiltinFunctionDescriptions

func BuiltinFunctionDescriptions() map[string]string

BuiltinFunctionDescriptions returns descriptions for DSL functions.

func BuiltinRuleDescriptions

func BuiltinRuleDescriptions() map[string]string

BuiltinRuleDescriptions returns descriptions for built-in rules.

func BuiltinVariableDescriptions

func BuiltinVariableDescriptions() map[string]string

BuiltinVariableDescriptions returns descriptions for DSL variables.

func ExtractQueryType

func ExtractQueryType(query string) string

ExtractQueryType extracts the type of SQL query (SELECT, INSERT, etc.).

func ExtractTableNames

func ExtractTableNames(query string) []string

ExtractTableNames attempts to extract table names from a query. This is a simple implementation - for complex queries, use a proper SQL parser.

func GetBuiltinFunctionNames

func GetBuiltinFunctionNames() []string

GetBuiltinFunctionNames returns the names of all built-in functions.

func GetBuiltinRules

func GetBuiltinRules() []string

GetBuiltinRules returns the IDs of built-in rules.

func HasJoinClause

func HasJoinClause(query string) bool

HasJoinClause checks if a query has a JOIN clause.

func HasWhereClause

func HasWhereClause(query string) bool

HasWhereClause checks if a query has a WHERE clause.

func IsBuiltinRule

func IsBuiltinRule(id string) bool

IsBuiltinRule checks if a rule ID is a built-in rule.

func JSONSchema

func JSONSchema() string

JSONSchema returns the JSON Schema for .unqueryvet.yaml configuration. This can be used by IDEs for validation and autocompletion.

func LoadAndCreateAnalyzer

func LoadAndCreateAnalyzer(configPath string) (*analysis.Analyzer, error)

LoadAndCreateAnalyzer loads config from file and creates an analyzer.

func MetavariableDescriptions

func MetavariableDescriptions() map[string]string

MetavariableDescriptions returns descriptions for pattern metavariables.

func SchemaURL

func SchemaURL() string

SchemaURL returns the URL for the JSON schema.

Types

type Action

type Action string

Action represents what to do when a pattern matches.

const (
	ActionReport Action = "report" // Report as violation (default)
	ActionAllow  Action = "allow"  // Allow/whitelist this pattern
	ActionIgnore Action = "ignore" // Silently ignore
)

type CompiledPattern

type CompiledPattern struct {
	Original    string
	Regex       *regexp.Regexp
	Metavars    []string // Names of metavariables in order of capture groups
	IsNegated   bool     // Pattern starts with !
	IsMultiline bool     // Pattern spans multiple lines
}

CompiledPattern holds a compiled pattern with metavariable extraction.

func (*CompiledPattern) Match

func (cp *CompiledPattern) Match(text string) (map[string]string, bool)

Match attempts to match a compiled pattern against text. Returns the captured metavariables if successful.

func (*CompiledPattern) MatchAll

func (cp *CompiledPattern) MatchAll(text string) []map[string]string

MatchAll finds all matches in the text.

type CompiledRule

type CompiledRule struct {
	Rule             *Rule
	Patterns         []*CompiledPattern
	ConditionProgram *vm.Program
}

CompiledRule is a rule ready for evaluation.

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler compiles DSL rules for efficient evaluation.

func NewCompiler

func NewCompiler() *Compiler

NewCompiler creates a new rule compiler.

func (*Compiler) ClearCache

func (c *Compiler) ClearCache()

ClearCache clears the compiled program cache.

func (*Compiler) Compile

func (c *Compiler) Compile(rule *Rule) (*CompiledRule, error)

Compile compiles a single rule.

func (*Compiler) CompileConfig

func (c *Compiler) CompileConfig(config *Config) ([]*CompiledRule, error)

CompileConfig compiles all rules in a configuration.

type Config

type Config struct {
	// Rules is a map of built-in rule IDs to their severity.
	// Example: {"select-star": "error", "n1-queries": "warning"}
	Rules map[string]Severity `yaml:"rules,omitempty"`

	// Ignore is a list of file patterns to ignore.
	Ignore []string `yaml:"ignore,omitempty"`

	// Allow is a list of SQL patterns to allow (whitelist).
	Allow []string `yaml:"allow,omitempty"`

	// CustomRules is a list of user-defined rules.
	CustomRules []Rule `yaml:"custom-rules,omitempty"`

	// LegacyConfig holds backward-compatible options.
	LegacyConfig `yaml:",inline"`
}

Config represents the complete DSL configuration.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks if the config is valid.

type DSLAnalyzer

type DSLAnalyzer struct {
	// contains filtered or unexported fields
}

DSLAnalyzer wraps the DSL evaluator for use with go/analysis.

func NewDSLAnalyzer

func NewDSLAnalyzer(config *Config) (*DSLAnalyzer, error)

NewDSLAnalyzer creates a new DSL-based analyzer.

func (*DSLAnalyzer) CreateAnalyzer

func (d *DSLAnalyzer) CreateAnalyzer() *analysis.Analyzer

CreateAnalyzer creates a go/analysis.Analyzer using DSL rules.

type EvalContext

type EvalContext struct {
	// File context
	File     string `expr:"file"`
	Package  string `expr:"package"`
	Function string `expr:"function"`

	// SQL context
	Query     string   `expr:"query"`
	QueryType string   `expr:"query_type"` // SELECT, INSERT, UPDATE, DELETE
	Table     string   `expr:"table"`
	Tables    []string `expr:"tables"`
	Columns   []string `expr:"columns"`
	HasJoin   bool     `expr:"has_join"`
	HasWhere  bool     `expr:"has_where"`

	// Code context
	InLoop    bool   `expr:"in_loop"`
	LoopDepth int    `expr:"loop_depth"`
	Builder   string `expr:"builder"` // gorm, squirrel, sqlx, etc.

	// Metavariables captured from pattern matching
	Metavars map[string]string `expr:"metavars"`
}

EvalContext provides context for evaluating rule conditions.

type Evaluator

type Evaluator struct {
	// contains filtered or unexported fields
}

Evaluator executes compiled DSL rules against code/SQL.

func NewEvaluator

func NewEvaluator(config *Config) (*Evaluator, error)

NewEvaluator creates a new rule evaluator.

func (*Evaluator) EvaluateSQL

func (e *Evaluator) EvaluateSQL(ctx *EvalContext, query string) ([]*Match, error)

EvaluateSQL evaluates all rules against a SQL query.

func (*Evaluator) GetRuleSeverity

func (e *Evaluator) GetRuleSeverity(ruleID string) Severity

GetRuleSeverity returns the severity for a rule from config.

func (*Evaluator) ShouldIgnoreFile

func (e *Evaluator) ShouldIgnoreFile(file string) bool

ShouldIgnoreFile checks if a file should be ignored based on config.

type LegacyConfig

type LegacyConfig struct {
	CheckSQLBuilders bool     `yaml:"check-sql-builders,omitempty"`
	AllowedPatterns  []string `yaml:"allowed-patterns,omitempty"`
	IgnoredFiles     []string `yaml:"ignored-files,omitempty"`
}

LegacyConfig holds options from the original .unqueryvet.yaml format.

type Match

type Match struct {
	Rule     *Rule
	File     string
	Line     int
	Column   int
	Message  string
	Severity Severity
	Fix      string
	Metavars map[string]string
}

Match represents a single match of a rule against code.

type Parser

type Parser struct{}

Parser handles parsing of DSL configuration files.

func NewParser

func NewParser() *Parser

NewParser creates a new DSL parser.

func (*Parser) DefaultConfig

func (p *Parser) DefaultConfig() *Config

DefaultConfig returns a sensible default configuration.

func (*Parser) FindConfigFile

func (p *Parser) FindConfigFile(startDir string) string

FindConfigFile searches for a configuration file in standard locations. Returns empty string if no config file is found.

func (*Parser) LoadConfig

func (p *Parser) LoadConfig(startDir string) (*Config, error)

LoadConfig loads configuration from the first found config file. If no config file is found, returns a default configuration.

func (*Parser) MergeConfigs

func (p *Parser) MergeConfigs(configs ...*Config) *Config

MergeConfigs merges multiple configs, with later configs taking precedence.

func (*Parser) Parse

func (p *Parser) Parse(data []byte) (*Config, error)

Parse parses a DSL configuration from bytes.

func (*Parser) ParseFile

func (p *Parser) ParseFile(path string) (*Config, error)

ParseFile parses a DSL configuration from a file.

type PatternCompiler

type PatternCompiler struct {
	// contains filtered or unexported fields
}

PatternCompiler compiles DSL patterns into regex patterns.

func NewPatternCompiler

func NewPatternCompiler() *PatternCompiler

NewPatternCompiler creates a new pattern compiler.

func (*PatternCompiler) Compile

func (pc *PatternCompiler) Compile(pattern string) (*CompiledPattern, error)

Compile compiles a DSL pattern into a regex-based CompiledPattern. Patterns support: - $VAR: matches any identifier (alphanumeric + underscore) - $TABLE: matches a table name - $QUERY: matches a string literal - Literal text: matched exactly (with regex escaping) - !pattern: negated pattern

func (*PatternCompiler) CompilePatterns

func (pc *PatternCompiler) CompilePatterns(patterns []string) ([]*CompiledPattern, error)

CompilePatterns compiles multiple patterns.

type Rule

type Rule struct {
	// ID is a unique identifier for the rule.
	ID string `yaml:"id"`

	// Pattern is the SQL or code pattern to match.
	// Supports metavariables like $TABLE, $VAR, etc.
	Pattern string `yaml:"pattern"`

	// Patterns allows multiple patterns for a single rule.
	Patterns []string `yaml:"patterns,omitempty"`

	// When is an optional condition expression (evaluated with expr-lang).
	// Available variables: file, package, function, query, table, in_loop, etc.
	When string `yaml:"when,omitempty"`

	// Message is the diagnostic message shown when the rule triggers.
	Message string `yaml:"message,omitempty"`

	// Severity is the severity level (error, warning, info, ignore).
	Severity Severity `yaml:"severity,omitempty"`

	// Action determines what to do when the pattern matches.
	Action Action `yaml:"action,omitempty"`

	// Fix is an optional suggested fix message.
	Fix string `yaml:"fix,omitempty"`
}

Rule represents a custom analysis rule.

func (*Rule) GetAction

func (r *Rule) GetAction() Action

GetAction returns the action, defaulting to report if not set.

func (*Rule) GetMessage

func (r *Rule) GetMessage() string

GetMessage returns the message, or a default if not set.

func (*Rule) GetPatterns

func (r *Rule) GetPatterns() []string

GetPatterns returns all patterns for the rule.

func (*Rule) GetSeverity

func (r *Rule) GetSeverity() Severity

GetSeverity returns the severity, defaulting to warning if not set.

func (*Rule) Validate

func (r *Rule) Validate() error

Validate checks if the rule configuration is valid.

type Severity

type Severity string

Severity represents the severity level of a rule violation.

const (
	SeverityError   Severity = "error"
	SeverityWarning Severity = "warning"
	SeverityInfo    Severity = "info"
	SeverityIgnore  Severity = "ignore"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL