Skip to content

Commit

Permalink
support sqlserver quoted identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
lu-zhengda committed Oct 10, 2023
1 parent 147954e commit 046f310
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
18 changes: 14 additions & 4 deletions sqllexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (s *Lexer) Scan() Token {
case isLetter(ch):
return s.scanIdentifier()
case isDoubleQuote(ch):
return s.scanDoubleQuotedIdentifier()
return s.scanDoubleQuotedIdentifier('"')
case isSingleQuote(ch):
return s.scanString()
case isSingleLineComment(ch, s.lookAhead(1)):
Expand Down Expand Up @@ -141,6 +141,9 @@ func (s *Lexer) Scan() Token {
case isOperator(ch):
return s.scanOperator()
case isPunctuation(ch):
if ch == '[' && s.config.DBMS == DBMSSQLServer {
return s.scanDoubleQuotedIdentifier('[')
}
return s.scanPunctuation()
case isEOF(ch):
return Token{EOF, ""}
Expand Down Expand Up @@ -296,15 +299,22 @@ func (s *Lexer) scanIdentifier() Token {
return Token{IDENT, s.src[s.start:s.cursor]}
}

func (s *Lexer) scanDoubleQuotedIdentifier() Token {
func (s *Lexer) scanDoubleQuotedIdentifier(delimiter rune) Token {
closingDelimiter := delimiter
if delimiter == '[' {
closingDelimiter = ']'
}

s.start = s.cursor
ch := s.next() // consume the opening quote
for {
// encountered the closing quote
// BUT if it's followed by .", then we should keep going
// e.g. postgre "foo"."bar"
if ch == '"' {
if s.matchAt([]rune(`"."`)) {
// e.g. sqlserver [foo].[bar]
if ch == closingDelimiter {
specialCase := []rune{closingDelimiter, '.', delimiter}
if s.matchAt([]rune(specialCase)) {
ch = s.nextBy(3) // consume the "."
continue
}
Expand Down
22 changes: 22 additions & 0 deletions sqllexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,28 @@ func TestLexer(t *testing.T) {
},
lexerOpts: []lexerOption{WithDBMS(DBMSSQLServer)},
},
{
name: "SQL Server quoted identifier",
input: "SELECT [user] FROM [test].[table] WHERE [id] = 1",
expected: []Token{
{IDENT, "SELECT"},
{WS, " "},
{IDENT, "[user]"},
{WS, " "},
{IDENT, "FROM"},
{WS, " "},
{IDENT, "[test].[table]"},
{WS, " "},
{IDENT, "WHERE"},
{WS, " "},
{IDENT, "[id]"},
{WS, " "},
{OPERATOR, "="},
{WS, " "},
{NUMBER, "1"},
},
lexerOpts: []lexerOption{WithDBMS(DBMSSQLServer)},
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 046f310

Please sign in to comment.