meoying / dbproxy

船新的数据库代理
13 stars 9 forks source link

重构 Hint 相关内容 #46

Open longyue0521 opened 3 months ago

longyue0521 commented 3 months ago

现在只有SELECT语句支持Hint语法, 但也不符合要求.

juniaoshaonian commented 3 months ago

现在只有SELECT语句支持Hint语法, 但也不符合要求.

  • [ ] 将SELECT语句支持的Hint语法从 /*useMaster*/ 修改为 /* use_master */ [待确认, use_master前后是否包含空格?]
  • [ ] 修改ANTLR4 的语法,让 SELECT,DELETE,UPDATE,INSERT 都支持,参考 SELECT 的写法。BEGIN 也可以支持 ? [待确认]
  • [ ] 重构 HintVisitor, 挪过去初始化 root 的地方,直接 visitor,那么只需要检测是不是 HintContext 就可以了。visitor 遍历都是一个递归,所以如果看到了 HintContext 就说明这个语句传入了 HINT。而我们可以通过修改 ANTRL4 的规则,让不同的语句都支持 HINT
  1. 现在前后加空格都可以
  2. begin支持的话 这样吗。这样mysql是可以运行的。
    begin /*aaaaa*/ 
flycash commented 3 months ago

基本上就是这种形态:

select /* @use_master  true*/
update /* @use_master true*/
delete /* @use_master true*/
insert /* @use_master true*/

也就是规范为 / @key value/ 的形式。

更进一步来说,还要允许多个 key-value,例如

SELECT /** 
    @key1 value1
    @key2 value2
    .... 
*/

这样写下去。但是这个语法比较复杂,在 AST 里面不太好写规则,那么可以考虑:

SELECT /* @proxy key1=value1;key2=value2*/

这种比较好些 AST 规则。

改写 AST 规则就是参考 SELECT 我的改写方法。

我的意思是把 hint 解析作为公共部分,而后在初始化的地方加入 HintVisitor。

func Parse(query string) parser.IRootContext {
    lexer := parser.NewMySqlLexer(antlr.NewInputStream(query))
    tokens := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
    paser := parser.NewMySqlParser(tokens)
    return paser.Root()
}

在这里加入 hintvisitor,然后提取出来 hint。应该要改这个方法的返回值。