github.com/pingcap/tidb/parser@v0.0.0-20231013125129-93a834a6bf8d/reserved_words_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //go:build reserved_words_test 15 // +build reserved_words_test 16 17 // This file ensures that the set of reserved keywords is the same as that of 18 // MySQL. To run: 19 // 20 // 1. Set up a MySQL server listening at 127.0.0.1:3306 using root and no password 21 // 2. Run this test with: 22 // 23 // go test -tags reserved_words_test -run '^TestCompareReservedWordsWithMySQL$' 24 25 package parser 26 27 import ( 28 // needed to connect to MySQL 29 30 dbsql "database/sql" 31 gio "io" 32 "os" 33 "testing" 34 35 _ "github.com/go-sql-driver/mysql" 36 "github.com/pingcap/tidb/parser/ast" 37 requires "github.com/stretchr/testify/require" 38 ) 39 40 func TestCompareReservedWordsWithMySQL(t *testing.T) { 41 parserFilename := "parser.y" 42 parserFile, err := os.Open(parserFilename) 43 requires.NoError(t, err) 44 data, err := gio.ReadAll(parserFile) 45 requires.NoError(t, err) 46 content := string(data) 47 48 reservedKeywordStartMarker := "\t/* The following tokens belong to ReservedKeyword. Notice: make sure these tokens are contained in ReservedKeyword. */" 49 unreservedKeywordStartMarker := "\t/* The following tokens belong to UnReservedKeyword. Notice: make sure these tokens are contained in UnReservedKeyword. */" 50 notKeywordTokenStartMarker := "\t/* The following tokens belong to NotKeywordToken. Notice: make sure these tokens are contained in NotKeywordToken. */" 51 tidbKeywordStartMarker := "\t/* The following tokens belong to TiDBKeyword. Notice: make sure these tokens are contained in TiDBKeyword. */" 52 identTokenEndMarker := "%token\t<item>" 53 54 reservedKeywords := extractKeywords(content, reservedKeywordStartMarker, unreservedKeywordStartMarker) 55 unreservedKeywords := extractKeywords(content, unreservedKeywordStartMarker, notKeywordTokenStartMarker) 56 notKeywordTokens := extractKeywords(content, notKeywordTokenStartMarker, tidbKeywordStartMarker) 57 tidbKeywords := extractKeywords(content, tidbKeywordStartMarker, identTokenEndMarker) 58 59 p := New() 60 db, err := dbsql.Open("mysql", "root@tcp(127.0.0.1:3306)/") 61 requires.NoError(t, err) 62 defer func() { 63 requires.NoError(t, db.Close()) 64 }() 65 66 for _, kw := range reservedKeywords { 67 switch kw { 68 case "CURRENT_ROLE", "INTERSECT", "STATS_EXTENDED", "TABLESAMPLE": 69 // special case: we do reserve these words but MySQL didn't, 70 // and unreservering it causes legit parser conflict. 71 continue 72 } 73 74 query := "do (select 1 as " + kw + ")" 75 errRegexp := ".*" + kw + ".*" 76 77 var err error 78 79 if _, ok := windowFuncTokenMap[kw]; !ok { 80 // for some reason the query does parse even then the keyword is reserved in TiDB. 81 _, _, err = p.Parse(query, "", "") 82 requires.Error(t, err) 83 requires.Regexp(t, errRegexp, err.Error()) 84 } 85 _, err = db.Exec(query) 86 requires.Error(t, err) 87 requires.Regexp(t, errRegexp, err.Error(), "MySQL suggests that '%s' should *not* be reserved!", kw) 88 } 89 90 for _, kws := range [][]string{unreservedKeywords, notKeywordTokens, tidbKeywords} { 91 for _, kw := range kws { 92 switch kw { 93 case "FUNCTION", // reserved in 8.0.1 94 "PURGE", "SYSTEM", "SEPARATOR": // ? 95 continue 96 } 97 98 query := "do (select 1 as " + kw + ")" 99 100 stmts, _, err := p.Parse(query, "", "") 101 requires.NoError(t, err) 102 requires.Len(t, stmts, 1) 103 requires.IsType(t, &ast.DoStmt{}, stmts[0]) 104 105 _, err = db.Exec(query) 106 println(query) 107 requires.NoErrorf(t, err, "MySQL suggests that '%s' should be reserved!", kw) 108 } 109 } 110 }