【 jsqlparser学习】
2022/1/5 2:03:56
本文主要是介绍【 jsqlparser学习】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
jsqlparser学习
一.主要开源API
1.guava下的graph包
graph包下的类,解决DAG矢量图问题(算子之间的顺序关系),不是本文重点,主要讲jsqlparser
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-jre</version> </dependency>
package com.google.common.graph;
2.jsqlparser
算子sql解析与生成
jsqlparser-4.2.jar
二.DDL算子实现过程
思路
需求: DDL算子的目的是通过一些特殊的操作,最终生成一个新的sql
jsqlparser功能:每一个sql都可以用jsqlparser进行解析
基于以上两点,我们在开发每一个DDL算子的时候,可以写一些简单的sql,比如筛选算子,其功能就是对已知的表或者结果集添加where条件,筛选得到我们想要的结果,我们可以写个简单的sql,比如:
select id,name from city where name='张三'
假设这条sql就是我们的筛选算子最终得到的结果,那么如何通过jsqlparser生成这样的一条sql呢?
我们可以把这条sql放在测试类,通过jsqlparser相关的api得到这条sql的对象信息
@Test public void test() throws Exception { String sql = "select id,name from city where name='张三'"; Select select = (Select) CCJSqlParserUtil.parse(sql); PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); }
该对象包含的信息如图所示
- 查询的列 id name
- where
- join
- group by
- order by
- 等…
我们可以通过测试类的结果,反向推出筛选算子的具体实现(实现的时候注意兼容性和扩展性,比如两表join是多表join的特例,要以多表join的实现逻辑来实现)
//获取前置节点的sql PlainSelect preSql = prePlainSelect(); PlainSelect newSql = new PlainSelect(); String tableAlias = tableAlias(); //设置别名 SubSelect subSelect = new SubSelect(); subSelect.setSelectBody(preSql); subSelect.setUseBrackets(true); subSelect.setAlias(new Alias(tableAlias)); newSql.setFromItem(subSelect); .............
其他算子的实现同筛选算子这个例子,因为我们第一次接触到jsqlparser的时候,并不是特别熟悉jsqlparser的对象的结构,我们可以通过写测试类先用jsqlparser解析,然后再反向写出jsqlparser生成sql对象的过程,每一个算子的实现,都会对jsqlparser的api有一个更深入的认识
按照上面这个思路,我们可以支持很多单个算子的实现,那么jsqlparser能否实现俄罗斯套娃呢?
答案是肯定的,前提条件是每个单独算子的健壮性和可扩展性,如果能保证单独算子的健壮性和可扩展性,无论算子之间如何嵌套,都是能够支持的.
三.解决算子bug思路
- 先通过传入的节点id,定位到是哪个算子出错
- 然后先看下这个错误的sql是什么样的,在日志中有打印
- 再思考下正确的sql应该怎么写
- debug修改下算子的实现,over
- 利用这个思路解决算子相关的bug会非常快,如果慢只是因为没有用jsqlparser拼过sql,不熟悉对象结构
四.关于jsqlparser的扩展
目前代码中只用到了一处扩展,就是在where条件的时候,如果or和and同时存在,如何给or和and条件添加自定义括号呢?这个在jsqlparser中是没有API的,但我们可以对jsqlparser进行扩展
扩展的逻辑非常简单,只需要重写toString方法,其实jsqlparser最终生成的是一个对象,对象的toString方法输出的是一个String类型的,在数据库可执行的sql,基于这个原理,jsqlparser的每一个组件,如where,join,group by等组件的toString方法都是通过java对象去拼接构造,然后生成我们想要的String-sql
基于这个简单的扩展,我们可以对其进行更加丰富的扩展,目前还未遇到相关需求
对and进行扩展
package com.deepexi.datasense.ddl.operator.core.extend; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; public class AndExpressionExtend extends AndExpression { public AndExpressionExtend() { } public AndExpressionExtend(Expression leftExpression, Expression rightExpression) { this.setLeftExpression(leftExpression); this.setRightExpression(rightExpression); } @Override public String toString() { return "(" + this.getLeftExpression() + " " + this.getStringExpression() + " " + this.getRightExpression() + ")"; } }
对or进行扩展
package com.deepexi.datasense.ddl.operator.core.extend; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; public class OrExpressionExtend extends OrExpression { public OrExpressionExtend() { } public OrExpressionExtend(Expression leftExpression, Expression rightExpression) { this.setLeftExpression(leftExpression); this.setRightExpression(rightExpression); } @Override public String toString() { return "(" + this.getLeftExpression() + " " + this.getStringExpression() + " " + this.getRightExpression() + ")"; } }
五.jsqlparser是万能的吗?
答案是否定的,jsqlparser不支持某些数据库的特定的一些函数,比如clickhouse的 array join 函数是解析不了的
这篇关于【 jsqlparser学习】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16Vue3资料:新手入门必读教程
- 2024-11-16Vue3资料:新手入门全面指南
- 2024-11-16Vue资料:新手入门完全指南
- 2024-11-16Vue项目实战:新手入门指南
- 2024-11-16React Hooks之useEffect案例详解
- 2024-11-16useRef案例详解:React中的useRef使用教程
- 2024-11-16React Hooks之useState案例详解
- 2024-11-16Vue入门指南:从零开始搭建第一个Vue项目
- 2024-11-16Vue3学习:新手入门教程与实践指南
- 2024-11-16Vue3学习:从入门到初级实战教程