Calcite分析 -- ConverterRule

Calcite Version:1.26.0

 

EnumerableRule是一种ConverterRule,用于将逻辑算子转化为物理算子,并改变其convention。 

 

EnumerableSortedAggregateRule

将LogicalAggregate转换成物理算子,

ConverterRule主要做两件事,

convert,真正的转换算子

transformTo,注册新生成的算子

 

convert

以EnumerableSortedAggregateRule为例,

2件事,

更改input的traits,典型的required;物理属性就是这样Topdown的往下传递的

生成新的物理算子,包含新生成的自身的selfTraits

 

更改input的traits,调用convert,这里的convert逻辑基本等同于changeTraits,参考Calcite分析 -- Convention&Converter

主要就是在input,增加subset,

 

transformTo

新生成的rel#26:EnumerableSortedAggregate.ENUMERABLE.[0],调用transformTo注册,

正常的注册过程,会新增一个subset,

rel#27:RelSubset#2.ENUMERABLE.[0] 

但这里会触发,getOrCreateSubset的addConverters (触发条件,subset为新创建,并且convention不为none,即新创建的物理算子)

 

注意required是false 

 

addConverters

RelSet是等价集合,所以每个SubSet应该都是等价的,Parent可以任意选取cost小的作为input。

Rule是等价变化,变换出来的RelNode和原先是等价的,但是有个问题是Rule本身是不会考虑物理属性的,Traits。

所以如果要做到物理属性的等价,就需要加入Conventer,来保证所有SubSet的物理属性的等价。

所以这里的逻辑是,如果subset中既有required,又有Delivered,那么需要将Delivered的物理属性转换成Required所需要的,这样parent才能用啊。

这里的case,是当前subset是非required,那么看看set的subset中是不是有required?

  

这里满足条件的只有,rel#24:RelSubset#2.ENUMERABLE.[0 DESC-nulls-last]

这里注意from和to的转换,一定是将非required的转换成required的

 

最终调用到增加converter,

两种选择,如果是非top down,那么创建AbstractConverter;否则调用Convention.enforce

AbstractConverter,只会修改Convention;Convention.enforce会对齐所有的traits

 

Convention.enforce

EnumerableConvention,会分别比较Convention和Collation,有不匹配的进行转换;

这里的case是Collation不同,所以创建一个EnumerableSort,

  

最后是注册这个新创建的enforcer,

注意enforcer是和to是等价的,因为他们的convention相同

结果,

 

继续注册,rel#26:EnumerableSortedAggregate.ENUMERABLE.[0]

在addRelToSubset中,完成addRels后,调用到ruleDriver.drive()

为新的rel#26:EnumerableSortedAggregate.ENUMERABLE.[0]增加Task,

 

这块逻辑,

- 非isLogical,是PhysicalNode或者convention不为null

- canPassThrough,等价于PhysicalNode,除非已经passThrough过了

PassThrough,

只是找出,subsets中是required,并且正在优化的,并且traitSet和当前node不符合的subset,对该subset再调用一遍OptimizeInput

 

getOptimizeInputTask,

和一般的常见逻辑比,这里由于rel和group的traitSet不匹配,所以先要convert生成新的匹配的node,然后再注册一下,

convert调用到passThrough,把物理属性传递到input,

用新生成的input,copy生成新的RelNode返回

  

返回新生成的RelNode是,

 

最后完成注册,并生成新的Task

总结一下,这个rule的过程,

 

EnumerableLimitRule

上面的例子是个ConvertRule的标准的例子,

而这个rule,重写了ConvertRule的onMatch,

但是做的工作仍然是两步,

convert,生成新的算子

transform,注册

- 但是这里没有显式的convert函数,都写在onMatch中了,transformTo以外的工作都是在convert

- 新增input,这里增加了一个input logicalSort算子;这也是他为什么不用标准的convertRule的原因

这里增加的logicalSort以原来的input为input,加了一层算子

 

这里replace不会改变原先traitSet的值,是会做clone的,所以RelNode的traits是不会改变的,Convention变化只是生成不同的Subset

 

changeTraits,

先ensureRegister,然后getOrCreateSubset,具体逻辑在Converter相关blog中分析过,

这里的sort是新的,所以会注册生成新的Relset,并生成带Enumerable convention的subset

transformTo,完成注册,

结果如图,

这个Rule的逻辑不复杂,但是新生成了一个RelSet,比较特殊

 

posted on 2021-09-08 11:18  fxjwind  阅读(565)  评论(0编辑  收藏  举报