Apache Calcite进行SQL解析(java代码实例)

 更新时间:2022年01月26日 10:19:02   作者:追求无悔  
Calcite是一款开源SQL解析工具, 可以将各种SQL语句解析成抽象语法树AST(Abstract Syntax Tree), 之后通过操作AST就可以把SQL中所要表达的算法与关系体现在具体代码之中,今天通过代码实例给大家介绍Apache Calcite进行SQL解析问题,感兴趣的朋友一起看看吧

背景

当一个项目分了很多模块,很多个服务的时候,一些公共的配置就需要统一管理了,于是就有了元数据驱动!

简介

什么是Calcite?
是一款开源SQL解析工具, 可以将各种SQL语句解析成抽象语法树AST(Abstract Syntax Tree), 之后通过操作AST就可以把SQL中所要表达的算法与关系体现在具体代码之中。
Calcite能做啥?

  • SQL 解析
  • SQL 校验
  • 查询优化
  • SQL 生成器
  • 数据连接

实例

今天主要是贴出一个java代码实例,实现了:解析SQL语句中的表名
上代码:
SQL语句转化:

public static SqlNode parseStatement(String sql) {
        SqlParser parser = SqlParser.create(sql, config.getParserConfig());
        try {
            return parser.parseQuery();
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnsupportedOperationException("operation not allowed");
        }
    }

解析Select中的表名:

