vet

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 3 Imported by: 0

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 HasError

func HasError(findings []Finding) bool

HasError reports whether any Finding in findings has Error severity.

func RulesByName

func RulesByName() map[string]Rule

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.

func Run

func Run(rules []Rule, queries []Query) []Finding

Run applies rules to queries and returns all Findings in a deterministic order: findings are grouped by query (in input order) then by rule (in DefaultRules order).

func RunPlanRules

func RunPlanRules(rules []PlanRule, q Query, plan []PlanRow) []Finding

RunPlanRules applies planRules to a single query+plan and returns all Findings. This is separate from Run (which operates on text rules) so the caller can drive the oracle loop separately.

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

func ParsePlanDetail(detail string) (PlanKind, string)

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

func FilterPlanRules(disabled []string) []PlanRule

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

func FilterRules(disabled []string) []Rule

FilterRules returns the subset of DefaultRules() whose names are not in disabled. The returned slice preserves the DefaultRules order.

type Severity

type Severity int

Severity classifies the importance of a Finding.

const (
	// Warning indicates a potentially problematic pattern that does not block
	// generation but should be reviewed.
	Warning Severity = iota
	// Error indicates a pattern that is almost certainly wrong and causes
	// runVet to exit non-zero.
	Error
)

func (Severity) String

func (s Severity) String() string

String returns the human-readable severity label.

Jump to

Keyboard shortcuts

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