Skip to content

SQL

Files ending in .sql are formatted by the SQL pack (rainbow_fmt.languages.sql, grammar tree-sitter-sql, which reads the common dialects).

select a.id, b.name as n, count(*) from users a join orders b on a.id = b.user_id where a.active = 1 and b.total > 10 group by a.id, b.name having count(*) > 1 order by n desc limit 10;

becomes

select a.id, b.name as n, count(*)
from users a
join orders b on a.id = b.user_id
where a.active = 1 and b.total > 10
group by a.id, b.name
having count(*) > 1
order by n desc
limit 10;

or, with clause_alignment = "right",

select a.id, b.name as n, count(*)
  from users a
  join orders b
    on a.id = b.user_id
 where a.active = 1 and b.total > 10
group by a.id, b.name
  having count(*) > 1
order by n desc
limit 10;

What changes and what does not

  • One clause per line: WITH (its common table expressions one per line when too long), SELECT, FROM, each JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, RETURNING, set operations. A clause that is only keywords shares its line with the next (DELETE FROM t).
  • The items of a clause stay on the keyword's line when they fit; otherwise they go one per line, indented by core.indent_size. A condition that does not fit breaks before each AND/OR.
  • With clause_alignment = "right", the keywords of SELECT, FROM, JOIN, ON and WHERE are right-aligned to the widest of them (a LEFT JOIN widens the column for the whole statement), GROUP BY and HAVING likewise, and ON takes a line of its own; every other clause (WITH, ORDER BY, LIMIT, UNION …) starts at the margin. Items that do not fit hang under the first one instead of moving to the next line, so a long WHERE reads and under and. A subquery still stays on one line.
  • Parenthesized lists (INSERT … (a, b) VALUES (1, 2), column definitions) break one item per line when too long. A call or a type size hugs its parenthesis (count(*), varchar(10)); IN (…) and VALUES (…) keep a space.
  • Subqueries stay on one line inside their parentheses.
  • Keywords are written in the case keyword_case asks for; identifiers, strings, numbers and operators are as written, and so is anything the grammar reads as one token (interval '7 days').
  • Statements are separated as written; blank lines between them are kept, at most core.max_blank_lines. Comments (-- and /* */) stay where they are.

Inline directives (-- rainbow: off … -- rainbow: on, -- rainbow: skip-next) keep statements as written (configuration.md).

Options

Key Values Default
language.sql.keyword_case "preserve", "upper", "lower" "preserve"
language.sql.clause_alignment "left", "right" (SELECT … WHERE end in one column, GROUP BY and HAVING in another) "left"