Calcite,version:1.26.0
什么是Convention
1. 是一种RelTrait,而且是默认必须有的RelTraitDef
2. 逻辑算子的convention为None,表示未被实现;反过来说物理算子的convention一定不会是None
在CBO优化前会把root进行convention转换,
changeTraits
这里对于logicalSort已经注册Subset#3,
这里调用getOrCreateSubset,目的是什么?
这里注意一个参数,required=true,什么意思?
这个代表当前Subset物理属性的状态,
解释一下?比如排序是一种物理属性,由于parent算子有排序的需求,所以要求,require,当前的算子具有RelCollation的物理属性。
这里required是true,因为这里的物理属性不是因为他自己或inputs,而是被外部显式调用加上的
这里调用getOrCreateSubset,是因为traits变了,Subset是和traits紧密关联的,
所以这里生成了新的Subset,
并且这里还加入了比较复杂的converter的相关逻辑,
因为在每次Subset的traits发生变化的时候,都需要看看是否需要加入converter,
这块逻辑其实不应该加在getOrCreateSubset里面,这样很影响可读性
那么翻译一下,逻辑是啥?
首先,如果convention==None,逻辑算子,不需要conventer
其次,如果物理算子,
新创建的subset,需要conventer
已有的subset,当required属性发生变化时,需要加converter;即原先不是required,现在是,或原先包含required,现在不是
addConverters
注释和底下这个条件匹配,为什么这么判断?
这里的判断和上面的不同,是因为这里是要给RelSet下所有的Subset判断是否要加converter;上面的判断是根据当前Subset判断是否要进入add;这里的逻辑有点混乱,前后很难顺下来
可以看到当前的subset都不满足,所以others为0
总之,changeTraits的结果就是增加一个新的traits的Subset。
setRoot
ensureRootConverters
- 这是唯一处,显式require增加converter的地方;其他地方都是由consumer来require,但是root没有consumer
- 要求root做在的RelSet中的所有subsets,只要和root的traitSet不同的,都增加一个converter
理解,要求这样的convention,你如果不满足,就加一层converter去转换成require的convention,满足需求
什么是,AbstractConverter
- Converter,用于convert一个Relnode到特定的输出convention
- AbstractConverter,抽象的,所以后面需要被rule转换成可实现的关系表达式
注册,有EquivRel,root
converter在注册的时候,
不同的地方在于,要判断一下RelSet,
Converter和他的input,就是需要被转换的RelNode,需要属于同一个RelSet
注册完的结果,
AbstractConverter和他的input,RelSubset#3,在一个Relset中
并且这个RelSet的Parents里面,也加上了这个Converter
在fireRules后,和AbstractConverter相match的rule为,
ExpandConversionRule
专门用于match,AbstractConverter
后面在触发的时候看看,具体做了什么
findBestExp
重复调用ensureRootConverters,避免没有调用setRoot,直接调用findBestExp?
这里会把AbstractConverter的input放到subsets中,避免重复加converter
这里可以看下,root.getRels,这里root是subset是无法直接get到rels的,需要找到Relset先
这里找到,rels中和subset的traitSet匹配的rels,
有意思的是,这里强行用linq4j转成Enumerable,使用了一下lambda,再转回iterator返回,秀啊!