这次遇到一种神奇的现象
1 | SELECT `DATE_CD`, SUM(`IB0002001_CN000`) |
采用规则CoreRules.AGGREGATE_REMOVE去除所以的外层select。会出现报错。。
1 | java.lang.AssertionError: Need to implement org.apache.calcite.plan.volcano.RelSubset |
看下转出来的规则树,出现了神奇的HepRelVertex
1 | LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)]) |
如果不采取规则,得出的规则树是
1 | LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)]) |
可以看出过滤条件居然变成了inner join的子查询了。
而CoreRules.AGGREGATE_REMOVE规则会把LogicalAggregate/LogicalValues这种树状结构错误优化得到HepRelVertex,就会出现错误。
如果修复这个问题呢,有两个做法
方法一,修改规则,不适配LogicalValues即可
复制CoreRules.AGGREGATE_REMOVE规则源码,修改matchs方法
1 |
|
方法二,过滤条件不转为子查询
通过测试,条件超过19个就会出现子查询,20是一个限制。
过滤源码找出所有跟20有关的数字,发现有这么一项配置
1 | public class SqlToelConverter{ |
一直找下去就可以发现在构建planner的时候有可以配置的地方。
1 | SqlToRelConverter.ConfigBuilder configBuilder = SqlToRelConverter.configBuilder(); |
完整代码1
2
3
4
5
6
7
8
9
10SqlParser.ConfigBuilder parserConfig = SqlParser.configBuilder();
SqlParser.Config build = parserConfig.setCaseSensitive(false).setLex(Lex.MYSQL).build();
SqlToRelConverter.ConfigBuilder configBuilder = SqlToRelConverter.configBuilder();
SqlToRelConverter.Config config = configBuilder.withInSubQueryThreshold(Integer.MAX_VALUE).build();
FrameworkConfig frameworkConfig = Frameworks.newConfigBuilder()
.parserConfig(build)
.sqlToRelConverterConfig(config)
.defaultSchema(rootSchema)
.build();
如果不想让子查询转为join
一般情况下,如果出现如下sql1
2
DATE_CD in ( SELECT DATE_CD FROM DIM_DATE WHERE DATE_CD = '2020-05-31' )
calcite 会自动将语句转为join语句,可以通过下面的开关关闭该功能。
1 |
|