• Calcite分析 -- Implement


    Calcite Version:1.26.0

    CsvTest

    select "EMPNO", "JOINTIMES" from "DATE" order by "JOINTIMES"

    到优化前的调用栈,

    其中avatica,是calcite项目中一个独立的子项目,用于封装和server之间的交互,参考,http://people.apache.org/~elserj/calcite/docs/avatica_overview.html

    Optimize

    在prepareSql中,先调用的是Optimize,

    经过优化生成的Cheapest计划,

    Programs,对于优化过程的封装,

    可以看到Volcano只是program1,前面还有去关联,trimFields的Hep优化,后面还有calcRules的Hep优化,

    这个Calc算子是Project和Filter的结合,目的就是为了减少算子?

    这里会触发到EnumerableProjectToCalcRule,将project算子转换为Calc

     

    implement

    目的是将物理算子转换成Linq4J的expressionTree,Expression是什么意思,参考C#里面的LinQ

    从而通过将ExpressionTree,bind到一个context,形成可执行代码,最终获取Enumerable的实现。

    CalcitePrepareImpl.implement

    EnumerableInterpretable

    EnumerableRelImplementor

    调用算子自身的implement函数,

    EnumerableSort

    递归调用child的implement,

    最终调用到,EnumerableTableScan

    到这implement调用栈,如前所说,目的就是调用各个算子自身的implement,实现转换

    调用getExpression,

     

    最终调用到,tableExpression,

    生成是实际是,MethodCallExpression,” Represents a call to either a static or an instance method“,

    表示这里的Expression表示函数调用,后面显示出具体的调用是什么,toString会accept一个ExpressionWriter

    其可以由Expression.call生成,这里是调用BuildInMethod.Schema_Get_Table,参数是一个Expressions.constant

    Result

    Blocks.toBlock,把一堆Expression封装成一个block,

    implementor.result,意思要得到这个block执行的Result,

    Result这里是一个封装,包含,

    PhysType,每个字段的类型和名称

    format,row的形式,这里是array,其他的还有list,row等

    block,代码段,这里原先的EnumerableTableScan,已经implement成一个Expression tree,这个tree就代表代码段

    回到EnumerableCalc,implement

    第一步生成代码,input.current,

    生成moveNext,

    生成Project逻辑,

    {
      final Object[] current = (Object[]) inputEnumerator.current();
      final Object input_value = current[0];
      final Object input_value0 = current[3];
      return new Object[] {
          input_value,
          input_value0};
    }

    最后拼出一个完整的逻辑,

    递归回到EnumerableSort,这里的逻辑也比较简单,就是调用内置的orderBy函数。

    这样就完成了所有算子的implement。

    EnumerableRelImplementor.implementRoot

    继续将上面得到block,封装到bind函数中,并生成baz类

    返回到EnumerableInterpretable.toBindable

    这里就是将implement得到的class,调用getBindable,即用Janino生成class,并创建实例,

    得到的Bindable是啥,

    bind接口,将statement绑定到某个DataContext上,从而能执行得到Enumerable的结果。

    这里最终生成的Bindable为,

    实际使用时,调用bind得到Enumerable,

    用这个迭代器的接口,next和current就可以真正的获取数据,从而完成执行

    public org.apache.calcite.linq4j.Enumerable bind(final org.apache.calcite.DataContext root) {
      final org.apache.calcite.linq4j.Enumerable _inputEnumerable = org.apache.calcite.schema.Schemas.enumerable((org.apache.calcite.schema.ScannableTable) root.getRootSchema().getSubSchema("BUG").getTable("DATE"), root);
      final org.apache.calcite.linq4j.AbstractEnumerable child = new org.apache.calcite.linq4j.AbstractEnumerable(){
        public org.apache.calcite.linq4j.Enumerator enumerator() {
          return new org.apache.calcite.linq4j.Enumerator(){
              public final org.apache.calcite.linq4j.Enumerator inputEnumerator = _inputEnumerable.enumerator();
              public void reset() {
                inputEnumerator.reset();
              }
    
              public boolean moveNext() {
                return inputEnumerator.moveNext();
              }
    
              public void close() {
                inputEnumerator.close();
              }
    
              public Object current() {
                final Object[] current = (Object[]) inputEnumerator.current();
                final Object input_value = current[0];
                final Object input_value0 = current[3];
                return new Object[] {
                    input_value,
                    input_value0};
              }
    
            };
        }
    
      };
      return child.orderBy(new org.apache.calcite.linq4j.function.Function1() {
          public Long apply(Object[] v) {
            return (Long) v[1];
          }
          public Object apply(Object v) {
            return apply(
              (Object[]) v);
          }
        }
        , org.apache.calcite.linq4j.function.Functions.nullsComparator(false, false));
    }
    
    
    public Class getElementType() {
      return java.lang.Object[].class;
    }
  • 相关阅读:
    作业4
    PSP记录个人项目耗时
    代码复审
    是否需要有代码规范?
    作业二(1)
    作业二(2)
    作业一
    软件工程学期总结
    作业4
    作业3(PSP表格)
  • 原文地址:https://www.cnblogs.com/fxjwind/p/15403929.html
Copyright © 2020-2023  润新知