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  }