Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

mnafees/pgvet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

2 Commits

Repository files navigation

pgvet

A static analysis tool for PostgreSQL SQL files, powered by the real PostgreSQL parser via pg_query_go.

pgvet parses your .sql files using the same parser that runs inside PostgreSQL itself and checks for common anti-patterns and correctness issues — no running database required.

Install

go install github.com/mnafees/pgvet@latest

Note: The first build takes ~3 minutes due to CGO compilation of the embedded PostgreSQL parser. Subsequent builds are fast.

Usage

# Check a file
pgvet queries.sql
# Check a directory recursively
pgvet sql/
# Check multiple paths
pgvet queries/ migrations/ views.sql
# Read from stdin
echo "SELECT * FROM users" | pgvet
# JSON output (for CI integration)
pgvet --format json sql/
# Run only specific rules
pgvet --rules not-in-subquery,select-star sql/
# Exclude specific rules
pgvet --exclude select-star sql/

Exit codes: 0 = no issues, 1 = issues found, 2 = usage/parse error.

Rules

Default rules

These rules run by default:

Rule Severity Description
select-star warning SELECT * in the outermost query is fragile — list columns explicitly
limit-without-order warning LIMIT without ORDER BY produces non-deterministic results (exempts LIMIT 1)
not-in-subquery error NOT IN (SELECT ...) is broken when the subquery can return NULLs — use NOT EXISTS instead
for-update-no-skip warning FOR UPDATE without SKIP LOCKED or NOWAIT can cause lock contention
distinct-on-order warning DISTINCT ON without a matching leading ORDER BY produces non-deterministic results
null-comparison error = NULL or <> NULL always yields NULL — use IS NULL or IS NOT NULL
update-without-where warning UPDATE without WHERE updates every row in the table
delete-without-where warning DELETE without WHERE deletes every row in the table
insert-without-columns warning INSERT without column list depends on column order — list columns explicitly
ban-char-type warning char(n) pads with spaces — use text or varchar instead
timestamp-without-timezone warning timestamp without time zone loses timezone context — use timestamptz instead
order-by-ordinal warning ORDER BY ordinal position is fragile — use column names or expressions
group-by-ordinal warning GROUP BY ordinal position is fragile — use column names or expressions
like-starts-with-wildcard warning LIKE/ILIKE pattern starting with % prevents index usage
offset-without-limit warning OFFSET without LIMIT returns all remaining rows — likely a mistake

Opt-in rules

These rules must be explicitly enabled with --rules:

Rule Severity Description
multi-statement error Multiple statements in a single query block — CTEs from the first statement are not visible to subsequent ones

Output formats

Text (default)

queries.sql:3:8: warning: [select-star] SELECT * in outermost query is fragile — list columns explicitly
queries.sql:7:30: error: [not-in-subquery] NOT IN (SELECT ...) is broken when the subquery can return NULLs — use NOT EXISTS instead

JSON

[
 {
 "rule": "select-star",
 "message": "SELECT * in outermost query is fragile — list columns explicitly",
 "file": "queries.sql",
 "line": 3,
 "col": 8,
 "severity": "warning"
 }
]

Writing custom rules

pgvet has a simple rule interface:

type Rule interface {
 Name() string
 Description() string
 Check(stmt *pg_query.RawStmt, sql string) []Diagnostic
}

Each rule receives a single parsed statement and the original SQL text. The walker package provides a generic AST traversal helper so rules don't need their own recursion logic.

License

MIT

About

Like go vet but for PostgreSQL

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /