github.com/XiaoMi/Gaea@v1.2.5/parser/analyzer.go (about)

     1  // Copyright 2012, Google Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Copyright 2016 The kingshard Authors. All rights reserved.
     6  //
     7  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     8  // not use this file except in compliance with the License. You may obtain
     9  // a copy of the License at
    10  //
    11  //     http://www.apache.org/licenses/LICENSE-2.0
    12  //
    13  // Unless required by applicable law or agreed to in writing, software
    14  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    15  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    16  // License for the specific language governing permissions and limitations
    17  // under the License.
    18  
    19  package parser
    20  
    21  // analyzer.go contains utility analysis functions.
    22  
    23  import (
    24  	"strings"
    25  	"unicode"
    26  )
    27  
    28  // These constants are used to identify the SQL statement type.
    29  const (
    30  	StmtSelect = iota
    31  	StmtStream
    32  	StmtInsert
    33  	StmtReplace
    34  	StmtUpdate
    35  	StmtDelete
    36  	StmtDDL
    37  	StmtBegin
    38  	StmtCommit
    39  	StmtRollback
    40  	StmtSet
    41  	StmtShow
    42  	StmtUse
    43  	StmtOther
    44  	StmtUnknown
    45  	StmtComment
    46  	StmtSavepoint
    47  )
    48  
    49  // Preview analyzes the beginning of the query using a simpler and faster
    50  // textual comparison to identify the statement type.
    51  func Preview(sql string) int {
    52  	trimmed := StripLeadingComments(sql)
    53  
    54  	firstWord := trimmed
    55  	if end := strings.IndexFunc(trimmed, unicode.IsSpace); end != -1 {
    56  		firstWord = trimmed[:end]
    57  	}
    58  	firstWord = strings.TrimLeftFunc(firstWord, func(r rune) bool { return !unicode.IsLetter(r) })
    59  	// Comparison is done in order of priority.
    60  	loweredFirstWord := strings.ToLower(firstWord)
    61  	switch loweredFirstWord {
    62  	case "select":
    63  		return StmtSelect
    64  	case "stream":
    65  		return StmtStream
    66  	case "insert":
    67  		return StmtInsert
    68  	case "replace":
    69  		return StmtReplace
    70  	case "update":
    71  		return StmtUpdate
    72  	case "delete":
    73  		return StmtDelete
    74  	}
    75  	// For the following statements it is not sufficient to rely
    76  	// on loweredFirstWord. This is because they are not statements
    77  	// in the grammar and we are relying on Preview to parse them.
    78  	// For instance, we don't want: "BEGIN JUNK" to be parsed
    79  	// as StmtBegin.
    80  	trimmedNoComments, _ := SplitMarginComments(trimmed)
    81  	switch strings.ToLower(trimmedNoComments) {
    82  	case "begin", "start transaction":
    83  		return StmtBegin
    84  	}
    85  	switch loweredFirstWord {
    86  	case "create", "alter", "rename", "drop", "truncate", "flush":
    87  		return StmtDDL
    88  	case "set":
    89  		return StmtSet
    90  	case "show":
    91  		return StmtShow
    92  	case "use":
    93  		return StmtUse
    94  	case "analyze", "describe", "desc", "explain", "repair", "optimize":
    95  		return StmtOther
    96  	case "commit":
    97  		return StmtCommit
    98  	case "rollback":
    99  		return StmtRollback
   100  	case "savepoint":
   101  		return StmtSavepoint
   102  	}
   103  	if strings.Index(trimmedNoComments, "release savepoint") == 0 {
   104  		return StmtSavepoint
   105  	}
   106  	if strings.Index(trimmed, "/*!") == 0 {
   107  		return StmtComment
   108  	}
   109  	return StmtUnknown
   110  }
   111  
   112  // StmtType returns the statement type as a string
   113  func StmtType(stmtType int) string {
   114  	switch stmtType {
   115  	case StmtSelect:
   116  		return "SELECT"
   117  	case StmtStream:
   118  		return "STREAM"
   119  	case StmtInsert:
   120  		return "INSERT"
   121  	case StmtReplace:
   122  		return "REPLACE"
   123  	case StmtUpdate:
   124  		return "UPDATE"
   125  	case StmtDelete:
   126  		return "DELETE"
   127  	case StmtDDL:
   128  		return "DDL"
   129  	case StmtBegin:
   130  		return "BEGIN"
   131  	case StmtCommit:
   132  		return "COMMIT"
   133  	case StmtRollback:
   134  		return "ROLLBACK"
   135  	case StmtSavepoint:
   136  		return "SAVEPOINT"
   137  	case StmtSet:
   138  		return "SET"
   139  	case StmtShow:
   140  		return "SHOW"
   141  	case StmtUse:
   142  		return "USE"
   143  	case StmtOther:
   144  		return "OTHER"
   145  	default:
   146  		return "UNKNOWN"
   147  	}
   148  }