Apache Calcite JDBC查询流程详解

之前写了一篇文章使用Apache Calcite进行JDBC多数据源关联里面使用Calcite的JDBC的Adapter对后端数据库进行SQL查询,代码例子如下,整个实现过程很简单,与常规的JDBC使用没有任何区别。但是Calcite在内部整个流程中做了很多有趣的工作,比如sql解析,生成关系表达式,优化关系表达式生成执行计划等。这篇文章会详细分析Calcite JDBC查询的整个流程实现,理解了这整个流程就对Calcite的核心功能和Calcite能做什么都会有深入的了解。

@Test
public void singleSourceTest() throws SQLException {
   
    Properties config = new Properties();
    config.put("model", TestUtil.resourcePath("singleSource.json"));
    config.put("lex", "MYSQL");
    String sql = "select s.name,c.name from student as s join colleage as c on s.cid = c.id";

    try (Connection con = DriverManager.getConnection("jdbc:calcite:", config)) {
   
        try (Statement stmt = con.createStatement()) {
   
            try (ResultSet rs = stmt.executeQuery(sql)) {
   
                printRs(rs);
            }
        }
    }
}

Calcite JDBC的实现类

在这里插入图片描述
Calcite不仅实现了它的核心功能,也为开发者提供了一个称为Avatica的构建JDBC和ODBC Driver的框架,如果希望实现自己的JDBC Driver可以详细学习一下这个框架
从上图可知,Calcite core模块中的JDBC的类实现都是基于Avatica框架。我们在使用Calcite进行JDBC查询时Connection,Statement和ResultSet实例其实就是CalciteJdbc41Connection,CalciteJdbc41Statement,CalciteResultSet。

Calcite的JDBC Driver

在使用Calcite的JDBC Driver时,我们无需手动注册。如下图所示,Calcite核心模块会利用SPI方式注册。
在这里插入图片描述
Avatica框架在创建JDBC的接口实例的时候要使用一个工场类来创建对应的实例。Calcite的Driver实现中通过getFactoryClassName方法获得这个工场类。另外,在这个方法中也可以看出Calcite JDBC实现只支持JDBC4.1版本。

 @Override protected String getFactoryClassName(JdbcVersion jdbcVersion) {
   
    switch (jdbcVersion) {
   
    case JDBC_30:
    case JDBC_40:
      throw new IllegalArgumentException("JDBC version not supported: "
          + jdbcVersion);
    case JDBC_41:
    default:
      return "org.apache.calcite.jdbc.CalciteJdbc41Factory";
    }
  }

如下图所示,通过CalciteJdbc41Factory提供的方法,可以获得Connection, Statement, ResultSet等实例对象。
在这里插入图片描述

获取Calcite的JDBC Conection

当我们通过DriverManager获取Calcite的Connection的时候,大致过程如下:
在这里插入图片描述
DriverManager会调用Calcite的Driver的connect方法来创建Calcite Connection实例:

  public Connection connect(String url, Properties info) throws SQLException {
   
    if (!acceptsURL(url)) {
   
      return null;
    }
    final String prefix = getConnectStringPrefix();
    assert url.startsWith(prefix);
    final String urlSuffix = url.substring(prefix.length());
    final Properties info2 = ConnectStringParser.parse(urlSuffix, info);
    final AvaticaConnection connection =
        factory.newConnection(this, factory, url, info2);
    handler.onConnectionInit(connection);
    return connection;
  }

上面的connect方法实现中,Calcite的Connection是通过前面说的CalciteJdbc41Factory创建的,Connection实例的类是CalciteJdbc41Connection。
另外在返回Connection之前,Calcite还会根据配置的model来解析model格式(json或yaml)生成JdbcSchema。

{
   
    "defaultSchema": "db1",
    "schemas": [
        {
   
            "factory": "org.apache.calcite.adapter.jdbc.JdbcSchema$Factory",
            "name": "db1",
            "operand": {
   
                "jdbcDriver": "com.mysql.cj.jdbc.Driver",
                "jdbcPassword": "changeme",
                "jdbcUrl": "jdbc:mysql://localhost:3306/test",
                "jdbcUser": "root"
            },
            "type": "custom"
        }
    ],
    "version": "1.0"
}

JdbcSchema在创建的过程主要是根据model中jdbc的信息建立与后端数据库的连接池。

创建Statement

在这里插入图片描述
当我们调用connection的createStatement方法创建Statement实例的时候,Calcite的执行流程如上图。整

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值