使用Calcite制作分库分表中间件,在实现功能的过程中,存在着几种用途,总得来说,有三种.

    1.仅分析或简单执行
    例子1

    观察此SQL

    UPDATE Person SET FirstName = ‘Fred’ WHERE LastName = ‘Wilson’
    Calcite会把它编译成类似下面的关系表达式

    LogicalTableModify
    LogicalFilter
    LogicalProject
    LogicalTableScan
    我们仅仅需要分析LogicalFilter条件,就能路由此sql,并不需要Calcite的执行器来执行

    例子2

    UPDATE Person SET FirstName = ‘Fred’ WHERE LastName = ‘Wilson’ AND 1=1;
    INSERT INTO Persons VALUES (‘Gates’, ‘Bill’, ‘Xuanwumen 10’, ‘Beijing’,1+1);
    与上述的例子不同,增加了表达式计算

    LogicalFilter(….,n=true)
    LogicalProject(….,1=1)
    LogicalValues(….,true)//常量折叠
    LogicalProject(….,1+1)
    LogicalValues({})//空的一行
    一般来说,LogicalProject会包含计算的表达式,此时我们基于使用分库分表的架构,我们可以继续分析LogicalFilter得出对应的分片,而且可以利用LogicalProject编译出表达式计算器,对sql的表达式进行化简,计算,最终得到常量,进一步转化为SQL语法树中的文本直接量.

    所以在这个例子中,我们并没有完全使用Calcite的执行器,仅仅使用了必要的部分LogicalProject的执行器.当然大部分情况下,SQL可以直接发往数据库中执行,并不需要对表达式计算,但是遇上一些特殊情况,我们就要处理它,比如按日期分片,使用now函数得出日期,我们就有必要执行now函数,得到常量值,然后进一步路由.或者函数需要引用Session级别的变量,比如user(),last_lnsert_id(),这些变量在物理库是不一致的,所以我们有必要对他们进行计算.

    2.用作查询器
    大部分项目都直接把Calcite用作查询器,毕竟现实条件就是如此,受到开发能力,时间限制,没有能力编写SQL查询编译器也没有能力实现完整的执行器.

    他们立足于Calcite支持的标准SQL语法定制改造.

    3.仅用作优化器
    当我们拥有自己实现的SQL编译器,也有了自己实现的执行器.我们就可以仅仅引入Calcite作为优化器.具体来说也很简单.使用RelBuilder构建出需要优化的部分RelNode,然后使用优化器进行优化,求解.然后把RelNode结果重新转换为自己实现的关系表达式/执行器.