Skip to content

Commit

Permalink
[parser] parser: support identifiers for window function (pingcap#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
alivxxx authored and xhebox committed Oct 8, 2021
1 parent be8dfaa commit e33bd48
Show file tree
Hide file tree
Showing 8 changed files with 5,587 additions and 5,418 deletions.
1 change: 1 addition & 0 deletions parser/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bin/
y.go
*.output
.idea/
2 changes: 1 addition & 1 deletion parser/consistent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *testConsistentSuite) TestKeywordConsistent(c *C) {
c.Assert(tokenMap[k], Equals, tokenMap[v])
}
keywordCount := len(reservedKeywords) + len(unreservedKeywords) + len(notKeywordTokens) + len(tidbKeywords)
c.Assert(len(tokenMap)-len(aliases), Equals, keywordCount)
c.Assert(len(tokenMap)-len(aliases), Equals, keywordCount-len(windowFuncTokenMap))

unreservedCollectionDef := extractKeywordsFromCollectionDef(content, "\nUnReservedKeyword:")
c.Assert(unreservedKeywords, DeepEquals, unreservedCollectionDef)
Expand Down
10 changes: 10 additions & 0 deletions parser/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ type Scanner struct {
specialComment specialCommentScanner

sqlMode mysql.SQLMode

// If the lexer should recognize keywords for window function.
// It may break the compatibility when support those keywords,
// because some application may already use them as identifiers.
supportWindowFunc bool
}

type specialCommentScanner interface {
Expand Down Expand Up @@ -190,6 +195,11 @@ func (s *Scanner) GetSQLMode() mysql.SQLMode {
return s.sqlMode
}

// EnableWindowFunc enables the scanner to recognize the keywords of window function.
func (s *Scanner) EnableWindowFunc() {
s.supportWindowFunc = true
}

// NewScanner returns a new scanner object.
func NewScanner(s string) *Scanner {
return &Scanner{r: reader{s: s}}
Expand Down
31 changes: 30 additions & 1 deletion parser/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"strings"

"github.com/pingcap/parser/charset"
"github.com/pingcap/tidb/util/hack"
)

func isLetter(ch rune) bool {
Expand Down Expand Up @@ -199,6 +200,7 @@ var tokenMap = map[string]int{
"COUNT": count,
"CREATE": create,
"CROSS": cross,
"CURRENT": current,
"CURRENT_DATE": currentDate,
"CURRENT_TIME": currentTime,
"CURRENT_TIMESTAMP": currentTs,
Expand Down Expand Up @@ -259,6 +261,7 @@ var tokenMap = map[string]int{
"FIXED": fixed,
"FLOAT": floatType,
"FLUSH": flush,
"FOLLOWING": following,
"FOR": forKwd,
"FORCE": force,
"FOREIGN": foreign,
Expand Down Expand Up @@ -312,6 +315,7 @@ var tokenMap = map[string]int{
"KEY_BLOCK_SIZE": keyBlockSize,
"KEYS": keys,
"KILL": kill,
"LAST": last,
"LEADING": leading,
"LEFT": left,
"LESS": less,
Expand Down Expand Up @@ -360,6 +364,7 @@ var tokenMap = map[string]int{
"NOT": not,
"NOW": now,
"NULL": null,
"NULLS": nulls,
"NUMERIC": numericType,
"NVARCHAR": nvarcharType,
"OFFSET": offset,
Expand All @@ -375,6 +380,7 @@ var tokenMap = map[string]int{
"PASSWORD": password,
"PLUGINS": plugins,
"POSITION": position,
"PRECEDING": preceding,
"PRECISION": precisionType,
"PREPARE": prepare,
"PRIMARY": primary,
Expand All @@ -401,6 +407,7 @@ var tokenMap = map[string]int{
"REPEAT": repeat,
"REPEATABLE": repeatable,
"REPLACE": replace,
"RESPECT": respect,
"REPLICATION": replication,
"RESTRICT": restrict,
"REVERSE": reverse,
Expand Down Expand Up @@ -487,6 +494,7 @@ var tokenMap = map[string]int{
"TRIM": trim,
"TRUE": trueKwd,
"TRUNCATE": truncate,
"UNBOUNDED": unbounded,
"UNCOMMITTED": uncommitted,
"UNDEFINED": undefined,
"UNION": union,
Expand Down Expand Up @@ -558,6 +566,24 @@ var btFuncTokenMap = map[string]int{
"VAR_SAMP": builtinVarSamp,
}

var windowFuncTokenMap = map[string]int{
"CUME_DIST": cumeDist,
"DENSE_RANK": denseRank,
"FIRST_VALUE": firstValue,
"GROUPS": groups,
"LAG": lag,
"LAST_VALUE": lastValue,
"LEAD": lead,
"NTH_VALUE": nthValue,
"NTILE": ntile,
"OVER": over,
"PERCENT_RANK": percentRank,
"RANK": rank,
"ROWS": rows,
"ROW_NUMBER": rowNumber,
"WINDOW": window,
}

// aliases are strings directly map to another string and use the same token.
var aliases = map[string]string{
"SCHEMA": "DATABASE",
Expand Down Expand Up @@ -601,7 +627,10 @@ func (s *Scanner) isTokenIdentifier(lit string, offset int) int {
return tok
}
}
tok := tokenMap[tokenStr]
tok, ok := tokenMap[hack.String(data)]
if !ok && s.supportWindowFunc {
tok = windowFuncTokenMap[hack.String(data)]
}
return tok
}

Expand Down
Loading

0 comments on commit e33bd48

Please sign in to comment.