jsqlparser:基于抽象语法树(AST)遍历SQL语句的语法元素
jsqlparser是一个java的SQL语句解析器,基于它可以实现很多之前无法完成的工作。
<!-- maven 依赖库引用 --><dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>4.5</version></dependency
比如如下的SQL语句:
SELECT person.id,person.name,group.name FROM person JOIN group ON person.group_id = group.id WHERE person.birthdate > '1980-01-01'
在MySQL中执行没有任何问题,但是如果用phoenix在HBase数据库中执行,语法是过不去的。因为phoenix中默认字段名,表名都是大写的,如果指定小写的字段和表名,需要加双引号.
SELECT "person"."id","person"."name","group"."name" FROM "person" JOIN "group" ON "person"."group_id" = "group"."id" WHERE "person"."birthdate" > '1980-01-01'
对于一个SQL语句如何能根据数据库的要求为字段名和表名自动加引号或双引号,就需要用到jsqlparser这个利器。
jsqlparser
解析一个SQL语句后会生成一个抽象语法树(AST-- Abstract Syntax Tree)对象SimpleNode
,并提供了用于遍历AST的接口CCJSqlParserVisitor
,应用层只要实现这个接口我们就可以通过接口方法得到想要的SQL语法元素节点对象,比如Column
,Table
。当然还可以根据实际需要干点别的。
以下就以为字段名和表名加双引号为例,说明如何用CCJSqlParserVisitor
来遍历所有AST节点
@Testpublic void test10ParseVisitor() throws ParseException {String sql = "SELECT person.id,person.name,group.name FROM person JOIN group ON person.group_id = group.id WHERE person.birthdat > '1980-01-01'";/** 创建SQL语句解析器实例 */CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);/** 解析SQL语句 */Statement stmt = parser.Statement();/** 使用 LogVisiter对象遍历AST的所有节点 */parser.getASTRoot().jjtAccept(new LogVisitor(), null);System.out.printf("sql--> %s",stmt);}/*** 遍历所有节点的{@link net.sf.jsqlparser.parser.CCJSqlParserVisitor} 接口实现类* @author guyadong**/static class LogVisitor extends CCJSqlParserDefaultVisitor{@Overridepublic Object visit(SimpleNode node, Object data) {Object value = node.jjtGetValue();/** 根据节点类型找出表名和字段名节点,对名字加上双引号 */if (node.getId() == CCJSqlParserTreeConstants.JJTCOLUMN) { System.out.printf("column %s",value.toString());Column column = (Column)value;column.setColumnName("\"" + column.getColumnName() + "\"");Table table = column.getTable();if(null != table){table.setName("\"" + table.getName() + "\"");}} else if (node.getId() == CCJSqlParserTreeConstants.JJTTABLE) {System.out.printf("table %s",value.toString());Table table = (Table)value;if(null != table){table.setName("\"" + table.getName() + "\"");}}else if(null != value){/** 其他类型节点输出节点类型值,Java类型和节点值 */System.out.printf("%d %s %s",node.getId(),value.getClass().getSimpleName(),value.toString());}return super.visit(node, data);}}
输出:
6 PlainSelect SELECT person.id, person.name, group.name FROM person JOIN group ON person.group_id = group.id WHERE person.birthdat > ‘1980-01-01’
9 SelectExpressionItem person.id
column person.id
9 SelectExpressionItem person.name
column person.name
9 SelectExpressionItem group.name
column group.name
table person
10 Join JOIN group ON person.group_id = group.id
table group
14 EqualsTo person.group_id = group.id
column person.group_id
column group.id
14 GreaterThan person.birthdat > ‘1980-01-01’
column person.birthdat
20 StringValue ‘1980-01-01’
sql–> SELECT “person”.“id”, “person”.“name”, “group”.“name” FROM “person” JOIN “group” ON “person”.“group_id” = “group”.“id” WHERE “person”.“birthdat” > ‘1980-01-01’
从上面最后一行输出可以看到,jsqlparser已经精确的将SQL语句中所有表名和字段名都自动加了双引号。
参考资料
《Parsing table and column names from SQL/HQL Java》
jsqlparser:基于抽象语法树(AST)遍历SQL语句的语法元素相关推荐
- 学习SQL应知道的动态SQL语句基本语法
学习SQL应知道的动态SQL语句基本语法 1 .普通SQL语句可以用Exec执行 9Kp=A ' CdaFr1 eg: Select * from tableName Wsc+A:<&q ...
- Sql Server实用操作-动态sql语句基本语法
如何将exec执行结果放入变量中? declare @num int, @sqls nvarchar(4000) set @sqls='select @a=count(*) from tableNam ...
- 动态sql语句基本语法
--****************** 动态sql语句基本语法 *****************------------------------------- ...
- 动态SQL语句的语法
动态SQL是在运行时生成和执行SQL语句的编程方法.动态是和静态相对而言的.静态SQL指的是在代码编译时刻就已经包含在代码中的那些已经充分明确的固定的SQL语句. PL/SQL提供了两种方式来编写动态 ...
- mysql创建多表视图sql语句_SQL语法(包括建库、建表、建视图、查询、增加、删除、修改)...
SQL语法(包括建库.建表.建视图.查询.增加.删除.修改) SQL分类: DDL-数据定义语言(CREATE,ALTER,DROP,DECLARE) DML-数据操纵语言(SELECT,DELETE ...
- 分布式事务seat对于sql语句的语法要求
昨天工作中,出现了一个系统异常 系统原因如下: io.seata.common.exception.NotSupportYetException: not support the syntax of ...
- SQL语句基础语法——简单的增,删,查,改
SQL语句全称为Structured Query Language,翻译为结构化查询语句,是面向数据库的语句.但是不同的数据库会有一些出入,使用数据库时应阅读相应的数据库手册. ...
- php原生sql语法,thinkphp执行原生SQL语句的实现方法
怎样在thinkphp里面执行原生的sql语句? $Model = new Model();//或者 $Model = D(); 或者 $Model = M(); $sql = "selec ...
- iOS逆向:【代码混淆】1、基于编译器混淆静态库(StaticLib)2、字符串加密:使用clang-c接口将源代码转换成抽象语法树,并对抽象语法树进行遍历和分析,分析代码中的字符串,并进行加密处理。
文章目录 前言 I .LLVM编译一个源文件的过程 1.1.预处理 1.2.将符号化后的内容转化为一棵解析树 (parse tree) 1.3.将 AST 转换为更低级的中间码 (LLVM IR) 1 ...
最新文章
- 数据库连接池到底应该设多大?
- 随机森林为何要有放回抽样
- Ubuntu中Samba的安装配置和使用[图文]
- python程序员工作怎样-现在Python就业薪资高吗?Python程序员前景怎么样?
- Docker logs 命令
- 《游戏大师Chris Crawford谈互动叙事》一22.1 互动叙事前途无量
- 解决ubuntu首次安装Mysql之后,首次登录出现ERROR 1698 (28000): Access denied for user 'root'@'localhost'的方法
- JAVA JDK1.5-1.9新特性
- Bootstrap基础3(表单)
- Oracle命令--查询语句
- equals()与hashCode()方法协作约定
- Windows令牌窃取提权和烂土豆提权学习
- AD检查步骤及其顺序
- usb芯片+android+驱动,PL2303芯片驱动
- electron-vue中调用系统屏幕键盘(linux与windows)
- php mud游戏源码,mud手游源码,mud安卓端源码,谁与争锋mud源码:关于MUD纯文字游戏架设(回答得好加分100)(开源mud游戏框架)-南开游戏网...
- ZXing之生成条形码
- 有卡却显示无服务器,为什么卡一直显示无服务
- Oracle RushQL勒索病毒恢复方法
- 时间序列中Hurst指数的计算(python代码)