Details
-
Improvement
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
None
-
None
-
None
Description
Currently, the code generation of scalar functions and operators are complex and messy.
There are several ways to support codegen for a function/operator:
(1) Implement generate... in ScalarOperatorGens and invoke it in the big match pattern of ExprCodeGenerator.
(2) Implement a CallGenerator and add it to FunctionGenerator.
(3) Implement a util method and add it to BuiltinMethods and FunctionGenerator.
It will confuse developer which is the most efficient way to implement a function.
In this issue, we will propose a unified way to code generate functions/operators.
Some initial idea:
1. Introduce an ExprCodeGen interface, and all the function/operators code generator should extend this to implement the codegen method. It's like a combination of PlannerExpression and CallGenerator.
2. Rename ExprCodeGenerator to RexCodeGenerator.
3. Use a big match pattern to mapping RexCall to specific ExprCodeGen
trait ExprCodeGen { def operands: Seq[GeneratedExpression] def resultType: InternalType def codegen(ctx: CodeGeneratorContext): GeneratedExpression } case class ConcatCodeGen(operands: Seq[GeneratedExpression]) extends ExprCodeGen { override def resultType: InternalType = InternalTypes.STRING override def codegen(ctx: CodeGeneratorContext): GeneratedExpression = { nullSafeCodeGen(ctx) { terms => s"$BINARY_STRING.concat(${terms.mkString(", ")})" } } }