github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/parsers/dialect/mysql/mysql_lexer.go (about) 1 // Copyright 2021 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mysql 16 17 import ( 18 "context" 19 "fmt" 20 "math" 21 "strconv" 22 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 25 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 26 ) 27 28 func Parse(ctx context.Context, sql string, lower int64, useOrigin int64) ([]tree.Statement, error) { 29 lexer := NewLexer(dialect.MYSQL, sql, lower, useOrigin) 30 defer PutScanner(lexer.scanner) 31 if yyParse(lexer) != 0 { 32 for _, s := range lexer.stmts { 33 s.Free() 34 } 35 return nil, lexer.scanner.LastError 36 } 37 if len(lexer.stmts) == 0 { 38 /** 39 For CORNER CASE like: 40 41 mysql> -- MySQL dump 10.13 Distrib 8.1.0, for macos11.7 (arm64) 42 43 the input will be stripped to empty string, and the parser will return 0 stmts. 44 but, the mysql server responds ok to the client. 45 so, we return an EmptyStmt that does nothing beside responding ok. 46 */ 47 return []tree.Statement{&tree.EmptyStmt{}}, nil 48 } 49 return lexer.stmts, nil 50 } 51 52 func ParseOne(ctx context.Context, sql string, lower int64, useOrigin int64) (tree.Statement, error) { 53 lexer := NewLexer(dialect.MYSQL, sql, lower, useOrigin) 54 defer PutScanner(lexer.scanner) 55 if yyParse(lexer) != 0 { 56 for _, s := range lexer.stmts { 57 s.Free() 58 } 59 return nil, lexer.scanner.LastError 60 } 61 if len(lexer.stmts) != 1 { 62 return nil, moerr.NewParseError(ctx, "syntax error, or too many sql to parse") 63 } 64 return lexer.stmts[0], nil 65 } 66 67 type Lexer struct { 68 scanner *Scanner 69 stmts []tree.Statement 70 paramIndex int 71 lower int64 72 useOrigin int64 73 } 74 75 func NewLexer(dialectType dialect.DialectType, sql string, lower int64, useOrigin int64) *Lexer { 76 return &Lexer{ 77 scanner: NewScanner(dialectType, sql), 78 paramIndex: 0, 79 lower: lower, 80 useOrigin: useOrigin, 81 } 82 } 83 84 func (l *Lexer) GetParamIndex() int { 85 l.paramIndex = l.paramIndex + 1 86 return l.paramIndex 87 } 88 89 func (l *Lexer) Lex(lval *yySymType) int { 90 typ, str := l.scanner.Scan() 91 l.scanner.LastToken = str 92 93 switch typ { 94 case INTEGRAL: 95 return l.toInt(lval, str) 96 case FLOAT: 97 return l.toFloat(lval, str) 98 } 99 100 lval.str = str 101 return typ 102 } 103 104 func (l *Lexer) Error(err string) { 105 errMsg := fmt.Sprintf("You have an error in your SQL syntax; check the manual that corresponds to your MatrixOne server version for the right syntax to use. %s", err) 106 near := l.scanner.buf[l.scanner.PrePos:] 107 var lenStr string 108 if len(near) > 1024 { 109 lenStr = " (total length " + strconv.Itoa(len(lenStr)) + ")" 110 near = near[:1024] 111 } 112 l.scanner.LastError = PositionedErr{Err: errMsg, Line: l.scanner.Line, Col: l.scanner.Col, Near: near, LenStr: lenStr} 113 } 114 115 func (l *Lexer) AppendStmt(stmt tree.Statement) { 116 l.stmts = append(l.stmts, stmt) 117 } 118 119 func (l *Lexer) toInt(lval *yySymType, str string) int { 120 ival, err := strconv.ParseUint(str, 10, 64) 121 if err != nil { 122 // TODO: toDecimal() 123 // l.scanner.LastError = err 124 lval.str = str 125 return DECIMAL_VALUE 126 } 127 switch { 128 case ival <= math.MaxInt64: 129 lval.item = int64(ival) 130 default: 131 lval.item = ival 132 } 133 lval.str = str 134 return INTEGRAL 135 } 136 137 func (l *Lexer) toFloat(lval *yySymType, str string) int { 138 fval, err := strconv.ParseFloat(str, 64) 139 if err != nil { 140 l.scanner.LastError = err 141 return LEX_ERROR 142 } 143 lval.item = fval 144 return FLOAT 145 }