searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

初探jsqlparser-sql解析器

2023-05-25 06:57:38
80
0

初探jsqlparser

大数据处理中离不开SQL,如使用flink、查询各种数据库等场景。
用户提交sql后,系统处理往往需要知道用户提交的一些信息(查询or更新、表名、字段等),因此需要sql解析

jsqlparser介绍

jsqlparser是开源的sql解析器,是mybatis底层解析,有着较为活跃的社区支撑。地址如下:
https://github.com/JSQLParser/JSqlParser
但特定db的特色语句无法支持,如mysql的show语法;


jsqlparser把sql解析成对应的抽象语法树,并通过visitor模式对其中的数据进行访问或改写。

示例

判断sql中是否进行聚合操作(group by),并提取出表名
1.对sql进行解析

CCJSqlParserManager pm = new CCJSqlParserManager();
Statement statement = pm.parse(new StringReader(sql));

2.定义一个visitor,对语句中的group by节点进行访问判断

public class SqlElementFinder implements SelectVisitor, FromItemVisitor{

    private boolean isGroupBy;

    private List<String> tables;

    public SqlElementFinder(){
        isGroupBy = false;
        tables = new ArrayList<>();
    }

    public boolean isGroupBy() {
        return isGroupBy;
    }

    public List<String> getTables() {
        return tables;
    }

    public boolean judge(Select select){
        select.getSelectBody().accept(this);
        return isGroupBy;
    }

    @Override
    public void visit(PlainSelect plainSelect) {
        if(plainSelect.getGroupBy() != null){
            isGroupBy = true;
        }
        plainSelect.getFromItem().accept(this);
    }

    @Override
    public void visit(Table table) {
        tables.add(table.getName());
    }

    @Override
   //考虑子查询情况
    public void visit(SubSelect subSelect) {
        subSelect.getSelectBody().accept(this);
    }

}


3.判断是否为select语句,并处理

        SqlElementFinder sqlElementFinder = new SqlElementFinder();
        if(statement instanceof Select){
            System.out.println("select");
            sqlElementFinder.judge(((Select) statement));


            System.out.println(sqlElementFinder.isGroupBy());
            System.out.println(sqlElementFinder.getTables());
        } else if (statement instanceof Insert) {
            System.out.println("insert");
        } else if (statement instanceof Update){
            System.out.println("update");
        }


4.结果

//语句     
select cc from (select aa,bb,cc from tt1 where id = 1) group by cc;

//结果
select
true
[tt1]

 


进一步开发

考虑到jsqlparser不支持特定db的特色语句,由于jsqlparser基于javacc能力进行解析,可通过自行修改语法规则描述,并重新生成分析器,即可满足需求。


总结

jsqlparser作为开源的sql解析器,功能基本能满足我们对基本sql的解析,若需自定义语句解析,可利用javacc能力,对jsqlparser进行修改。

0条评论
0 / 1000
冼****铭
4文章数
0粉丝数
冼****铭
4 文章 | 0 粉丝
冼****铭
4文章数
0粉丝数
冼****铭
4 文章 | 0 粉丝
原创

初探jsqlparser-sql解析器

2023-05-25 06:57:38
80
0

初探jsqlparser

大数据处理中离不开SQL,如使用flink、查询各种数据库等场景。
用户提交sql后,系统处理往往需要知道用户提交的一些信息(查询or更新、表名、字段等),因此需要sql解析

jsqlparser介绍

jsqlparser是开源的sql解析器,是mybatis底层解析,有着较为活跃的社区支撑。地址如下:
https://github.com/JSQLParser/JSqlParser
但特定db的特色语句无法支持,如mysql的show语法;


jsqlparser把sql解析成对应的抽象语法树,并通过visitor模式对其中的数据进行访问或改写。

示例

判断sql中是否进行聚合操作(group by),并提取出表名
1.对sql进行解析

CCJSqlParserManager pm = new CCJSqlParserManager();
Statement statement = pm.parse(new StringReader(sql));

2.定义一个visitor,对语句中的group by节点进行访问判断

public class SqlElementFinder implements SelectVisitor, FromItemVisitor{

    private boolean isGroupBy;

    private List<String> tables;

    public SqlElementFinder(){
        isGroupBy = false;
        tables = new ArrayList<>();
    }

    public boolean isGroupBy() {
        return isGroupBy;
    }

    public List<String> getTables() {
        return tables;
    }

    public boolean judge(Select select){
        select.getSelectBody().accept(this);
        return isGroupBy;
    }

    @Override
    public void visit(PlainSelect plainSelect) {
        if(plainSelect.getGroupBy() != null){
            isGroupBy = true;
        }
        plainSelect.getFromItem().accept(this);
    }

    @Override
    public void visit(Table table) {
        tables.add(table.getName());
    }

    @Override
   //考虑子查询情况
    public void visit(SubSelect subSelect) {
        subSelect.getSelectBody().accept(this);
    }

}


3.判断是否为select语句,并处理

        SqlElementFinder sqlElementFinder = new SqlElementFinder();
        if(statement instanceof Select){
            System.out.println("select");
            sqlElementFinder.judge(((Select) statement));


            System.out.println(sqlElementFinder.isGroupBy());
            System.out.println(sqlElementFinder.getTables());
        } else if (statement instanceof Insert) {
            System.out.println("insert");
        } else if (statement instanceof Update){
            System.out.println("update");
        }


4.结果

//语句     
select cc from (select aa,bb,cc from tt1 where id = 1) group by cc;

//结果
select
true
[tt1]

 


进一步开发

考虑到jsqlparser不支持特定db的特色语句,由于jsqlparser基于javacc能力进行解析,可通过自行修改语法规则描述,并重新生成分析器,即可满足需求。


总结

jsqlparser作为开源的sql解析器,功能基本能满足我们对基本sql的解析,若需自定义语句解析,可利用javacc能力,对jsqlparser进行修改。

文章来自个人专栏
大数据组件学习
4 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0