使用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结果重新转换为自己实现的关系表达式/执行器.