sql-formatter-org / sql-formatter

A whitespace formatter for different query languages
https://sql-formatter-org.github.io/sql-formatter/
MIT License
2.37k stars 405 forks source link

[VSCODE] `SQL-Formatter-VSCode.expressionWidth` not respected #755

Closed mxr closed 4 months ago

mxr commented 4 months ago

Describe the bug

Hello, thanks for this tool. When I set SQL-Formatter-VSCode.expressionWidth the value is not respected and lines are broken prematurely

To Reproduce

  1. Go to VSCode settings
  2. Filter by @ext:renesaarsoo.sql-formatter-vsc
  3. Scroll down to "SQL-Formatter-VSCode: Expression Width"
  4. Set this to 120

Now create a file with the following contents

SELEC id, dt
FROM foo
QUALIFY ROW_NUMBER() over ( PARTITION BY id ORDER BY dt desc ) = 1
;

Change language mode to "Snowflake SQL" or "SQL"

Run the VSCode formatter with ⇧⌥F

Expected behavior

QUALIFY ROW_NUMBER() over ( PARTITION BY id ORDER BY dt desc ) = 1 should stay on one line as the expression between parentheses is < 120 characters. Instead, the expression gets split up over multiple lines

QUALIFY
    ROW_NUMBER() over (
        PARTITION BY
            id
        ORDER BY
            dt desc
    ) = 1
;

Screenshots

n/a

Usage

Snowflake SQL and SQL

1.91.0

My user settings are:

$ jq -S 'with_entries(select(.key | startswith("SQL-Formatter-VSCode")))' "$HOME/Library/Application Support/Code/User/settings.json"
{
  "SQL-Formatter-VSCode.dataTypeCase": "upper",
  "SQL-Formatter-VSCode.dialect": "snowflake",
  "SQL-Formatter-VSCode.expressionWidth": 120,
  "SQL-Formatter-VSCode.functionCase": "upper",
  "SQL-Formatter-VSCode.identifierCase": "lower",
  "SQL-Formatter-VSCode.keywordCase": "upper",
  "SQL-Formatter-VSCode.newlineBeforeSemicolon": true
}

Additional context Another example

SELECT CASE WHEN (id = 1 or id = 2 or id = 3) THEN 'A' END AS id, dt
FROM foo
;

Gets broken up into

SELECT
    CASE
        WHEN (
            id = 1
            OR id = 2
            OR id = 3
        ) THEN 'A'
    END AS id,
    dt
FROM
    foo
;
nene commented 4 months ago

Thanks for reporting. However, this feature works as designed. Although it's not designed particularly well.

The expressionWidth is only applied when there are no other rules that trigger newlines inside the parenthesis. In the first example PARTITION BY and ORDER BY get always formatted on separate lines, no matter the context where they are.

Similarly in the second example the OR is always put to separate line. I admit that this is unfortunate, but it's a result of the formatter not understanding any context - that is, the main goal of that is to separate the conditions inside FROM and WHERE clauses, but the formatter has no idea whether it's formatting text inside WHERE clause or somewhere else.

This is unlikely to change as it would require a major architectual change and I've opted to instead write another formatting tool rather than attempt to fix this one.

I'm also closing this issue as this isn't really a problem in the VSCode extension itself, but in the underlying SQL formatter library.

mxr commented 4 months ago

Got it. Thanks for the clear response and next steps!