golang 解析 sql 从中获取表名
antlr
ANTLR是Another Tool for Language Recognition的简写,是一个用Java语言编写的识别器工具。它能够自动生成解析器,并将用户编写的ANTLR语法规则直接生成目标语言的解析器,它能够生成Java、Go、C等语言的解析器客户端。
作者还维护了很多语法规则其中就有mysql规则
使用
下载最新的jar包https://www.antlr.org/download/antlr-4.10.1-complete.jar
从github中下载MySqlLexer.g4
和MySqlParser.g4
执行命令生成go文件 (需要java环境)java -jar antlr-4.10.1-complete.jar -visitor -Dlanguage=Go -o parser MySqlLexer.g4
java -jar antlr-4.10.1-complete.jar -visitor -Dlanguage=Go -o parser MySqlParser.g4
目录结构如下:
├── MySqlLexer.g4
├── MySqlParser.g4
├── antlr-4.10.1-complete.jar
├── antlr.go
└── parser
├── MySqlLexer.interp
├── MySqlLexer.tokens
├── MySqlParser.interp
├── MySqlParser.tokens
├── mysql_lexer.go
├── mysql_parser.go
├── mysqlparser_base_listener.go
└── mysqlparser_listener.go
antlr.go
:
package antlr
import (
"github.com/antlr/antlr4/runtime/Go/antlr"
logs "github.com/danbai225/go-logs"
"strings"
"test/antlr/parser"
)
type Ml struct {
*parser.BaseMySqlParserListener
tableNames map[string]struct{}
}
func (m *Ml) EnterTableName(ctx *parser.TableNameContext) {
if m.tableNames == nil {
m.tableNames = make(map[string]struct{})
}
m.tableNames[ctx.GetText()] = struct{}{}
}
func (m *Ml) GetTableNames() []string {
arr := make([]string, 0)
if m.tableNames != nil {
for k := range m.tableNames {
arr = append(arr, k)
}
}
return arr
}
func GetTableNames(sql string, sqlType string) []string {
tokenStream := antlr.NewCommonTokenStream(parser.NewMySqlLexer(antlr.NewInputStream(strings.ToUpper(sql))), antlr.TokenDefaultChannel)
sqlParser := parser.NewMySqlParser(tokenStream)
ml := Ml{}
switch sqlType {
case "dml":
antlr.ParseTreeWalkerDefault.Walk(&ml, sqlParser.DmlStatement())
case "ddl":
antlr.ParseTreeWalkerDefault.Walk(&ml, sqlParser.DdlStatement())
}
return ml.GetTableNames()
}
func Antlr() {
sql := "SELECT without FROM fails"
logs.Info(GetTableNames(sql, "dml"))
}
通过覆盖实现BaseMySqlParserListener
的EnterTableName
接口
再解析的过程中每个表名节点都将调用这个方法收集表名。
怀念以前用antlr4解析各种防火墙配置语法的时光
求楼主给一个select 的字段名 规则打印。我试了
楼主有antlr 生成的MySQL 代码注释吗好难。看不懂因为没注释