Formatting
Preview Feature: The formatter is currently in preview. We'd love feedback from early adopters! Please report any issues or unexpected output at GitHub Issues.
Known Limitations
The language server provides SQL formatting that produces consistent, readable code. Built on Postgres' own parser, the formatter ensures 100% syntax compatibility with your SQL.
Comments are not processed during formatting. They get removed before formatting and restored after.
Configuration
Configure formatting behavior in your postgres-language-server.jsonc:
{
"format": {
"enabled": true,
"lineWidth": 100,
"indentSize": 2,
"indentStyle": "spaces",
"keywordCase": "lower",
"constantCase": "lower",
"typeCase": "lower",
"functionArgumentGroups": {
"my_pair_func": 2
}
}
}
Options
| Option | Default | Description |
|---|---|---|
enabled |
true |
Enable or disable the formatter |
lineWidth |
100 |
Maximum line width before breaking |
indentSize |
2 |
Number of spaces (or tab width) for indentation |
indentStyle |
"spaces" |
Use "spaces" or "tabs" for indentation |
keywordCase |
"lower" |
Casing for SQL keywords: "upper" or "lower" |
constantCase |
"lower" |
Casing for constants (NULL, TRUE, FALSE): "upper" or "lower" |
typeCase |
"lower" |
Casing for data types (text, int, varchar): "upper" or "lower" |
commaStyle |
"trailing" |
Where a comma sits when a list breaks: "trailing" or "leading" |
logicalOperatorPlacement |
"trailing" |
Where AND and OR sit when a condition breaks: "trailing" or "leading" |
layout |
"fit" |
How a statement is laid out: "fit" breaks only past the line width, "expanded" always breaks between clauses |
castStyle |
"cast" |
How an explicit cast is spelled: "cast" for CAST(x AS t), "operator" for x::t |
clauseBodyStyle |
"break" |
Where a clause body starts: "break" for a new line, "compact" to keep the first element on the keyword line |
isolateSemicolon |
false |
Put the terminating semicolon on its own line when the statement spans several lines |
functionArgumentGroups |
{} (plus built-in defaults, see below) |
Function names mapped to the number of adjacent arguments that should stay together when wrapping |
functionArgumentGroups matches the final, unqualified function name
case-insensitively. A group size of 2 is useful for functions whose arguments
form key/value pairs:
select jsonb_build_object(
'amountTTC', to_amount(amount_ttc, invoices.currency),
'amountVAT', to_amount(amount_vat, invoices.currency)
);
A group stays on one line when it fits; when it does not, the formatter breaks between its arguments rather than exceeding the line width.
json_build_object and jsonb_build_object are grouped in pairs by default,
without configuration. Configure a function explicitly to use a different group
size; a size of 1 opts out of the built-in default:
{
"format": {
"functionArgumentGroups": {
"jsonb_build_object": 1
}
}
}
Example Output
With default settings (lowercase):
create table users (
id serial primary key,
name text not null,
active boolean default true
);
select * from users where active = true;
With uppercase keywords and constants:
CREATE TABLE users (
id serial PRIMARY KEY,
name text NOT NULL,
active boolean DEFAULT TRUE
);
SELECT * FROM users WHERE active = TRUE;
CLI Usage
Format files using the CLI:
# Format and show diff
postgres-language-server format file.sql
# Format and write changes
postgres-language-server format file.sql --write
# Format entire directory
postgres-language-server format migrations/ --write
Editor Integration
The formatter integrates with your editor via the Language Server Protocol. Use your editor's format document command (typically bound to a keyboard shortcut) to format SQL files.
Ignoring Files
Use the ignore and include options to control which files are formatted:
{
"format": {
"ignore": ["**/generated/**", "**/vendor/**"],
"include": ["**/*.sql"]
}
}