diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fe7c27..a3dc4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Formatting Changes and Bug Fixes + +- sqlfmt no longer adds a space between the function name and parens for `filter()` and `isnull()` (but it also permits `filter ()` and `isnull ()` to support dialects where those are operators, not function names) ([#641](https://github.com/tconbeer/sqlfmt/issues/641) - thank you [@williamscs](https://github.com/williamscs) and [@hongtron](https://github.com/hongtron)!). +- sqlfmt now supports Spark type-hinted numeric literals like `32y` and `+3.2e6bd` and will not introduce a space between the digits and their type suffix ([#640](https://github.com/tconbeer/sqlfmt/issues/640) - thank you [@ShaneMazur](https://github.com/ShaneMazur)!). + ## [0.23.3] - 2024-11-12 ### Bug Fixes diff --git a/src/sqlfmt/rules/core.py b/src/sqlfmt/rules/core.py index 92ddb9d..9e7f6ac 100644 --- a/src/sqlfmt/rules/core.py +++ b/src/sqlfmt/rules/core.py @@ -65,11 +65,22 @@ action=actions.raise_sqlfmt_bracket_error, ), Rule( + # see https://spark.apache.org/docs/latest/sql-ref-literals.html#integral-literal-syntax + name="spark_int_literals", + priority=349, + pattern=group( + r"(\+|-)?\d+(l|s|y)", + ), + action=actions.handle_number, + ), + Rule( + # the (bd|d|f) groups add support for Spark fractional literals + # https://spark.apache.org/docs/latest/sql-ref-literals.html#fractional-literals-syntax name="number", priority=350, pattern=group( - r"(\+|-)?\d+(\.\d*)?(e(\+|-)?\d+)?", - r"(\+|-)?\.\d+(e(\+|-)?\d+)?", + r"(\+|-)?\d+(\.\d*)?(e(\+|-)?\d+)?(bd|d|f)?", + r"(\+|-)?\.\d+(e(\+|-)?\d+)?(bd|d|f)?", ), action=actions.handle_number, ), diff --git a/tests/data/unformatted/132_spark_number_literals.sql b/tests/data/unformatted/132_spark_number_literals.sql new file mode 100644 index 0000000..cf1e457 --- /dev/null +++ b/tests/data/unformatted/132_spark_number_literals.sql @@ -0,0 +1,54 @@ +-- source: https://spark.apache.org/docs/latest/sql-ref-literals.html#integral-literal-syntax +-- see: https://github.com/tconbeer/sqlfmt/issues/640 +SELECT -2147483648 AS col; +SELECT 9223372036854775807l AS col; +SELECT -32Y AS col; +SELECT 482S AS col; +SELECT 12.578 AS col; +SELECT -0.1234567 AS col; +SELECT -.1234567 AS col; +SELECT 123. AS col; +SELECT 123.BD AS col; +SELECT 5E2 AS col; +SELECT 5D AS col; +SELECT -5BD AS col; +SELECT 12.578e-2d AS col; +SELECT -.1234567E+2BD AS col; +SELECT +3.e+3 AS col; +SELECT -3.E-3D AS col; +)))))__SQLFMT_OUTPUT__((((( +-- source: +-- https://spark.apache.org/docs/latest/sql-ref-literals.html#integral-literal-syntax +-- see: https://github.com/tconbeer/sqlfmt/issues/640 +select -2147483648 as col +; +select 9223372036854775807l as col +; +select -32Y as col +; +select 482S as col +; +select 12.578 as col +; +select -0.1234567 as col +; +select -.1234567 as col +; +select 123. as col +; +select 123.BD as col +; +select 5E2 as col +; +select 5D as col +; +select -5BD as col +; +select 12.578e-2d as col +; +select -.1234567E+2BD as col +; +select +3.e+3 as col +; +select -3.E-3D as col +; diff --git a/tests/functional_tests/test_general_formatting.py b/tests/functional_tests/test_general_formatting.py index afabdda..85138c2 100644 --- a/tests/functional_tests/test_general_formatting.py +++ b/tests/functional_tests/test_general_formatting.py @@ -51,6 +51,7 @@ "unformatted/129_duckdb_joins.sql", "unformatted/130_athena_data_types.sql", "unformatted/131_assignment_statement.sql", + "unformatted/132_spark_number_literals.sql", "unformatted/133_for_else.sql", "unformatted/200_base_model.sql", "unformatted/201_basic_snapshot.sql", diff --git a/tests/unit_tests/test_rule.py b/tests/unit_tests/test_rule.py index 3af0ae3..d69cd04 100644 --- a/tests/unit_tests/test_rule.py +++ b/tests/unit_tests/test_rule.py @@ -57,6 +57,9 @@ def get_rule(ruleset: List[Rule], rule_name: str) -> Rule: (MAIN, "statement_start", "case"), (MAIN, "statement_end", "END"), (CORE, "star", "*"), + (CORE, "spark_int_literals", "145y"), + (CORE, "spark_int_literals", "-145s"), + (CORE, "spark_int_literals", "5l"), (CORE, "number", "145.8"), (CORE, "number", "-.58"), (CORE, "number", "+145.8"), @@ -64,6 +67,13 @@ def get_rule(ruleset: List[Rule], rule_name: str) -> Rule: (CORE, "number", "1e9"), (CORE, "number", "1e-9"), (CORE, "number", "1.55e-9"), + (CORE, "number", "145.8bd"), + (CORE, "number", "-.58d"), + (CORE, "number", "+145.8f"), + (CORE, "number", "+.58bd"), + (CORE, "number", "1e9d"), + (CORE, "number", "1e-9f"), + (CORE, "number", "1.55e-9bd"), (CORE, "bracket_open", "["), (CORE, "bracket_close", ")"), (CORE, "double_colon", "::"),