Druid SQL 解析器概览
概览
Druid 的官方 wiki 对 SQL 解析器部分的讲解内容并不多,但虽然不多,也有利于完全没接触过 Druid 的人对 SQL 解析器有个初步的印象。
说到解析器,脑海里便很容易浮现 parser 这个单词,然后便很容易联想到计算机科学中理论性比较强的学科------编译原理。想必很多人都知道(即使不知道,应该也耳濡目染)能够手写编译器的人并不多,并且这类人呢,理论知识和工程能力都比较强。在缺乏人力的条件下,大多数时候实现一个编译器,往往是选择采用一些工具,比如说 ANTLR,只需要描述好语法规则,这个工具就能生成对应的编译器。
不过,Druid 的 SQL 解析器是手写的,官方宣称性能是 ANTLR 这类工具的10倍以上。
解析器组成部分
在 Druid 的 SQL 解析器中,有三个重要的组成部分,它们分别是:
Parser
词法分析
语法分析
AST(Abstract Syntax Tree,抽象语法树)
Visitor
这三者的关系如下图所示:
Parser 由两部分组成,词法分析和语法分析。
当拿到一条形如 select id, name from user 的 SQL 语句后,首先需要解析出每个独立的单词,select,id,name,from,user。这一部分,称为词法分析,也叫作 Lexer。
通过词法分析后,便要进行语法分析了。
经常能听到很多人在调侃自己英文水平很一般时会说:26个字母我都知道,但是一组合在一起我就不知道是什么意思了。这说明他掌握了词法分析的技能,却没有掌握语法分析的技能。
那么对于 SQL 解析器来说呢,它不仅需要知道每个单词,而且要知道这些单词组合在一起后,表达了什么含义。语法分析的职责就是明确一个语句的语义,表达的是什意思。
自然语言和形式语言的一个重要区别是,自然语言的一个语句,可能有多重含义,而形式语言的一个语句,只能有一个语义;形式语言的语法是人为规定的,有了一定的语法规则,语法解析器就能根据语法规则,解析出一个语句的一个唯一含义。
AST 是 Parser 的产物,语句经过词法分析,语法分析后,它的结构需要以一种计算机能读懂的方式表达出来,最常用的就是抽象语法树。
树的概念很接近于一个语句结构的表示,一个语句,我们经常会对它这样看待:它由哪些部分组成?其中一个组成部分又有哪些部分组成?例如一条 select 语句,它由 select 列表、where 子句、排序字段、分组字段等组成,而 select 列表则由一个或多个 select 项组成,where 子句又由一个或者多个 where条件组成。
在我们人类的思维中,这种组成结构就是一个总分的逻辑结构,用树来表达,最合适不过。并且对于计算机来说,它显然比人类更擅长处理“树”。
AST 仅仅是语义的表示,但如何对这个语义进行表达,便需要去访问这棵 AST,看它到底表达什么含义。通常遍历语法树,使用 VISITOR 模式去遍历,从根节点开始遍历,一直到最后一个叶子节点,在遍历的过程中,便不断地收集信息到一个上下文中,整个遍历过程完成后,对这棵树所表达的语法含义,已经被保存到上下文了。有时候一次遍历还不够,需要二次遍历。遍历的方式,广度优先的遍历方式是最常见的。
快速上手
使用 Druid SQL Parser 来解析 SQL 语句,一般需要进行以下几个步骤:
新建一个 Parser
使用 Parser 解析 SQL,生成 AST
使用 Visitor 访问 AST
如下代码所示:
package io.beansoft.demo;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.sql.parser.SQLStatementParser;
/**
*
*
* @author beanlam
* @date 2017年1月10日 下午11:06:26
* @version 1.0
*
*/
public class ParserMain {
public static void main(String[] args) {
String sql = "select id,name from user";
// 新建 MySQL Parser
SQLStatementParser parser = new MySqlStatementParser(sql);
// 使用Parser解析生成AST,这里SQLStatement就是AST
SQLStatement statement = parser.parseStatement();
// 使用visitor来访问AST
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
statement.accept(visitor);
// 从visitor中拿出你所关注的信息
System.out.println(visitor.getColumns());
}
}
以上代码运行后控制台的输出为
[user.id, user.name]
当然,不使用 Visitor,直接操作 AST 也可以得到 SQL 语句的信息,在 Druid 现有内置的 Visitor 不能满足需求时,可以自己去实现 Visitor,对于用 Visitor 无法解析到的信息,可以直接访问 AST 去获取。
Druid SQL 解析器概览的更多相关文章
- SQL解析器详解
1.概述 最近,有同学留言关于SQL解析器方面的问题,今天笔者就为大家分享一下SQL解析器方便的一些内容. 2.内容 2.1 SQL解析器是什么? SQL解析与优化是属于编辑器方面的知识,与C语言这类 ...
- 如何实现一个SQL解析器
作者:vivo 互联网搜索团队- Deng Jie 一.背景 随着技术的不断的发展,在大数据领域出现了越来越多的技术框架.而为了降低大数据的学习成本和难度,越来越多的大数据技术和应用开始支持SQL进 ...
- SQL解析器的性能測试
对同一个sql语句,使用3种解析器解析出ast语法树(这是编译原理上的说法,在sql解析式可能就是解析器自己定义的statement类型).运行100万次的时间对照. package demo.tes ...
- SpringBoot与MybatisPlus3.X整合之动态表名 SQL 解析器(七)
pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId& ...
- 【druid 】数据库连接池-sql解析
https://segmentfault.com/a/1190000008120254?utm_source=tuicool&utm_medium=referral sql解析 Druid 的 ...
- atitit.java解析sql语言解析器解释器的实现
atitit.java解析sql语言解析器解释器的实现 1. 解析sql的本质:实现一个4gl dsl编程语言的编译器 1 2. 解析sql的主要的流程,词法分析,而后进行语法分析,语义分析,构建sq ...
- c# 怎样能写个sql的解析器
c# 怎样能写个sql的解析器 本示例主要是讲明sql解析的原理,真实的源代码下查看 sql解析器源代码 详细示例DEMO 请查看demo代码 前言 阅读本文需要有一定正则表达式基础 正则表达式基础教 ...
- SQL解析在美团的应用
https://tech.meituan.com/SQL_parser_used_in_mtdp.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来 ...
- 转载:一文详解SQL解析与应用
转载地址:http://www.elecfans.com/emb/20180618696111.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来严 ...
随机推荐
- ORM,Entity Framework介绍以及其所包含的基础架构介绍
一:entity framework 6.0 ORM (实体关系模型) O: Domain Object 领域模型 R: Relational Database 关系型数据库 M: Mapping 映 ...
- [LeetCode 题解]:Best Time to Buy and Sell Stock
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Say you ha ...
- Android之常用开发框架
1.Rajawali介绍:安卓的OpenGL ES 2.0/3.0 引擎.可以用于制作普通应用或者动态壁纸,当然也可以用于制作游戏.项目地址: https://github.com/Rajawali/ ...
- [Erlang01] 使用catch与try catch避免嵌套nest_case
catch 如此好用,为什么官方还是推荐用try catch? 1. catch 的用法非常简单: catch case do_check(Test) of {ok,Result} -> do_ ...
- INDEX--关于索引的琐碎
--=========================================================更新时的操作1>更新时有两种方式,一种是在原来的位置更新,另外一种是移除删除 ...
- 透明数据加密 (TDE)常见问题解答
透明数据加密 (TDE)常见问题解答问题任何人只要有权访问加密数据就能对其进行解密吗?TDE 会带来哪些开销?哪些加密算法可与 TDE 一同使用?可以使用第三方加密算法代替 TDE 提供的算法吗?可以 ...
- “全栈2019”Java第六十六章:抽象类与接口详细对比
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- API自动化测试 Soap UI工具介绍
一. 建立测试用例 (一) 基本概念 soapUI 中工程的层次结构 项目名称:位于最上层 (BookStoreTest),项目可以包含多个服务的定义. REST 服务定义:服务其实是对多个 ...
- React-Native 工程添加推送功能 (iOS 篇)
推送已经是是手机应用的基本功能,如果自己实现一套推送系统费时费力,所有一般我们会使用第三方的推送服务,这里我使用「极光推送」作为集成推送的例子,因为有现成的 react native 插件 jpush ...
- 虚拟机CentOS防火墙设置
CentOS6关闭防火墙使用以下命令, 开启防火墙 systemctl start firewalld //临时关闭 # service iptables stop //禁止开机启动 # chkcon ...