Uh oh!
There was an error while loading. Please reload this page.
[fix](be) Fix TIMESTAMPTZ nullable type equality - #66722
Conversation
hello-stephen
commented
Aug 13, 2026
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
Mryange
commented
Aug 13, 2026
/review |
There was a problem hiding this comment.
Automated review opinion: no blocking or material correctness issue was found. The change is suitable to merge once the required CI checks complete.
Critical checkpoint conclusions:
- Goal and proof: the old
DataTypeTimeStampTz::equalstreatedTIMESTAMPTZ(6)as equal toNullable(TIMESTAMPTZ(6)), making recursive Struct equality asymmetric and allowing a cast identity path to retain the wrong physical child-column shape. Exact dynamic type plus scale restores the intended equality contract. The unit test proves scale sensitivity, both nullable operand orders, and recursive Struct behavior; the regression proves the insert/read result. - Scope and clarity: the production change is a focused equality-predicate correction and mirrors the established TIMEV2/DATETIMEV2 implementation. No additional production site needs modification.
- Concurrency: datatype metadata is immutable and this comparison adds no shared mutation, thread interaction, lock, or atomic state.
- Lifecycle and ownership: no lifecycle or static-initialization behavior changes. The corrected comparison prevents an invalid identity cast from sharing a non-nullable child under a nullable target; the existing Struct cast now constructs the required nullable child.
- Configuration: no configuration item or dynamic-update behavior is added or changed.
- Compatibility: there is no symbol, wire protocol, storage layout, serialized block, or persisted metadata change, so no rolling-upgrade compatibility branch is needed.
- Parallel and special-case paths: scalar, NULL, multi-field, nested Array/Map/Struct, scale-changing, non-folded, cloud, and shared-nothing paths were traced. Recursive equality/cast wrappers propagate the leaf fix, and precision-ignoring callers explicitly remove nullable wrappers or execute after nullable unnesting.
- Test coverage: the BE unit test directly covers the faulty equality boundary. The regression reaches ordinary BE constant materialization through
VExpr::open/get_const_coland the sink Struct cast even without enabling the optional FE-to-BE fold RPC. Nearby TIMESTAMPTZ suites cover additional complex-type, NULL, scale, and timezone behavior. - Test results: the generated expected value is correct and deterministic:
2024-03-30 20:45:00 -03:30normalizes to2024-03-31 00:15:00.000000+00:00. The test follows the table-cleanup, hardcoded-name, ordered-query, and generated-output conventions. Per the review-runner instruction, I did not run builds or tests; formatter/checkstyle/license and other lightweight PR checks were passing at review time, while BE UT was still pending. - Error handling and observability: no Status or exception path is weakened. Existing cast/type checks provide failure context, and this local metadata correction does not require new logs, metrics, or user-facing diagnostics.
- Transactions, persistence, and writes: the regression exercises a real insert/read, but transaction atomicity, visible versions, EditLog, rowsets, delete bitmaps, and crash recovery are unchanged.
- FE-BE state: no new variable or metadata field is transmitted; existing Struct nullability and TIMESTAMPTZ scale metadata are sufficient.
- Performance and memory: the comparison replaces primitive/scale virtual calls with one RTTI comparison and a scale load. The nullable child allocation selected for the corrected cast is required output materialization; no redundant hot-path work or untracked ownership was introduced.
- Other issues and user focus: no additional review focus was provided, and the full changed-file sweep found no other substantiated issue.
Review completion: the review converged after round 1. Two full-review subagents and one separate risk-focused subagent all returned NO_NEW_VALUABLE_FINDINGS; every initial risk was independently resolved, there were no existing review threads to duplicate, and no inline comment is warranted.
Mryange
commented
Aug 13, 2026
run buildall |
hello-stephen
commented
Aug 13, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
Mryange
commented
Aug 13, 2026
run performance |
1 similar comment
Mryange
commented
Aug 17, 2026
run performance |
Mryange
commented
Aug 17, 2026
run buildall |
PR approved by at least one committer and no changes requested. |
PR approved by anyone and no changes requested. |
Mryange
commented
Aug 18, 2026
run buildall |
hello-stephen
commented
Aug 18, 2026
TPC-H: Total hot run time: 17047 ms |
hello-stephen
commented
Aug 18, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
Aug 18, 2026
TPC-DS: Total hot run time: 81899 ms |
hello-stephen
commented
Aug 18, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
Aug 18, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
Aug 18, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
Aug 18, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
Uh oh!
There was an error while loading. Please reload this page.
A TIMESTAMPTZ data type was considered equal to its nullable variant because the equality check only compared the primitive type and scale. During constant folding of a STRUCT expression, this caused a type mismatch when a `STRUCT<TIMESTAMPTZ>` constant was assigned to a `STRUCT<Nullable(TIMESTAMPTZ)>` expression. The equality check now also requires the concrete data type to match, preventing the invalid equivalence while preserving scale-sensitive comparisons. Regression coverage verifies inserting a constant TIMESTAMPTZ value into a STRUCT column and reading the normalized UTC value. ### Release note None ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [ ] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Behavior changed: - [ ] No. - [ ] Yes. <!-- Explain the behavior change --> - Does this need documentation? - [ ] No. - [ ] Yes. <!-- Add document PR link here. eg: apache/doris-website#1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into -->
Problem Summary:
A TIMESTAMPTZ data type was considered equal to its nullable variant because the equality check only compared the primitive type and scale. During constant folding of a STRUCT expression, this caused a type mismatch when a
STRUCT<TIMESTAMPTZ>constant was assigned to aSTRUCT<Nullable(TIMESTAMPTZ)>expression. The equality check now also requires the concrete data type to match, preventing the invalid equivalence while preserving scale-sensitive comparisons. Regression coverage verifies inserting a constant TIMESTAMPTZ value into a STRUCT column and reading the normalized UTC value.Release note
None
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)