Skip to content

[SPARK-58186][SQL] Add bitmap_contains function - #58117

Open
jiangxt2 wants to merge 4 commits into
apache:masterfrom
jiangxt2:feat/bitmap-contains-resubmission
Open

[SPARK-58186][SQL] Add bitmap_contains function#58117
jiangxt2 wants to merge 4 commits into
apache:masterfrom
jiangxt2:feat/bitmap-contains-resubmission

Conversation

@jiangxt2

@jiangxt2jiangxt2 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

This PR adds bitmap_contains(bitmap, bit_position), a scalar predicate for Spark's existing flat BinaryType bitmap function family. It is available through SQL, the Scala DataFrame API, PySpark classic, and PySpark Connect.

The function:

  • checks a bucket-local bit position in constant time;
  • accepts a binary bitmap and a numeric position that is cast to BIGINT using Spark's existing cast semantics;
  • propagates SQL NULL for null bitmap or position inputs;
  • returns false for negative positions, positions at or above 32768, and positions beyond the actual bitmap byte length.

For an original value, callers use bitmap_bucket_number(value) to select the bitmap bucket and bitmap_bit_position(value) as the position passed to bitmap_contains.

This is a clean resubmission of #57336 against the current Spark codebase. It retains the function-argument documentation requested during the earlier review and expands the coverage for bucket semantics and bucket-aware joins. It keeps Spark's existing flat bitmap representation and does not introduce another bitmap type, serialization format, or external dependency.

This PR is independent of #58066, which proposes scalar bitmap set operations. The APIs are complementary: if both changes are merged, bitmap_contains can also test a bitmap returned by the scalar set operations.

Why are the changes needed?

Spark can construct flat bitmaps, aggregate them across rows, and count their set bits, but it has no built-in predicate for testing whether a specific position is present.

Without this function, users must convert the bitmap to another collection representation or use a UDF. That loses the consistent SQL, Scala, PySpark classic, and Spark Connect API surface provided by a native Catalyst expression.

bitmap_contains completes the existing bitmap workflow and allows precomputed bitmaps to be used directly in filters, CASE WHEN expressions, and bucket-aware membership joins.

Does this PR introduce any user-facing change?

Yes. Released Spark versions do not provide this function, and this PR does not change the behavior of any existing bitmap function.

It adds the following function in SQL, the Scala DataFrame API, PySpark classic, and PySpark Connect:

bitmap_contains(bitmap BINARY, bit_position BIGINT) ->BOOLEAN

The position is local to one bitmap bucket. A query using original values must match the bucket and pass bitmap_bit_position(value) to bitmap_contains.

For example:

WITH bitmaps AS (
SELECT
bitmap_bucket_number(value) AS bucket,
bitmap_construct_agg(bitmap_bit_position(value)) AS bitmap
FROMVALUES (1L), (32769L) AS source(value)
GROUP BY bitmap_bucket_number(value)
)
SELECTprobe.valueFROM bitmaps
JOINVALUES (1L), (2L), (32769L), (32770L) AS probe(value)
ONbitmaps.bucket= bitmap_bucket_number(probe.value)
AND bitmap_contains(bitmaps.bitmap, bitmap_bit_position(probe.value))
ORDER BYprobe.value;

This returns 1 and 32769.

A null bitmap or position produces SQL NULL. A negative position, a position at or above 32768, or a position beyond the actual bitmap byte length produces false.

How was this patch tested?

The patch adds coverage for:

  • helper-level lookup of set and unset bits;
  • empty and short bitmaps;
  • fixed-range and Long boundaries;
  • SQL and Scala DataFrame API behavior;
  • null propagation;
  • numeric casts in ANSI and non-ANSI modes;
  • invalid bitmap and position types;
  • filter and CASE WHEN predicates;
  • bucket-aware join usage across multiple buckets;
  • PySpark classic and Connect parity;
  • Scala Connect plan generation.

The SQL expression schema and Connect query-test golden files were regenerated.

