[WIP] Add preliminary Clickhouse formatter by mattbasta · Pull Request #922 · sql-formatter-org/sql-formatter
Hey @nene, I've been making a lot of progress getting things in order. The code is in a much better place, but I wanted to pause before continuing to ask for your opinion, because I don't know that there's an obvious right answer to what I'm running into. There's two components to this, which are intertwined.
The first part is that Clickhouse lets you drop/alter multiple resources at once. For instance:
would be valid according to https://clickhouse.com/docs/sql-reference/statements/drop#drop-table
However, with DROP TABLE appearing as a tabular one-line clause, this would be formatted as
which doesn't seem correct. It would seem to me that the more appropriate choice would be to make DROP TABLE a reserved clause, which would format it like this instead:
This makes it consistent with similar syntax, like with ORDER BY. In the simplest case where these are just table identifiers, this doesn't feel great, especially when a simple DROP TABLE statement ends up looking like
To my knowledge, there's no way to make a clause conditionally tabular, unless I'm missing something. On one hand, this could be made consistent with the other dialects and the feature tests would pass, but the multi-resource case would be pretty unfortunate. On the other hand, I could break convention with the other formatters and use a reserved clause here, and have a slightly less pleasant single-resource case that looks solid with multiple resources.
As a note, SELECT without a WHERE/FROM/etc. looks like the second case:
So this isn't completely unprecedented cosmetically.
My personal preference is the second option, but I can also appreciate that you'd want the different formatters to behave consistently.
The second piece is essentially the same issue. Consider this statement:
ALTER ROW POLICY IF EXISTS policy1 ON CLUSTER cluster_name1 ON database1.table1 RENAME TO new_name1, policy2 ON CLUSTER cluster_name2 ON database2.table2 RENAME TO new_name2;
RENAME TO behaves sort of like an infix operator here, and I think that this statement looks great when it's considered a keyword phrase, with ALTER ROW POLICY treated as a reserved clause:
ALTER ROW POLICY IF EXISTS
policy1 ON CLUSTER cluster_name1 ON database1.table1 RENAME TO new_name1,
policy2 ON CLUSTER cluster_name2 ON database2.table2 RENAME TO new_name2;
However, this disagrees with the existing built-in feature tests, which would format
ALTER TABLE supplier RENAME TO the_one_who_supplies
as
ALTER TABLE supplier
RENAME TO the_one_who_supplies
where RENAME TO is considered a tabular one-line clause. With my choice to make this a keyword phrase, this feature test would be formatted as a single line (essentially unchanged from the input).
Similar to the first item I noted above, I could break convention with the existing tests and follow the rules that I believe make Clickhouse format in a way that I believe looks the best and with internal consistency (making multi-resource statements into reserved clauses and having RENAME TO as a keyword phrase). I could also choose to make it consistent with other formatters at the expense of having certain statements produce confusing/ugly results (using tabular one-line clauses for all statements and RENAME TO).
One other option (which addresses the tabular one-line clause vs reserved clause discrepancy, but not the RENAME TO discrepancy) is for me to implement the ability to have a conditionally tabular one-line clause. For a conditionally tabular clause, it would format as a tabular one-line clause if an EOF/semicolon or another clause was encountered first, or as a reserved clause if another clause was encountered first. E.g., making DROP TABLE a conditionally tabular clause would format
-- DROP TABLE foo
DROP TABLE foo -- EOF triggers tabular behavior
-- DROP TABLE foo, bar
DROP TABLE
foo, -- comma triggers reserved clause behavior
bar
I haven't done a lot of research to understand how big of an undertaking this would be, and as far as I can tell, this isn't something that exists already (but if it does and I've missed it, please let me know!)
I'd love your thoughts on this.