Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions datafusion/functions-nested/src/empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,19 @@ fn array_empty_inner(args: &[ArrayRef]) -> Result<ArrayRef> {
}

fn general_array_empty<O: OffsetSizeTrait>(array: &ArrayRef) -> Result<ArrayRef> {
let result = as_generic_list_array::<O>(array)?
.iter()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calling iter on ListArray is slow since it slice each list values which every slice recompute the null count and more

.map(|arr| arr.map(|arr| arr.is_empty()))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter also return None for nulls which means that it need to read the null info while it is not needed

.collect::<BooleanArray>();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

collect not using the from_trusted_len_iter helper which is faster

let result = as_generic_list_array::<O>(array)?;
let is_empty_iter = result.offsets().lengths().map(|n| n == 0);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is faster since we only need to look at one buffer and can make it very fast
the values of the list are irrelevent

// SAFETY: this is safe since the iterator lengths is exact size and
// trusted - it maps over fixed known number of elements
let output_buffer = unsafe { BooleanArray::from_trusted_len_iter(is_empty_iter) };

let (values, _) = output_buffer.into_parts();

// Add the nulls
let result = BooleanArray::new(
values,
result.nulls().filter(|n| n.null_count() > 0).cloned(),
);

Ok(Arc::new(result))
}
Loading