Skip to content

[fix](types) Fix binary value ownership and timestamp primitives - #68301

Merged
yiguolei merged 6 commits into
apache:masterfrom
Gabriel39:fix/binary-timestamp-primitives-master
Sep 22, 2026
Merged

yiguolei merged 6 commits into
apache:masterfrom
Gabriel39:fix/binary-timestamp-primitives-master

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

This ports #68297 to master, preserving the first of five planned extractions from #67784.

Binary Field values can retain references to released source storage, and Hive binary text needs its own Base64 contract. TIMESTAMPTZ output can lose historical offset seconds, format invalid NULL payloads, or fail again while reporting a boundary cast error.

  • Own long binary Field values while keeping short values inline. Preserve execution type lengths and decoder bytes, and add Hive Base64 and hexadecimal decoding support.
  • Explicitly reject unsupported binary hash keys, IN, aggregates, predicates and computed partition transforms. Keep the existing FE comparison/group/join restrictions and existing binary scalar functions. Reject unsupported collection kernels in each function's legality check before coercion.
  • Preserve historical second offsets in both TIMESTAMPTZ formatting and parsing. Skip masked NULL payloads, reject unrepresentable local years, and preserve cast error/NULL behavior at boundaries.

Arrow convertor migration, Parquet/ORC semantics, external writer changes and catalog mapping migration belong to the subsequent extractions. This PR does not enable native VARBINARY storage.

Master adaptation

  • Retain the fixed-offset normalization and tests already present on master.
  • Use the current void-returning VInPredicate::_prepare_zonemap_min_max interface in both the guard and its test.
  • Retain master header cleanup and existing timestamp-nanosecond tests.
  • Retain the existing master binary-literal encoder and its StringView input contract; the older std::string-based caller fix is not applicable.

Testing

  • TIMESTAMPTZ regression follow-up: reproduced both binary-output and stream-load failures using the master PR CI artifact, regenerated the two snapshots through run-regression-test.sh, and passed both suites in comparison mode from each branch checkout. Explicit Asia/Shanghai session settings were verified with the server default session zone set to UTC. Only historical offset seconds changed in the generated results.

  • Function-local validation update: 18 FE tests passed with Checkstyle enabled, covering direct legality checks, nested/mixed/variadic VARBINARY arguments, both collect_set arities, supported ordinary types, SQL analysis, and existing array rewrites. The new direct-legality tests reproduced missing rejection before the change.

  • BE ASAN build and 199 tests passed across 17 suites using run-be-ut.sh, including binary lifetime/SerDe/rejection, timestamp parsing/casts, and existing Arrow/Variant serialization coverage.

  • VarBinaryUnsupportedCollectionTest: passed (13 unsupported expressions plus supported byte-preserving collection analysis). The FE test reactor and repository Checkstyle passed after cleaning stale branch build artifacts.

  • Repository clang-format 16 check and build-header hygiene checks: passed; 31 changed C++ source/header files.

  • Groovy compilation of the three regression suites: passed. Live SQL regression execution remains pending CI.

  • clang-tidy was attempted but could not complete because master already contains an unmatched NOLINTEND in be/src/core/types.h. A diagnostic run with the compiler resource directory corrected reproduced that blocker; the other reported findings in column_varbinary.cpp were outside changed lines. This is not a clean clang-tidy result.

The focused BE test source list and local test/build settings were restored before committing. No build configuration changes are included.

Release note

Fix binary value lifetime and serialization, reject unsupported binary computation paths, and preserve TIMESTAMPTZ historical offsets and boundary error behavior.

Check List (For Author)

  • Test
    • Regression test (three self-checking suites added; execution pending CI)
    • Unit Test
  • Behavior changed:
    • Yes. Binary rejection and timestamp boundary behavior are described above.
  • Does this need documentation?
    • No. This fixes existing type behavior without introducing a configuration option.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

Scoped review follow-up

This follow-up only fixes correctness/stability defects introduced by this PR. Compatibility preservation, pre-existing limitations, additional VARBINARY computation/validation, performance refactors, and test-style-only rewrites are excluded.

  • Separate historical TIMESTAMPTZ wire-offset parsing from session fixed-zone limits in both parser paths.
  • Use UTC diagnostics for the TIMESTAMP_NS cast/comparison failures affected by the new local-year formatting exception.
  • Validation: 31 focused ASAN BE tests passed, including ordinary DATE/DATETIME parsing. Three targeted tests failed before the fixes. clang-format 16 and build hygiene passed. Full clang-tidy remains affected by pre-existing diagnostics.
  • Branch-specific UTC/GMT normalization and FE folding fixes are handled in [fix](types) Fix binary value ownership and timestamp primitives #68297; the corresponding master behavior predates this PR or already defers folding.

CI test follow-up

  • Keep the binary literal test's owning Field alive while reading its StringView. Branch-4.1 now has the corresponding short/long embedded-NUL coverage using its execution API.
  • Replace the obsolete +15:00 rejection input with +24:00. Add generated historical-offset checks in both cast modes; all prior snapshot results are unchanged.
  • Validation: 34 focused ASAN BE tests passed on each branch. The lifetime error and the original SQL mismatch were reproduced. The complete cast regression suite passed in comparison mode from both branch checkouts against the reported master CI artifact. clang-format 16 passed; full clang-tidy remains blocked by pre-existing diagnostics.

This follow-up changes tests only and retains the agreed scope: no compatibility work or additional binary computation support. Existing muted failures are outside this fix.

### What problem does this PR solve?

This ports apache#68297 to `master`, preserving the first of five planned extractions from apache#67784.

Binary `Field` values can retain references to released source storage, and Hive binary text needs its own Base64 contract. TIMESTAMPTZ output can lose historical offset seconds, format invalid NULL payloads, or fail again while reporting a boundary cast error.

- Own long binary Field values while keeping short values inline. Preserve execution type lengths and decoder bytes, and add Hive Base64 and hexadecimal decoding support.
- Explicitly reject unsupported binary hash keys, IN, aggregates, predicates and computed partition transforms. Keep the existing FE comparison/group/join restrictions and existing binary scalar functions. Reject unsupported collection kernels before coercion.
- Preserve historical second offsets in both TIMESTAMPTZ formatting and parsing. Skip masked NULL payloads, reject unrepresentable local years, and preserve cast error/NULL behavior at boundaries.

Arrow convertor migration, Parquet/ORC semantics, external writer changes and catalog mapping migration belong to the subsequent extractions. This PR does not enable native VARBINARY storage.

### Master adaptation

- Retain the fixed-offset normalization and tests already present on master.
- Use the current void-returning `VInPredicate::_prepare_zonemap_min_max` interface in both the guard and its test.
- Retain master header cleanup and existing timestamp-nanosecond tests.
- Retain the existing master binary-literal encoder and its StringView input contract; the older std::string-based caller fix is not applicable.

### Testing

- BE ASAN build and **199 tests passed** across 17 suites using `run-be-ut.sh`, including binary lifetime/SerDe/rejection, timestamp parsing/casts, and existing Arrow/Variant serialization coverage.
- `VarBinaryUnsupportedCollectionTest`: **passed** (13 unsupported expressions plus supported byte-preserving collection analysis). The FE test reactor and repository Checkstyle passed after cleaning stale branch build artifacts.
- Repository clang-format 16 check and build-header hygiene checks: **passed**; 31 changed C++ source/header files.
- Groovy compilation of the three regression suites: **passed**. Live SQL regression execution remains pending CI.
- clang-tidy was attempted but could not complete because master already contains an unmatched `NOLINTEND` in `be/src/core/types.h`. A diagnostic run with the compiler resource directory corrected reproduced that blocker; the other reported findings in `column_varbinary.cpp` were outside changed lines. This is not a clean clang-tidy result.

The focused BE test source list and local test/build settings were restored before committing. No build configuration changes are included.

### Release note

Fix binary value lifetime and serialization, reject unsupported binary computation paths, and preserve TIMESTAMPTZ historical offsets and boundary error behavior.

### Check List (For Author)

- Test
  - [x] Regression test (three self-checking suites added; execution pending CI)
  - [x] Unit Test
- Behavior changed:
  - [x] Yes. Binary rejection and timestamp boundary behavior are described above.
- Does this need documentation?
  - [x] No. This fixes existing type behavior without introducing a configuration option.

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

Comment thread fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java Outdated
### What problem does this PR solve?

Related PR: apache#68301

Move VARBINARY collection restrictions from the generic type coercion utility into each function's legality check. Preserve rejection before implicit casts, nested array and variadic argument coverage, existing error messages, and the CollectSet constant-limit check.

### Release note

None

### Check List (For Author)

- Test: 18 FE unit tests passed via run-fe-ut.sh; repository Checkstyle passed. New direct-legality tests reproduced the missing checks before the change.
- Behavior changed: No SQL behavior change; function-local validation now enforces the same restrictions.
- Does this need documentation: No
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot 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.

Static review of exact head 44eef01c38d2ee094290cfc1db07535c76ec2274 found five blocking issues: the shared VARBINARY hash guard removes previously supported serialized multi-key paths in PartitionTopN, INTERSECT/EXCEPT, and recursive UNION DISTINCT; Iceberg identity partitions are allowed even though the writer/commit path cannot represent VARBINARY; two TIMESTAMP_NS error branches re-enter the new throwing formatter; historical offsets emitted by the formatter remain outside both parsers' accepted range; and the three new deterministic regression suites do not use runner-generated golden output.

Critical checkpoints: Field ownership, copy/move/destruction, decoder-page lifetime, raw/Hive-Base64/nested-hex SerDe routing, nullable handling, and protobuf length restoration were traced without another issue. FE/BE and parallel-path review found the hash-consumer regression above; comparison/join/group fences, IN, single-value aggregates, crc32, collect-set, and collection coercion candidates were either already covered or dismissed with concrete evidence. TIMESTAMPTZ strict/non-strict parsing, local-year boundaries, NULL masking, and protocol formatting were traced; the two reported timestamp defects are the surviving error/round-trip gaps. No additional concurrency, persistence, configuration, performance, or observability defect was substantiated.

Validation is static-only: no builds or tests were run under this review constraint. Author-reported FE/BE checks and CI claims were not independently validated, and the PR description says live SQL regression execution is pending. There were no user-supplied focus points beyond the full review.

This review is capped/incomplete for convergence purposes: valuable new scope and one new candidate appeared in round 3, the maximum permitted round. All candidates currently identified have nevertheless been independently adjudicated, deduplicated, and either included below or dismissed with evidence.

