Skip to content

Conversation

@gouhongshen
Copy link
Contributor

@gouhongshen gouhongshen commented Jan 26, 2026

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue ##23009

What this PR does / why we need it:

Summary
This PR implements the NULL-safe equal operator (<=>), providing full compatibility with MySQL semantics. It ensures that NULL <=> NULL returns 1 (TRUE) and Value <=> NULL returns 0 (FALSE), never returning NULL.

Changes

  • Function Registration: Added NULL_SAFE_EQUAL to function_id.go and initialized metadata in init.go and list_operator.go.
  • Execution Logic: Implemented vectorized nullSafeEqualFn in func_compare.go with support for all major data types (Numeric, String, JSON, Decimal, Date/Time, etc.).
  • Plan & Binding:
    • Updated base_binder.go to bind tree.NULL_SAFE_EQUAL to the <=> function.
    • Implemented Tuple expansion logic: (a, b) <=> (c, d) is automatically expanded to (a <=> c) AND (b <=> d).
  • Optimizer Integration: Marked the operator as PRODUCE_NO_NULL, allowing the optimizer to deduce NotNullable properties and perform optimizations like IS NULL constant folding.
  • Safety & Correctness:
    • Join: Explicitly excluded from equi-join identification (IsEqualFunc) to avoid incorrect result dropping in the current Hash
      Join implementation regarding NULL keys.
    • Zonemap: Disabled ZONEMAPPABLE flag to prevent incorrect block pruning, as the generic evaluator currently lacks specialized logic for NULL-safe comparisons.

Testing

  • Added comprehensive BVT cases in test/distributed/cases/function/func_null_safe_equal.sql.
  • Coverage:
    • Basic scalar comparisons with all NULL combinations.
    • Table-based filtering and Join correctness (NULL matching NULL).
    • Complex types: JSON, Decimal (with scale alignment), and Date/Time.
    • Tuple comparisons and nested logic.
    • Optimizer attribute verification (verifying results are never NULL).
  • All tests verified against a live MatrixOne instance.

@matrix-meow matrix-meow added the size/L Denotes a PR that changes [500,999] lines label Jan 26, 2026
@mergify mergify bot added the kind/feature label Jan 26, 2026
@gouhongshen gouhongshen requested a review from aunjgr January 28, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature size/XL Denotes a PR that changes [1000, 1999] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants