-
Notifications
You must be signed in to change notification settings - Fork 2
/
query_string.go
117 lines (98 loc) · 2.75 KB
/
query_string.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package sqlstr
import (
"regexp"
"strings"
"unicode"
)
type QueryString struct {
query string
lowered string
}
func NewQueryString(query string) *QueryString {
query = Clean(query)
return &QueryString{
query: query,
lowered: strings.ToLower(query),
}
}
// After word
func (p QueryString) After(word string) string {
iWord := strings.Index(p.lowered, strings.ToLower(word)) + len(word) + 1
return p.after(iWord)
}
// AfterAll word
func (p QueryString) AfterAll(word string) (atAfters []string) {
indices := regexp.MustCompile(strings.ToLower(word)).
FindAllStringIndex(p.lowered, -1)
for _, index := range indices {
atAfters = append(atAfters, p.after(index[1]))
}
return
}
// TableNames of Query
func (p QueryString) TableNames() (names []string) {
firstSyntax := p.lowered[:strings.IndexRune(p.lowered, ' ')]
switch firstSyntax {
case "update":
names = append(names, cleanName(p.After("update")))
return
case "insert":
index := regexp.MustCompile("insert(.*?)into").FindStringIndex(p.lowered)
names = append(names, cleanName(p.after(index[1])))
return
case "delete":
index := regexp.MustCompile("delete(.*?)from").FindStringIndex(p.lowered)
names = append(names, cleanName(p.after(index[1])))
return
}
names = append(names, p.tableNamesByFROM()...)
names = append(names, p.AfterAll("join")...)
return
}
func (p QueryString) tableNamesByFROM() (names []string) {
indices := regexp.MustCompile("from(.*?)(left|inner|right|outer|full)|from(.*?)join|from(.*?)where|from(.*?);|from(.*?)$").
FindAllStringIndex(p.lowered, -1)
for _, index := range indices {
fromStmt := p.lowered[index[0]:index[1]]
lastSyntax := fromStmt[strings.LastIndex(fromStmt, " ")+1:]
var tableStmt string
if lastSyntax == "from" || lastSyntax == "where" || lastSyntax == "left" ||
lastSyntax == "right" || lastSyntax == "join" || lastSyntax == "inner" ||
lastSyntax == "outer" || lastSyntax == "full" {
tableStmt = p.query[index[0]+len("from")+1 : index[1]-len(lastSyntax)-1]
} else {
tableStmt = p.query[index[0]+len("from")+1:]
}
for _, name := range strings.Split(tableStmt, ",") {
names = append(names, cleanName(name))
}
}
return
}
func cleanName(name string) string {
name = strings.Fields(name)[0]
name = strings.TrimSpace(name)
name = strings.Trim(name,"`")
lastRune := name[len(name)-1]
if lastRune == ';' {
name = name[:len(name)-1]
}
return name
}
func (p QueryString) after(iWord int) (atAfter string) {
iAfter := 0
for i := iWord; i < len(p.lowered); i++ {
r := rune(p.lowered[i])
if unicode.IsLetter(r) && iAfter <= 0 {
iAfter = i
}
if (unicode.IsSpace(r) || unicode.IsPunct(r)) && iAfter > 0 {
atAfter = p.query[iAfter:i]
break
}
}
if atAfter == "" {
atAfter = p.query[iAfter:]
}
return
}