您現(xiàn)在的位置:首頁(yè)>教程>編程開(kāi)發(fā)>mssql數(shù)據(jù)庫(kù) > mixer:sql詞法分析器設(shè)計(jì) mixer:sql詞法分析器設(shè)計(jì) 感謝 3lian8 的投遞 時(shí)間:2014-03-25 來(lái)源:三聯(lián)教程 介紹 mixer希望在proxy這層就提供自定義路由,sql黑名單,防止sql注入攻擊等功能,而這些的基石就在
您現(xiàn)在的位置:首頁(yè) > 教程 > 編程開(kāi)發(fā) > mssql數(shù)據(jù)庫(kù) > mixer:sql詞法分析器設(shè)計(jì)
mixer:sql詞法分析器設(shè)計(jì)
感謝 3lian8 的投遞 時(shí)間:2014-03-25 來(lái)源:三聯(lián)教程
介紹
mixer希望在proxy這層就提供自定義路由,sql黑名單,防止sql注入攻擊等功能,而這些的基石就在于將用戶發(fā)上來(lái)的sql語(yǔ)句進(jìn)行解析。也就是我最頭大的詞法分析和語(yǔ)法分析。
到現(xiàn)在為止,我只是實(shí)現(xiàn)了一個(gè)比較簡(jiǎn)單的詞法分析器,用以將sql語(yǔ)句分解成多個(gè)token。而對(duì)于從token在進(jìn)行語(yǔ)法分析,構(gòu)建sql的AST,,我現(xiàn)在還真沒(méi)啥經(jīng)驗(yàn)(編譯原理太差了),急需牛人幫忙。
所以,這里只是簡(jiǎn)單介紹一下mixer的詞法分析。
tokenize
在很多地方,我們都需要進(jìn)行詞法分析,通常會(huì)有幾種方式:
使用一個(gè)強(qiáng)大的工具,譬如lex,mysql-proxy就用的這種方式
使用正則表達(dá)式
state machine
對(duì)于使用工具,我覺(jué)得有一個(gè)不怎么好的地方在于學(xué)習(xí)成本,譬如我用lex的時(shí)候就需要學(xué)習(xí)它的語(yǔ)法,同時(shí)通過(guò)工具生成的代碼可讀性都不怎么好,代碼量大,更嚴(yán)重的是可能會(huì)比較慢。所以mysql自身也是自己實(shí)現(xiàn)一個(gè)詞法分析模塊。
而對(duì)于正則表達(dá)式,性能問(wèn)題可能是一個(gè)很需要考慮的,而且復(fù)雜度并不比使用類似lex這樣的工具低。
狀態(tài)機(jī)可能是我覺(jué)得自己動(dòng)手實(shí)現(xiàn)詞法解析一個(gè)很好的方式,對(duì)于sql的詞法解析,我覺(jué)得使用state machine的方式來(lái)自己寫一個(gè)難度并不大,所以mixer自己實(shí)現(xiàn)了一個(gè)。
state machine
通常,一個(gè)狀態(tài)機(jī)的實(shí)現(xiàn)采用的是state + action + switch的做法,可能如下:
?
1
2
3
4
5
6
7
8
switch state {
case state1:
state = action1()
case state2:
state = action2()
case state3:
state = action3()
}
對(duì)于一個(gè)state,我們通過(guò)switch知道它將會(huì)由哪一個(gè)action進(jìn)行處理,而對(duì)于每一個(gè)action,我們則知道執(zhí)行完成之后下一個(gè)state是什么。
對(duì)于上面的實(shí)現(xiàn),如果state過(guò)多,可能會(huì)導(dǎo)致太多的case語(yǔ)句,我們可以通過(guò)state function進(jìn)行簡(jiǎn)化。
一個(gè)state function就是執(zhí)行當(dāng)前的state action,并且直接返回下一個(gè)state function。
我們可以這樣做:
?
1
2
3
4
5
type stateFn func(*Lexer) stateFn
for state := startState; state != nil {
state = state(lexer)
}
所以我們需要實(shí)現(xiàn)的就是每一個(gè)state function以及對(duì)應(yīng)的它的下一個(gè)需要執(zhí)行的state function。
mixer lexer
mixer的詞法分析實(shí)現(xiàn)主要參考這個(gè)。主要實(shí)現(xiàn)在parser模塊。
對(duì)于一個(gè)lexer,需要提供的是NextToken的功能,供外部獲取下一個(gè)token,從而進(jìn)行后續(xù)的操作(譬如語(yǔ)法分析)。
lexer的next token如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func (l *Lexer) NextToken() (Token, error) {
for {
select {
case t := <-l.tokens:
return t, nil
default:
if l.state == nil {
return Token{TK_EOF, ""}, l.err
}
l.state = l.state(l)
if l.err != nil {
return Token{TK_UNKNOWN, ""}, l.err
}
}
}
}
tokens是一個(gè)channel,每次state解析的token都會(huì)emit到這個(gè)channel上面,供NextToken獲取,如果channel為空了,則再次調(diào)用state function。
可以看到,用go實(shí)現(xiàn)一個(gè)詞法解析是很容易的事情,剩下的就是寫相應(yīng)的state function用來(lái)解析sql。
todo
mixer的詞法分析還有很多不完善的地方,譬如對(duì)于科學(xué)計(jì)數(shù)法數(shù)值的解析就不完善,后續(xù)準(zhǔn)備參考mysql官方的詞法分析模塊在好好完善一下。
相關(guān)文章
標(biāo)簽:
[返回三聯(lián)首頁(yè)] [返回mssql數(shù)據(jù)庫(kù)欄目] / [加入三聯(lián)文集]
Copyright ? 2019- 91gzw.com 版權(quán)所有 湘ICP備2023023988號(hào)-2
違法及侵權(quán)請(qǐng)聯(lián)系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市萬(wàn)商天勤律師事務(wù)所王興未律師提供法律服務(wù)