A linter for finding unused sqlc queries in your Go code.
This tool scans your SQL files for sqlc query definitions and checks if they're actually being used in your Go code. It helps you identify and remove dead queries that are no longer needed.
The linter automatically detects and uses your sqlc.yaml configuration file to find query locations, so it works out of the box with your existing sqlc setup.
go install github.com/malpou/unusedsqlc/cmd/unusedsqlc@latestgo get github.com/malpou/unusedsqlc# Analyze current directory
unusedsqlc
# Analyze specific directory
unusedsqlc -dir ./pkg/db
# Output as JSON
unusedsqlc -format json
# Exclude specific queries
unusedsqlc -exclude GetUser,GetPost
# Exclude query patterns
unusedsqlc -exclude-patterns 'Test*,*Internal'
# Verbose output
unusedsqlc -verbosepackage main
import (
"go/parser"
"go/token"
"log"
"github.com/malpou/unusedsqlc"
)
func main() {
// Parse Go files
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, ".", nil, parser.ParseComments)
if err != nil {
log.Fatal(err)
}
var files []*ast.File
for _, pkg := range pkgs {
for _, file := range pkg.Files {
files = append(files, file)
}
}
// Configure and run the linter
config := unusedsqlc.DefaultConfig()
config.ExcludePatterns = []string{"Test*"}
linter := unusedsqlc.New(config)
messages, err := linter.Run(files, fset, ".")
if err != nil {
log.Fatal(err)
}
// Process results
for _, msg := range messages {
log.Printf("%s:%d: %s\n", msg.Pos.Filename, msg.Pos.Line, msg.Message)
}
}The linter automatically reads your sqlc.yaml file to find query locations. You can exclude specific queries using command-line flags:
# Exclude specific queries by name
unusedsqlc -exclude GetSystemUser,GetConfig
# Exclude queries matching patterns
unusedsqlc -exclude-patterns 'Test*,*_test,*Internal'When using as a library:
config := unusedsqlc.DefaultConfig()
config.ExcludeQueries = []string{"GetSystemUser"}
config.ExcludePatterns = []string{"Test*", "*_test", "*Internal"}The exclude patterns support wildcards (*) for prefix, suffix, and substring matching.
The linter does three things:
- Reads your
sqlc.yamlto find query files (or searches common directories if no config is found) - Parses SQL files to find sqlc query definitions (the
-- name: QueryName :typecomments) - Analyzes your Go code to see which queries are actually being called
- Reports any queries that exist but are never used
It understands all the standard sqlc query types: :one, :many, :exec, :execrows, :execresult, and :copyfrom.
To use with golangci-lint, add it as a custom linter in your .golangci.yml:
linters-settings:
custom:
unusedsqlc:
path: github.com/malpou/unusedsqlc
description: Find unused SQLc queries
original-url: github.com/malpou/unusedsqlcSay you have a SQL file with these queries:
-- name: GetUser :one
SELECT * FROM users WHERE id = $1;
-- name: UnusedQuery :many
SELECT * FROM users WHERE active = true;And your Go code only uses GetUser:
func main() {
db, _ := sql.Open("postgres", "...")
queries := New(db)
user, _ := queries.GetUser(ctx, 1)
// UnusedQuery is never called
}Running the linter will output:
queries.sql:4: unused sqlc query "UnusedQuery" defined at queries.sql:4
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
MIT