83b215fd25d32a748b76b834db0559370dd37d41
Align the formatter defaults and layout with the hand-formatted reference procedures in dist/examples so a clean `pgtidy fmt` produces the house style. config.Default(): - align_param_types: false (no type-column alignment in param lists) - plpgsql_declare_align_type / plpgsql_declare_align_eq: true Formatter: - routine header: leading-comma params at column 0, first param at one indent, RETURNS/LANGUAGE/volatility/SECURITY each indented one level - %type / %rowtype printed tight (isPctTypeBoundary) - DECLARE = / := / DEFAULT column padded only to the widest declaration that carries an assignment - WHERE continuations in body UPDATE/DELETE: AND/OR aligned with WHERE - EXCEPTION aligned to its enclosing BEGIN; column-0 comment continuations kept flush-left Safety gate: - SemanticallyEqual tolerates CRLF vs LF inside string literals (normNL); the formatter re-emits all layout with st.Newline, so a \r\n inside a multi-line string literal is normalisation, not a code change. This was why action_init and event_exec_func previously refused to format. Corpus: - add the four CRLF reference files as idempotence/safety fixtures - regenerate test_a and test_mm_proc goldens FOR...LOOP body indentation keeps the existing +1 convention (LOOP aligned with FOR); the dist/examples use +2, so loop-body regions differ by whitespace only.
PgTidy
A PostgreSQL linter and formatter. Enforces consistent SQL style, detects PG-specific issues, and formats migrations, schemas, functions, procedures, and triggers.
Ships as a CLI, LSP server, VSCode extension, and DataGrip plugin.
Install
go install git.warky.dev/wdevs/pgtidy/cmd/pgtidy@latest
Or download a pre-built binary from Releases.
CLI
pgtidy fmt [flags] [files...] Format SQL/PL-pgSQL (stdin if no files)
pgtidy lint [flags] [files...] Lint SQL
pgtidy config Print effective configuration
pgtidy lsp Start LSP server (stdio)
pgtidy version
fmt flags
| Flag | Effect |
|---|---|
-w, --write |
Rewrite files in place |
-l, --list |
List unformatted files |
-d, --diff |
Print unified diff |
--check |
Exit non-zero if not formatted (CI) |
Examples
pgtidy fmt -w schema.sql # format in place
pgtidy fmt --check migrations/ # CI check
cat query.sql | pgtidy fmt # stdin → stdout
pgtidy lint schema.sql # lint a file
Config — .pgtidy.yaml
Discovered by walking up from the target file. Defaults = house style.
style:
indent: 2
keyword_case: upper # upper | lower | preserve
identifier_case: lower
type_case: lower
leading_comma: true
pgtidy config # print resolved config
House Style (defaults)
- Keywords
UPPERCASE; data types and identifierslowercase - 2-space indent
- Leading-comma lists (SELECT columns, function params)
- Function params one-per-line;
LANGUAGE,SECURITY, volatility each on own line - PL/pgSQL:
DECLAREblock vars 2-space indented;BEGIN/ENDat body level - Spaces around binary operators (
=,<>,||,:=); no space before(or around::,->,->>
Build from Source
git clone https://git.warky.dev/wdevs/pgtidy
cd pgtidy
make build # → dist/pgtidy
make test # all tests + corpus harness
make snapshot # multi-platform binaries (requires goreleaser)
Editor Integration
VSCode — install the extension from the marketplace or build locally:
make vscode-package
DataGrip / JetBrains — install via the plugin marketplace (LSP4IJ-based).
Other LSP editors — run pgtidy lsp as a stdio LSP server.
