Skip to content

Support NullType output types in codegen dispatch #5525

Description

@grorge123

What is the problem the feature request solves?

Any expression whose output type contains NullType is rejected by the codegen dispatch gate and the whole operator falls back to Spark, even though a NullType column can only ever hold nulls.

Spark's untyped constructors leave NullType children behind, so this hits common literals:

  • map()MapType(NullType, NullType)
  • map('a', NULL)MapType(StringType, NullType)
  • array()ArrayType(NullType)
  • map_from_arrays(array(), array()), struct(map()), and anything nested around them

CreateMap and friends are routed through codegen dispatch (spark/src/main/scala/org/apache/comet/serde/maps.scala:214), so a projection containing one of these literals is currently kicked out of the native plan with codegen dispatch: unsupported output type ....

Why the gate rejects it today:

  • isSupportedDataType (spark/src/main/scala/org/apache/comet/codegen/CometBatchKernelCodegen.scala:85) has no NullType case, so it falls through to false, recursively for ArrayType / StructType / MapType children.
  • canHandle applies that same predicate to both the output type (CometBatchKernelCodegen.scala:120) and every BoundReference input (CometBatchKernelCodegen.scala:172).

The rejection is only needed on the input side: CometScalaUDFCodegen.specFor has no way to build an ArrowColumnSpec for a NullVector, so a NullType input must keep falling back. On the output side the kernel only needs to emit an all-null Arrow NullVector, which the rest of the pipeline already understands (serializeDataType maps NullType to its own type id and Utils.toArrowField maps it to ArrowType.Null).

Describe the potential solution

Make the type gate asymmetric:

  • Accept NullType (top-level or nested inside array / struct / map) for the output type in canHandle, and keep rejecting it for BoundReference inputs.
  • Teach the output emitter (CometBatchKernelCodegenOutput) to map NullType to NullVector and to write it with setNull only, without reading a source value.
  • Keep the output emitter's type surface in sync with the gate, as the existing doc comments require, so plan-time acceptance never turns into an execute-time exception.
  • Update the Scala/Java UDF user guide: NullType arguments remain unsupported, NullType return types become supported.

Done when a CometSqlFileTestSuite fixture such as SELECT map(), SELECT map('a', NULL), SELECT array(map()), and a map() column carried through ORDER BY runs without a Spark fallback, and unit tests in CometCodegenSourceSuite lock in the output/input asymmetry and the gate/emitter agreement.

Additional context

No native changes are needed: the NullType support in serde and Arrow field conversion already exists; the missing piece is entirely in the JVM codegen gate and output emitter.

I have a patch for this ready and will open a PR referencing this issue.

Assisted-by: Claude Code (claude-fable-5)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions