performance

package
v1.14.0 Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package performance provides linter rules for detecting SQL anti-patterns that cause poor query performance, full table scans, or N+1 problems.

Rules:

  • L016: SELECT * (fetches all columns)
  • L017: Missing WHERE on SELECT (full scan risk)
  • L018: Leading wildcard LIKE (prevents index use)
  • L019: NOT IN with subquery (NULL risk)
  • L020: Correlated subquery in SELECT list (N+1)
  • L021: OR instead of IN (multiple equality conditions)
  • L022: Function on indexed column in WHERE
  • L023: Implicit cross join (comma-separated tables)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FunctionOnColumnRule

type FunctionOnColumnRule struct{ linter.BaseRule }

FunctionOnColumnRule (L022) detects function calls wrapped around column references in WHERE clauses (e.g., YEAR(created_at) = 2024). Wrapping a column in a function prevents the query planner from using indexes.

func NewFunctionOnColumnRule

func NewFunctionOnColumnRule() *FunctionOnColumnRule

NewFunctionOnColumnRule creates a new L022 rule instance.

func (*FunctionOnColumnRule) Check

Check walks the AST looking for function-on-column patterns in WHERE clauses.

func (*FunctionOnColumnRule) Fix

func (r *FunctionOnColumnRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: rewriting function-on-column requires domain knowledge.

type ImplicitCrossJoinRule

type ImplicitCrossJoinRule struct{ linter.BaseRule }

ImplicitCrossJoinRule (L023) flags queries that reference multiple tables in the FROM clause without explicit JOIN syntax. Comma-separated tables create an implicit cross join (Cartesian product) which is almost always unintentional and produces an explosive result set.

func NewImplicitCrossJoinRule

func NewImplicitCrossJoinRule() *ImplicitCrossJoinRule

NewImplicitCrossJoinRule creates a new L023 rule instance.

func (*ImplicitCrossJoinRule) Check

Check inspects the AST for SELECT statements with multiple FROM tables and no JOINs.

func (*ImplicitCrossJoinRule) Fix

func (r *ImplicitCrossJoinRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: converting implicit cross join to explicit JOIN requires intent.

type LeadingWildcardRule

type LeadingWildcardRule struct{ linter.BaseRule }

LeadingWildcardRule (L018) flags LIKE patterns with a leading wildcard (% or _). A leading wildcard forces a full table scan — it cannot use a B-tree index.

func NewLeadingWildcardRule

func NewLeadingWildcardRule() *LeadingWildcardRule

NewLeadingWildcardRule creates a new L018 rule instance.

func (*LeadingWildcardRule) Check

Check walks the AST looking for LIKE patterns with leading wildcards.

func (*LeadingWildcardRule) Fix

func (r *LeadingWildcardRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: leading wildcard removal requires schema/query redesign.

type MissingWhereRule

type MissingWhereRule struct{ linter.BaseRule }

MissingWhereRule (L017) flags SELECT statements with no WHERE clause and no LIMIT on queries that reference at least one table — indicating a potential full table scan.

func NewMissingWhereRule

func NewMissingWhereRule() *MissingWhereRule

NewMissingWhereRule creates a new L017 rule instance.

func (*MissingWhereRule) Check

func (r *MissingWhereRule) Check(ctx *linter.Context) ([]linter.Violation, error)

Check inspects the AST for SELECT statements without WHERE/LIMIT on tables.

func (*MissingWhereRule) Fix

func (r *MissingWhereRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: adding WHERE/LIMIT requires understanding business logic.

type NotInWithNullRule

type NotInWithNullRule struct{ linter.BaseRule }

NotInWithNullRule (L019) flags NOT IN (subquery) patterns. If the subquery returns any NULL value, the entire NOT IN expression evaluates to UNKNOWN (never true), silently returning zero rows — a common SQL trap.

func NewNotInWithNullRule

func NewNotInWithNullRule() *NotInWithNullRule

NewNotInWithNullRule creates a new L019 rule instance.

func (*NotInWithNullRule) Check

func (r *NotInWithNullRule) Check(ctx *linter.Context) ([]linter.Violation, error)

Check walks the AST looking for NOT IN (subquery) patterns.

func (*NotInWithNullRule) Fix

func (r *NotInWithNullRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: changing NOT IN to NOT EXISTS requires semantic understanding.

type OrInsteadOfInRule

type OrInsteadOfInRule struct{ linter.BaseRule }

OrInsteadOfInRule (L021) detects repeated equality conditions on the same column joined by OR (e.g., col = A OR col = B OR col = C) and suggests using IN instead. Multiple ORs on the same column can prevent index use and are harder to read.

func NewOrInsteadOfInRule

func NewOrInsteadOfInRule() *OrInsteadOfInRule

NewOrInsteadOfInRule creates a new L021 rule instance.

func (*OrInsteadOfInRule) Check

func (r *OrInsteadOfInRule) Check(ctx *linter.Context) ([]linter.Violation, error)

Check walks the AST looking for OR-based equality chains on the same column.

func (*OrInsteadOfInRule) Fix

func (r *OrInsteadOfInRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: refactoring OR to IN requires careful SQL manipulation.

type SelectStarRule

type SelectStarRule struct{ linter.BaseRule }

SelectStarRule (L016) flags SELECT * usage. SELECT * fetches all columns, preventing index-only scans and over-fetching data.

func NewSelectStarRule

func NewSelectStarRule() *SelectStarRule

NewSelectStarRule creates a new L016 rule instance.

func (*SelectStarRule) Check

func (r *SelectStarRule) Check(ctx *linter.Context) ([]linter.Violation, error)

Check inspects the AST for SELECT * usage.

func (*SelectStarRule) Fix

func (r *SelectStarRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: cannot auto-fix without schema knowledge.

type SubqueryInSelectRule

type SubqueryInSelectRule struct{ linter.BaseRule }

SubqueryInSelectRule (L020) flags correlated subqueries in the SELECT column list. A subquery in the SELECT list is executed once per row — this is the classic N+1 problem.

func NewSubqueryInSelectRule

func NewSubqueryInSelectRule() *SubqueryInSelectRule

NewSubqueryInSelectRule creates a new L020 rule instance.

func (*SubqueryInSelectRule) Check

Check inspects the AST for subqueries used as SELECT column expressions.

func (*SubqueryInSelectRule) Fix

func (r *SubqueryInSelectRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is a no-op: refactoring N+1 requires schema/query redesign.

Jump to

Keyboard shortcuts

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