Skip to content

fix(plan): allow NULL arguments in GREATEST() and LEAST() - #24628

Merged
XuPeng-SH merged 7 commits into
matrixorigin:mainfrom
VioletQwQ-0:violet/issue-24546-greatest-least
May 28, 2026
Merged

fix(plan): allow NULL arguments in GREATEST() and LEAST()#24628
XuPeng-SH merged 7 commits into
matrixorigin:mainfrom
VioletQwQ-0:violet/issue-24546-greatest-least

Conversation

@VioletQwQ-0

Copy link
Copy Markdown
Collaborator

What type of PR is this?

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

Which issue(s) this PR fixes:

issue #24546

What this PR does / why we need it:

The type checker for GREATEST() and LEAST() required all arguments to have the exact same type OID, which rejected explicit NULL constants (type T_any). This prevented queries like GREATEST(NULL, 1) from working, returning "bad value [ANY BIGINT]" instead of NULL per MySQL behavior.

Key changes in pkg/sql/plan/function/:

  • leastGreatestCheck() now skips T_any (NULL) arguments when validating that all non-NULL inputs share a common type.
  • New leastGreatestParamType() helper so leastFn/greatestFn can find the first non-T_any parameter to determine the dispatch type.
  • retType callbacks now search for the first non-T_any argument, falling back to T_varchar when all inputs are T_any.
  • BVT test cases added for NULL argument handling and type coercion across NULLs.

Special notes for your reviewer:

The base implementation of GREATEST() and LEAST() was already merged in #22838. This PR fixes a gap where explicit NULL values were rejected during type checking. The NULL propagation behavior (return NULL if any arg is NULL) was already correct in the execution functions; the fix is purely in the type checking layer.

The type checker for GREATEST() and LEAST() required all arguments to
have the exact same type OID, which rejected explicit NULL constants
(type T_any). This prevented queries like GREATEST(NULL, 1) from
working, returning "bad value [ANY BIGINT]" instead of NULL per MySQL
behavior.

Changes:
- Relax leastGreatestCheck() to skip T_any (NULL) arguments when
  validating that all non-NULL inputs share a common type.
- Add leastGreatestParamType() helper so leastFn/greatestFn can
  find the first non-T_any parameter to determine the dispatch type.
- Fix retType to search for the first non-T_any argument, falling
  back to T_varchar when all inputs are T_any.
- Add BVT test cases for NULL argument handling.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@mergify mergify Bot added the kind/bug Something isn't working label May 27, 2026
@matrix-meow matrix-meow added the size/S Denotes a PR that changes [10,99] lines label May 27, 2026
VioletQwQ-0 and others added 2 commits May 28, 2026 11:37
When all arguments are NULL constants (T_any), the dispatch type
selector returned T_any which has no matching case in the switch.
Fall back to T_varchar so the NULL result is computed correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@XuPeng-SH XuPeng-SH left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed multi-angle: this NULL-handling fix is scoped correctly to the type/dispatch layer. leastGreatestCheck() now ignores T_any only for explicit NULL arguments, dispatch/retType pick the first non-NULL type, and the all-NULL case is routed to an existing varchar path so GREATEST(NULL, NULL) / LEAST(NULL, NULL) return NULL instead of failing. I did not find a correctness blocker in the change.

@XuPeng-SH
XuPeng-SH merged commit 69bd8be into matrixorigin:main May 28, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bug Something isn't working size/S Denotes a PR that changes [10,99] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants