Skip to content

planner: nullable WEEK/YEARWEEK mode can be misclassified as null-rejecting #68816

@winoros

Description

@winoros

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

The planner null-reject proof can treat predicates using WEEK(date, mode) or YEARWEEK(date, mode) as null-rejecting when the nullable inner-side column is the mode argument.

Minimal query shape:

CREATE TABLE t1 (id INT PRIMARY KEY);
CREATE TABLE t2 (id INT, mode INT);
INSERT INTO t1 VALUES (1);

SELECT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE WEEK('2024-01-08', t2.mode) >= 0;

SELECT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE YEARWEEK('2024-01-08', t2.mode) >= 0;

t2.mode is NULL for the null-complemented row produced by the left join. TiDB/MySQL treats a NULL mode argument as mode 0 for these functions, so these predicates are not null-rejecting on t2.mode.

2. What did you expect to see? (Required)

The null-complemented row from t1 should not be rejected by the predicates above. The planner should not use the mode argument of WEEK or YEARWEEK as a NULL-preserving proof.

3. What did you see instead (Required)

pkg/planner/util/null_misc_builtins.go classified WEEK and YEARWEEK as whole-function NULL-preserving builtins. That lets the null-reject proof conclude that predicates such as WEEK('2024-01-08', t2.mode) >= 0 and YEARWEEK('2024-01-08', t2.mode) >= 0 are null-rejecting on t2.mode, which is unsafe for outer join simplification and can drop preserved rows.

4. What is your TiDB version? (Required)

Observed on current master before the fix, at commit 11b814992610648c33ba00425989c92d8b516d48.

No released version was checked locally.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    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