inline HashKeyType get_hash_key_type(const std::vector<DataTypePtr>& data_types) {
// Reject binary before the multi-key serialization fallback can enable joins or grouping.
for (const auto& type : data_types) {
if (type->get_primitive_type() == TYPE_VARBINARY) {

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.

[P1] Preserve the existing serialized path for supported multi-key consumers. This pre-check now runs before the multi-key branch, so it also rejects keys that previously selected HashKeyType::serialized: default-enabled PartitionTopN windows, multi-column INTERSECT/EXCEPT, and recursive UNION DISTINCT. Their PartitionedHashMapVariants, SetDataVariants, and DistinctDataVariants all implement serialized keys, and ColumnVarbinary supplies serialization; only single-key VARBINARY was already unsupported. Please move the rejection to the join/group consumers that require it (or otherwise retain these byte-safe consumers) and add multi-key window, set-operation, and recursive-CTE coverage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The rejection is intentional for this change. Preserving previously reachable serialized hash consumers is a compatibility concern, so the common VARBINARY hash restriction is retained.

const doris::iceberg::PartitionField& field, const DataTypePtr& source_type) {
auto& transform = field.transform();
// Identity/void only carry values; computed binary partition transforms are unsupported.
if (source_type->get_primitive_type() == TYPE_VARBINARY && transform != "identity" &&

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.

[P1] Reject identity until the writer supports binary partitions. This branch deliberately leaves identity enabled, but IdentityPartitionColumnTransform returns ColumnVarbinary and VIcebergTableWriter::_get_iceberg_partition_value has no TYPE_VARBINARY arm, so a non-null dynamic identity partition falls into "Unsupported type for partition". The later partition-string and FE commit reconstruction paths also have no binary-safe representation. With enable.mapping.varbinary=true, inserts into Iceberg BINARY/FIXED identity partitions therefore fail. Please either reject identity here too, or implement byte-safe extraction/transport/reconstruction and add an end-to-end identity test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The binary identity extraction/commit path was already incomplete before this PR. This PR does not add binary partition-writing support; completing that pipeline or redesigning its rejection boundary is outside this follow-up.

cctz::civil_second civ = lookup_result.cs;
// UTC storage bounds do not guarantee a representable session-local year. Reject
// overflow before DateTimeV2 formatting could produce an offset-only wire value.
if (civ.year() < 0 || civ.year() > 9999) {

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.

[P2] Keep the remaining TIMESTAMP_NS error paths from re-entering this throwing formatter. With the session zone +08:00, the maximum UTC TIMESTAMPTZ first fails local conversion because the year becomes 10000; strict TIMESTAMPTZ-to-TIMESTAMP_NS cast and TIMESTAMPTZ/TIMESTAMP_NS comparison then call to_string(local_zone) while building their InvalidArgument Status, so this exception escapes before that Status is returned. The parallel cast paths changed in this PR already render utc_dt() instead. Please update these two missed callers the same way and add strict-cast and comparison boundary tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0765475. Both remaining TIMESTAMP_NS error paths now format the valid UTC value instead of calling the session-local formatter again. ASAN tests cover both year endpoints, strict errors/non-strict NULL results, and both comparison operand orders; all 31 focused BE tests passed.

"invalid timezone offset '{}'",
combine_tz_offset(sign, part[0], part[1]));

if (second_offset != 0) {

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.

[P2] Accept every historical offset the formatter emits. TimestampTzValue::to_string() now emits the exact cctz offset, but both parser branches still cap the hour at 14 and this seconds branch additionally caps negative offsets at 12. IANA history includes larger values (for example Asia/Manila used -15:56:08 before 1845), so Doris can return a TIMESTAMPTZ string that it cannot parse back. Please align both parser branches with the formatter's range and add strict/non-strict round-trip coverage for an extreme historical zone.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0765475. Both strict and fallback TIMESTAMPTZ parsers now interpret historical wire offsets independently of the narrower session fixed-zone policy. Tests cover Manila (-15:56:08), Guam (-14:21), positive offsets beyond +14:00, and malformed offsets. DATE/DATETIME parsing is retained; this completes the exact-offset round-trip contract introduced by this PR.

as timestamptz(6))
from numbers('number' = '1')
""")[0][0].toString()
assertEquals(testCase[2], wire)

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.

[P2] Record these deterministic results as golden output. All three new TIMESTAMPTZ suites assert successful query results directly and add no .out files, while this repository requires determined regression results to use qt_/order_qt_ cases with runner-generated output. Please keep the test { sql; exception } blocks for failures, convert the successful cases in all three suites, and generate their checked-in .out files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These suites already assert their results. Converting all three suites to golden-output tests is a test-style change, not a newly introduced correctness or stability fix, so they are not rewritten in this follow-up.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28080 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 44eef01c38d2ee094290cfc1db07535c76ec2274, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17775	3924	3907	3907
q2	2166	375	304	304
q3	10091	1449	795	795
q4	4693	492	355	355
q5	7494	844	551	551
q6	186	178	142	142
q7	768	779	636	636
q8	9303	1687	1535	1535
q9	5474	4188	4238	4188
q10	6812	1335	1016	1016
q11	438	282	266	266
q12	642	420	295	295
q13	18090	2601	1983	1983
q14	263	259	238	238
q15	q16	730	715	681	681
q17	1751	1137	954	954
q18	6549	5610	5595	5595
q19	1172	1275	1030	1030
q20	497	410	266	266
q21	5386	3439	3032	3032
q22	447	362	311	311
Total cold run time: 100727 ms
Total hot run time: 28080 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4620	4693	4415	4415
q2	743	605	550	550
q3	5540	5265	4630	4630
q4	2245	2304	1453	1453
q5	4842	4393	4565	4393
q6	235	183	133	133
q7	2059	1695	1500	1500
q8	2347	2091	1971	1971
q9	7395	7277	7273	7273
q10	3676	3640	3177	3177
q11	534	375	339	339
q12	707	712	496	496
q13	2280	2619	1992	1992
q14	268	291	256	256
q15	q16	675	679	606	606
q17	7274	6730	6634	6634
q18	11958	11164	11745	11164
q19	1070	1040	1009	1009
q20	2187	2211	1950	1950
q21	4964	4072	4267	4072
q22	513	459	419	419
Total cold run time: 66132 ms
Total hot run time: 58432 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152721 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 44eef01c38d2ee094290cfc1db07535c76ec2274, data reload: false

query5	4303	592	471	471
query6	422	227	186	186
query7	4846	576	309	309
query8	336	182	160	160
query9	8810	4015	4056	4015
query10	490	314	261	261
query11	5876	3541	3224	3224
query12	155	92	88	88
query13	1294	631	422	422
query14	6541	4515	4175	4175
query14_1	3979	3969	3970	3969
query15	210	199	180	180
query16	965	495	436	436
query17	921	657	545	545
query18	2422	479	337	337
query19	206	187	155	155
query20	83	82	80	80
query21	217	135	116	116
query22	13031	12969	12716	12716
query23	14089	13405	12449	12449
query23_1	12456	12565	12530	12530
query24	7243	1114	720	720
query24_1	688	723	728	723
query25	557	444	379	379
query26	1264	309	168	168
query27	2702	573	336	336
query28	4558	2029	1987	1987
query29	1584	734	544	544
query30	304	225	186	186
query31	911	768	647	647
query32	146	106	99	99
query33	541	322	253	253
query34	1204	1112	638	638
query35	738	761	654	654
query36	805	863	689	689
query37	151	107	96	96
query38	1837	1772	1682	1682
query39	692	692	674	674
query39_1	649	664	659	659
query40	226	124	122	122
query41	91	69	67	67
query42	98	96	99	96
query43	338	346	298	298
query44	1407	727	713	713
query45	185	179	166	166
query46	1077	1218	753	753
query47	1519	1505	1410	1410
query48	431	419	291	291
query49	595	417	298	298
query50	943	338	258	258
query51	10763	10259	10244	10244
query52	92	95	79	79
query53	237	264	196	196
query54	297	215	185	185
query55	79	73	68	68
query56	224	224	211	211
query57	1515	1407	1369	1369
query58	276	260	250	250
query59	1976	2053	1851	1851
query60	280	242	221	221
query61	149	147	137	137
query62	394	317	263	263
query63	217	174	177	174
query64	2814	1020	831	831
query65	3470	3406	3409	3406
query66	1784	412	312	312
query67	20084	20105	20079	20079
query68	3290	1540	924	924
query69	416	307	261	261
query70	914	785	802	785
query71	309	245	213	213
query72	2757	2502	2231	2231
query73	799	798	421	421
query74	4638	4475	4273	4273
query75	2303	2288	1930	1930
query76	2394	1104	727	727
query77	373	415	293	293
query78	9128	9067	8483	8483
query79	1302	1191	739	739
query80	568	455	381	381
query81	532	321	291	291
query82	649	172	135	135
query83	301	221	198	198
query84	308	148	116	116
query85	844	459	381	381
query86	321	253	231	231
query87	2001	1996	1827	1827
query88	3611	2710	2711	2710
query89	375	286	242	242
query90	1943	175	177	175
query91	171	155	135	135
query92	99	89	90	89
query93	1494	1455	899	899
query94	523	351	323	323
query95	683	379	341	341
query96	1097	782	355	355
query97	2395	2426	2284	2284
query98	161	159	145	145
query99	731	721	616	616
Total cold run time: 236878 ms
Total hot run time: 152721 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.84 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 44eef01c38d2ee094290cfc1db07535c76ec2274, data reload: false

query1	0.00	0.00	0.00
query2	0.09	0.05	0.05
query3	0.27	0.13	0.13
query4	1.61	0.13	0.13
query5	0.27	0.23	0.22
query6	1.16	0.91	0.94
query7	0.04	0.01	0.00
query8	0.05	0.04	0.03
query9	0.42	0.34	0.33
query10	0.56	0.56	0.59
query11	0.20	0.14	0.15
query12	0.18	0.15	0.15
query13	0.47	0.47	0.46
query14	0.95	0.96	0.95
query15	0.60	0.58	0.58
query16	0.31	0.33	0.30
query17	1.02	1.12	1.08
query18	0.21	0.20	0.20
query19	1.97	1.89	1.91
query20	0.01	0.01	0.01
query21	15.44	0.24	0.13
query22	4.69	0.05	0.05
query23	16.15	0.31	0.12
query24	3.06	0.44	0.32
query25	0.13	0.05	0.04
query26	0.73	0.22	0.15
query27	0.03	0.03	0.04
query28	3.58	0.79	0.36
query29	12.49	4.07	3.22
query30	0.27	0.15	0.17
query31	2.77	0.56	0.31
query32	3.22	0.59	0.48
query33	3.20	3.12	3.14
query34	15.61	3.92	3.26
query35	3.22	3.21	3.24
query36	0.54	0.45	0.44
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.09	0.02	0.03
query42	0.04	0.03	0.02
query43	0.04	0.04	0.03
Total cold run time: 96.04 s
Total hot run time: 23.84 s

Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Sep 21, 2026
### What problem does this PR solve?

Related PR: apache#68301, apache#68297

The TIMESTAMPTZ binary-output and stream-load suites expected truncated historical offsets after formatting was fixed to preserve offset seconds. Set Asia/Shanghai explicitly in the relevant sessions and regenerate both result files to retain +08:05:43. Keep fixed-offset text-protocol and modern-date expectations unchanged.

### Release note

None

### Check List (For Author)

- Test: Both suites reproduced the original failures using the master PR CI artifact. Regenerated results through run-regression-test.sh and reran both suites in comparison mode: 2 passed, 0 failed. The isolated server default session time zone was UTC.
- Behavior changed: No product behavior change; tests cover historical offset seconds independently of server defaults.
- Does this need documentation: No
### What problem does this PR solve?

Related PR: apache#68301, apache#68297

The TIMESTAMPTZ binary-output and stream-load suites expected truncated historical offsets after formatting was fixed to preserve offset seconds. Set Asia/Shanghai explicitly in the relevant sessions and regenerate both result files to retain +08:05:43. Keep fixed-offset text-protocol and modern-date expectations unchanged.

### Release note

None

### Check List (For Author)

- Test: Both suites reproduced the original failures using the master PR CI artifact. Regenerated results through run-regression-test.sh and reran both suites in comparison mode: 2 passed, 0 failed. The isolated server default session time zone was UTC.
- Behavior changed: No product behavior change; tests cover historical offset seconds independently of server defaults.
- Does this need documentation: No
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27623 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit f68c0babcebd1ef82e9804e26900b4357efd99ab, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17687	3821	3824	3821
q2	2183	372	312	312
q3	10092	1441	766	766
q4	4677	474	346	346
q5	7473	809	544	544
q6	178	167	135	135
q7	730	785	593	593
q8	9293	1480	1493	1480
q9	5402	4170	4152	4152
q10	6808	1308	1021	1021
q11	429	266	240	240
q12	632	427	294	294
q13	18085	2671	2067	2067
q14	269	268	252	252
q15	q16	755	726	679	679
q17	1854	1153	1069	1069
q18	6619	5633	5554	5554
q19	1221	1218	1042	1042
q20	474	385	259	259
q21	5354	2889	2707	2707
q22	408	341	290	290
Total cold run time: 100623 ms
Total hot run time: 27623 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4142	4021	4022	4021
q2	728	541	505	505
q3	4453	4876	4259	4259
q4	2212	2305	1453	1453
q5	4162	4058	4075	4058
q6	223	174	126	126
q7	1699	1586	1431	1431
q8	2144	2052	2066	2052
q9	7321	7273	7470	7273
q10	3759	3601	3190	3190
q11	566	404	368	368
q12	735	746	528	528
q13	2439	2719	2157	2157
q14	314	297	287	287
q15	q16	693	729	616	616
q17	7868	7138	7115	7115
q18	11917	11156	11809	11156
q19	1169	1097	1068	1068
q20	2258	2225	1940	1940
q21	5324	4403	4459	4403
q22	519	440	412	412
Total cold run time: 64645 ms
Total hot run time: 58418 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152870 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit f68c0babcebd1ef82e9804e26900b4357efd99ab, data reload: false

query5	4302	606	470	470
query6	430	241	198	198
query7	4890	573	306	306
query8	323	187	175	175
query9	8812	3991	3982	3982
query10	449	299	256	256
query11	5823	3534	3219	3219
query12	142	87	88	87
query13	1250	573	441	441
query14	6507	4496	4224	4224
query14_1	3963	3945	3924	3924
query15	200	191	175	175
query16	976	442	413	413
query17	887	663	531	531
query18	2432	455	340	340
query19	198	180	143	143
query20	82	83	81	81
query21	219	130	113	113
query22	13163	12983	12759	12759
query23	13903	12918	12525	12525
query23_1	12531	12614	12572	12572
query24	7261	1201	671	671
query24_1	720	688	703	688
query25	567	425	373	373
query26	1285	313	166	166
query27	2700	554	354	354
query28	4593	1965	1975	1965
query29	1613	747	526	526
query30	305	221	181	181
query31	892	765	642	642
query32	145	96	98	96
query33	525	308	256	256
query34	1202	1200	629	629
query35	759	756	653	653
query36	771	831	707	707
query37	146	109	97	97
query38	1839	1770	1698	1698
query39	701	680	687	680
query39_1	636	653	680	653
query40	218	129	104	104
query41	72	67	72	67
query42	98	93	91	91
query43	332	342	300	300
query44	1372	723	719	719
query45	187	178	162	162
query46	1068	1205	718	718
query47	1495	1493	1395	1395
query48	412	401	293	293
query49	594	410	299	299
query50	993	357	267	267
query51	10663	10345	10424	10345
query52	91	88	79	79
query53	235	253	185	185
query54	279	221	195	195
query55	83	77	72	72
query56	240	222	230	222
query57	1426	1473	1296	1296
query58	296	278	254	254
query59	2021	2072	1895	1895
query60	290	254	242	242
query61	167	169	167	167
query62	407	322	267	267
query63	216	210	179	179
query64	2768	990	807	807
query65	3467	3404	3432	3404
query66	1805	414	304	304
query67	19939	20217	20181	20181
query68	3168	1552	916	916
query69	411	305	259	259
query70	920	822	814	814
query71	310	232	216	216
query72	2610	2419	2217	2217
query73	836	763	440	440
query74	4646	4487	4309	4309
query75	2306	2259	1939	1939
query76	2351	1107	722	722
query77	360	389	296	296
query78	9105	9121	8405	8405
query79	1406	1165	747	747
query80	744	452	387	387
query81	555	325	276	276
query82	630	163	123	123
query83	298	222	195	195
query84	316	143	114	114
query85	874	461	383	383
query86	343	224	229	224
query87	1999	1977	1835	1835
query88	3654	2752	2766	2752
query89	363	282	246	246
query90	1827	184	174	174
query91	174	156	128	128
query92	101	89	89	89
query93	1514	1414	821	821
query94	577	352	313	313
query95	665	474	326	326
query96	1057	785	328	328
query97	2438	2441	2323	2323
query98	161	147	145	145
query99	729	720	618	618
Total cold run time: 236468 ms
Total hot run time: 152870 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.87 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit f68c0babcebd1ef82e9804e26900b4357efd99ab, data reload: false

query1	0.01	0.00	0.00
query2	0.09	0.04	0.05
query3	0.26	0.14	0.13
query4	1.61	0.14	0.14
query5	0.24	0.22	0.22
query6	1.15	0.92	0.91
query7	0.04	0.01	0.01
query8	0.06	0.05	0.04
query9	0.40	0.33	0.33
query10	0.53	0.59	0.58
query11	0.19	0.15	0.14
query12	0.19	0.16	0.16
query13	0.46	0.46	0.46
query14	0.95	0.95	0.96
query15	0.60	0.59	0.58
query16	0.31	0.31	0.31
query17	1.07	1.03	1.10
query18	0.22	0.20	0.21
query19	2.03	1.91	1.84
query20	0.02	0.02	0.01
query21	15.42	0.21	0.13
query22	4.91	0.06	0.05
query23	16.16	0.29	0.12
query24	2.98	0.47	0.29
query25	0.11	0.06	0.04
query26	0.77	0.19	0.14
query27	0.04	0.04	0.03
query28	3.48	0.78	0.35
query29	12.47	4.07	3.20
query30	0.29	0.15	0.14
query31	2.78	0.56	0.32
query32	3.23	0.59	0.48
query33	3.24	3.25	3.24
query34	15.68	3.96	3.27
query35	3.22	3.25	3.21
query36	0.55	0.43	0.43
query37	0.08	0.07	0.06
query38	0.05	0.05	0.04
query39	0.04	0.03	0.04
query40	0.18	0.16	0.14
query41	0.08	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.27 s
Total hot run time: 23.87 s

@github-actions github-actions Bot 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.

Request changes — exact-head static review of f68c0babcebd1ef82e9804e26900b4357efd99ab against the authoritative merge-base diff. I found 13 new, distinct issue groups (3 P1, 10 P2) and attached them inline. The existing live threads covering the blanket multi-key hash rejection, Iceberg identity partitions, extreme historical-offset parsing, two missed TIMESTAMP_NS/error-formatting callers, and missing regression golden files remain valid duplicate fences and are intentionally not repeated here.

Critical checkpoint conclusions:

  • Goal and correctness: not yet met. The Field ownership and PType-length work is coherent, but top-level Hive partition parsing is broken, TIMESTAMPTZ still has parallel formatter/folding inconsistencies, and the advertised unsupported-VARBINARY boundary remains incomplete across FE/BE entry points.
  • Scope and clarity: the local changes are generally focused, but the function-by-function rejection design leaves numerous public scalar and aggregate paths FE-legal and BE-failing, and it rejects one supported arity of array_enumerate_uniq.
  • Concurrency, lifecycle, configuration, and persistence: no new concurrency, lock-order, dynamic-configuration, transaction, EditLog, or static-initialization issue was found. The new owning Field and decoder-copy lifetimes were traced through copy/move/destruction and appear safe.
  • Compatibility and parallel paths: serialized VARBINARY length restoration is sound, and no new storage-format incompatibility was found. Parallel evaluator, formatter, literal-folding, connector, scalar-arity, and aggregate-factory paths are not aligned; the inline comments identify the concrete failures.
  • Data writes/connectors: the new Hive partition-materialization failure is reported inline. The separate Iceberg identity-write failure is already covered by a live thread.
  • Error/null/performance: nullable TIMESTAMPTZ correctness improves, but the generic fix regresses all sparse-null cast-to-string blocks to row-wise virtual formatting. Error/format behavior also remains inconsistent in the reported parallel paths.
  • Tests: the PR adds useful unit coverage for ownership, SerDe, parser, and boundary behavior, but it misses the newly reported FE/BE and session-path cases and asserts rejection for the supported multi-array array_enumerate_uniq branch. The existing live thread already covers the three assertion-only regression suites and missing runner-generated .out files.
  • Observability and FE/BE variables: no additional metrics/logging or new variable transport is required. The existing short_circuit_evaluation setting does, however, expose inconsistent correctness for VARBINARY conditional expressions.
  • User focus: no additional focus was supplied; the full changed-file set and relevant call chains were reviewed.
  • Convergence: the third and final permitted round found linear_histogram, ndv/approx_count_distinct, and the multi-array array_enumerate_uniq regression; these are included in the aggregate-inventory and arity-specific comments. Under the review contract this makes the review capped/incomplete; no fourth discovery round was permitted.

Validation is static only: I did not run builds or tests. At submission time, GitHub reports compile, Clang format, CheckStyle, license, performance, and vault P0 passing; BE UT is failing (the TeamCity details are authentication-gated), while FE UT and several regression lanes remain pending. Those CI results are not independent validation of the findings above.

private ArrayFunctionUtils() {
}

static void checkNoVarBinaryArguments(ScalarFunction function) {

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.

[P2] Cover the remaining unsupported collection entry points with this pre-coercion check. array_except_all, array_min, and array_max still accept ARRAY<VARBINARY> in Nereids: array_except_all then reaches dispatch_switch_all, which has no VARBINARY case, while array_min/array_max reach the newly added VARBINARY throw in the single-value aggregate factory. Please invoke this guard from those three functions and add them to the FE rejection tests so these queries fail during analysis instead of BE preparation/execution.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These operations were already unsupported in BE. Moving their rejection into FE would broaden the function-validation work and is not needed to fix a newly introduced execution defect.

return creator_without_type::create_unary_arguments<
AggregateFunctionsSingleValue<Data<SingleValueDataComplexType>>>(
argument_types, result_is_nullable, attr);
case PrimitiveType::TYPE_VARBINARY:

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.

[P2] Add the matching FE rejection for every aggregate routed here. Nereids still accepts min(VARBINARY), max(VARBINARY), and any_value(VARBINARY) (Min/Max only reject metric types and AnyValue has an unrestricted signature), but all three names are registered through this factory and now throw while the BE builds the aggregate. Please reject them before coercion and add analysis tests for the public names.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These aggregate inputs were already unsupported; the new BE branch reports that unsupported case explicitly. A broader FE rejection inventory is outside this follow-up.

return Status::OK();
}
// Binary IO must not route IN through the shared string/storage predicate implementation.
if (context->get_arg_type(0)->get_primitive_type() == TYPE_VARBINARY) {

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.

[P2] Reject this type in Nereids as well. InPredicate.checkLegalityBeforeTypeCoercion excludes object/complex types, and supportCompare accepts VARBINARY as an ordinary primitive, so same-typed IN/NOT IN expressions still plan successfully and fail only when this BE function opens. Please add the pre-coercion check and same-/mixed-type analysis coverage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

VARBINARY IN/NOT IN remains unsupported. Moving the existing unsupported-type failure to FE is an analysis/diagnostic improvement rather than a new correctness fix.

// Inspect original arguments before coercion can hide unsupported binary comparison/hash inputs.
for (Expression argument : function.getArguments()) {
DataType type = argument.getDataType();
while (type instanceof ArrayType) {

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.

[P2] Apply the same restriction to the map membership entry points. map_contains_key, map_contains_value, and map_contains_entry have broad Nereids signatures and no legality check, but the first two forward to the array-index dispatcher and the third uses its own dispatch_switch_all; neither dispatches VARBINARY. Add equivalent recursive checks for VARBINARY keys/values and FE analysis coverage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The referenced map-membership dispatchers already lacked VARBINARY support before this PR. Expanding function-local FE validation is outside this follow-up.

Status DataTypeVarbinarySerDe::from_string(StringRef& str, IColumn& column,
const FormatOptions& options) const {
// Partition structs use the same hex representation as nested VARBINARY output. Decode it
// before appending so arbitrary bytes survive JSON transport instead of becoming NULL.

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.

[P1] Preserve the top-level partition-string contract here. With enable.mapping.varbinary=true, HiveScanRange copies each non-null HMS partition value directly into columns_from_path, and FileScannerV2::_parse_partition_value calls this from_string; any ordinary value not starting with 0x now fails with Invalid VARBINARY hex representation. The 0x grammar is symmetric only with nested serialization (to_string emits it at nesting level >= 2), so please restrict hex decoding to that context or use a dedicated nested decoder, and add a Hive partition scan test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The top-level and nested encodings differ, but the pre-PR VARBINARY SerDe inherited from_string() returning NotSupported. Thus this is not a regression of a previously supported Hive partition decoder. Adding that decoder is outside the current primitive changes.

Comment thread be/src/util/raw_value.h
inline uint32_t RawValue::zlib_crc32(const void* v, size_t len, const PrimitiveType& type,
uint32_t seed) {
// Reject binary even for NULL instead of reaching the default-type assertion or hash path.
if (type == TYPE_VARBINARY) {

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.

[P2] Fence the SQL caller as well. crc32_internal is a registered builtin whose Nereids class accepts variadic AnyDataType, and its BE implementation calls RawValue::zlib_crc32 for every non-null argument, so crc32_internal(VARBINARY) now plans successfully and throws here at execution. Please reject VARBINARY in Crc32Internal before coercion (with an FE analysis test), or implement the byte hash if the debug scalar should support it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

crc32_internal VARBINARY was already unsupported before the explicit BE rejection. Adding another FE function guard or a binary hash implementation is outside this follow-up.

} else if (primitive_type == TYPE_AGG_STATE) {
// Do nothing
nested = std::make_shared<DataTypeAggState>();
} else if (primitive_type == TYPE_VARBINARY) {

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.

[P2] Complete execution support for this newly reconstructible type in the default conditional evaluators. With the default short_circuit_evaluation=false, a multi-row coalesce whose selected values come from different arguments reaches filled_result_column, where dispatch_switch_scalar omits VARBINARY; a two-or-more-WHEN CASE separately reaches VCaseExpr::_execute_update_result, whose type switch also omits it. Both expressions are FE-legal, and both work when short-circuit evaluation is enabled through generic insert_from, so results currently depend on this session setting. Please add the generic/VARBINARY paths and regression cases for mixed-row COALESCE and multi-branch CASE under both settings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The normal COALESCE/CASE dispatch omissions and the alternate short-circuit paths predate this PR. The protobuf datatype reconstruction change does not introduce those evaluator branches. Adding VARBINARY execution support is outside this follow-up.

while (type instanceof ArrayType) {
type = ((ArrayType) type).getItemType();
}
if (type.isVarBinaryType()) {

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.

[P2] Include the remaining scalar ordering entry points in the pre-coercion rejection sweep. least and greatest preserve VARBINARY as their common type, but with two or more arguments the BE creates a ColumnVarbinary, misses the string branch, and reaches dispatch_switch_scalar, which has no VARBINARY case. Please add a shared legality check for both names and two-argument analysis tests; the deliberate unary passthrough can remain supported if desired.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The multiple-argument VARBINARY ordering dispatcher was already unsupported. Adding FE validation or preserving the unary compatibility path is outside this follow-up.

AggregateFunctionsSingleValue<Data<SingleValueDataComplexType>>>(
argument_types, result_is_nullable, attr);
case PrimitiveType::TYPE_VARBINARY:
// Owning binary values for IO must not implicitly enable single-value aggregates.

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.

[P2] Extend the FE-before-BE rejection inventory beyond this factory. The same mismatch remains for min_by/max_by with a VARBINARY ordering key, group_array_intersect/group_array_union with ARRAY<VARBINARY>, and VARBINARY inputs to histogram/hist, linear_histogram, topn_array, ndv/approx_count_distinct, map_agg_v1, map_agg_v2, and alias map_agg: their Nereids signatures admit the type, while the corresponding BE creator dispatches omit it and return no function. Please add function-local pre-coercion checks and analysis coverage for these public names, or add BE support where byte ordering/copying is intended.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These dispatcher omissions predate this PR. Completing the aggregate/alias validation inventory or introducing new BE support would broaden the change, so neither is included.

*/
@Override
public void checkLegalityBeforeTypeCoercion() {
ArrayFunctionUtils.checkNoVarBinaryArguments(this);

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.

[P2] Restrict this rejection to the one-array form. The unary BE branch uses dispatch_switch_scalar and cannot handle VARBINARY, but with two or more arrays FunctionArrayEnumerateUniq directly selects MethodSerialized; that path serializes every nested column, and this PR supplies the required serialization methods for ColumnVarbinary. The blanket guard therefore turns a supported multi-array form into an analysis error. Please preserve that arity and replace the mixed-array rejection assertion with execution coverage for long, empty, embedded-NUL, duplicate, and nullable binary tuple components.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Preserving the multi-array form is a compatibility request and is not part of this follow-up. Also, ColumnVarbinary serialization methods already existed before this PR; they were not introduced by it. The current rejection remains.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (26/26) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Historical TIMESTAMPTZ output could contain offsets rejected by its parsers.
Parse wire offsets independently of session fixed-zone limits in both modes.
The new local-year formatter exception also interrupted TIMESTAMP_NS cast and
comparison error reporting; render UTC values when constructing those errors.

### Release note

Preserve historical TIMESTAMPTZ round trips and timestamp conversion errors.

### Check List (For Author)

- Test: 31 focused ASAN BE tests passed, including ordinary date/datetime parsing;
  three targeted tests failed before the fixes. clang-format 16 and build hygiene passed.
  Full clang-tidy remains affected by pre-existing diagnostics.
- Behavior changed: Yes; accept historical wire offsets and preserve InvalidArgument/NULL handling.
- Does this need documentation: No.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot 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.

Static review of exact head 0765475366abe60678176acbbb82ef7d34366bec against base 695c88b57723ffd93c6a0978daa8725cb21b2562. I found two new actionable issues after deduplicating against all live inline threads and replies.

Checkpoint conclusions:

  • Objective, scope, and focus: reviewed all 55 authoritative changed paths and the relevant VARBINARY/TIMESTAMPTZ call chains; there was no additional user-provided focus. The implementation intent is clear, but the widened offset parser invalidates an existing checked-in regression expectation.
  • Concurrency, locking, lifecycle, and static initialization: no new shared-state or locking path is introduced. The Field owner, copy/move/assignment/destruction paths and decoder lifetimes were traced; no distinct lifetime defect remained. No relevant static-initialization issue was found.
  • Configuration dynamics: strict/non-strict casts, session time zones, folding, nullable shapes, and session-state restoration were traced. The nullable batch-performance concern is already covered by an existing thread; no additional configuration-dependent correctness issue remained.
  • Compatibility and rolling behavior: protobuf VARBINARY length reconstruction preserves declared/default length, and no persisted/replay format changes were found. Historical TIMESTAMPTZ text can now be 35 bytes, but MySQL result metadata still advertises 32; see the inline finding.
  • Parallel paths and special checks: strict/fallback parsers, central/ISO/FE formatters, text/prepared MySQL rows, Arrow, hash consumers, aggregates, predicates, Iceberg, collection aliases, and FE legality were reconciled. The surviving parallel-path issues already have live threads and were not duplicated.
  • Tests and results: one pre-existing golden will now deterministically fail at +15:00; the separate missing-golden convention issue already has a live thread. This review was static only: no build or test was run. Author-reported test results are not independent validation. At submission time, formatter/checkstyle/license/title checks pass, while compile, FE/BE unit tests, performance, and automated review checks remain pending.
  • Observability and error handling: the reviewed head fixes the prior throw-while-formatting TIMESTAMP_NS errors; no new distinct diagnostic/observability issue remained.
  • Persistence, transactions, and data writes: no new replay, atomicity, or transaction defect was found. The Iceberg binary identity path is already covered by a live thread.
  • FE/BE contracts: remaining VARBINARY over-rejections and missing FE-before-BE gates are already covered by live threads; no new entry point survived deduplication.
  • Performance: no new distinct issue beyond the already-threaded nullable batch deoptimization.
  • Other correctness: no additional finding survived two review rounds and the final changed-file sweep.

}
SET_PARAMS_RET_FALSE_IFN(part[0] <= 14, "invalid hour offset '{}'", part[0]);
SET_PARAMS_RET_FALSE_IFN(
part[0] < (type == DataTimeCastEnumType::TIMESTAMP_TZ ? 24U : 15U),

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.

[P1] Update the existing +15:00 regression expectation. This widened range now accepts +15:00 in both parsers (and the new unit test explicitly treats it as valid), but test_cast_timestamptz.groovy still includes +15:00 in its non-strict invalid row with a checked-in NULL in test_cast_timestamptz.out. Because that suite disables constant folding, it reaches this BE branch and will return a value instead of NULL. Move +15:00 to the valid cases (retain +24:00 as the rejection boundary) and regenerate the golden output.

buffer[len++] = '0' + offset_mins % 10;
// Historical zones can have sub-minute offsets. Dropping their seconds changes the
// instant represented by the client-visible wall clock and offset when read back.
const int offset_seconds = abs_offset % 60;

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.

[P2] Keep MySQL column metadata wide enough for the new format. With scale 6, appending :SS produces a 35-byte value (YYYY-MM-DD HH:MM:SS.ffffff+HH:MM:SS), and both text and prepared-result paths send that full string. MysqlSerializer.getMysqlTypeLength(TIMESTAMPTZ), however, still advertises 32 bytes based on +HH:mm, so clients see a display width smaller than rows this formatter now emits. Please raise the TIMESTAMPTZ metadata width to 35 and cover the serialized Column Definition value.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27685 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0765475366abe60678176acbbb82ef7d34366bec, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17722	3968	3849	3849
q2	2193	402	316	316
q3	10065	1397	787	787
q4	4693	477	351	351
q5	7466	847	545	545
q6	184	182	140	140
q7	752	784	605	605
q8	9301	1508	1426	1426
q9	5434	4211	4148	4148
q10	6828	1349	1047	1047
q11	434	268	244	244
q12	630	414	310	310
q13	18013	2645	2005	2005
q14	266	272	238	238
q15	q16	736	719	659	659
q17	1807	1110	1050	1050
q18	6463	5611	5571	5571
q19	1141	1311	1066	1066
q20	471	388	278	278
q21	5128	3034	2750	2750
q22	443	353	300	300
Total cold run time: 100170 ms
Total hot run time: 27685 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4326	4174	4176	4174
q2	717	558	534	534
q3	4451	4843	4350	4350
q4	2243	2338	1463	1463
q5	4192	4140	4109	4109
q6	226	173	128	128
q7	1728	1602	1424	1424
q8	2237	2505	2072	2072
q9	7556	7300	7414	7300
q10	3704	3639	3170	3170
q11	607	443	405	405
q12	728	719	526	526
q13	2459	2887	2114	2114
q14	286	290	270	270
q15	q16	699	707	638	638
q17	7967	7377	7120	7120
q18	12008	11139	11953	11139
q19	1222	1100	1101	1100
q20	2255	2252	1958	1958
q21	5418	4575	4565	4565
q22	551	455	410	410
Total cold run time: 65580 ms
Total hot run time: 58969 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153045 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0765475366abe60678176acbbb82ef7d34366bec, data reload: false

query5	4319	605	463	463
query6	435	210	196	196
query7	4858	568	304	304
query8	318	183	166	166
query9	8788	4070	4082	4070
query10	464	323	267	267
query11	5884	3539	3204	3204
query12	149	94	84	84
query13	1263	594	450	450
query14	6543	4547	4216	4216
query14_1	3987	4017	3995	3995
query15	206	201	182	182
query16	987	472	428	428
query17	915	684	547	547
query18	2436	463	332	332
query19	204	181	145	145
query20	83	81	81	81
query21	217	136	118	118
query22	13061	13074	12757	12757
query23	13933	12940	12470	12470
query23_1	12467	12437	12516	12437
query24	7265	1115	679	679
query24_1	721	687	750	687
query25	563	431	374	374
query26	1252	306	170	170
query27	2702	561	354	354
query28	4607	2002	2007	2002
query29	1580	759	531	531
query30	299	214	187	187
query31	902	762	650	650
query32	150	95	92	92
query33	533	319	257	257
query34	1212	1157	647	647
query35	742	765	663	663
query36	811	806	762	762
query37	152	103	94	94
query38	1823	1782	1713	1713
query39	717	674	651	651
query39_1	664	654	640	640
query40	230	128	106	106
query41	72	71	72	71
query42	105	93	93	93
query43	339	355	303	303
query44	1381	728	729	728
query45	187	179	164	164
query46	1088	1242	763	763
query47	1495	1504	1402	1402
query48	415	427	308	308
query49	597	458	297	297
query50	923	352	254	254
query51	10487	10446	10259	10259
query52	87	89	76	76
query53	235	261	178	178
query54	235	214	204	204
query55	77	76	69	69
query56	224	209	209	209
query57	1587	1371	1424	1371
query58	274	258	248	248
query59	1972	2083	1893	1893
query60	279	248	214	214
query61	148	159	137	137
query62	397	320	270	270
query63	214	177	175	175
query64	2799	1022	813	813
query65	3451	3422	3433	3422
query66	1806	420	300	300
query67	20346	20085	20067	20067
query68	3185	1526	984	984
query69	407	304	266	266
query70	923	811	805	805
query71	292	235	217	217
query72	2647	2302	2255	2255
query73	847	771	433	433
query74	4656	4492	4306	4306
query75	2289	2288	1965	1965
query76	2296	1091	740	740
query77	368	402	296	296
query78	9029	9084	8439	8439
query79	1344	1209	740	740
query80	569	454	361	361
query81	532	322	276	276
query82	622	170	125	125
query83	309	236	203	203
query84	331	145	111	111
query85	867	452	378	378
query86	345	244	232	232
query87	2008	1967	1848	1848
query88	3606	2739	2735	2735
query89	374	288	249	249
query90	1881	178	178	178
query91	179	159	135	135
query92	100	90	92	90
query93	1656	1575	873	873
query94	550	359	290	290
query95	659	463	350	350
query96	1054	825	330	330
query97	2439	2441	2301	2301
query98	162	150	158	150
query99	720	729	621	621
Total cold run time: 236388 ms
Total hot run time: 153045 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.16 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0765475366abe60678176acbbb82ef7d34366bec, data reload: false

query1	0.01	0.00	0.01
query2	0.09	0.05	0.05
query3	0.26	0.14	0.13
query4	1.60	0.14	0.14
query5	0.25	0.22	0.22
query6	1.16	0.92	0.93
query7	0.04	0.01	0.01
query8	0.05	0.03	0.04
query9	0.40	0.34	0.34
query10	0.55	0.56	0.52
query11	0.20	0.14	0.15
query12	0.19	0.16	0.15
query13	0.47	0.47	0.48
query14	0.96	0.95	0.94
query15	0.60	0.59	0.59
query16	0.31	0.32	0.32
query17	1.06	1.09	1.09
query18	0.22	0.20	0.20
query19	2.01	1.92	1.96
query20	0.03	0.01	0.02
query21	15.51	0.23	0.13
query22	4.75	0.06	0.06
query23	16.14	0.31	0.13
query24	3.02	0.44	0.33
query25	0.10	0.04	0.04
query26	0.73	0.21	0.16
query27	0.03	0.04	0.03
query28	3.58	0.79	0.37
query29	12.46	4.13	3.26
query30	0.28	0.15	0.14
query31	2.78	0.54	0.31
query32	3.22	0.58	0.49
query33	3.13	3.20	3.27
query34	15.55	3.90	3.31
query35	3.21	3.22	3.25
query36	0.57	0.45	0.44
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.09	0.03	0.03
query42	0.03	0.04	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.03 s
Total hot run time: 24.16 s

### What problem does this PR solve?

The binary literal unit test used a StringView after the temporary owning Field
was destroyed. Keep that Field alive through the assertion, covering short and
long values with embedded NUL bytes.

The TIMESTAMPTZ cast regression still classified +15:00 as invalid after the
historical wire-offset parser fix. Use +24:00 for the rejection test and cover
valid historical offsets in both cast modes with generated snapshots.

### Release note

None; this only fixes tests for the existing PR behavior.

### Check List (For Author)

- Test: 34 focused ASAN BE tests passed on each branch. The original lifetime
  bug reproduced under ASAN. The original SQL failure reproduced on the master CI artifact; the full
  corrected cast suite passed in comparison mode with generated new snapshots.
  clang-format 16 passed. Full clang-tidy is blocked by pre-existing diagnostics.
- Behavior changed: No production behavior change.
- Does this need documentation: No.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27949 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 74fc4477d87e46094cf8c449de2c88bb2288c473, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17662	3909	3887	3887
q2	2228	367	316	316
q3	10041	1499	789	789
q4	4684	476	348	348
q5	7489	821	559	559
q6	176	177	139	139
q7	826	780	602	602
q8	9324	1496	1585	1496
q9	5468	4229	4186	4186
q10	6848	1351	1013	1013
q11	427	286	233	233
q12	634	413	291	291
q13	18075	2624	2001	2001
q14	267	263	244	244
q15	q16	732	716	663	663
q17	1734	1104	1069	1069
q18	6855	5649	5544	5544
q19	1312	1244	995	995
q20	468	391	257	257
q21	5750	3462	3015	3015
q22	460	376	302	302
Total cold run time: 101460 ms
Total hot run time: 27949 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4716	4705	4429	4429
q2	708	551	554	551
q3	4820	5143	4563	4563
q4	2229	2350	1470	1470
q5	4602	4609	4507	4507
q6	224	171	125	125
q7	1850	1699	1485	1485
q8	2378	2035	2037	2035
q9	7284	7243	7252	7243
q10	3616	3555	3084	3084
q11	509	370	339	339
q12	713	699	501	501
q13	2300	2594	1990	1990
q14	266	284	249	249
q15	q16	663	686	596	596
q17	7294	6749	6628	6628
q18	11896	11005	11836	11005
q19	1092	1002	1048	1002
q20	2213	2184	1911	1911
q21	4952	4122	4267	4122
q22	521	480	389	389
Total cold run time: 64846 ms
Total hot run time: 58224 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152852 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 74fc4477d87e46094cf8c449de2c88bb2288c473, data reload: false

query5	4312	606	462	462
query6	423	207	191	191
query7	4814	553	297	297
query8	319	177	158	158
query9	8799	3986	3987	3986
query10	442	295	251	251
query11	5882	3538	3238	3238
query12	150	91	86	86
query13	1258	566	412	412
query14	6508	4469	4246	4246
query14_1	3946	3988	3938	3938
query15	202	199	177	177
query16	991	455	418	418
query17	911	665	539	539
query18	2436	459	343	343
query19	200	184	145	145
query20	81	82	82	82
query21	223	131	117	117
query22	13109	12955	12783	12783
query23	14017	13037	12376	12376
query23_1	12611	12528	12643	12528
query24	7368	1116	646	646
query24_1	666	679	684	679
query25	553	411	360	360
query26	1279	312	166	166
query27	2691	533	342	342
query28	4574	1958	1972	1958
query29	1599	702	502	502
query30	296	217	181	181
query31	904	756	625	625
query32	187	98	94	94
query33	501	295	247	247
query34	1210	1080	642	642
query35	730	759	643	643
query36	823	782	704	704
query37	144	101	87	87
query38	1827	1776	1677	1677
query39	691	689	682	682
query39_1	648	678	633	633
query40	217	116	107	107
query41	67	66	64	64
query42	93	87	95	87
query43	335	348	306	306
query44	1366	734	712	712
query45	187	176	164	164
query46	1067	1179	731	731
query47	1507	1519	1384	1384
query48	393	403	298	298
query49	590	419	302	302
query50	1013	357	268	268
query51	10500	10607	10418	10418
query52	89	95	77	77
query53	242	251	179	179
query54	248	200	199	199
query55	78	74	69	69
query56	234	219	218	218
query57	1542	1492	1243	1243
query58	297	261	252	252
query59	2004	2071	1901	1901
query60	282	242	234	234
query61	152	155	146	146
query62	398	324	269	269
query63	212	179	177	177
query64	2802	970	931	931
query65	3484	3426	3437	3426
query66	1836	445	316	316
query67	20118	20341	20082	20082
query68	3180	1606	985	985
query69	425	309	279	279
query70	894	824	787	787
query71	303	247	213	213
query72	2766	2654	2261	2261
query73	796	744	431	431
query74	4644	4512	4265	4265
query75	2315	2287	1930	1930
query76	2336	1093	751	751
query77	356	395	306	306
query78	9125	9100	8480	8480
query79	1354	1241	799	799
query80	554	465	389	389
query81	539	332	284	284
query82	893	166	125	125
query83	305	219	197	197
query84	317	145	117	117
query85	844	465	385	385
query86	337	242	222	222
query87	2006	1981	1840	1840
query88	3684	2757	2707	2707
query89	363	289	251	251
query90	1959	186	181	181
query91	175	161	151	151
query92	104	89	81	81
query93	1542	1480	868	868
query94	553	318	287	287
query95	647	451	337	337
query96	1021	775	357	357
query97	2450	2430	2301	2301
query98	162	150	142	142
query99	712	735	625	625
Total cold run time: 236922 ms
Total hot run time: 152852 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.15 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 74fc4477d87e46094cf8c449de2c88bb2288c473, data reload: false

query1	0.01	0.00	0.01
query2	0.11	0.05	0.04
query3	0.27	0.14	0.14
query4	1.61	0.15	0.14
query5	0.24	0.22	0.23
query6	1.17	0.93	0.96
query7	0.04	0.00	0.00
query8	0.06	0.04	0.04
query9	0.40	0.35	0.34
query10	0.59	0.59	0.55
query11	0.20	0.15	0.15
query12	0.18	0.15	0.15
query13	0.47	0.46	0.48
query14	0.96	0.96	0.94
query15	0.61	0.59	0.58
query16	0.31	0.33	0.31
query17	1.08	1.09	1.07
query18	0.22	0.20	0.22
query19	2.02	1.97	1.98
query20	0.02	0.02	0.01
query21	15.50	0.20	0.15
query22	4.85	0.06	0.05
query23	16.13	0.32	0.13
query24	2.95	0.44	0.35
query25	0.13	0.05	0.04
query26	0.73	0.21	0.16
query27	0.05	0.04	0.04
query28	3.50	0.78	0.35
query29	12.53	4.12	3.19
query30	0.30	0.18	0.17
query31	2.77	0.56	0.31
query32	3.22	0.60	0.49
query33	3.28	3.13	3.23
query34	15.52	4.03	3.28
query35	3.24	3.26	3.23
query36	0.55	0.44	0.44
query37	0.11	0.07	0.07
query38	0.06	0.04	0.04
query39	0.04	0.04	0.03
query40	0.18	0.16	0.15
query41	0.09	0.04	0.04
query42	0.04	0.03	0.04
query43	0.05	0.04	0.04
Total cold run time: 96.39 s
Total hot run time: 24.15 s

@github-actions github-actions Bot 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.

Static review conclusion: request changes for one newly introduced stability issue.

The VARBINARY lifetime, decoder-copy, Hive/nested SerDe, protobuf-length, explicit capability-gate, and TIMESTAMPTZ parser/formatter/null-boundary changes are otherwise internally coherent. Copy/move/destruction and text/prepared TIMESTAMPTZ paths were traced; no new concurrency, locking, configuration, persistence, transaction, data-write sequencing, or FE-BE propagation issue was found. Compatibility and parallel-path concerns that remain are already covered by current inline threads and were not duplicated.

Blocking point: long VARBINARY Field ownership allocates through raw new[], skipping Doris task-tracker accounting and the checked pre-allocation failure path.

Tests/observability: changed tests cover lifetime, decoder, SerDe, malformed data, historical offset parsing/formatting, nullable behavior, boundaries, and protocol paths; errors remain actionable. This review was static only as required: no builds or tests were run, and author/CI results were not independently validated.

No additional user-provided focus was present.

Comment thread be/src/core/field.cpp
view = StringView(bytes, value.size());
}
OwnedBinaryField(const OwnedBinaryField&) = delete;
OwnedBinaryField& operator=(const OwnedBinaryField&) = delete;

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.

[P1] Allocate this retained payload through Doris's checked allocator. Every non-inline VARBINARY value materialized as a Field now duplicates value.size() bytes with raw new[]; this is reached by ordinary column extraction plus Iceberg defaults and Parquet metadata, and the declared length can be Integer.MAX_VALUE. The current jemalloc hook only routes allocation calls and does not consume/release the task tracker, while raw new[] also skips Allocator::memory_check and its controlled MEM_ALLOC_FAILED path. A large value (and the temporary/destination deep-copy peak) can therefore exceed a query or process limit without Doris charging it or rejecting it at the configured limit. Please use DorisUniqueBufferPtr or an equivalent allocator-backed owner that still fits Field::storage, and cover allocation/destruction under a limited tracker.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 221207e and synchronized to #68297 (0a220b4).

Long binary payloads now use Allocator for checked allocation and release. The RAII owner remains standard-layout and fits Field::storage, preserving the leading StringView access. It stores the allocation length separately because Field::get() exposes a mutable view. Inline payloads remain allocation-free.

Added limited-tracker tests for retained/copy accounting, replacement and destruction, oversized allocation rejection, and failed copy/assignment preserving the original value. Both new tests failed with the original new[] implementation. All 40 focused ASAN BE tests pass on each branch.

Also stabilized the failing historical-offset fixture with fixed zones so the large negative offsets and second-precision round trips do not depend on the host's historical Manila/Guam tzdata. This change stays within the existing PR scope.

clang-format 16 and master build hygiene passed. Full clang-tidy remains blocked by pre-existing diagnostics, including the unmatched NOLINTEND in core/types.h. CI has been retriggered on both PRs.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (26/26) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Long binary Fields retained payloads with raw new[], bypassing Doris memory
tracking and allocation checks. Use an allocator-backed standard-layout owner
that fits the existing Field storage. Release the original allocation size even
if the exposed view changes, and preserve existing values on failed replacement.

Historical Manila offsets differ across tzdata versions. Use fixed zones for
large negative offset fixtures while retaining second-precision round trips.

### Release note

Retained binary Field payloads now use Doris memory accounting and limit checks.

### Check List (For Author)

- Test: 40 focused ASAN BE unit tests passed. Both new memory tests failed
  against the original allocator path. clang-format 16, build hygiene and diff
  checks passed. Full clang-tidy is blocked by pre-existing diagnostics.
- Behavior changed: Yes, retained binary payloads use checked allocations.
- Does this need documentation: No.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27795 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 221207ec3a1ae824b81657a1ea4dbb9b8bd51fb0, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17672	3821	3834	3821
q2	2291	363	317	317
q3	10020	1387	773	773
q4	4683	486	348	348
q5	7557	807	553	553
q6	183	169	136	136
q7	737	778	638	638
q8	9318	1526	1573	1526
q9	5373	4202	4167	4167
q10	6822	1321	1011	1011
q11	438	263	239	239
q12	628	412	298	298
q13	18057	2618	1977	1977
q14	261	258	236	236
q15	q16	733	723	657	657
q17	1786	1172	996	996
q18	6393	5566	5536	5536
q19	1191	1305	1023	1023
q20	491	389	268	268
q21	5461	3319	2973	2973
q22	442	354	302	302
Total cold run time: 100537 ms
Total hot run time: 27795 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4494	4475	4343	4343
q2	719	562	554	554
q3	4745	5334	4565	4565
q4	2239	2359	1447	1447
q5	4626	4516	4607	4516
q6	234	185	132	132
q7	1823	1695	1491	1491
q8	2307	2017	2076	2017
q9	7258	7153	6899	6899
q10	3626	3558	3105	3105
q11	514	365	338	338
q12	713	702	513	513
q13	2261	2615	2000	2000
q14	266	271	251	251
q15	q16	662	681	602	602
q17	7303	6738	6618	6618
q18	11872	11090	11834	11090
q19	1119	998	996	996
q20	2217	2189	1915	1915
q21	4989	4077	4256	4077
q22	512	442	401	401
Total cold run time: 64499 ms
Total hot run time: 57870 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152387 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 221207ec3a1ae824b81657a1ea4dbb9b8bd51fb0, data reload: false

query5	4298	576	461	461
query6	419	209	191	191
query7	4816	562	288	288
query8	315	175	160	160
query9	8790	3965	4011	3965
query10	450	292	250	250
query11	5808	3532	3213	3213
query12	139	90	83	83
query13	1246	576	425	425
query14	6515	4524	4222	4222
query14_1	3946	3952	4266	3952
query15	198	200	181	181
query16	990	482	430	430
query17	906	683	545	545
query18	2425	467	332	332
query19	201	174	142	142
query20	87	80	79	79
query21	220	134	113	113
query22	13161	13010	12908	12908
query23	13855	13037	12439	12439
query23_1	12520	12566	12479	12479
query24	7297	1152	653	653
query24_1	704	659	717	659
query25	598	439	372	372
query26	1263	325	163	163
query27	2657	583	338	338
query28	4550	1985	1963	1963
query29	1585	760	506	506
query30	298	220	183	183
query31	892	757	635	635
query32	141	91	88	88
query33	523	294	223	223
query34	1158	1095	634	634
query35	716	746	627	627
query36	788	782	716	716
query37	139	106	95	95
query38	1834	1749	1696	1696
query39	673	707	666	666
query39_1	645	649	643	643
query40	223	119	98	98
query41	64	63	61	61
query42	99	94	90	90
query43	339	343	298	298
query44	1347	717	702	702
query45	188	169	157	157
query46	1069	1155	724	724
query47	1468	1513	1393	1393
query48	409	376	288	288
query49	580	402	289	289
query50	963	357	243	243
query51	10545	10779	10521	10521
query52	89	92	75	75
query53	243	256	179	179
query54	244	200	193	193
query55	78	74	69	69
query56	236	223	212	212
query57	1496	1482	1377	1377
query58	292	264	253	253
query59	2001	2084	1881	1881
query60	266	240	220	220
query61	147	148	137	137
query62	390	319	264	264
query63	208	167	173	167
query64	2805	970	806	806
query65	3493	3417	3444	3417
query66	1804	408	308	308
query67	19974	19828	19810	19810
query68	3238	1497	937	937
query69	395	293	253	253
query70	950	834	803	803
query71	293	232	216	216
query72	2577	2522	2176	2176
query73	817	760	445	445
query74	4639	4495	4303	4303
query75	2316	2290	1934	1934
query76	2307	1097	754	754
query77	367	393	311	311
query78	9006	8941	8415	8415
query79	1341	1219	754	754
query80	620	480	387	387
query81	522	328	288	288
query82	620	167	128	128
query83	304	226	203	203
query84	311	151	119	119
query85	900	523	451	451
query86	330	238	233	233
query87	1998	1952	1835	1835
query88	3615	2733	2702	2702
query89	353	287	249	249
query90	1940	181	175	175
query91	176	154	125	125
query92	102	93	89	89
query93	1408	1467	871	871
query94	502	329	305	305
query95	665	458	331	331
query96	1012	848	317	317
query97	2424	2433	2339	2339
query98	155	148	146	146
query99	716	735	602	602
Total cold run time: 235327 ms
Total hot run time: 152387 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.03 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 221207ec3a1ae824b81657a1ea4dbb9b8bd51fb0, data reload: false

query1	0.01	0.01	0.00
query2	0.09	0.05	0.05
query3	0.25	0.14	0.13
query4	1.61	0.14	0.14
query5	0.25	0.22	0.22
query6	1.16	0.95	0.95
query7	0.04	0.01	0.00
query8	0.06	0.03	0.04
query9	0.39	0.34	0.33
query10	0.60	0.52	0.56
query11	0.20	0.14	0.15
query12	0.18	0.15	0.15
query13	0.47	0.47	0.47
query14	0.95	0.95	0.94
query15	0.61	0.60	0.58
query16	0.31	0.33	0.34
query17	1.08	1.07	1.05
query18	0.22	0.20	0.19
query19	1.97	1.92	1.88
query20	0.02	0.01	0.02
query21	15.47	0.23	0.15
query22	4.84	0.05	0.06
query23	16.15	0.31	0.12
query24	2.98	0.43	0.32
query25	0.11	0.04	0.05
query26	0.71	0.20	0.16
query27	0.05	0.03	0.03
query28	3.51	0.83	0.37
query29	12.46	4.06	3.20
query30	0.28	0.15	0.15
query31	2.77	0.56	0.31
query32	3.24	0.59	0.48
query33	3.17	3.28	3.28
query34	15.57	3.98	3.29
query35	3.21	3.24	3.21
query36	0.56	0.42	0.43
query37	0.08	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.17	0.14	0.14
query41	0.08	0.03	0.03
query42	0.04	0.02	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.05 s
Total hot run time: 24.03 s


void ColumnVarbinary::insert_many_continuous_binary_data(const char* data, const uint32_t* offsets,
size_t num) {
reserve(size() + num);

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.

这个reserve 是错的。 不是 +num,应该是计算一下offsets【num】 - 0 ?

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 98.66% (147/149) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.78% (29675/46528)
Line Coverage 48.46% (309160/637917)
Region Coverage 44.01% (249337/566573)
Branch Coverage 45.59% (115947/254308)

@github-actions github-actions Bot 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.

Static exact-head review of 221207ec3a1ae824b81657a1ea4dbb9b8bd51fb0. I found five blocking correctness/compatibility issues: the Hive BINARY read contract is neither propagated nor matched, Hive binary text conversion stages unadmitted full-cell buffers, several previously valid mixed array calls are rejected before coercion, BE and FE disagree at a fractional-carry/year boundary, and the new seconds-offset formatter output is rejected by FE catalog literal parsing.

Checkpoint summary: I reviewed all 58 changed paths and relevant upstream/downstream call chains, including ownership and failure rollback, legacy/v2 Hive text paths, storage/Parquet copying, collection signature resolution and BE dispatch, both TIMESTAMPTZ parsers, FE folding/catalog parsing, MySQL output, error/NULL paths, and persistence/configuration boundaries. The allocator-backed hidden Field owner is lifecycle- and tracker-balanced; its remaining move/deep-copy peak is already covered by an existing inline thread. No additional concurrency, static-initialization, transaction, or persisted-format defect survived deduplication. Existing MySQL-width, ISO8601, shared hash-key, partition-hex, collection-inventory, and nullable-performance threads were treated as hard duplicate fences.

Validation is static only: the authoritative review bundle prohibited builds and tests. Author/CI results were not treated as independent execution evidence. Targeted coverage is still needed for Hive raw/versioned decoding under memory limits, supported mixed-type coercions, folded/non-folded boundary rounding, and formatter-to-FE-default round trips.

return Status::OK();
}

Status DataTypeVarbinarySerDe::deserialize_one_cell_from_hive_text(

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.

[P1] Propagate the Hive BINARY decoding contract instead of guessing it from each cell. Hive 4 supports hive.serialization.decode.binary.as.base64=false for raw TEXTFILE values, but FE drops that property, so a configured raw value such as test is silently Base64-decoded here to different bytes. In default mode Hive 4/current LazyBinary also uses the strict Basic decoder with raw fallback, while this code accepts URL-safe letters/whitespace and truncates a one-sextet tail (for example Hive preserves -_8= but Doris returns 0xfb 0xff). Please pass the property/version-selected mode through TFileAttributes, use the matching decoder, and cover raw plus Hive 3/4 Base64 cases. See the Hive TEXTFILE contract and Hive 4 LazyBinary.

// Hive LazyBinary uses lenient Base64 (including URL-safe letters and whitespace),
// falling back to the original bytes for non-Base64 input or an empty decoding.
// Keep this separate from JSON/CSV: those formats do not share Hive's encoding contract.
std::string encoded;

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.

[P1] Put these full-cell Hive staging buffers behind Doris's checked allocator. For every valid binary field this reserves slice.size in encoded, base64_decode then resizes a second std::string to the same size, and ColumnVarbinary finally copies the decoded bytes into its arena. Ordinary std::string storage does not run the Allocator<false> admission check, so one large external field can build roughly two input-sized buffers before the tracked column allocation rejects it; the new write path likewise materializes both value.to_string() and its Base64 output. Please decode/encode directly into checked destination storage (and avoid the hex path's equivalent whole-cell temporary), with a limited-memory scan/write test.

while (type instanceof ArrayType) {
type = ((ArrayType) type).getItemType();
}
if (type.isVarBinaryType()) {

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.

[P2] Reject the resolved execution type rather than every original argument. For array_contains(ARRAY<STRING>, VARBINARY), the FOLLOW signature resolves the scalar to STRING and the existing implicit cast feeds the supported BE string kernel; array_position, count_equal, array_remove, and array_contains_all share that pattern. With default new type coercion, indexed-Any common-type selection likewise resolves mixed ARRAY<STRING>/ARRAY<VARBINARY> inputs to STRING for arrays_overlap, array_except, and array_union, whose BE implementations have ColumnString paths. This guard rejects all of them before coercion, and the new mixed-type test locks in the regression. Please reject signatures that resolve to VARBINARY, but allow binary inputs that resolve to supported execution types.

Comment thread be/src/exprs/function/cast/cast_to_datetimev2_impl.hpp
Comment thread be/src/core/value/timestamptz_value.cpp
@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 98.66% (147/149) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.14% (34303/45054)
Line Coverage 61.00% (384716/630641)
Region Coverage 57.33% (323480/564289)
Branch Coverage 58.20% (147556/253521)

@yiguolei
yiguolei merged commit 7dc2985 into apache:master Sep 22, 2026
40 of 41 checks passed
Gabriel39 added a commit that referenced this pull request Sep 22, 2026
)

### What problem does this PR solve?

This is the first of five planned extractions from #67784, targeting
`branch-4.1`.

Binary `Field` values can retain references to released source storage,
and Hive binary text needs its own Base64 contract. TIMESTAMPTZ output
can lose historical offset seconds, format invalid NULL payloads, or
fail again while reporting a boundary cast error.

- Own long binary Field values while keeping short values inline.
Preserve execution type lengths and decoder bytes, fix binary literal
encoding, and add Hive Base64 and hexadecimal decoding support.
- Explicitly reject unsupported binary hash keys, IN, aggregates,
predicates and computed partition transforms. Keep the existing FE
comparison/group/join restrictions and existing binary scalar functions.
Reject unsupported collection kernels before coercion.
- Normalize fixed timezone offsets and preserve historical second
offsets in both TIMESTAMPTZ formatting and parsing. Skip masked NULL
payloads, reject unrepresentable local years, and preserve cast
error/NULL behavior at boundaries.

Arrow convertor migration, Parquet/ORC semantics, external writer
changes and catalog mapping migration belong to the subsequent
extractions. This PR does not enable native VARBINARY storage.

### Testing
- TIMESTAMPTZ regression follow-up: reproduced both binary-output and
stream-load failures using the master PR CI artifact, regenerated the
two snapshots through `run-regression-test.sh`, and passed both suites
in comparison mode from each branch checkout. Explicit `Asia/Shanghai`
session settings were verified with the server default session zone set
to UTC. Only historical offset seconds changed in the generated results.
- Function-local validation update: 17 FE tests passed after a clean
build with Checkstyle enabled. Coverage includes direct legality checks,
nested/mixed/variadic VARBINARY arguments, both `collect_set` arities,
supported ordinary types, SQL analysis, and existing array rewrites.
Collection restrictions now live in each function's legality check
before coercion; existing branch-specific argument rules are preserved.

- Rebuilt the BE ASAN test target from this extraction: **184 tests
passed**, zero failures. Coverage includes binary
lifetime/SerDe/rejection paths, timestamp parsing/casts, hash and
partition guards, and existing Arrow/Variant serialization tests.
- `VarBinaryUnsupportedCollectionTest`: **passed** (13 unsupported
collection expressions, plus existing byte-preserving array/collection
analysis).
- FE reactor `validate` with repository Checkstyle: **passed**.
- clang-format 16 check on all 34 changed C++ source/header files:
**passed**.
- Groovy compilation of the three new regression suites: **passed**.
Live SQL regression execution is pending CI.

The local BE test source list was narrowed for the focused build and
restored before committing. No build configuration changes are included.

### Release note

Fix binary value lifetime and serialization, reject unsupported binary
computation paths, and preserve TIMESTAMPTZ historical offsets and
boundary error behavior.

### Check List (For Author)

- Test
- [x] Regression test (three self-checking suites added; execution
pending CI)
  - [x] Unit Test
- Behavior changed:
- [x] Yes. Binary rejection and timestamp boundary behavior are
described above.
- Does this need documentation?
- [x] No. This fixes existing type behavior without introducing a
configuration option.

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label

### Scoped review follow-up

This follow-up only fixes correctness/stability defects introduced by
this PR. Compatibility preservation, pre-existing limitations,
additional VARBINARY computation/validation, and unrelated refactors are
excluded.

- Separate historical TIMESTAMPTZ wire-offset parsing from session
fixed-zone limits in both parser paths.
- Validate the complete UTC/GMT fixed offset and exclude rejected
endpoint values from the timezone cache.
- Decline FE string folding when the session-local year is outside the
new BE display range. Preserve the CAST for BE evaluation in both cast
modes instead of folding non-strict casts to NULL.
- Validation: 29 focused ASAN BE tests and 15 FE tests passed. Four BE
tests and the new FE boundary test failed before the fixes. clang-format
16 and FE Checkstyle passed.
- The corresponding master follow-up is in #68301. Master already has
different timezone normalization and FE folding behavior; its additional
TIMESTAMP_NS error-reporting fix does not apply to branch-4.1.

### CI test follow-up

- Keep the binary literal test's owning Field alive while reading its
StringView. Branch-4.1 now has the corresponding short/long embedded-NUL
coverage using its execution API.
- Replace the obsolete +15:00 rejection input with +24:00. Add generated
historical-offset checks in both cast modes; all prior snapshot results
are unchanged.
- Validation: 34 focused ASAN BE tests passed on each branch. The
lifetime error and the original SQL mismatch were reproduced. The
complete cast regression suite passed in comparison mode from both
branch checkouts against the reported master CI artifact. clang-format
16 passed; full clang-tidy remains blocked by pre-existing diagnostics.

This follow-up changes tests only and retains the agreed scope: no
compatibility work or additional binary computation support. Existing
muted failures are outside this fix.
yiguolei pushed a commit that referenced this pull request Sep 23, 2026
)

### What problem does this PR solve?

This is the first of five planned extractions from #67784, targeting
`branch-4.1`.

Binary `Field` values can retain references to released source storage,
and Hive binary text needs its own Base64 contract. TIMESTAMPTZ output
can lose historical offset seconds, format invalid NULL payloads, or
fail again while reporting a boundary cast error.

- Own long binary Field values while keeping short values inline.
Preserve execution type lengths and decoder bytes, fix binary literal
encoding, and add Hive Base64 and hexadecimal decoding support.
- Explicitly reject unsupported binary hash keys, IN, aggregates,
predicates and computed partition transforms. Keep the existing FE
comparison/group/join restrictions and existing binary scalar functions.
Reject unsupported collection kernels before coercion.
- Normalize fixed timezone offsets and preserve historical second
offsets in both TIMESTAMPTZ formatting and parsing. Skip masked NULL
payloads, reject unrepresentable local years, and preserve cast
error/NULL behavior at boundaries.

Arrow convertor migration, Parquet/ORC semantics, external writer
changes and catalog mapping migration belong to the subsequent
extractions. This PR does not enable native VARBINARY storage.

### Testing
- TIMESTAMPTZ regression follow-up: reproduced both binary-output and
stream-load failures using the master PR CI artifact, regenerated the
two snapshots through `run-regression-test.sh`, and passed both suites
in comparison mode from each branch checkout. Explicit `Asia/Shanghai`
session settings were verified with the server default session zone set
to UTC. Only historical offset seconds changed in the generated results.
- Function-local validation update: 17 FE tests passed after a clean
build with Checkstyle enabled. Coverage includes direct legality checks,
nested/mixed/variadic VARBINARY arguments, both `collect_set` arities,
supported ordinary types, SQL analysis, and existing array rewrites.
Collection restrictions now live in each function's legality check
before coercion; existing branch-specific argument rules are preserved.

- Rebuilt the BE ASAN test target from this extraction: **184 tests
passed**, zero failures. Coverage includes binary
lifetime/SerDe/rejection paths, timestamp parsing/casts, hash and
partition guards, and existing Arrow/Variant serialization tests.
- `VarBinaryUnsupportedCollectionTest`: **passed** (13 unsupported
collection expressions, plus existing byte-preserving array/collection
analysis).
- FE reactor `validate` with repository Checkstyle: **passed**.
- clang-format 16 check on all 34 changed C++ source/header files:
**passed**.
- Groovy compilation of the three new regression suites: **passed**.
Live SQL regression execution is pending CI.

The local BE test source list was narrowed for the focused build and
restored before committing. No build configuration changes are included.

### Release note

Fix binary value lifetime and serialization, reject unsupported binary
computation paths, and preserve TIMESTAMPTZ historical offsets and
boundary error behavior.

### Check List (For Author)

- Test
- [x] Regression test (three self-checking suites added; execution
pending CI)
  - [x] Unit Test
- Behavior changed:
- [x] Yes. Binary rejection and timestamp boundary behavior are
described above.
- Does this need documentation?
- [x] No. This fixes existing type behavior without introducing a
configuration option.

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label

### Scoped review follow-up

This follow-up only fixes correctness/stability defects introduced by
this PR. Compatibility preservation, pre-existing limitations,
additional VARBINARY computation/validation, and unrelated refactors are
excluded.

- Separate historical TIMESTAMPTZ wire-offset parsing from session
fixed-zone limits in both parser paths.
- Validate the complete UTC/GMT fixed offset and exclude rejected
endpoint values from the timezone cache.
- Decline FE string folding when the session-local year is outside the
new BE display range. Preserve the CAST for BE evaluation in both cast
modes instead of folding non-strict casts to NULL.
- Validation: 29 focused ASAN BE tests and 15 FE tests passed. Four BE
tests and the new FE boundary test failed before the fixes. clang-format
16 and FE Checkstyle passed.
- The corresponding master follow-up is in #68301. Master already has
different timezone normalization and FE folding behavior; its additional
TIMESTAMP_NS error-reporting fix does not apply to branch-4.1.

### CI test follow-up

- Keep the binary literal test's owning Field alive while reading its
StringView. Branch-4.1 now has the corresponding short/long embedded-NUL
coverage using its execution API.
- Replace the obsolete +15:00 rejection input with +24:00. Add generated
historical-offset checks in both cast modes; all prior snapshot results
are unchanged.
- Validation: 34 focused ASAN BE tests passed on each branch. The
lifetime error and the original SQL mismatch were reproduced. The
complete cast regression suite passed in comparison mode from both
branch checkouts against the reported master CI artifact. clang-format
16 passed; full clang-tidy remains blocked by pre-existing diagnostics.

This follow-up changes tests only and retains the agreed scope: no
compatibility work or additional binary computation support. Existing
muted failures are outside this fix.
yiguolei pushed a commit that referenced this pull request Sep 23, 2026
…68396)

### What problem does this PR solve?

Related PR: #68381. This is the master version of the second split from
#67784, based on the primitives merged in #68301.

Arrow batch conversion mixes protocol serialization with table-specific
UUID handling, while writers construct schemas separately. Introduce
explicit Doris, Python, Arrow Flight, Parquet, Hive, Iceberg and Paimon
convertors with instance-owned schema parameters and timezone. Move
schema construction/decoding into the convertors and route nested SerDe
writes through the selected format.

Separate Parquet, Hive and Iceberg writers and migrate existing callers.
Preserve master's tracked Arrow memory pools, Iceberg statistics and
timestamp-nanosecond support. Master does not yet contain the Paimon
write backend or physical Variant table writes present on branch-4.1;
this pick adds the converter interfaces without importing those
features. Parquet timestamp encoding and external type mappings remain
unchanged.

Include the Python timezone regression correction from #68381: the
single string output uses ARRAY<STRING>, so the lateral-view comparison
reaches execution instead of failing on a STRUCT-versus-STRING
comparison. Retain coverage for four session timezones, microseconds,
pre-epoch values, NULLs, UDF, UDTF and UDAF.

### Release note

Fix Python UDF timestamp conversion to preserve wall-clock values when
the Arrow protocol declares a fixed-offset timezone.

### Check List (For Author)

- Test
- [x] Unit Test: explicit schemas and independent converter instances,
nested/null values, UUID and fixed binary bytes, timestamp bindings, and
Iceberg writer statistics.
- [x] Regression test: Python UDF/UDTF/UDAF timezone comparisons and the
existing timestamp snapshot corrections.
- Behavior changed:
- [x] Yes: align Python UDF conversion with its Arrow timezone
declaration; reject invalid nested bindings before casts.
- Does this need documentation?
    - [x] No.

Validation: ASAN BE build and 310 focused tests passed (53 suites),
covering Arrow conversion, Parquet/ORC, Variant SerDe and Python. All 42
affected C++ files passed clang-format 16, and header hygiene passed.
The original UDTF declaration reproduced the SQL analysis error on an
isolated FE; the corrected declaration passed the same analysis. Groovy
and embedded Python checks passed. Full Python SQL and external-catalog
regressions remain for CI. clang-tidy was attempted: the new converter's
size warning was resolved; analysis remains blocked by a pre-existing
unmatched NOLINTEND in core/types.h.

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
Sign up for free to 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.

5 participants