fix: keep spaces around - operator in dialects with dashed identifiers by sarathfrancis90 · Pull Request #953 · sql-formatter-org/sql-formatter · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/dialect.ts
11 changes: 10 additions & 1 deletion src/formatter/ExpressionFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export interface ProcessedDialectFormatOptions {
alwaysDenseOperators: string[];
onelineClauses: Record<string, boolean>;
tabularOnelineClauses: Record<string, boolean>;
// True when the dialect allows dashes inside identifiers (e.g. BigQuery).
// In such dialects the "-" operator must keep its surrounding spaces,
// otherwise "a - b" densed to "a-b" would re-parse as a single identifier.
identifierDashes: boolean;
}

/** Formats a generic SQL expression */
Expand Down Expand Up @@ -330,7 +334,12 @@ export default class ExpressionFormatter {
}

private formatOperator({ text }: OperatorNode) {
if (this.cfg.denseOperators || this.dialectCfg.alwaysDenseOperators.includes(text)) {
// In dialects that allow dashes inside identifiers (e.g. BigQuery) the "-"
// operator must keep its surrounding spaces. Densing "a - b" into "a-b"
// would otherwise re-parse as a single dashed identifier.
if (text === '-' && this.dialectCfg.identifierDashes) {
this.layout.add(text, WS.SPACE);
} else if (this.cfg.denseOperators || this.dialectCfg.alwaysDenseOperators.includes(text)) {
this.layout.add(WS.NO_SPACE, text);
} else if (text === ':') {
this.layout.add(WS.NO_SPACE, text, WS.SPACE);
Expand Down
18 changes: 17 additions & 1 deletion test/bigquery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ describe('BigQueryFormatter', () => {
'EXCEPT DISTINCT',
'INTERSECT DISTINCT',
]);
supportsOperators(format, ['&', '|', '^', '~', '>>', '<<', '||', '=>'], { any: true });
supportsOperators(format, ['&', '|', '^', '~', '>>', '<<', '||', '=>'], {
any: true,
identifierDashes: true,
});
supportsIsDistinctFrom(format);
supportsParams(format, { positional: true, named: ['@'], quoted: ['@``'] });
supportsWindow(format);
Expand All @@ -80,6 +83,19 @@ describe('BigQueryFormatter', () => {
`);
});

// Because dashes are allowed inside identifiers, densing the "-" operator
// would glue its operands into a single identifier ("a - b" -> "a-b"),
// changing the meaning of the query. So denseOperators must keep it spaced.
it('keeps spaces around the - operator in dense mode', () => {
expect(format('SELECT a - b, x - foo(y)\nFROM t', { denseOperators: true })).toBe(dedent`
SELECT
a - b,
x - foo (y)
FROM
t
`);
});

it('supports @@variables', () => {
expect(format('SELECT @@error.message, @@time_zone')).toBe(dedent`
SELECT
Expand Down
11 changes: 10 additions & 1 deletion test/features/operators.ts
Loading