Skip to content

Commit e1e8621

Browse files
authored
Format inline CASE <expression> WHEN correctly (#86)
1 parent b8924af commit e1e8621

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

.github/workflows/sqlformat.yml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,28 @@ jobs:
2828
- conf: latest-nightly
2929
toolchain: nightly
3030
steps:
31-
- uses: actions/checkout@v2
31+
- uses: actions/checkout@v5
3232
- name: Install ${{ matrix.toolchain }}
33-
uses: actions-rs/toolchain@v1
33+
uses: dtolnay/rust-toolchain@stable
3434
with:
35-
profile: minimal
3635
toolchain: ${{ matrix.toolchain }}
37-
override: true
3836
components: clippy, rustfmt
3937
- name: Cache cargo registry
40-
uses: actions/cache@v1
38+
uses: actions/cache@v4
4139
with:
4240
path: ~/.cargo/registry/cache
4341
key: ${{ runner.os }}-${{ matrix.conf }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
4442
restore-keys: |
4543
${{ runner.os }}-${{ matrix.conf }}-cargo-registry-
4644
- name: Run rustfmt
4745
if: matrix.toolchain == 'stable'
48-
uses: actions-rs/cargo@v1
49-
with:
50-
command: fmt
51-
args: -- --check
46+
run: |
47+
cargo fmt --all -- --check
5248
- name: Run clippy
5349
if: matrix.toolchain == 'stable'
54-
uses: actions-rs/clippy-check@v1
50+
uses: actions-rs-plus/clippy-check@v2.3.0
5551
with:
56-
token: ${{ secrets.GITHUB_TOKEN }}
57-
args: -- -D warnings
52+
args: --all -- -D warnings
5853
# FIXME: criterion and its dependencies require a newer version than 1.65, but it is only used for benchmarks.
5954
# Is there a way to not have criterion built when we run tests?
6055
- name: Run cargo check

src/formatter.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ impl<'a> Formatter<'a> {
323323

324324
if !self.inline_block.is_active() {
325325
self.add_new_line(query);
326+
} else if token.value.to_lowercase() == "case" {
327+
query.push(' ');
326328
}
327329
}
328330

src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,33 @@ mod tests {
15991599
assert_eq!(format(input, &QueryParams::None, &options), expected);
16001600
}
16011601

1602+
#[test]
1603+
fn it_formats_case_when_inside_an_order_by() {
1604+
let input = "SELECT a, created_at FROM b ORDER BY (CASE $3 WHEN 'created_at_asc' THEN created_at END) ASC, (CASE $3 WHEN 'created_at_desc' THEN created_at END) DESC;";
1605+
let max_line = 120;
1606+
let options = FormatOptions {
1607+
max_inline_block: max_line,
1608+
max_inline_arguments: Some(max_line),
1609+
joins_as_top_level: true,
1610+
uppercase: Some(true),
1611+
ignore_case_convert: Some(vec!["status"]),
1612+
..Default::default()
1613+
};
1614+
1615+
let expected = indoc!(
1616+
"
1617+
SELECT
1618+
a, created_at
1619+
FROM
1620+
b
1621+
ORDER BY
1622+
(CASE $3 WHEN 'created_at_asc' THEN created_at END) ASC,
1623+
(CASE $3 WHEN 'created_at_desc' THEN created_at END) DESC;"
1624+
);
1625+
1626+
assert_eq!(format(input, &QueryParams::None, &options), expected);
1627+
}
1628+
16021629
#[test]
16031630
fn it_recognizes_lowercase_case_end() {
16041631
let input = "case when option = 'foo' then 1 else 2 end;";

src/tokenizer.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ fn get_join_token<'a>() -> impl Parser<&'a str, Token<'a>, ContextError> {
557557
alt((standard_joins, specific_joins, special_joins)).parse_next(&mut uc_input);
558558

559559
if let Ok(token) = result {
560-
let final_word = token.split(' ').last().unwrap();
560+
let final_word = token.split(' ').next_back().unwrap();
561561
let input_end_pos =
562562
input.to_ascii_uppercase().find(final_word).unwrap() + final_word.len();
563563
let token = input.next_slice(input_end_pos);
@@ -607,7 +607,7 @@ fn get_newline_reserved_token<'a>(
607607
let result: Result<&str> = alt((operators, alter_table_actions)).parse_next(&mut uc_input);
608608

609609
if let Ok(token) = result {
610-
let final_word = token.split(' ').last().unwrap();
610+
let final_word = token.split(' ').next_back().unwrap();
611611
let input_end_pos =
612612
input.to_ascii_uppercase().find(final_word).unwrap() + final_word.len();
613613
let token = input.next_slice(input_end_pos);
@@ -648,7 +648,7 @@ fn get_top_level_reserved_token_no_indent<'i>(input: &mut &'i str) -> Result<Tok
648648
))
649649
.parse_next(&mut uc_input);
650650
if let Ok(token) = result {
651-
let final_word = token.split(' ').last().unwrap();
651+
let final_word = token.split(' ').next_back().unwrap();
652652
let input_end_pos = input.to_ascii_uppercase().find(final_word).unwrap() + final_word.len();
653653
let token = input.next_slice(input_end_pos);
654654
Ok(Token {
@@ -1069,7 +1069,7 @@ fn get_plain_reserved_two_token<'i>(input: &mut &'i str) -> Result<Token<'i>> {
10691069
))
10701070
.parse_next(&mut uc_input);
10711071
if let Ok(token) = result {
1072-
let final_word = token.split(' ').last().unwrap();
1072+
let final_word = token.split(' ').next_back().unwrap();
10731073
let input_end_pos = input.to_ascii_uppercase().find(final_word).unwrap() + final_word.len();
10741074
let token = input.next_slice(input_end_pos);
10751075
Ok(Token {

0 commit comments

Comments
 (0)