Targeted validation completed for the production implementation before the final bucket-aware join test rewrite:

  • BitmapExpressionUtilsSuite: 9 tests passed.
  • BitmapExpressionsQuerySuite: 19 tests passed.
  • PlanGenerationTestSuite: 745 tests passed, with 2 ignored.
  • ProtoToParsedPlanTestSuite: 750 tests passed.
  • PySpark classic functions: 175 tests passed, with 6 dependency-based skips.
  • PySpark Connect parity: 123 tests passed, with 4 expected skips.
  • Classic and Connect function doctests passed.

The current head, c52d16aa09ce406f38084d4adf7a54d86ef80e94, includes the final bucket-aware join test. Its GitHub CI rollup passed: 30 checks succeeded, and one Kubernetes integration check was skipped.

Current cumulative diff static validation:

  • git diff --check: passed.
  • Spark Scalafmt validation: passed.
  • Spark Scalastyle for main and test sources: passed.
  • Ruff on the changed Python files: passed.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Codex and Claude AI

jiangxt2and others added 2 commits August 19, 2026 18:35
This change adds the `bitmap_contains(bitmap, bit_position)` scalar function
to the existing flat BinaryType bitmap function family. It checks whether the
bit at the given position is set in a bitmap, so that prebuilt bitmaps can be
used directly in WHERE, CASE WHEN and join conditions as a membership
predicate.
The function returns false for a negative position, a position outside the
32768-bit fixed range, or a position beyond the actual byte array length.
Type-valid SQL NULL inputs follow Spark nullable expression semantics and
produce NULL. The second argument accepts any Spark numeric value and is
explicitly cast to BIGINT with standard Spark cast semantics, including ANSI
mode behavior, before the lookup.
Implementation:
- Add the BitmapContains expression as a RuntimeReplaceable that invokes
the bitmapContains helper in BitmapExpressionUtils, and register the
`bitmap_contains` function in FunctionRegistry.
- Add the Scala `bitmap_contains(bitmap: Column, bitPosition: Column)` API
and the PySpark classic / Spark Connect wrappers with full docs.
- Add unit, SQL, PySpark and Connect plan generation tests, and regenerate the
SQL expression schema and Connect golden files.
Tests: Targeted BitmapExpressionUtilsSuite, BitmapExpressionsQuerySuite,
PySpark functions tests and doctests, Connect plan generation, and golden-file
validation pass.
Signed-off-by: jiangxt2 <jiangxt2@vip.qq.com>
Clarify that bitmap_contains checks a bucket-local bit position and document
the required bitmap_bucket_number and bitmap_bit_position mapping for original
values. Update the join test to exercise the complete bucketed lookup path.
Signed-off-by: jiangxt2 <jiangxt2@vip.qq.com>
Co-Authored-By: Zhang Dong <zdcheerful@hotmail.com>
Co-Authored-By: ArtificialIdoit <bill.sea@hotmail.com>
Co-Authored-By: cwq222 <15503804976@163.com>
@jiangxt2
jiangxt2 marked this pull request as ready for review August 20, 2026 07:10
@jiangxt2

Copy link
Copy Markdown
ContributorAuthor

Additional ecosystem context:

Apache Doris and StarRocks expose bitmap_contains, while ClickHouse exposes bitmapContains. This comparison supports the API naming and the value of a native membership predicate only; it does not imply binary-format or semantic compatibility. Those engines use native bitmap representations, while this PR keeps Spark's existing flat BINARY bitmap representation and bucket-local position mapping.

Preserve bitmap_contains while incorporating the upstream bitmap_xor_agg changes.
Co-Authored-By: Chang-Tong <zdcheerful@hotmail.com>
Signed-off-by: jiangxt2 <jiangxt2@vip.qq.com>
@uros-b

Copy link
Copy Markdown
Member

Thank you @jiangxt2!

@uros-b

Copy link
Copy Markdown
Member

cc @HyukjinKwon who reviewed #57336
also cc @cloud-fan

Merge current master changes while preserving bitmap_contains and bitmap scalar set operation implementations and tests.
Co-Authored-By: cwq222 <15503804976@163.com>
Signed-off-by: jiangxt2 <jiangxt2@vip.qq.com>
@jiangxt2

Copy link
Copy Markdown
ContributorAuthor

Hi @cloud-fan, if you have time, would you mind taking a look at this PR? It adds bitmap_contains to Spark’s bitmap function family. Thanks!

Sign up for freeto 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

@jiangxt2@uros-b