Skip to content

Commit 2a6d515

Browse files
committed
init
1 parent bfc60c4 commit 2a6d515

26 files changed

+17604
-1
lines changed

Makefile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2017 Google 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+
# 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+
MAKEFLAGS = -s
16+
17+
sql.go: sql.y
18+
goyacc -o sql.go sql.y
19+
gofmt -w sql.go
20+
21+
clean:
22+
rm -f y.output sql.go

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
# sqlparser
2-
sql parser
2+
从vitess复制过来的,添加解析ddl相关语句
3+
1. create database
4+
2. drop database
5+
6+

analyzer.go

+308
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/*
2+
Copyright 2017 Google Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package sqlparser
18+
19+
// analyzer.go contains utility analysis functions.
20+
21+
import (
22+
"fmt"
23+
"strconv"
24+
"strings"
25+
"unicode"
26+
27+
"vitess.io/vitess/go/sqltypes"
28+
"vitess.io/vitess/go/vt/vterrors"
29+
30+
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
31+
)
32+
33+
// These constants are used to identify the SQL statement type.
34+
const (
35+
StmtSelect = iota
36+
StmtStream
37+
StmtInsert
38+
StmtReplace
39+
StmtUpdate
40+
StmtDelete
41+
StmtDDL
42+
StmtBegin
43+
StmtCommit
44+
StmtRollback
45+
StmtSet
46+
StmtShow
47+
StmtUse
48+
StmtOther
49+
StmtUnknown
50+
StmtComment
51+
)
52+
53+
// Preview analyzes the beginning of the query using a simpler and faster
54+
// textual comparison to identify the statement type.
55+
func Preview(sql string) int {
56+
trimmed := StripLeadingComments(sql)
57+
58+
firstWord := trimmed
59+
if end := strings.IndexFunc(trimmed, unicode.IsSpace); end != -1 {
60+
firstWord = trimmed[:end]
61+
}
62+
63+
// Comparison is done in order of priority.
64+
loweredFirstWord := strings.ToLower(firstWord)
65+
switch loweredFirstWord {
66+
case "select":
67+
return StmtSelect
68+
case "stream":
69+
return StmtStream
70+
case "insert":
71+
return StmtInsert
72+
case "replace":
73+
return StmtReplace
74+
case "update":
75+
return StmtUpdate
76+
case "delete":
77+
return StmtDelete
78+
}
79+
// For the following statements it is not sufficient to rely
80+
// on loweredFirstWord. This is because they are not statements
81+
// in the grammar and we are relying on Preview to parse them.
82+
// For instance, we don't want: "BEGIN JUNK" to be parsed
83+
// as StmtBegin.
84+
trimmedNoComments, _ := SplitTrailingComments(trimmed)
85+
switch strings.ToLower(trimmedNoComments) {
86+
case "begin", "start transaction":
87+
return StmtBegin
88+
case "commit":
89+
return StmtCommit
90+
case "rollback":
91+
return StmtRollback
92+
}
93+
switch loweredFirstWord {
94+
case "create", "alter", "rename", "drop", "truncate":
95+
return StmtDDL
96+
case "set":
97+
return StmtSet
98+
case "show":
99+
return StmtShow
100+
case "use":
101+
return StmtUse
102+
case "analyze", "describe", "desc", "explain", "repair", "optimize":
103+
return StmtOther
104+
}
105+
if strings.Index(trimmed, "/*!") == 0 {
106+
return StmtComment
107+
}
108+
return StmtUnknown
109+
}
110+
111+
// StmtType returns the statement type as a string
112+
func StmtType(stmtType int) string {
113+
switch stmtType {
114+
case StmtSelect:
115+
return "SELECT"
116+
case StmtStream:
117+
return "STREAM"
118+
case StmtInsert:
119+
return "INSERT"
120+
case StmtReplace:
121+
return "REPLACE"
122+
case StmtUpdate:
123+
return "UPDATE"
124+
case StmtDelete:
125+
return "DELETE"
126+
case StmtDDL:
127+
return "DDL"
128+
case StmtBegin:
129+
return "BEGIN"
130+
case StmtCommit:
131+
return "COMMIT"
132+
case StmtRollback:
133+
return "ROLLBACK"
134+
case StmtSet:
135+
return "SET"
136+
case StmtShow:
137+
return "SHOW"
138+
case StmtUse:
139+
return "USE"
140+
case StmtOther:
141+
return "OTHER"
142+
default:
143+
return "UNKNOWN"
144+
}
145+
}
146+
147+
// IsDML returns true if the query is an INSERT, UPDATE or DELETE statement.
148+
func IsDML(sql string) bool {
149+
switch Preview(sql) {
150+
case StmtInsert, StmtReplace, StmtUpdate, StmtDelete:
151+
return true
152+
}
153+
return false
154+
}
155+
156+
// GetTableName returns the table name from the SimpleTableExpr
157+
// only if it's a simple expression. Otherwise, it returns "".
158+
func GetTableName(node SimpleTableExpr) TableIdent {
159+
if n, ok := node.(TableName); ok && n.Qualifier.IsEmpty() {
160+
return n.Name
161+
}
162+
// sub-select or '.' expression
163+
return NewTableIdent("")
164+
}
165+
166+
// IsColName returns true if the Expr is a *ColName.
167+
func IsColName(node Expr) bool {
168+
_, ok := node.(*ColName)
169+
return ok
170+
}
171+
172+
// IsValue returns true if the Expr is a string, integral or value arg.
173+
// NULL is not considered to be a value.
174+
func IsValue(node Expr) bool {
175+
switch v := node.(type) {
176+
case *SQLVal:
177+
switch v.Type {
178+
case StrVal, HexVal, IntVal, ValArg:
179+
return true
180+
}
181+
}
182+
return false
183+
}
184+
185+
// IsNull returns true if the Expr is SQL NULL
186+
func IsNull(node Expr) bool {
187+
switch node.(type) {
188+
case *NullVal:
189+
return true
190+
}
191+
return false
192+
}
193+
194+
// IsSimpleTuple returns true if the Expr is a ValTuple that
195+
// contains simple values or if it's a list arg.
196+
func IsSimpleTuple(node Expr) bool {
197+
switch vals := node.(type) {
198+
case ValTuple:
199+
for _, n := range vals {
200+
if !IsValue(n) {
201+
return false
202+
}
203+
}
204+
return true
205+
case ListArg:
206+
return true
207+
}
208+
// It's a subquery
209+
return false
210+
}
211+
212+
// NewPlanValue builds a sqltypes.PlanValue from an Expr.
213+
func NewPlanValue(node Expr) (sqltypes.PlanValue, error) {
214+
switch node := node.(type) {
215+
case *SQLVal:
216+
switch node.Type {
217+
case ValArg:
218+
return sqltypes.PlanValue{Key: string(node.Val[1:])}, nil
219+
case IntVal:
220+
n, err := sqltypes.NewIntegral(string(node.Val))
221+
if err != nil {
222+
return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err)
223+
}
224+
return sqltypes.PlanValue{Value: n}, nil
225+
case StrVal:
226+
return sqltypes.PlanValue{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, node.Val)}, nil
227+
case HexVal:
228+
v, err := node.HexDecode()
229+
if err != nil {
230+
return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err)
231+
}
232+
return sqltypes.PlanValue{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, v)}, nil
233+
}
234+
case ListArg:
235+
return sqltypes.PlanValue{ListKey: string(node[2:])}, nil
236+
case ValTuple:
237+
pv := sqltypes.PlanValue{
238+
Values: make([]sqltypes.PlanValue, 0, len(node)),
239+
}
240+
for _, val := range node {
241+
innerpv, err := NewPlanValue(val)
242+
if err != nil {
243+
return sqltypes.PlanValue{}, err
244+
}
245+
if innerpv.ListKey != "" || innerpv.Values != nil {
246+
return sqltypes.PlanValue{}, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: nested lists")
247+
}
248+
pv.Values = append(pv.Values, innerpv)
249+
}
250+
return pv, nil
251+
case *NullVal:
252+
return sqltypes.PlanValue{}, nil
253+
}
254+
return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "expression is too complex '%v'", String(node))
255+
}
256+
257+
// StringIn is a convenience function that returns
258+
// true if str matches any of the values.
259+
func StringIn(str string, values ...string) bool {
260+
for _, val := range values {
261+
if str == val {
262+
return true
263+
}
264+
}
265+
return false
266+
}
267+
268+
// ExtractSetValues returns a map of key-value pairs
269+
// if the query is a SET statement. Values can be int64 or string.
270+
// Since set variable names are case insensitive, all keys are returned
271+
// as lower case.
272+
func ExtractSetValues(sql string) (keyValues map[string]interface{}, scope string, err error) {
273+
stmt, err := Parse(sql)
274+
if err != nil {
275+
return nil, "", err
276+
}
277+
setStmt, ok := stmt.(*Set)
278+
if !ok {
279+
return nil, "", fmt.Errorf("ast did not yield *sqlparser.Set: %T", stmt)
280+
}
281+
result := make(map[string]interface{})
282+
for _, expr := range setStmt.Exprs {
283+
key := expr.Name.Lowered()
284+
285+
switch expr := expr.Expr.(type) {
286+
case *SQLVal:
287+
switch expr.Type {
288+
case StrVal:
289+
result[key] = string(expr.Val)
290+
case IntVal:
291+
num, err := strconv.ParseInt(string(expr.Val), 0, 64)
292+
if err != nil {
293+
return nil, "", err
294+
}
295+
result[key] = num
296+
default:
297+
return nil, "", fmt.Errorf("invalid value type: %v", String(expr))
298+
}
299+
case *NullVal:
300+
result[key] = nil
301+
case *Default:
302+
result[key] = "default"
303+
default:
304+
return nil, "", fmt.Errorf("invalid syntax: %s", String(expr))
305+
}
306+
}
307+
return result, strings.ToLower(setStmt.Scope), nil
308+
}

0 commit comments

Comments
 (0)