ANTLR4解析MySQL语句

作者: lndyzwdxhs | 来源:发表于2019-01-16 12:30 被阅读243次

ANTLR

一款强大的生成"语法解析器"的工具,可以用作读取、处理、执行或翻译结构化文本或二进制文件。广泛的用来构建新的语言、工具和框架。这个"语法解析器"创建和遍历语法树。

eg:Hive和Spark使用antlr生成词法语法解析器、Twitter使用antlr来解析用户输入的查询内容,Oracle把antlr的功能内嵌在SQL 开发IDE中,NetBeans IDE使用antlr解析C++语言,也有公司使用antlr来从文件中抽取信息

ANTLR官网

大致流程:

  • 首先需要编写文法文件(g4后缀);
  • 然后使用g4文法文件通过antlr工具生成lexer词法解析器、parser语法解析器、visitor和listener的runtime target文件(支持多种语言)
  • 然后可以直接使用输出的runtime target文件模块进行开发工作

生成MySQL语法解析器

官方提供的各种语言的g4文件
Python target说明

安装ANTLR工具:

cd /usr/local/lib
wget https://www.antlr.org/download/antlr-4.7.2-complete.jar
export CLASSPATH=".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"
alias antlr4='java -jar /usr/local/lib/antlr-4.7.2-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'

根据mysql文法文件生成Python词法/语法解析器:

antlr4 -Dlanguage=Python2 MySqlLexer.g4
antlr4 -Dlanguage=Python2 MySqlParser.g4

安装Python runtime模块

pip install antlr4-python2-runtime

测试用例:

import sys
from antlr4 import *
from antlr4.InputStream import InputStream
from MySqlLexer import MySqlLexer
from MySqlParser import MySqlParser


class CaseChangingCharInputStream(InputStream):
    def __init__(self, data, upper=True):
        super(CaseChangingCharInputStream, self).__init__(data)
        self.upper = upper

    def LA(self, pos):
        value = super(CaseChangingCharInputStream, self).LA(pos)
        if 0 <= value < 256:
            if pos <= 0: return value
            str_value = chr(value)
            return ord(str_value.upper()) if self.upper else ord(str_value.lower())
        else:
            return value


class CaseChangingCharFileStream(FileStream, CaseChangingCharInputStream):
    def __init__(self, file, upper=True):
        super(CaseChangingCharFileStream, self).__init__(file)
        self.upper = upper


if __name__ == '__main__':
    if len(sys.argv) > 1:
        input_stream = CaseChangingCharFileStream(sys.argv[1])
    else:
        input_stream = CaseChangingCharInputStream('SeLeCT id FROM student')

    lexer = MySqlLexer(input_stream)
    token_stream = CommonTokenStream(lexer)
    parser = MySqlParser(token_stream)
    tree = parser.root()

问题

  • mysql语句不区分大小写,但是目前官方提供的g4文件是区分大小写的,所以使用lexer/parser时会报错。
    • 两种方案:一种是修改g4文件;一种是在喂给lexer之前,将所有字符转成大写。
    • 官方解释
# 重写LA
class CaseChangingCharInputStream(InputStream):
    def __init__(self, data, upper=True):
        super(CaseChangingCharInputStream, self).__init__(data)
        self.upper = upper

    def LA(self, pos):
        value = super(CaseChangingCharInputStream, self).LA(pos)
        if 0 <= value < 256:
            if pos <= 0: return value
            str_value = chr(value)
            return ord(str_value.upper()) if self.upper else ord(str_value.lower())
        else:
            return value


class CaseChangingCharFileStream(FileStream, CaseChangingCharInputStream):
    def __init__(self, file, upper=True):
        super(CaseChangingCharFileStream, self).__init__(file)
        self.upper = upper

欢迎关注微信公众号(coder0x00)或扫描下方二维码关注,我们将持续搜寻程序员必备基础技能包提供给大家。


相关文章

  • ANTLR4解析MySQL语句

    ANTLR 一款强大的生成"语法解析器"的工具,可以用作读取、处理、执行或翻译结构化文本或二进制文件。广泛的用来构...

  • mysql 技术点汇总

    MYSQL存储引擎介绍 索引 mysql 执行过程 mysql 语句解析过程 https://www.cnblog...

  • 第一讲 一条 sql 查询语句的执行

    通过对一句 select 语句,来解析 Mysql 的基础架构。 语句拆解 语句在 MySQL 的各个功能模块中的...

  • MySQL_MySQL中的begin-end流程控制语句与局部变

    MySQL:if语句、if...else语句、case语句,使用方法解析 if语句做为表达式使用,语法格式如下: ...

  • PHP MYSQL SQL预编译

    MySQL的预编译是指在创建数据库对象时就将指定的SQL语句编译完成,这时SQL语句已经被MySQL解析、审查,所...

  • PHP中MySQL的预处理(预编译)执行方式

    MySQL的预编译是指在创建数据库对象时就将指定的SQL语句编译完成,这时SQL语句已经被MySQL解析、审查,所...

  • MySQL 查询缓存

    开启查询缓存后,查询语句的解析过程: 在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查...

  • MySQL语法收集

    MYSQL基础语句解析 SELECT SELECT DISTINCT 返回唯一不同的值 WHERE 条件 AND ...

  • antlr4 精简入门

    antlr4 是什么 antlr 是一个由java编写的语法识别工具,官方介绍为Antlr4是一款强大的解析器生成...

  • daily --mysql JOIN查询基础

    JOIN语句基础 SQL执行顺序 手写的SQL 手写代码经过MySQL解析器解析成机器识别的SQL

网友评论

    本文标题:ANTLR4解析MySQL语句

    本文链接:https://www.haomeiwen.com/subject/aexmdqtx.html