一、概述

CodegenContext 作为代码生成的上下文,记录了将要生成的代码中的各种元素,包括变量、函数等。

二、实现

CodegenContext 作为代码生成的上下文,记录了将要生成的代码中的各种元素,包括变量、函数等。

2.1. 属性

2.1.1. references

references 是一个数组,用来保存生成代码中的对象(objects),可以通过 addReferenceObj 方法添加。

2.2. 方法

2.2.1. 变量数组 mutableStates 相关方法

  1. $addMutableState()$

    方法用来添加变量,需要指定 Java 类型、变量名称和变量初始化代码。

  2. $addBufferedState()$

    用来添加缓冲变量,与常规的状态变量的不同之处是,缓冲变量一般用来存储来自 InternalRow 中的数据,比如一行数据中的某些列等。因此,这些变量仅在类中声明,但是不会在初始化函数中执行,该方法返回的是 ExprCode 对象。

  3. $declareMutableStates()$

    用来在生成的 Java 类中声明这些变量(默认均为 private 类型)

  4. $initMutableStates()$

    用来在类的初始化函数中生成变量的初始化代码,输出的元素都是每行一个。

2.2.2. 函数相关

除变量外,生成的代码中另一个比较重要的部分是添加的函数。在 CodegenContext 中,$addedFunctions()$ 类型为 Map[String, String],提供了函数名和函数代码的映射关系。在代码生成
的过程中,可以通过 $addNewFunction()$ 方法添加函数,并通过 $declareAddedFunctions()$ 方法声明函数。

2.2.3. 数据类型映射相关方法

从直接执行 Spark 到生成 Java 代码来执行,必然会涉及数据类型方面的对应关系。CodegenContext 中提供了一系列的方法来完成数据类型的映射。

  1. $javaType(dt: DataType)$

    根据 Spark 中的 DataType 得到 Java 中的数据类型。可以看到,有些类型属于多对一的关系,例如 IntegerType 和 DateType 都会生成 int 类型。

2.2.4. 辅助方法

此外,CodegenContext 还提供了大量的辅助方法与变量。

  1. $currentVars$

    类型为 Seq[ExprCode] 的 currentVars,用来记录生成的各列作为当前算子的输入

  2. $freshName$

    freshName 方法与类型为 HashMap [String, Int] 的 freshNameIds 配合,用来生成具有唯一ID 的变量名

  3. $nullSafeExec$

    添加 null 检测的逻辑。

ExprValue

ExprValue 是有类型的 Java 表达式片段,即一个 Java 变量或者常量或者计算式。

其有四个子类:

  1. VariableValue 表示一个局部变量表达式。
  2. GlobalValue 表示一个全局变量表达式。
  3. LiteralValue 表示一个字面量表达式(有两个子类: TrueLiteral 和 FalseLiteral)
  4. SimpleExprValue 表示一个有类型 java 表达式片段,例如:1+1

ExprValue本质内容还是JavaCode中的字符串,只是增加了Java类型。

1
2
3
4
trait ExprValue extends JavaCode {
def javaType: Class[_]
def isPrimitive: Boolean = javaType.isPrimitive
}

ExprCode

ExprCode 表示一段 Java 代码,使用 InternalRow 作为输入,计算一个 Expression。

1
case class ExprCode(var code: Block, var isNull: ExprValue, var value: ExprValue)

code 表示计算表达式的 Java 代码块(如果 isNull 和 value 已经存在,code 中含有空字符串)。isNull 表示表达式计算结果是否是 Null,value 表示表达式计算代码块返回的结果(如果 isNull 为 true,那么 value 是无效的)。

ExprCode 本质内容是 JavaCode 中的字符串,只是它增加了 isNull 和 Value ,用于表示是否为空和返回值信息。