Skip to content

array_filter: array_compact fast path misfires when IsNotNull operand is not the lambda variable #4830

Description

@andygrove

Describe the bug

CometArrayFilter.convert has a fast path that lowers filter(arr, x -> x IS NOT NULL) to the native array_compact serde, to avoid the per-batch JNI cost of the codegen dispatcher. The guard only checks that the lambda body's first child is an IsNotNull, not that the IsNotNull operand is the lambda variable being iterated.

expr.function.children.headOption match {
  case Some(_: IsNotNull) =>
    // Fast path: `array_compact` lowers to `filter(arr, x -> x is not null)`.
    CometArrayCompact.convert(expr, inputs, binding)
  ...
}

As a result, a lambda whose body is IsNotNull of something other than the element (for example a captured column) is incorrectly treated as array_compact.

To Reproduce

A query like:

SELECT filter(arr, x -> captured_col IS NOT NULL) FROM t

Spark semantics: keep every element of arr when captured_col is non-null for that row, and produce an empty array when captured_col is null. The x variable is unused.

Comet fast-path semantics: array_compact(arr), i.e. drop the null elements of arr regardless of captured_col.

These diverge whenever arr contains null elements or captured_col is null.

Expected behavior

The fast path should only fire when the IsNotNull operand is the lambda's own variable, so the rewrite is a faithful array_compact. Any other shape should fall through to the native higher-order-function path (once available) or the codegen dispatcher / Spark.

Additional context

This predates #4744 (introduced in #2536), but it became more visible while reviewing the native lambda work in #4744. The fix is to tighten the guard in CometArrayFilter.convert (spark/src/main/scala/org/apache/comet/serde/arrays.scala) to confirm the IsNotNull argument references the single NamedLambdaVariable of the lambda. A regression test with a captured column and null elements would cover it.

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions