Documentation
¶
Overview ¶
Package vet provides a SQL query lint engine for db-catalyst.
It defines a Rule interface and a set of built-in rules that operate on the text and metadata of parsed queries. Rules are pure: they require no database connection and produce Findings that describe potential problems.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RulesByName ¶
RulesByName returns a map from rule name to Rule, built from DefaultRules. Useful for disabling rules by name.
func SortFindings ¶
func SortFindings(findings []Finding)
SortFindings sorts findings in-place by (Path, Line, Rule) for deterministic output when the input order does not guarantee stability across map iteration.
Types ¶
type Finding ¶
type Finding struct {
// Rule is the name of the rule that produced this finding.
Rule string
// Message is a human-readable description of the violation.
Message string
// Path is the source file path of the query, if available.
Path string
// Line is the 1-based source line of the query annotation (best-effort).
Line int
// Column is the 1-based column of the violation (best-effort; 0 = unknown).
Column int
// Severity is Warning or Error.
Severity Severity
}
Finding describes a single rule violation on a query.
type PlanKind ¶
type PlanKind int
PlanKind classifies a single EXPLAIN QUERY PLAN detail string.
const ( // PlanScan indicates a full table scan (no index used). Detail starts with // "SCAN <table>". PlanScan PlanKind = iota // PlanSearch indicates an indexed access (SEARCH … USING INDEX or // USING INTEGER PRIMARY KEY). Detail starts with "SEARCH <table>". PlanSearch // PlanOther covers all other detail strings (USE TEMP B-TREE, subquery // execution steps, compound union steps, etc.) that are not base-table // scans and should not trigger the query-plan-scan rule. PlanOther )
func ParsePlanDetail ¶
ParsePlanDetail classifies a single EXPLAIN QUERY PLAN detail string and extracts the base table name (lowercase). It returns (PlanOther, "") for any detail that is not a base-table SCAN or SEARCH step.
SQLite detail format (modernc bundled version, stable substring contract):
"SCAN <table> [AS <alias>]" "SEARCH <table> [AS <alias>] USING INDEX <name> (...)" "SEARCH <table> [AS <alias>] USING INTEGER PRIMARY KEY (...)" "USE TEMP B-TREE FOR ..." "EXECUTE CORRELATED SCALAR SUBQUERY ..."
type PlanRow ¶
type PlanRow struct {
// ID is the node identifier returned by EXPLAIN QUERY PLAN.
ID int
// Parent is the parent node identifier (0 for the root).
Parent int
// Detail is the human-readable description of the access strategy chosen
// for this step, e.g. "SCAN users" or "SEARCH users USING INDEX idx_email".
Detail string
}
PlanRow is a single row from EXPLAIN QUERY PLAN. It is defined here (in package vet) so that the rule engine stays free of database-driver imports. The sqlite oracle returns its own sqlite.PlanRow; callers in cmd convert between the two.
type PlanRule ¶
type PlanRule interface {
// Name returns the stable kebab-case identifier of the rule (same
// convention as Rule.Name).
Name() string
// CheckPlan inspects the query and its EXPLAIN QUERY PLAN rows, returning
// any Findings. An empty or nil slice means the query passes.
CheckPlan(q Query, plan []PlanRow) []Finding
}
PlanRule is the interface for rules that need the EXPLAIN QUERY PLAN output in addition to the text of the query. PlanRules are separate from the text Rule interface so that the rule engine can skip them when a plan is not available (e.g. for non-SQLite engines).
func DefaultPlanRules ¶
func DefaultPlanRules() []PlanRule
DefaultPlanRules returns the built-in PlanRules. The order is stable.
func FilterPlanRules ¶
FilterPlanRules returns the subset of DefaultPlanRules whose names are not in disabled.
type Query ¶
type Query struct {
// Name is the query name from the annotation (e.g. "GetUser").
Name string
// SQL is the raw SQL body of the query (without the annotation comment).
SQL string
// Verb is the command string from the annotation (e.g. ":one", ":many", ":exec").
Verb string
// Path is the source file path, if available.
Path string
// Line is the 1-based line of the query's name annotation.
Line int
}
Query is the minimal view of a parsed query passed to rules.
type Rule ¶
type Rule interface {
// Name returns the stable kebab-case identifier of the rule.
Name() string
// Check inspects q and returns any Findings. An empty or nil slice means
// the query passes the rule.
Check(q Query) []Finding
}
Rule is the interface that all lint rules must satisfy.
func DefaultRules ¶
func DefaultRules() []Rule
DefaultRules returns the full set of built-in rules. The order is stable and determines the output order produced by Run when multiple rules fire on the same query.
func FilterRules ¶
FilterRules returns the subset of DefaultRules() whose names are not in disabled. The returned slice preserves the DefaultRules order.