Skip to content

Conversation

@ntodd
Copy link
Contributor

@ntodd ntodd commented Jan 20, 2026

Adds support for Polars' nulls_equal join parameter to DataFrame.join/3, allowing NULL values to match during join operations. Defaults to false (standard SQL semantics where NULL != NULL).

Changes

  • Added :nulls_equal option to DataFrame.join/3 public API
  • Refactored NIF boundary to use an options map (ExJoinOptions struct with #[derive(NifMap)]) to make other options easier to add in the future
  • Added tests for all join types with nulls_equal: true

Example

left = Explorer.DataFrame.new(a: [1, nil], b: ["a", "b"])
right = Explorer.DataFrame.new(a: [1, nil], c: ["d", "e"])

# Default behavior (SQL semantics): nil != nil
Explorer.DataFrame.join(left, right)
# => 1 row (only matches on a=1)

# With nulls_equal: true
Explorer.DataFrame.join(left, right, nulls_equal: true)
# => 2 rows (matches on a=1 and a=nil)

Adds support for Polars' join_nulls parameter, allowing NULL values to
match during join operations. Default is false (SQL semantics).

Also refactors join options to use a map at the NIF boundary for
extensibility, using Rustler's NifMap derive macro.
Copy link
Member

@billylanchantin billylanchantin left a comment

Choose a reason for hiding this comment

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

Thank you, this is a wonderful addition! No notes :)

@billylanchantin billylanchantin merged commit 62b53b6 into elixir-explorer:main Jan 31, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants