Add a Multiline option for CASE expressions (WHEN/THEN/ELSE on their own lines)
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 56/100
Research direction
Start by reading SqlScriptGeneratorOptions and the Sql170ScriptGenerator behavior for the existing Multiline* options, then compare how CASE expressions are emitted. Trace the relevant generator tests if present and verify that the default preserves inline output while MultilineCaseExpression places WHEN and ELSE branches on separate indented lines.
Written by the indexing model from the issue text.
Description
Is your feature request related to a problem? Please describe
When Sql170ScriptGenerator regenerates a script, a CASE expression is always emitted inline — every
WHEN/THEN/ELSE is joined onto one logical line. For multi-branch CASE expressions this makes the
output substantially harder to read than the input, and where a WHEN predicate has multiple conjuncts
the hanging indent compounds: each AND is indented to the width of the preceding WHEN, and the next
WHEN is then appended after that indented continuation, producing a staircase.
Input (longest line 81 chars):
SELECT CASE
WHEN o.status = 'P' AND o.paid_amount >= o.total_amount THEN 'settled'
WHEN o.status = 'P' AND o.paid_amount > 0 THEN 'part-paid'
WHEN o.status = 'C' THEN 'cancelled'
ELSE 'open'
END AS settlement_state,
CASE WHEN o.due_date < SYSUTCDATETIME() THEN 1 ELSE 0 END AS is_overdue
FROM orders AS o
WHERE o.tenant_id = 42;
Output with MultilineSelectElementsList = true, IndentationSize = 4 (longest line 185 chars):
SELECT CASE WHEN o.status = 'P'
AND o.paid_amount >= o.total_amount THEN 'settled' WHEN o.status = 'P'
AND o.paid_amount > 0 THEN 'part-paid' WHEN o.status = 'C' THEN 'cancelled' ELSE 'open' END AS settlement_state,
CASE WHEN o.due_date < SYSUTCDATETIME() THEN 1 ELSE 0 END AS is_overdue
FROM orders AS o
WHERE o.tenant_id = 42;
An 81-character input becomes a 185-character line. There is currently no option that affects this:
of the 46 properties on SqlScriptGeneratorOptions, none matches Case or When, and none provides a
maximum line width. AlignClauseBodies, ClauseBodyAlignment and the Multiline* options do not reach
inside a CASE.
Describe the solution you'd like
A MultilineCaseExpression option (default false, preserving current output) that places each WHEN
branch and the ELSE on its own line, indented one level from the CASE:
SELECT CASE
WHEN o.status = 'P' AND o.paid_amount >= o.total_amount THEN 'settled'
WHEN o.status = 'P' AND o.paid_amount > 0 THEN 'part-paid'
WHEN o.status = 'C' THEN 'cancelled'
ELSE 'open'
END AS settlement_state,
This fits the existing naming and behaviour of the Multiline* family —
MultilineSelectElementsList, MultilineWherePredicatesList, MultilineInValuesList,
MultilineViewColumnsList, MultilineSetClauseItems, MultilineInsertTargetsList,
MultilineInsertSourcesList, MultilineProcedureParametersList — so it should need no new concepts.
A single-branch CASE staying inline when the option is off (as
CASE WHEN … THEN 1 ELSE 0 END above) seems the right default; whether a one-branch CASE should also
break under the option is a judgement call I have no strong view on.
Describe alternatives you've considered
- Existing options —
AlignClauseBodies,ClauseBodyAlignment = Indented,
MultilineSelectElementsList, and reducedIndentationSize. None affects the interior of aCASE;
the best combination I found did not shorten these lines. - A general maximum-line-width option. More broadly useful, but a much larger change and a different
model from the current per-construct toggles, so I have not requested it here. - Post-processing the generated text. Re-wrapping
CASEwith a regex outside the generator defeats
the point of using an AST-based formatter and is not reliable in the presence of string literals.
Additional context
Microsoft.SqlServer.TransactSql.ScriptDom180.78.1 (assembly 18.0.0.0),net8.0; behaviour is the
same onSql160ScriptGenerator,Sql170ScriptGeneratorandSql180ScriptGenerator.- Related open requests of the same shape, both asking for a construct to be broken across lines:
#189 (INSERT columns) and #21 (stored-procedure parameters). - Happy to test a change against a large real-world T-SQL corpus if that is useful.
- Dominant language
- GAP
- Stars
- 277
- Forks
- 43
- Avg merge
- 6d 17h
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/SqlScriptDOM
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
microsoft/SqlScriptDOM#228 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
microsoft/SqlScriptDOM#183 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
microsoft/SqlScriptDOM#225 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 58/100
microsoft/SqlScriptDOM#224 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
microsoft/SqlScriptDOM#222 ·
All issues in microsoft/SqlScriptDOM
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
use-agent-os/agent-os#3314 ·
-
agentic-workflows
Difficulty 1/5 Under an hour Newbie friendliness 85/100
githubnext/rig#534 ·
-
documentation low-priority templates
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
jesseray718/openroot#87 ·
-
factory-active factory-automatic task-bug-reproduction-cannot-reproduce task-identify-harness-labels-done task-identify-issue-type-done
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
ReedClanton/NixOS#41 ·