Skip to main content

Clarify precedence

clarifyPrecedence adds parentheses around each and group inside an or, so that SQL's precedence is visible instead of remembered. a or b and c means a or (b and c); with the option on, that is how it is written.

Default: false. It is the one option that adds tokens you did not write, and a formatter that changes the text rather than the whitespace has to be asked. It is also switched off, whatever it is set to, for a file whose parse had to recover from an error: a paren placed from a guessed tree lands wherever the guess said.

Turn it on for a project whose where clauses mix and and or and are read by people who should not have to re-derive the precedence each time. A chain of only and, or only or, gets no parentheses; there is nothing to clarify.

A long WHERE, off and on​

select * from orders where status = 'shipped' and shipped_at > now() or status = 'pending' and created_at > now() and priority = 'high'
select *
from orders
where
    status = 'shipped' and shipped_at > now()
    or status = 'pending' and created_at > now() and priority = 'high'
select * from orders where status = 'shipped' and shipped_at > now() or status = 'pending' and created_at > now() and priority = 'high'
select *
from orders
where
    (status = 'shipped' and shipped_at > now())
    or (status = 'pending' and created_at > now() and priority = 'high')

Set operations keep the shape you wrote​

The option parenthesises and groups and nothing else. The operands of union, intersect and except are not wrapped, because a paren around one changes what the query returns. In this DuckDB query the order by 1 limit 2 applies to the whole union and the result is 1, 2; around the last operand alone the same clause sorts and cuts that operand, and the union returns 3, 1, 2, 4. SQL Server refuses an order by inside a parenthesised operand outright.

The first operand's where mixes and with or, so the option has something to do here. It does it inside the operand and leaves the operands themselves alone.

select a from (values (3), (1)) t1(a) where a = 3 or a = 1 and a > 0
union all
select b from (values (2), (4)) t2(b)
order by 1 limit 2
select a
from (values (3), (1)) t1(a)
where a = 3 or a = 1 and a > 0
union all
select b
from (values (2), (4)) t2(b)
order by 1
limit 2
select a from (values (3), (1)) t1(a) where a = 3 or a = 1 and a > 0
union all
select b from (values (2), (4)) t2(b)
order by 1 limit 2
select a
from (values (3), (1)) t1(a)
where a = 3 or (a = 1 and a > 0)
union all
select b
from (values (2), (4)) t2(b)
order by 1
limit 2