private static Set<String> extractSourceTableInSelectSql(SqlNode sqlNode, boolean fromOrJoin) {
        if (sqlNode == null) {
            return new HashSet<>();
        }
        final SqlKind sqlKind = sqlNode.getKind();
        if (SqlKind.SELECT.equals(sqlKind)) {
            SqlSelect selectNode = (SqlSelect) sqlNode;
            Set<String> selectList = new HashSet<>(extractSourceTableInSelectSql(selectNode.getFrom(), true));
            selectNode.getSelectList().getList().stream().filter(node -> node instanceof SqlCall)
                .forEach(node -> selectList.addAll(extractSourceTableInSelectSql(node, false)));
            selectList.addAll(extractSourceTableInSelectSql(selectNode.getWhere(), false));
            selectList.addAll(extractSourceTableInSelectSql(selectNode.getHaving(), false));
            return selectList;
        if (SqlKind.JOIN.equals(sqlKind)) {
            SqlJoin sqlJoin = (SqlJoin) sqlNode;
            Set<String> joinList = new HashSet<>();
            joinList.addAll(extractSourceTableInSelectSql(sqlJoin.getLeft(), true));
            joinList.addAll(extractSourceTableInSelectSql(sqlJoin.getRight(), true));
            return joinList;

        if (SqlKind.AS.equals(sqlKind)) {
            SqlCall sqlCall = (SqlCall) sqlNode;
            return extractSourceTableInSelectSql(sqlCall.getOperandList().get(0), fromOrJoin);
        if (SqlKind.IDENTIFIER.equals(sqlKind)) {
            Set<String> identifierList = new HashSet<>();
            if (fromOrJoin) {
                SqlIdentifier sqlIdentifier = (SqlIdentifier) sqlNode;
                identifierList.add(sqlIdentifier.toString());
            }
            return identifierList;
        Set<String> defaultList = new HashSet<>();
        if (sqlNode instanceof SqlCall) {
            SqlCall call = (SqlCall) sqlNode;
            call.getOperandList()
                .forEach(node -> defaultList.addAll(extractSourceTableInSelectSql(node, false)));
        return defaultList;
    }

解析Insert语句中的表名:

private static Set<String> extractSourceTableInInsertSql(SqlNode sqlNode, boolean fromOrJoin) {
        SqlInsert sqlInsert = (SqlInsert) sqlNode;
        Set<String> insertList = new HashSet<>(extractSourceTableInSelectSql(sqlInsert.getSource(), false));
        final SqlNode targetTable = sqlInsert.getTargetTable();
        if (targetTable instanceof SqlIdentifier) {
            insertList.add(((SqlIdentifier) targetTable).toString());
        }
        return insertList;
    }

执行效果

private static final String sql0 = "SELECT MIN(relation_id) FROM tableA JOIN TableB  GROUP BY account_instance_id, follow_account_instance_id HAVING COUNT(*)>1";

private static final String sql1 = "SELECT * FROM blog_user_relation a WHERE (a.account_instance_id,a.follow_account_instance_id) IN (SELECT account_instance_id,follow_account_instance_id FROM Blogs_info GROUP BY account_instance_id, follow_account_instance_id HAVING COUNT(*) > 1)";
private static final String sql2 = "select name from (select * from student)";
private static final String sql3 = "SELECT * FROM Student LEFT JOIN Grade ON Student.sID = Grade.gID\n" +
            "UNION\n" +
            "SELECT * FROM Student RIGHT JOIN Grade ON Student.sID = Grade.gID";
private static final String sql4 = "SELECT *\n" +
            "FROM teacher\n" +
            "WHERE birth = (SELECT MIN(birth)\n" +
            "               FROM employee)";
private static final String sql5 = "SELECT sName\n" +
            "FROM Student\n" +
            "WHERE '450' NOT IN (SELECT courseID\n" +
            "                    FROM Course\n" +
            "                    WHERE sID = Student.sID)";
final SqlNode sqlNode0 = parseStatement(sql0);
System.out.println("sqlNode0: " + extractSourceTableInSelectSql(sqlNode0, false));

结果为:

到此这篇关于Apache Calcite进行SQL解析的文章就介绍到这了,更多相关Apache Calcite解析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Elasticsearch如何实现简单的脚本排序

    详解Elasticsearch如何实现简单的脚本排序

    Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎,可以为所有类型的数据提供近乎实时的搜索和分析。本文主要介绍了Elasticsearch如何实现简单的脚本排序,感兴趣的可以了解一下
    2023-01-01
  • JDK版本修改不生效的解决方法

    JDK版本修改不生效的解决方法

    本文主要介绍了在配置新电脑环境时遇到JDK版本切换失败的问题,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • Springboot项目引入druid安装部署使用教程

    Springboot项目引入druid安装部署使用教程

    这篇文章主要介绍了Springboot项目引入druid安装部署使用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • Java中的Map集合简单汇总解析

    Java中的Map集合简单汇总解析

    这篇文章主要介绍了Java中的Map集合简单汇总解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • javaweb中Filter(过滤器)的常见应用

    javaweb中Filter(过滤器)的常见应用

    这篇文章主要介绍了javaweb中Filter的常见应用,过滤器的使用方法,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • Java读取resources目录下文件路径的九种代码示例教程

    Java读取resources目录下文件路径的九种代码示例教程

    在Java开发中经常需要读取项目中resources目录下的文件或获取资源路径,这篇文章主要给大家介绍了关于Java读取resources目录下文件路径的九种代码示例教程,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Spring Boot实现分布式锁的自动释放的示例代码

    Spring Boot实现分布式锁的自动释放的示例代码

    在实际开发中,我们可以使用 Redis、Zookeeper 等分布式系统来实现分布式锁,本文将介绍如何使用 Spring Boot 来实现分布式锁的自动释放,感兴趣的朋友跟随小编一起看看吧
    2023-06-06
  • java图片格式转换的三段代码

    java图片格式转换的三段代码

    这篇文章主要分享了java图片格式转换的三段代码,小编查找资料整理了java图片格式转换的三段不同代码,推荐给大家。
    2015-11-11
  • 解决MyEclipse下启动项目时JBoss内存溢出的问题

    解决MyEclipse下启动项目时JBoss内存溢出的问题

    下面小编就为大家带来一篇解决MyEclipse下启动项目时JBoss内存溢出的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java并发之BlockingQueue的使用

    Java并发之BlockingQueue的使用

    这篇文章主要介绍了Java并发之BlockingQueue的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06

最新评论