Skip to content

IdentifierBracketing.IncludeBrackets brackets aggregate function name in PIVOT (SUM becomes [SUM]), producing invalid T-SQL #239

Open

Description

@PiemanJ

Summary

With IdentifierBracketing.IncludeBrackets, the script generator wraps the aggregate function name inside a PIVOT clause in square brackets. The output is invalid T-SQL and fails to parse.

This shows up in SSMS 22.7+ (built-in SQL formatter with identifier_bracketing = IncludeBrackets), because the formatter is built on ScriptDOM.

Repro

Input:

SELECT [p].[2024], [p].[2025]
FROM [#chk] PIVOT (SUM([volume]) FOR [year] IN ([2024], [2025])) AS [p];

Format with IdentifierBracketing = IncludeBrackets (SSMS: Tools > Options > SQL Formatter, or identifier_bracketing = IncludeBrackets in .editorconfig).

Actual output:

... PIVOT ([SUM] ([volume]) FOR [year] IN ([2024], [2025])) AS [p];

Executing the result fails with:

Msg 102, Level 15, State 1
Incorrect syntax near '('.

Expected output: SUM stays unbracketed:

... PIVOT (SUM([volume]) FOR [year] IN ([2024], [2025])) AS [p];

Likely cause

PivotedTableReference.AggregateFunctionIdentifier is a MultiPartIdentifier, and SqlScriptGeneratorVisitor.PivotedTableReference.cs emits it with GenerateFragmentIfNotNull(node.AggregateFunctionIdentifier). That sends it through the normal identifier path in SqlScriptGeneratorVisitor.Identifier.cs, so IncludeBrackets applies to it like a column or table name.

The aggregate name should probably be exempt from bracketing. built_in_function_casing should apply to it instead of identifier_casing, so that with identifier_casing = Lowercase we don't get [sum].

Workaround

Use IdentifierBracketing.Preserve, or rewrite the PIVOT as conditional aggregation (SUM(CASE WHEN [year] = 2024 THEN [volume] END) AS [2024]).

Environment

  • SSMS 22.7+ built-in SQL formatter (ScriptDOM-based)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions