From e3826592c0a067f5cae361c4e05198e34109ec96 Mon Sep 17 00:00:00 2001 From: Rene Saarsoo Date: Sun, 21 Jan 2024 13:48:45 +0200 Subject: [PATCH] Fix crash when .. syntax encountered in Transact-SQL Fixes #700 --- src/formatter/ExpressionFormatter.ts | 2 +- src/lexer/Tokenizer.ts | 2 +- src/lexer/token.ts | 2 +- src/parser/ast.ts | 1 + src/parser/grammar.ne | 1 + test/transactsql.test.ts | 9 +++++++++ test/unit/__snapshots__/Parser.test.ts.snap | 3 +++ 7 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/formatter/ExpressionFormatter.ts b/src/formatter/ExpressionFormatter.ts index fe1505c00..584416b4e 100644 --- a/src/formatter/ExpressionFormatter.ts +++ b/src/formatter/ExpressionFormatter.ts @@ -179,7 +179,7 @@ export default class ExpressionFormatter { private formatPropertyAccess(node: PropertyAccessNode) { this.formatNode(node.object); - this.layout.add(WS.NO_SPACE, '.'); + this.layout.add(WS.NO_SPACE, node.operator); this.formatNode(node.property); } diff --git a/src/lexer/Tokenizer.ts b/src/lexer/Tokenizer.ts index 27552ff6b..6edc64342 100644 --- a/src/lexer/Tokenizer.ts +++ b/src/lexer/Tokenizer.ts @@ -184,7 +184,7 @@ export default class Tokenizer { ]), }, { type: TokenType.ASTERISK, regex: /[*]/uy }, - { type: TokenType.DOT, regex: /[.]/uy }, + { type: TokenType.DOT, regex: /[.]+/uy }, ]); } diff --git a/src/lexer/token.ts b/src/lexer/token.ts index 152102073..ee627ef24 100644 --- a/src/lexer/token.ts +++ b/src/lexer/token.ts @@ -28,7 +28,7 @@ export enum TokenType { OPERATOR = 'OPERATOR', COMMA = 'COMMA', ASTERISK = 'ASTERISK', // * - DOT = 'DOT', // . + DOT = 'DOT', // . (or .. in Transact-SQL) OPEN_PAREN = 'OPEN_PAREN', CLOSE_PAREN = 'CLOSE_PAREN', LINE_COMMENT = 'LINE_COMMENT', diff --git a/src/parser/ast.ts b/src/parser/ast.ts index 0a944c0f8..ac7939c22 100644 --- a/src/parser/ast.ts +++ b/src/parser/ast.ts @@ -128,6 +128,7 @@ export interface LiteralNode extends BaseNode { export interface PropertyAccessNode extends BaseNode { type: NodeType.property_access; object: AstNode; + operator: string; property: IdentifierNode | ArraySubscriptNode | AllColumnsAsteriskNode; } diff --git a/src/parser/grammar.ne b/src/parser/grammar.ne index d2d50f6ab..f6b8f8688 100644 --- a/src/parser/grammar.ne +++ b/src/parser/grammar.ne @@ -265,6 +265,7 @@ property_access -> atomic_expression _ %DOT _ (identifier | array_subscript | al return { type: NodeType.property_access, object: addComments(object, { trailing: _1 }), + operator: dot.text, property: addComments(property, { leading: _2 }), }; } diff --git a/test/transactsql.test.ts b/test/transactsql.test.ts index 022514765..cb788d03b 100644 --- a/test/transactsql.test.ts +++ b/test/transactsql.test.ts @@ -101,6 +101,15 @@ describe('TransactSqlFormatter', () => { `); }); + it('formats .. shorthand for database.schema.table', () => { + expect(format('SELECT x FROM db..tbl')).toBe(dedent` + SELECT + x + FROM + db..tbl + `); + }); + it('formats ALTER TABLE ... ALTER COLUMN', () => { expect(format(`ALTER TABLE t ALTER COLUMN foo INT NOT NULL DEFAULT 5;`)).toBe(dedent` ALTER TABLE t diff --git a/test/unit/__snapshots__/Parser.test.ts.snap b/test/unit/__snapshots__/Parser.test.ts.snap index c863bc4bf..197bb318c 100644 --- a/test/unit/__snapshots__/Parser.test.ts.snap +++ b/test/unit/__snapshots__/Parser.test.ts.snap @@ -293,6 +293,7 @@ Array [ "text": "ident", "type": "identifier", }, + "operator": ".", "property": Object { "type": "all_columns_asterisk", }, @@ -642,6 +643,7 @@ Array [ "text": "foo", "type": "identifier", }, + "operator": ".", "property": Object { "quoted": false, "text": "bar", @@ -649,6 +651,7 @@ Array [ }, "type": "property_access", }, + "operator": ".", "property": Object { "quoted": false, "text": "baz",