Skip to content

[fix](be) Fix Parquet timestamp decoding and export defaults#65446

Open
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:agent/fix-format-v2-timestamp-decoding
Open

[fix](be) Fix Parquet timestamp decoding and export defaults#65446
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:agent/fix-format-v2-timestamp-decoding

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Problem Summary:

Timestamp decoding had two correctness problems in scanner v2:

  1. Parquet INT96 does not carry a timezone annotation. Applying the Doris SQL session timezone shifted raw wall-clock fields written by Trino/UTC-style writers. The writer convention cannot be inferred reliably from Parquet metadata.
  2. ORC nanoseconds were truncated to microseconds, while row decoding, stripe statistics, and SARG predicates need the same half-up rounding boundary. Millisecond-precision stripe statistics also require operator-specific conservative bounds to avoid false-negative pruning.

This PR follows Trino's explicit connector-configuration model and adds hive.parquet.time-zone for scanner v2:

  • Unset or empty (default): preserve INT96 raw wall-clock fields and ignore the SQL session timezone.
  • Set to an IANA timezone or UTC offset in -12:00..+14:00: convert INT96 TIMESTAMP values with that configured timezone.
  • Supported shorthand such as 8:00 is canonicalized to +08:00; ambiguous short aliases such as CST are rejected.
  • HMS catalogs and external file TVFs can provide the property.
  • Hive and Hudi Parquet scans apply the property; Iceberg keeps its table-format timestamp semantics.
  • Scalar and nested scanner-v2 INT96 values use the same conversion.
  • Standard INT64 logical timestamps keep their existing behavior.
  • INT96 mapped to TIMESTAMPTZ keeps the same UTC instant and ignores this compatibility conversion.
  • Invalid values are rejected during analysis.

The legacy v1 Parquet reader is intentionally unchanged and can return different results. v1/v2 behavioral parity is outside this PR's scope, and switching to v1 is not the migration mechanism for this change.

Parquet Export and Outfile now write INT64 logical timestamps by default. Set enable_int96_timestamps=true only when a legacy downstream reader such as Hive 2 or Hive 3 requires INT96. Doris INT96 export normalizes timestamps using the export session timezone; when scanner v2 reads that file back, configure hive.parquet.time-zone with the export session timezone. An end-to-end regression exports under Asia/Shanghai, reads under an America/Los_Angeles session, and verifies that the compatibility property restores the original wall-clock values.

For existing Hive and Hudi catalogs, upgrading users should inspect representative INT96 files. If a legacy writer normalized timestamps using a known timezone, set the catalog property before relying on scanner-v2 results:

ALTER CATALOG hive_legacy SET PROPERTIES (
    "hive.parquet.time-zone" = "Asia/Shanghai"
);

For ORC, this PR rounds nanoseconds to microseconds with second carry for both DATETIMEV2 and TIMESTAMPTZ, applies the same rounding to statistics, and uses conservative millisecond SARG boundaries. Timestamp NE, NOT IN, and negated timestamp subtrees fall back to exact Doris row filtering because negating a widened statistics envelope is unsafe.

Release note

Parquet Export and Outfile now write INT64 logical timestamps by default. Set enable_int96_timestamps=true to request INT96 for legacy readers. Scanner v2 preserves raw Parquet INT96 wall-clock values by default; set hive.parquet.time-zone for Hive/Hudi files normalized by a known writer timezone. Existing Hive and Hudi catalogs containing normalized INT96 files should be checked during upgrade. FileScannerV1 remains unchanged. ORC timestamp nanoseconds are rounded consistently to microseconds and timestamp SARG pruning is conservative.

Check List (For Author)

  • Test: Unit Test / Regression Test
    • On gabriel@10.26.20.3:/mnt/disk3/gabriel/Workspace/dev2/doris:
      • ./build.sh --fe passed.
      • cd fe && mvn checkstyle:check -pl fe-core passed with 0 violations.
      • 39 targeted FE tests covering scan propagation, HMS/TVF timezone validation, Parquet properties, and export commands passed.
      • Targeted Parquet and ORC BE unit tests passed.
      • test_outfile_parquet, test_hive_read_parquet, test_hive_read_parquet_complex_type, test_hdfs_parquet_group0, and paimon_timestamp_types passed in their validated environments.
      • test_doris_int96_round_trip passed in generated-output and comparison modes. It verifies that the configured compatibility timezone, rather than a different read session timezone, restores explicitly exported INT96 values.
      • The three S3 outfile suites were attempted but were blocked before the changed assertions because the configured OSS credential returned InvalidAccessKeyId; no expected output was generated manually.
  • Behavior changed: Yes
    • Scanner v2 preserves raw INT96 wall-clock values by default and applies an explicit catalog or TVF timezone when configured.
    • Hive and Hudi scans apply the compatibility property; Iceberg is intentionally unaffected.
    • Parquet export defaults to INT64 logical timestamps; explicit INT96 remains available for legacy interoperability.
    • Ambiguous timezone aliases are rejected.
    • ORC nanoseconds are rounded to microseconds, and timestamp SARG pruning is conservative at millisecond statistic boundaries.
    • The legacy v1 Parquet reader is unchanged.
  • Does this need documentation: Yes. [doc](lakehouse) Document timestamp compatibility changes doris-website#3982

@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 Gabriel39 marked this pull request as ready for review July 10, 2026 05:55
@Gabriel39 Gabriel39 requested a review from yiguolei as a code owner July 10, 2026 05:55
@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.

Automated review completed. I found one correctness issue that should be fixed before merge: plain ORC timestamp SARG pruning is not using the same session-timezone semantics as row decoding and aggregate min/max.

Critical checkpoint conclusions: the PR is focused on format v2 timestamp decoding and pruning; row decode, ORC statistics rounding, and Parquet INT96 row materialization were reviewed. No new concurrency, lifecycle, persistence, protocol-compatibility, or observability risk was found. The main gap is a parallel-path inconsistency in ORC timestamp SARG pruning, and the tests do not cover non-UTC plain ORC timestamp SARG behavior. git diff --check passed; build/unit tests were not run in this checkout because .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc are missing.

Subagent conclusions: TSC-001 was accepted as MAIN-001 and submitted inline. OPT-001 was dismissed with evidence from the ORC C++ public statistics/writer shape. Convergence round 2 ended with both optimizer-rewrite and tests-session-config reporting NO_NEW_VALUABLE_FINDINGS for the same current ledger/comment set.

User focus: no additional user-provided focus was present.

Comment thread be/src/format_v2/orc/orc_search_argument.cpp Outdated
@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch 2 times, most recently from e8f9938 to 4f5fa22 Compare July 10, 2026 08:07
@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Review step was skipped (possibly timeout or cancelled)
Workflow run: https://github.com/apache/doris/actions/runs/29079325644

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.39% (1896/2450)
Line Coverage 64.42% (34053/52862)
Region Coverage 64.81% (17520/27032)
Branch Coverage 54.01% (9392/17390)

@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.

Review result: request changes.

I reviewed the changed FE/thrift wiring, Parquet/ORC format-v2 reader paths, timestamp decoding/rounding behavior, and the added BE/FE tests. Validation was static because this runner is a shallow checkout and thirdparty/installed/bin/protoc is missing; I did verify the live PR head, GitHub file scope, existing inline comments, and git diff --check for the GitHub-listed changed files against the fetched base.

Critical checkpoints:

  • Goal/test coverage: The PR mostly covers top-level Parquet INT96 timezone behavior and ORC nanosecond rounding, but it misses nested INT96 materialization and shorthand timezone propagation.
  • Scope/focus: The implementation is mostly focused, but the new timezone contract is not applied uniformly across all Parquet INT96 value materialization paths.
  • Concurrency/lifecycle: No new concurrent mutable state or lifecycle hazard found in the reviewed paths.
  • Config/session propagation: Found one FE/BE normalization mismatch for hive.parquet.time-zone shorthand offsets.
  • Compatibility: The thrift field is optional, so old senders remain compatible; BE still validates invalid values. The accepted shorthand case is the compatibility gap.
  • Parallel paths: Top-level INT96 and nested INT96 paths diverge; this is covered by an inline comment.
  • Test results: I did not run builds/tests in this runner due missing thirdparty/protoc prerequisites. Static changed-file whitespace check passed.
  • Observability/performance/persistence: No additional blocking issue found.

Subagent conclusions:

  • optimizer-rewrite proposed the nested Parquet INT96 timezone gap; it was accepted as M1.
  • tests-session-config proposed the FE/BE shorthand timezone normalization gap; it was accepted as M2.
  • The existing ORC timestamp SARG timezone concern is already covered by discussion_r3556745988 and was not resubmitted.
  • Convergence round C2 ended with both live subagents replying NO_NEW_VALUABLE_FINDINGS for the final M1/M2 comment set.

User focus: no additional user-provided review focus was supplied.

Comment thread be/src/format_v2/parquet/reader/parquet_leaf_reader.cpp
Comment thread fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalCatalog.java Outdated
@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch from 4f5fa22 to 05da9fa Compare July 10, 2026 09:32
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 81.25% (13/16) 🎉
Increment coverage report
Complete coverage report

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at 10:57 AM.
Workflow run: https://github.com/apache/doris/actions/runs/29083832746

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 93.75% (15/16) 🎉
Increment coverage report
Complete coverage report

@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.

Review result: request changes.

I found one additional non-duplicate correctness issue: the new HMS Parquet INT96 timezone property is honored by scanner v2, but the legacy FileScanner path is still reachable and ignores the new scan parameter. Existing inline threads already cover the ORC plain TIMESTAMP SARG timezone issue, nested INT96 forwarding, and shorthand timezone canonicalization, so I did not duplicate those comments.

Critical checkpoint conclusions:

  • Goal/test: the PR addresses format v2 Parquet INT96 and ORC timestamp rounding, with targeted BE/FE tests, but the new catalog property is not proven across the legacy scanner path.
  • Scope/focus: the change is mostly focused, but it misses a parallel read path that users can still select.
  • Concurrency/lifecycle: no new shared-state or lifecycle issue found in the reviewed changes.
  • Config/session propagation: FE-to-BE propagation is present for scanner v2, but not for legacy scanner fallback/disablement.
  • Compatibility/protocol: the new thrift field is optional and absence is handled; mixed-version field absence did not show a separate issue.
  • Parallel paths: legacy Hive Parquet scanning remains inconsistent with scanner v2 for INT96 timezone semantics.
  • Tests: new tests cover scanner v2 behavior, nested INT96, canonicalized timezone params, and ORC rounding; missing coverage for enable_file_scanner_v2=false. Existing review context already requests non-UTC ORC TIMESTAMP SARG coverage.
  • Performance/observability: no additional issue found.
  • Transaction/persistence/data writes: not applicable to this PR.

Subagent conclusions: OPT-1 became the inline comment below. OPT-2 and TSC-1 were verified as duplicates of existing GitHub thread discussion_r3556745988 and were not resubmitted. Convergence round 1 ended with both live subagents replying NO_NEW_VALUABLE_FINDINGS for the same ledger/comment set after the accepted candidate update.

User focus: no additional user-provided review focus.

Validation: static review only. This checkout is shallow/grafted and is missing .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc, so I did not run BE/FE tests or style checks.

Comment thread be/src/format_v2/table_reader.cpp
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17636	4056	4018	4018
q2	2019	339	212	212
q3	10592	1456	828	828
q4	4773	474	339	339
q5	8356	868	588	588
q6	350	173	137	137
q7	830	848	616	616
q8	10614	1483	1465	1465
q9	5901	4436	4422	4422
q10	6866	1808	1507	1507
q11	501	345	309	309
q12	717	554	428	428
q13	18130	3383	2765	2765
q14	267	269	234	234
q15	q16	783	775	710	710
q17	919	931	987	931
q18	7107	5630	5553	5553
q19	1152	1213	1029	1029
q20	745	637	557	557
q21	5583	2597	2492	2492
q22	433	351	295	295
Total cold run time: 104274 ms
Total hot run time: 29435 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4357	4268	4287	4268
q2	290	317	222	222
q3	4588	4964	4453	4453
q4	2043	2168	1372	1372
q5	4417	4398	4322	4322
q6	222	172	128	128
q7	2182	1992	1667	1667
q8	2555	2189	2153	2153
q9	8198	7863	7887	7863
q10	4739	4683	4296	4296
q11	561	434	377	377
q12	748	759	540	540
q13	3227	3646	2949	2949
q14	289	315	270	270
q15	q16	735	734	638	638
q17	1333	1311	1460	1311
q18	7934	7290	7190	7190
q19	1160	1057	1017	1017
q20	2211	2197	1932	1932
q21	5189	4511	4406	4406
q22	527	444	403	403
Total cold run time: 57505 ms
Total hot run time: 51777 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 179312 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 05da9fa5db564bcf716ffd22b449b1e8f15f3998, data reload: false

query5	4309	649	484	484
query6	456	219	192	192
query7	4879	620	345	345
query8	349	187	178	178
query9	8783	4057	3974	3974
query10	459	369	301	301
query11	5839	2376	2116	2116
query12	159	102	99	99
query13	1289	599	437	437
query14	6284	5314	4954	4954
query14_1	4280	4298	4284	4284
query15	221	202	192	192
query16	1014	471	460	460
query17	1132	750	595	595
query18	2559	488	386	386
query19	196	181	142	142
query20	110	108	102	102
query21	233	151	136	136
query22	13651	13548	13320	13320
query23	17421	16505	16158	16158
query23_1	16325	16233	16286	16233
query24	7468	1768	1289	1289
query24_1	1307	1298	1285	1285
query25	529	452	363	363
query26	1326	333	207	207
query27	2622	558	347	347
query28	4472	2001	1989	1989
query29	1068	615	488	488
query30	340	264	227	227
query31	1108	1089	986	986
query32	112	61	60	60
query33	514	308	245	245
query34	1155	1135	619	619
query35	765	775	674	674
query36	1385	1397	1206	1206
query37	152	105	91	91
query38	1875	1714	1641	1641
query39	918	918	900	900
query39_1	876	888	905	888
query40	247	167	141	141
query41	70	62	63	62
query42	94	96	91	91
query43	317	316	278	278
query44	1438	789	767	767
query45	208	191	188	188
query46	1042	1176	735	735
query47	2390	2293	2223	2223
query48	403	448	296	296
query49	573	424	321	321
query50	1007	413	339	339
query51	10669	10802	10902	10802
query52	83	92	72	72
query53	272	276	204	204
query54	282	222	236	222
query55	75	69	63	63
query56	290	294	270	270
query57	1407	1411	1312	1312
query58	281	260	252	252
query59	1606	1624	1440	1440
query60	303	270	246	246
query61	155	151	147	147
query62	678	646	586	586
query63	241	204	208	204
query64	2813	1030	822	822
query65	4846	4736	4756	4736
query66	1805	550	390	390
query67	29617	29520	29333	29333
query68	3318	1530	993	993
query69	405	305	269	269
query70	1079	934	977	934
query71	357	344	304	304
query72	3072	2705	2479	2479
query73	827	771	430	430
query74	5064	4953	4750	4750
query75	2601	2568	2207	2207
query76	2306	1192	793	793
query77	359	378	289	289
query78	12313	12264	11728	11728
query79	1169	1101	727	727
query80	578	564	453	453
query81	459	325	281	281
query82	236	155	121	121
query83	309	321	295	295
query84	284	156	131	131
query85	882	610	517	517
query86	325	301	282	282
query87	1817	1807	1727	1727
query88	3621	2769	2767	2767
query89	422	396	362	362
query90	2175	195	193	193
query91	203	189	161	161
query92	63	60	55	55
query93	1574	1643	1006	1006
query94	548	357	325	325
query95	785	496	480	480
query96	1050	833	361	361
query97	2695	2709	2566	2566
query98	230	209	202	202
query99	1149	1181	1042	1042
Total cold run time: 263947 ms
Total hot run time: 179312 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.09	0.05	0.05
query3	0.26	0.14	0.13
query4	1.63	0.13	0.15
query5	0.26	0.22	0.21
query6	1.25	1.04	1.03
query7	0.04	0.01	0.00
query8	0.06	0.04	0.03
query9	0.38	0.31	0.30
query10	0.56	0.57	0.55
query11	0.18	0.14	0.14
query12	0.17	0.14	0.14
query13	0.46	0.46	0.47
query14	1.02	1.01	1.00
query15	0.61	0.60	0.59
query16	0.32	0.33	0.30
query17	1.05	1.10	1.05
query18	0.23	0.21	0.21
query19	2.05	1.96	1.95
query20	0.02	0.01	0.01
query21	15.43	0.22	0.13
query22	4.88	0.06	0.05
query23	16.10	0.32	0.11
query24	3.02	0.43	0.32
query25	0.12	0.04	0.04
query26	0.74	0.20	0.14
query27	0.05	0.04	0.04
query28	3.52	0.95	0.53
query29	12.50	3.99	3.24
query30	0.27	0.15	0.15
query31	2.77	0.59	0.31
query32	3.22	0.59	0.47
query33	3.11	3.19	3.30
query34	15.57	4.26	3.51
query35	3.50	3.48	3.52
query36	0.56	0.44	0.41
query37	0.10	0.06	0.07
query38	0.06	0.04	0.04
query39	0.05	0.03	0.03
query40	0.19	0.16	0.15
query41	0.09	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.57 s
Total hot run time: 24.77 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 25.81% (8/31) 🎉
Increment coverage report
Complete coverage report

@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch from 05da9fa to 5c21eda Compare July 11, 2026 12:51
@Gabriel39 Gabriel39 changed the title [fix](be) Fix format v2 timestamp decoding [fix](be) Fix Parquet INT96 timezone decoding Jul 11, 2026
@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.

Automated review completed for the current PR head.

No additional non-duplicate, diff-scoped blocking issues were found beyond the existing inline review context. I am not adding new inline comments in this review.

User focus: no additional user-provided review focus.

Critical checkpoint conclusions:

  • Goal and tests: the patch focuses on Parquet INT96 timezone decoding and ORC timestamp rounding/SARG behavior; current head includes targeted FE and BE tests for catalog timezone canonicalization/propagation, scanner-v2 and legacy scanner paths, nested INT96 decode, ORC timestamp rounding, and conservative SARG behavior.
  • Scope: reviewed changed FE scan parameter plumbing, thrift field addition, BE Parquet legacy/v2 readers, ORC decode/stat/SARG paths, and related tests.
  • Parallel paths: scanner-v2 and legacy Parquet paths both propagate hive.parquet.time-zone; nested INT96 decode also receives the configured timezone.
  • Config/protocol compatibility: the new scan parameter is an optional thrift field; FE canonicalizes shorthand timezone values before sending them and BE validates/uses the configured zone when present.
  • Concurrency/lifecycle: no new shared concurrency or lifecycle risk was identified; timezone state is carried on per-reader state and used within reader lifetimes.
  • Data correctness: ORC timestamp rounding and SARG bounds appear conservative in the reviewed paths, and Parquet INT96 decode uses the catalog timezone in the covered scalar/nested paths.
  • Transactions/persistence/writes: not applicable to this read-path change.
  • Observability/performance: no new logging/metric requirement was identified; pruning remains conservative for the timestamp edge cases reviewed.
  • Validation: static review only. I did not run BE/FE builds or tests because this checkout is missing thirdparty/installed and thirdparty/installed/bin/protoc.

Subagent conclusions:

  • optimizer-rewrite: no candidates; convergence round returned NO_NEW_VALUABLE_FINDINGS.
  • tests-session-config: no candidates; convergence round returned NO_NEW_VALUABLE_FINDINGS.

Existing review threads were treated as already-submitted context and were not duplicated.

@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.

Automated review complete for head d53edf539f1fd5cc44b8d796f52694727510470f.

I found no new inline findings after duplicate suppression. The one verified defect I still see is the EXPORT enable_int96_timestamps strict-boolean validation gap, but it is already covered by existing inline thread discussion_r3569980146, so I did not add a duplicate comment. The earlier mixed-case export-property candidate was dismissed because ExportCommand.fileProperties is an ImmutableSortedMap with String.CASE_INSENSITIVE_ORDER.

Checkpoint summary:

  • Scope/focus: no additional user focus was provided. I reviewed ORC timestamp rounding/SARG/aggregate fallback, Parquet INT96 timezone propagation, FE Hive/TVF property scoping and canonicalization, export-property persistence, and changed tests/baselines.
  • Correctness/compatibility: ORC unsafe pushdown paths now fall back; Parquet INT96 scanner-v2 propagation reaches the intended top-level and nested DATETIMEV2 readers while TIMESTAMPTZ and metadata-stat paths stay conservative; FE sends canonical timezone values only on the intended Hive/TVF paths.
  • Lifecycle/concurrency/performance: I found no new shared concurrency issue. Parquet timezone parsing is once per reader with stable scan-state lifetime, and I found no per-row timezone parsing.
  • Tests: I reviewed the added unit/regression coverage statically. I did not run builds or tests because this review prompt is review-only and the checkout is not worktree-initialized (.worktree_initialized/thirdparty setup unavailable).

Convergence: main review plus two subagent rounds completed. Round 2 full-diff, candidate/dedup, and risk-sweep agents all returned NO_NEW_VALUABLE_FINDINGS against the final ledger/comment set.

@924060929 924060929 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.

Thanks for taking this on — the INT96 problem is real, and following Trino's explicit hive.parquet.time-zone model rather than guessing the writer convention from metadata is the right call. Excluding Iceberg (and testing it) is a nice catch too.

I reviewed this focusing on the FE side. The main issue I found is cross-cutting, and I think it blocks the merge.

1. Doris can no longer read back its own default Parquet export

The write and read paths now disagree on INT96 by default.

Write (not touched by this PR): enable_int96_timestamps defaults to true (ParquetFileFormatProperties.java:64), and vparquet_transformer.cpp:241 builds the arrow type with _state->timezone(), so the INT96 that gets written is a UTC-normalized instant.

Read (changed by this PR): parquet_leaf_reader.cpp:387

view.timezone = batch._value_kind == DecodedValueKind::INT96 ? _int96_timezone : _timezone;

_int96_timezone stays nullptr unless hive.parquet.time-zone is set (parquet_reader.cpp:356, and :653 passes nullptr otherwise), so INT96 is read as a raw wall clock.

Round trip on default settings with time_zone = Asia/Shanghai:

INSERT INTO t VALUES (1, '2017-10-01 00:00:00');
SELECT * FROM t INTO OUTFILE "s3://.../" FORMAT AS PARQUET PROPERTIES(...);  -- INT96 = 2017-09-30T16:00:00Z
SELECT * FROM S3("uri" = ".../0.parquet", "format" = "parquet", ...);
-- before: 2017-10-01 00:00:00
-- after:  2017-09-30 16:00:00   <-- silent -8h

This PR's own diff is the evidence:

  • Pre-PR test_outfile_parquet_array_type.out had select_base_datetime = 2017-10-01 00:00:00 and select_load_datetime = 2017-10-01 00:00:00.000000. The round trip was exact — writer-UTC and reader-session-tz cancelled out.
  • This PR adds "enable_int96_timestamps" = "false" to 8 export tests (test_show_export ×2, test_outfile_parquet{,_array_type,_complex_type,_map_type}, test_export_data_types, test_export_parquet, test_export_external_table).
  • test_show_export.out is not regenerated — it still reads 2017-10-01T00:00. That is only possible because the groovy now forces INT96 off; on the old default that line would have become 2017-09-30T16:00.
  • The .out files that were regenerated go .000000.000. That is the INT96→INT64 type change (scale-0 datetime → arrow SECOND → TIMESTAMP_MILLIS), i.e. those files now record the output of a different statement, not a corrected value.

Net effect: after this PR, no test covers DATETIME with the default INT96 write→read path. The only surviving OUTFILE test on the true default is test_iceberg_export_timestamp_tz.groovy, whose columns are timestamptz, which the leaf reader explicitly exempts.

test_hive_read_parquet.groovy states the conflict out loud — the same table now has to be exported twice, INT64 for Doris to read and INT96 for Hive to read.

Could you confirm whether the writer staying UTC-normalized while the reader moves to raw wall clock is intentional? Two ways out:

  • (a) Reader default stays on session tz; hive.parquet.time-zone becomes a pure opt-in override for Trino/UTC-style writers. Worth noting Trino's own hive.parquet.time-zone defaults to the JVM zone, not to "no conversion" — so "" meaning UTC is a defensible but distinct choice.
  • (b) Keep the new reader default and stop normalizing on the INT96 write path so the round trip closes — but that breaks Hive/Impala/Spark interop in the other direction, so probably not what you want.

Either way, please keep at least one regression test on the default round trip.

2. v1 and v2 now return different timestamps for the same file

enable_file_scanner_v2 is a session variable defaulting to true (SessionVariable.java:1172), and it is the standard escape hatch when someone hits a v2 issue. But v1 still applies the session timezone to INT96:

  • file_scanner.cpp:1373 passes &_state->timezone_obj() into the v1 reader
  • INT96 carries no logicalType, so the isAdjustedToUTC branch in ConvertParams::init never fires and ctz stays the session tz
  • parquet_column_convert.h:877 Int96toTimestampfrom_unixtime(epoch_seconds, *_convert_params->ctz)

So SET enable_file_scanner_v2 = false silently shifts INT96 by 8h. I don't think "v1/v2 behavioral parity is outside this PR's scope" holds for a user-flippable, default-on session variable — at minimum this deserves an explicit callout.

3. Every existing Hive INT96 user changes behavior on upgrade

This PR adds hive.parquet.time-zone = 'Asia/Shanghai' to 17 suites, 14 of them Hive catalogs — and zero .out files under regression-test/data/external_table_p0/hive/ changed. The property was added purely to keep the existing expected output valid; without it those 14 suites would fail.

Real users' Hive catalogs are no different from those tests. There is no session-level switch and no error — just an 8h shift until they run per-catalog DDL. If that is the intended migration, it needs a prominent release note and an upgrade guide, not only "Behavior changed: Yes".

Minor but useful detail: the observed shift in test_hdfs_parquet_group2.out is 17:07:4609:02:03 = 8h05m43s, not a round 8h — that is Asia/Shanghai's historical LMT offset for year 1001. Users will report odd numbers like this.

4. CST is silently remapped to Asia/Shanghai

getHiveParquetTimeZone() resolves via ZoneId.of(std, TimeUtils.timeZoneAliasMap), and TimeUtils.java:111:

// set CST to +08:00 instead of America/Chicago
timeZoneMap.put("CST", DEFAULT_TIME_ZONE);   // Asia/Shanghai
timeZoneMap.put("PRC", DEFAULT_TIME_ZONE);

A user migrating from Trino who sets hive.parquet.time-zone = 'CST' meaning US Central gets +08:00 — a silent 14h skew, accepted without error. This property exists precisely to prevent that class of bug.

Related: the error message says the value "must be an IANA timezone or UTC offset", but testHiveParquetTimeZoneCanonicalizesJavaShortAlias asserts AET is accepted, and AET/CST/PRC are not IANA IDs — message and behavior disagree. Suggest ZoneId.of(std) without the alias map, or explicitly rejecting ZoneId.SHORT_IDS keys.

FE details (non-blocking)

  • Duplicated constant. FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE and HMSExternalCatalog.HIVE_PARQUET_TIME_ZONE hold the same literal with no cross-reference and no test pinning them equal. Note the sibling convention is deliberately the opposite: enable_mapping_varbinary (TVF) vs enable.mapping.varbinary (catalog) are different strings on purpose.
  • Duplicated validation. The ~10-line validate/canonicalize block is byte-identical in HMSExternalCatalog and ExternalFileTableValuedFunction. The TVF copy has no negative test; the catalog one does.
  • Layering. FileQueryScanNode (the generic base) now does instanceof HMSExternalTable / HMSExternalCatalog. The sibling getEnableMappingTimestampTz() goes through generic ExternalTable/ExternalCatalog + CatalogProperty. Canonicalizing once at DDL time and storing the result in CatalogProperty would fix this and the next point together.
  • Query-time DdlException. getHiveParquetTimeZone() re-parses and re-validates on every initSchemaParams(). CatalogMgr.java:559 skips checkProperties() on replay/image load, and unknown catalog keys aren't rejected at CREATE — so a bad value persisted by an older FE would make every query on that catalog fail after upgrade, rather than failing at DDL.
  • HUDI gap. The new javadoc says a configured value "applies to every INT96 TIMESTAMP file in this catalog", but the gate is DLAType.HIVE only. Spark-written Hudi COW base files (INT96 was Spark's pre-3.0 default) in the same HMS catalog get no correction, while byte-identical files registered as a Hive table do. Iceberg exclusion is correct and tested; Hudi looks unintentional — either include it or narrow the javadoc.
  • getFetchTableStructureRequest reads the private field rather than the overridable getHiveParquetTimeZone(). Works today only because FileTableValuedFunction.getTableColumns() also delegates, so schema fetch happens on the delegate. Latent.
  • enable_int96_timestamps has no value validation. Boolean.valueOf gives false for "yes", "1", " true". Unlike with_bom, garbage here flips away from a true default and silently produces INT64 that Hive 2/3 cannot read at all. Also convertOutfileProperties() adds the key unconditionally, unlike the format-gated block above it, so format=csv + enable_int96_timestamps is now silently accepted and ignored (previously Invalid property key). Consider a strict boolean parse in ParquetFileFormatProperties.analyzeFileFormatProperties, and surfacing the value in SHOW EXPORT (ExportMgr.composeExportJobInfo) — an operator currently cannot tell whether a finished job produced INT96 or INT64.
  • HiveScanNodeTest.testHiveParquetTimeZoneComesFromCatalogInsteadOfSession stubs getHiveParquetTimeZone() itself and never sets or varies a session timezone, so it does not test what its name claims.
  • Two .out files (test_hdfs_parquet_group4.out, test_hdfs_orc_group6_orc_files.out) are binary and unreviewable in the diff. I decoded them separately — they look consistent with the intended change (8h shift; ORC 07:04:05.99999907:04:06 second carry) — but flagging since reviewers can't see them.

Merge state

The base predates #65562 ("fix Fix ORC V2 pushdown correctness and fallback"), which has landed on master and also touches be/src/format_v2/orc/orc_search_argument.cpp. git merge-tree against current master reports conflicts in 9 files, so this needs a rebase and the ORC SARG portion may now partly overlap. Thrift field 34 is still free on master — no id collision.

Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Jul 15, 2026
Issue Number: None

Related PR: apache#65446

Problem Summary: Timestamp decoding had two correctness problems in scanner v2. Parquet INT96 does not carry a timezone annotation, so applying the Doris SQL session timezone shifted raw wall-clock fields written by Trino/UTC-style writers. ORC nanoseconds were truncated inconsistently across row decoding, statistics, and SARG predicates, which could also produce unsafe pruning at millisecond statistic boundaries.

Add an explicit `hive.parquet.time-zone` compatibility property for scanner-v2 Parquet INT96 reads. By default scanner v2 preserves raw INT96 wall-clock fields; when configured, it interprets them with the requested timezone. The legacy v1 reader remains unchanged, INT64 logical timestamps retain their standard behavior, and INT96 values mapped to TIMESTAMPTZ preserve their UTC instant. Apply half-up nanosecond rounding consistently to ORC rows and statistics, use conservative SARG bounds, and fall back to exact row filtering where negating a widened timestamp envelope would be unsafe.

Update export and interoperability coverage so Doris paths exercise INT64 logical timestamps, legacy Hive 2/3 compatibility checks use INT96 only where required, and expected timestamp precision reflects the physical Parquet time unit without changing timezone-offset expectations. Make external regression cases deterministic by explicitly selecting the compatibility timezone for legacy INT96 fixtures and the expected session timezone for Paimon timestamp_ltz data.

Add `hive.parquet.time-zone` for scanner-v2 Parquet INT96 compatibility and fix ORC timestamp rounding and SARG pruning.

- Test:
    - Build: `./build.sh --fe` passed on the designated remote host.
    - Unit Test: targeted Parquet and ORC BE unit tests passed on the designated remote host.
    - Unit Test: FileQueryScanNodeTest, HiveScanNodeTest, and ExternalFileTableValuedFunctionTest passed on the designated remote host.
    - Regression test: test_hive_read_parquet and test_hive_read_parquet_complex_type passed on the designated remote host.
    - Regression test: test_hdfs_parquet_group0 passed completely on an isolated FileScannerV2 cluster on the designated remote host.
    - Regression test: paimon_timestamp_types passed completely for JNI and native readers on the isolated cluster on the designated remote host.
    - Regression test: TeamCity builds 994160 and 994162 produced matching millisecond-precision real results for the updated ARRAY, MAP, and STRUCT expectations.
    - Regression test: the three S3 outfile suites were attempted on the designated remote host but were blocked before the changed assertions because the configured OSS credential returned InvalidAccessKeyId.
- Behavior changed: Yes. Scanner v2 preserves raw INT96 wall-clock values by default, supports explicit timezone conversion, and ORC timestamp rounding and pruning are made consistent and conservative.
- Does this need documentation: No
@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch from d53edf5 to e7cffba Compare July 15, 2026 04:55
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.39% (1896/2450)
Line Coverage 64.49% (34090/52862)
Region Coverage 64.92% (17548/27032)
Branch Coverage 54.12% (9411/17390)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	18446	4177	4167	4167
q2	2037	330	199	199
q3	10285	1498	822	822
q4	4683	481	344	344
q5	7510	852	581	581
q6	182	168	138	138
q7	801	828	626	626
q8	9343	1514	1447	1447
q9	5649	4402	4396	4396
q10	6770	1745	1470	1470
q11	505	343	317	317
q12	710	583	432	432
q13	18442	3380	2746	2746
q14	269	259	249	249
q15	q16	768	772	713	713
q17	1008	1010	964	964
q18	7009	5748	5656	5656
q19	1153	1355	1016	1016
q20	800	650	587	587
q21	5593	2682	2356	2356
q22	447	369	297	297
Total cold run time: 102410 ms
Total hot run time: 29523 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4496	4308	4406	4308
q2	288	326	210	210
q3	4588	4998	4420	4420
q4	2085	2206	1400	1400
q5	4430	4348	4278	4278
q6	223	173	129	129
q7	1789	2164	1713	1713
q8	2542	2195	2310	2195
q9	8042	8120	7879	7879
q10	4697	4667	4204	4204
q11	578	411	408	408
q12	780	755	571	571
q13	3291	3646	3006	3006
q14	317	301	279	279
q15	q16	706	756	666	666
q17	1344	1326	1435	1326
q18	8055	7534	7285	7285
q19	1173	1093	1070	1070
q20	2226	2215	1938	1938
q21	5357	4605	4365	4365
q22	532	462	404	404
Total cold run time: 57539 ms
Total hot run time: 52054 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178396 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 e7cffba2d6ef7547f197ca49d7c293434daabb53, data reload: false

query5	4373	655	517	517
query6	475	228	222	222
query7	4853	573	349	349
query8	345	197	177	177
query9	8804	4119	4073	4073
query10	468	389	334	334
query11	5910	2315	2133	2133
query12	157	103	102	102
query13	1305	577	407	407
query14	6205	5262	4921	4921
query14_1	4264	4276	4291	4276
query15	215	204	182	182
query16	1022	502	470	470
query17	938	753	592	592
query18	2456	482	364	364
query19	214	195	159	159
query20	111	109	108	108
query21	237	158	135	135
query22	13475	13541	13330	13330
query23	17345	16575	16247	16247
query23_1	16206	16281	16284	16281
query24	7640	1763	1288	1288
query24_1	1323	1286	1300	1286
query25	567	473	396	396
query26	1364	360	212	212
query27	2569	583	389	389
query28	4463	2024	1997	1997
query29	1081	642	510	510
query30	331	264	229	229
query31	1118	1096	989	989
query32	107	63	64	63
query33	528	333	258	258
query34	1168	1090	628	628
query35	778	780	679	679
query36	1206	1170	1020	1020
query37	156	104	96	96
query38	1895	1709	1657	1657
query39	896	874	855	855
query39_1	834	858	840	840
query40	260	210	135	135
query41	65	64	62	62
query42	95	89	91	89
query43	322	334	281	281
query44	1397	772	755	755
query45	186	177	171	171
query46	1059	1219	732	732
query47	2095	2133	2006	2006
query48	382	421	299	299
query49	579	422	315	315
query50	1032	401	321	321
query51	10946	10832	10789	10789
query52	86	86	74	74
query53	259	277	193	193
query54	282	232	216	216
query55	78	75	66	66
query56	289	280	294	280
query57	1312	1285	1198	1198
query58	267	250	260	250
query59	1559	1639	1402	1402
query60	347	269	255	255
query61	153	157	151	151
query62	568	491	436	436
query63	238	204	202	202
query64	2856	1027	839	839
query65	4727	4609	4612	4609
query66	1828	495	393	393
query67	29372	29352	29112	29112
query68	3373	1452	1031	1031
query69	428	307	280	280
query70	1053	922	963	922
query71	340	326	305	305
query72	3095	2686	2415	2415
query73	869	835	466	466
query74	5054	4924	4724	4724
query75	2531	2481	2129	2129
query76	2318	1157	751	751
query77	353	380	285	285
query78	11965	11904	11345	11345
query79	1367	1115	738	738
query80	1281	527	450	450
query81	533	323	275	275
query82	604	152	122	122
query83	370	314	285	285
query84	318	158	134	134
query85	963	591	491	491
query86	448	282	286	282
query87	1844	1824	1760	1760
query88	3700	2809	2771	2771
query89	428	374	326	326
query90	1893	198	190	190
query91	206	192	162	162
query92	68	59	56	56
query93	1667	1534	1023	1023
query94	760	371	327	327
query95	787	489	548	489
query96	1089	783	361	361
query97	2636	2651	2495	2495
query98	216	211	210	210
query99	1078	1132	978	978
Total cold run time: 264012 ms
Total hot run time: 178396 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.06
query3	0.26	0.15	0.14
query4	1.60	0.17	0.15
query5	0.26	0.23	0.22
query6	1.26	1.05	1.08
query7	0.04	0.00	0.00
query8	0.06	0.03	0.04
query9	0.38	0.32	0.31
query10	0.57	0.54	0.53
query11	0.20	0.14	0.15
query12	0.18	0.14	0.15
query13	0.46	0.46	0.47
query14	1.01	1.01	1.01
query15	0.61	0.59	0.61
query16	0.33	0.33	0.33
query17	1.10	1.09	1.14
query18	0.22	0.21	0.21
query19	2.02	1.96	1.99
query20	0.02	0.02	0.01
query21	15.43	0.22	0.14
query22	4.73	0.05	0.05
query23	16.24	0.30	0.13
query24	2.89	0.43	0.34
query25	0.12	0.05	0.04
query26	0.75	0.21	0.14
query27	0.05	0.04	0.03
query28	3.56	0.94	0.54
query29	12.52	4.11	3.32
query30	0.28	0.15	0.16
query31	2.77	0.59	0.32
query32	3.22	0.60	0.48
query33	3.20	3.24	3.21
query34	15.72	4.27	3.51
query35	3.53	3.55	3.55
query36	0.56	0.43	0.42
query37	0.10	0.07	0.06
query38	0.05	0.04	0.03
query39	0.03	0.03	0.03
query40	0.18	0.17	0.15
query41	0.07	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.03	0.03
Total cold run time: 96.77 s
Total hot run time: 25.16 s

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

Issue Number: None

Related PR: apache#65446

Problem Summary: Timestamp decoding had two correctness problems in scanner v2. Parquet INT96 does not carry a timezone annotation, so applying the Doris SQL session timezone shifted raw wall-clock fields written by Trino/UTC-style writers. ORC nanoseconds were truncated inconsistently across row decoding, statistics, and SARG predicates, which could also produce unsafe pruning at millisecond statistic boundaries.

Add an explicit `hive.parquet.time-zone` property for scanner-v2 Parquet INT96 reads. By default scanner v2 preserves raw INT96 wall-clock fields; when configured, it interprets them with the requested unambiguous IANA timezone or valid UTC offset. Reject ambiguous short aliases such as `CST`, share timezone parsing across HMS catalogs and file TVFs, and propagate the setting through generic external-table and TVF interfaces for Hive and Hudi while leaving Iceberg semantics unchanged.

Change Parquet export to write INT64 logical timestamps by default and require `enable_int96_timestamps` to be exactly `true` or `false`. Update export regressions to exercise the new default directly while retaining explicit INT96 only for legacy Hive interoperability coverage.

Apply half-up nanosecond rounding consistently to ORC rows and statistics, use conservative SARG bounds, and fall back to exact row filtering where negating a widened timestamp envelope would be unsafe. The legacy v1 reader remains unchanged by design.

### Release note

Parquet export now writes INT64 logical timestamps by default. Set `enable_int96_timestamps=true` to request INT96. The `hive.parquet.time-zone` property accepts unambiguous IANA timezone IDs or valid UTC offsets; ambiguous short aliases such as `CST` are rejected.

### Check List (For Author)

- Test:
    - Build: `./build.sh --fe` passed on the designated remote host.
    - Checkstyle: `cd fe && mvn checkstyle:check -pl fe-core` passed on the designated remote host with 0 violations.
    - Unit Test: 39 targeted FE tests covering scan propagation, HMS/TVF timezone validation, Parquet properties, and export commands passed on the designated remote host.
    - Unit Test: targeted Parquet and ORC BE unit tests passed on the designated remote host.
    - Regression test: `test_outfile_parquet` passed on an isolated scanner-v2 cluster on the designated remote host and verified default Parquet export/stream-load round-trip results.
    - Regression test: `test_hive_read_parquet` and `test_hive_read_parquet_complex_type` passed on the designated remote host.
    - Regression test: `test_hdfs_parquet_group0` passed completely on an isolated scanner-v2 cluster on the designated remote host.
    - Regression test: `paimon_timestamp_types` passed completely for JNI and native readers on the isolated cluster on the designated remote host.
    - Regression test: TeamCity builds 994160 and 994162 produced matching millisecond-precision real results for the updated ARRAY, MAP, and STRUCT expectations.
    - Regression test: the three S3 outfile suites were attempted on the designated remote host but were blocked before the changed assertions because the configured OSS credential returned `InvalidAccessKeyId`.
- Behavior changed: Yes. Scanner v2 preserves raw INT96 wall-clock values by default, Parquet export defaults to INT64 timestamps, timezone aliases are rejected, and ORC timestamp rounding and pruning are consistent and conservative.
- Does this need documentation: Yes. apache/doris-website#3982
@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch from e7cffba to 4a6e5e7 Compare July 15, 2026 06:44
@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 81.08% (180/222) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.20% (23802/41614)
Line Coverage 40.94% (233843/571182)
Region Coverage 36.78% (184607/501966)
Branch Coverage 37.91% (82737/218257)

@Gabriel39

Copy link
Copy Markdown
Contributor Author

@924060929 Thanks for the detailed review. I addressed the actionable items in commit 4a6e5e747b0 and revalidated the updated behavior. Here is the item-by-item result for this review:

  1. Default Parquet export round trip — Fixed. enable_int96_timestamps now defaults to false, so Doris writes INT64 logical timestamps unless the user explicitly requests INT96. The affected export/OUTFILE regressions no longer set false explicitly, which makes them exercise the real default. Legacy Hive interoperability branches still set true explicitly where Hive INT96 is required. The default test_outfile_parquet export -> stream-load round trip passed on an isolated scanner-v2 cluster.

  2. Scanner v1/v2 behavior difference — Intentionally unchanged. This PR defines the expected scanner-v2 behavior; maintaining parity with the old scanner-v1 interpretation is not a goal.

  3. Existing Hive INT96 upgrade compatibility — Intentionally no legacy fallback or migration mode was added. The previous implicit session-timezone conversion was incorrect, so scanner v2 now preserves the raw wall-clock value unless the catalog/TVF explicitly configures hive.parquet.time-zone.

  4. CST mapping to Asia/Shanghai — Fixed by removing Doris/Java short-alias resolution from this property. CST, PRC, AET, and other ambiguous short aliases are rejected. Users must specify an unambiguous IANA ID such as Asia/Shanghai/America/Chicago, or a valid UTC offset. UTC and GMT remain valid.

  5. Duplicated property constant and timezone validation — Fixed. The property name comes only from FileFormatConstants.PROP_HIVE_PARQUET_TIME_ZONE, and HMS catalogs plus file TVFs share FileFormatUtils.parseHiveParquetTimeZone. UTC/GMT-prefixed offsets are also checked against the -12:00 to +14:00 range.

  6. Generic scan-node dependency on HMS concrete classes — Fixed. FileQueryScanNode now consumes generic ExternalTable/TableValuedFunctionIf accessors and no longer imports or branches on HMSExternalCatalog/HMSExternalTable.

  7. Hudi did not receive the catalog property — Fixed. HMS-backed Hive and Hudi tables propagate the property; HMS Iceberg explicitly ignores it because Iceberg defines its own timestamp semantics.

  8. Fetch-schema path read the private TVF field directly — Fixed. It now obtains the value through the overridable accessor, matching the scan path.

  9. Boolean.valueOf("yes") silently became false — Fixed. enable_int96_timestamps now accepts only case-insensitive true or false; values such as yes, 1, and whitespace-padded values fail analysis. I did not add a separate CSV-only rejection or new SHOW EXPORT column in this change; the correctness fix is strict validation plus the new INT64 default.

  10. Session-timezone test did not actually verify session independence — Fixed. The test now creates two scan nodes with America/Los_Angeles and Asia/Tokyo sessions and verifies both receive the same catalog +08:00 value. Separate tests cover Hive, Hudi, Iceberg, file TVFs, and unrelated TVFs.

  11. Query-time validation failure concern — DDL/catalog property validation still rejects invalid values during catalog checking. The shared accessor intentionally continues validating when materializing scan parameters so replayed or otherwise pre-existing invalid metadata fails explicitly instead of being silently accepted.

  12. Regression output changes — This follow-up does not change .out files for the default-export switch; the existing expected values remain unchanged. Earlier precision-only expected-result updates remain, while timezone-offset expectations are preserved.

  13. Merge state — Rebased on current master; the PR now contains one squashed commit.

Remote validation completed:

  • cd fe && mvn checkstyle:check -pl fe-core: passed, 0 violations.
  • Targeted FE unit tests: 39 passed, 0 failures/errors.
  • ./build.sh --fe: passed.
  • ./run-regression-test.sh --run -d export_p0/outfile/parquet -s test_outfile_parquet: passed, 1 suite/0 failures.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929 924060929 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.

Thanks for the quick turnaround. The FE side is in much better shape: FileFormatUtils.parseHiveParquetTimeZone as a single shared validator, short aliases (AET/CST/PRC) now explicitly rejected with ZoneId.of() no longer going through the alias map, the ExternalTable/TableValuedFunctionIf base methods removing the HMS-specific instanceof from FileQueryScanNode, Hudi folded in with the javadoc updated to match, strict parseEnableInt96Timestamps validated eagerly in ExportCommand, and the rebase past #65562. That all reads well.

Three things on the new revision.

1. The export default flipped from INT96 to INT64, and nothing in the PR says so

ParquetFileFormatProperties.java:64:

-    private boolean enableInt96Timestamps = true;
+    private boolean enableInt96Timestamps = false;

This is how the round trip got closed — not by making the writer and reader agree, but by moving the default off the INT96 path. The write path itself is untouched (no transformer/arrow files in the PR), and all seven "enable_int96_timestamps" = "false" test compensations are gone because false is now the default.

The round trip does close for the default, and that's a real improvement. But this is now the single most user-visible change in the PR, and it is invisible to anyone reading it:

  • Behavior changed: Yes lists only the three read-side items. The default flip isn't there.
  • The release note says only "Add hive.parquet.time-zone for scanner-v2 Parquet INT96 compatibility and fix ORC timestamp rounding and SARG pruning."
  • Does this need documentation: No, though apache/doris-website#3982 exists for exactly this.
  • The PR body still records HiveScanNodeTest passing (17 tests), but HiveScanNodeTest.java was dropped from the PR in this revision.

What it costs users: Hive 2 and 3 can no longer read Doris's default Parquet export. That's your own comment in test_hive_read_parquet.groovy — "Hive 2 and 3 do not support Parquet INT64 logical timestamps." And true has been the default since #51384, backported to branch-3.1 (fdf5d055972), so this changes behavior that has been released since 3.1 — it isn't correcting a recent regression.

For a PR titled "Fix Parquet INT96 timezone decoding", flipping the FE export encoding default is a big rider. I'd suggest splitting it into its own PR: it's independently reviewable, it's the part most likely to need a revert, and bundled here it will not get the attention it deserves. At minimum it needs a release note and a migration note.

Related, and worth deciding explicitly: with enable_int96_timestamps = true — which Hive 2/3 interop still requires — the round trip is still broken. Writer normalizes to UTC, reader takes the raw wall clock, so Doris reading back its own INT96 export is off by the session offset unless hive.parquet.time-zone is also set. This is self-consistent with the PR's model (Doris's INT96 output is a Hive-convention file), but it's a sharp edge and it has no coverage: test_hive_read_parquet.groovy now exports twice, and the INT96 file is only ever read by Hive (qt_hive_docker_02), never by Doris. The comment documents the gap rather than closing it. A test that reads the INT96 export back through Doris with hive.parquet.time-zone set would pin the intended contract.

2. apache/doris-website#3982 is now factually wrong

That PR is still on 66d97811 (last updated 2026-07-14) and this revision landed after it, so two of its claims now contradict the code — and both were correct against the previous revision:

  • "The default is true, which writes INT96" / "默认值为 true,写入 INT96" — now false.
  • "It does not affect Hudi or Iceberg tables in the same Hive Metastore" / "不影响同一 Hive Metastore 中的 Hudi 或 Iceberg 表" — Hudi now does get the property, and this PR's own javadoc says "applies to Hive and Hudi Parquet files in this catalog".

Its advice to "disable INT96 output with enable_int96_timestamps = false" is also redundant now that it's the default. The two PRs need to move together.

3. Orphaned javadoc

HMSExternalCatalog.java:70-78 — removing the duplicate HIVE_PARQUET_TIME_ZONE constant (good change) left its javadoc behind, and it now documents the thread-pool size:

/**
 * Timezone used to reverse legacy Parquet INT96 writer normalization. This intentionally
 * follows Trino's hive.parquet.time-zone catalog property instead of the SQL session timezone.
 * ...
 */
private static final int FILE_SYSTEM_EXECUTOR_THREAD_NUM = 16;

Still open from the previous round

Both unchanged, both previously discussed — restating only so they're not lost:

  • v1/v2 divergence. SET enable_file_scanner_v2 = false still shifts INT96 by the session offset, on a session variable that defaults to true and is the standard escape hatch for v2 issues.
  • Existing Hive catalogs. 14 Hive suites still carry hive.parquet.time-zone = 'Asia/Shanghai' purely to keep their expected output valid, and regression-test/data/external_table_p0/hive/ still has zero .out changes. Real users' catalogs are in the same position: an 8h shift on upgrade, no error, no session-level switch. That needs an upgrade note whatever else happens here.

Also minor, from last round: HMSExternalCatalog.getHiveParquetTimeZone() still re-parses and re-validates on every initSchemaParams(), and checkProperties() is skipped on replay/image load. Canonicalizing once at DDL time and storing the result in CatalogProperty would make the query path a plain map read and remove the query-time DdlException risk.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 80.00% (48/60) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Issue Number: None

Related PR: apache#65446

Problem Summary: Timestamp decoding had two correctness problems in scanner v2. Parquet INT96 does not carry a timezone annotation, so applying the Doris SQL session timezone shifted raw wall-clock fields written by Trino/UTC-style writers. ORC nanoseconds were truncated inconsistently across row decoding, statistics, and SARG predicates, which could also produce unsafe pruning at millisecond statistic boundaries.

Add an explicit `hive.parquet.time-zone` property for scanner-v2 Parquet INT96 reads. By default scanner v2 preserves raw INT96 wall-clock fields; when configured, it interprets them with the requested unambiguous IANA timezone or valid UTC offset. Reject ambiguous short aliases such as `CST`, share timezone parsing across HMS catalogs and file TVFs, and propagate the setting through generic external-table and TVF interfaces for Hive and Hudi while leaving Iceberg semantics unchanged.

Change Parquet export to write INT64 logical timestamps by default and require `enable_int96_timestamps` to be exactly `true` or `false`. Update export regressions to exercise the new default directly while retaining explicit INT96 only for legacy Hive interoperability coverage. Add an end-to-end regression that exports INT96 in one session timezone and reads it through scanner v2 in another session timezone with `hive.parquet.time-zone` configured.

Apply half-up nanosecond rounding consistently to ORC rows and statistics, use conservative SARG bounds, and fall back to exact row filtering where negating a widened timestamp envelope would be unsafe. The legacy v1 reader remains unchanged by design.

### Release note

Parquet export now writes INT64 logical timestamps by default. Set `enable_int96_timestamps=true` to request INT96. When scanner v2 reads legacy INT96 files that were normalized by a writer timezone, set `hive.parquet.time-zone` to that timezone. The property accepts unambiguous IANA timezone IDs or valid UTC offsets; ambiguous short aliases such as `CST` are rejected. Existing Hive and Hudi catalogs containing normalized INT96 files should be checked during upgrade.

### Check List (For Author)

- Test:
    - Build: `./build.sh --fe` passed on the designated remote host.
    - Checkstyle: `cd fe && mvn checkstyle:check -pl fe-core` passed on the designated remote host with 0 violations.
    - Unit Test: 39 targeted FE tests covering scan propagation, HMS/TVF timezone validation, Parquet properties, and export commands passed on the designated remote host.
    - Unit Test: targeted Parquet and ORC BE unit tests passed on the designated remote host.
    - Regression test: `test_outfile_parquet` passed on an isolated scanner-v2 cluster on the designated remote host and verified default Parquet export/stream-load round-trip results.
    - Regression test: `test_hive_read_parquet` and `test_hive_read_parquet_complex_type` passed on the designated remote host.
    - Regression test: `test_doris_int96_round_trip` passed in generated-output and comparison modes on the designated remote host, verifying that the configured compatibility timezone overrides a different read session timezone.
    - Regression test: `test_hdfs_parquet_group0` passed completely on an isolated scanner-v2 cluster on the designated remote host.
    - Regression test: `paimon_timestamp_types` passed completely for JNI and native readers on the isolated cluster on the designated remote host.
    - Regression test: TeamCity builds 994160 and 994162 produced matching millisecond-precision real results for the updated ARRAY, MAP, and STRUCT expectations.
    - Regression test: the three S3 outfile suites were attempted on the designated remote host but were blocked before the changed assertions because the configured OSS credential returned `InvalidAccessKeyId`.
- Behavior changed: Yes. Scanner v2 preserves raw INT96 wall-clock values by default, Parquet export defaults to INT64 timestamps, timezone aliases are rejected, and ORC timestamp rounding and pruning are consistent and conservative.
- Does this need documentation: Yes. apache/doris-website#3982
@Gabriel39 Gabriel39 force-pushed the agent/fix-format-v2-timestamp-decoding branch from 4a6e5e7 to ef8f1e8 Compare July 15, 2026 09:38
@Gabriel39 Gabriel39 changed the title [fix](be) Fix Parquet INT96 timezone decoding [fix](be) Fix Parquet timestamp decoding and export defaults Jul 15, 2026
@Gabriel39

Copy link
Copy Markdown
Contributor Author

已按这轮 review 的前 5 项处理,最后一项 catalog replay/query-time 重复解析留到后续 PR:

  1. 默认 Parquet export 从 INT96 改为 INT64:这是有意的行为变更,本 PR 不拆分。已更新 PR 标题、Problem Summary、Release note、Behavior changed 和测试记录,明确默认 enable_int96_timestamps=false;Hive 2/3 等旧读取端需要显式设置 true。另外新增 test_doris_int96_round_trip,在 Asia/Shanghai session 显式导出 INT96,再切换到 America/Los_Angeles session,通过 TVF 设置 hive.parquet.time-zone=Asia/Shanghai,验证 Doris 读回原始墙上时间和微秒精度。该用例在指定远端以生成和普通比对两种模式均通过。
  2. [doc](lakehouse) Document timestamp compatibility changes doris-website#3982:已更新并 force-with-lease 推送到 1cc4728f。英文和中文文档现在明确默认导出 INT64、Hive 2/3 显式 INT96 用法、Hive/Hudi 作用域(Iceberg 不应用)、显式 INT96 的读回配置,以及现有 Catalog 的升级检查和迁移建议。docs:features:changed 无 findings,docs:i18n-sync:changed 仅保留当前版本范围之外的预期提示。
  3. 孤立 javadoc:已从 FILE_SYSTEM_EXECUTOR_THREAD_NUM 移到 getHiveParquetTimeZone()
  4. v1/v2 差异:按设计保留,不追求一致。PR 和文档均明确 FileScannerV1 有意不改、可能返回不同结果,切换 v1 不是本次变更的兼容方案。
  5. 现有 Hive/Hudi Catalog 升级行为:不回退新的 scanner-v2 语义,但已在 PR release note 和网站迁移章节明确升级前抽样核对 INT96 文件;对于被旧写入端按已知时区归一化的文件,应设置 hive.parquet.time-zone

本次 Doris 更新已 squash 为单提交 ef8f1e8c020 并推送。独立自审未发现新的高置信度问题。

按约定,getHiveParquetTimeZone() 在 replay/image load 后的持久化 canonicalization 与 query-time 重复解析优化不在当前 PR 处理。

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 81.08% (180/222) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.20% (23802/41614)
Line Coverage 40.93% (233799/571188)
Region Coverage 36.75% (184486/501972)
Branch Coverage 37.90% (82721/218263)

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.39% (1896/2450)
Line Coverage 64.47% (34077/52859)
Region Coverage 64.89% (17539/27030)
Branch Coverage 54.07% (9401/17388)

@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.

Reviewed the current PR head against the provided authoritative diff and existing review threads. I did not find additional actionable issues beyond the already-known threads.

Critical checkpoint conclusions:

  • Goal/scope: the PR focuses on scanner-v2 Parquet INT96 timezone compatibility, ORC timestamp rounding/SARG safety, and Parquet export INT96 defaults/properties. The current changes appear focused for that scope.
  • Data correctness: scanner-v2 Parquet INT96 DATETIMEV2 materialization now receives hive.parquet.time-zone through the FE -> thrift -> TableReader -> ParquetReader -> scheduler -> leaf-reader chain, including nested values. TIMESTAMPTZ and non-INT96 paths remain unaffected. ORC timestamp row decoding, statistics conversion, SARG envelopes, and aggregate pushdown fallbacks appear conservative for the reviewed TIMESTAMP/TIMESTAMP_INSTANT cases.
  • Compatibility/scope: HMS Iceberg is excluded from the Hive Parquet timezone property; legacy scanner-v1 parity remains an already-discussed non-scope item in the existing threads.
  • Persistence/property handling: enable_int96_timestamps is strictly parsed before EXPORT job creation, persisted through the job, and replayed back into OUTFILE properties when explicitly set. The default Parquet writer behavior is updated and covered by tests/regression outputs.
  • Concurrency/lifecycle: I did not find new concurrency-sensitive shared state. The parsed Parquet INT96 timezone is owned by the reader scan state and borrowed only during scanner-v2 reader lifetime.
  • Tests: the PR adds/updates focused BE/FE unit tests and regression expectations for the changed timestamp behavior. I did not run builds or tests in this review environment.
  • User focus: no additional user-provided review focus was present.

The round-1 full-review subagents and risk-focused subagents all returned NO_NEW_VALUABLE_FINDINGS, and the main-agent reconciliation found no unresolved candidate points.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17707	4287	4151	4151
q2	2083	332	212	212
q3	10267	1406	843	843
q4	4687	469	335	335
q5	7517	854	564	564
q6	176	170	135	135
q7	752	825	612	612
q8	9408	1496	1553	1496
q9	5567	4349	4315	4315
q10	6782	1725	1470	1470
q11	525	347	305	305
q12	722	549	428	428
q13	18255	3404	2759	2759
q14	269	255	237	237
q15	q16	775	775	705	705
q17	1016	929	980	929
q18	7122	5791	5510	5510
q19	1366	1345	1031	1031
q20	737	651	558	558
q21	6493	2892	2635	2635
q22	468	376	323	323
Total cold run time: 102694 ms
Total hot run time: 29553 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5301	5150	5099	5099
q2	283	330	209	209
q3	4950	5352	4682	4682
q4	2057	2168	1371	1371
q5	4958	4649	4694	4649
q6	225	187	131	131
q7	1894	1739	1616	1616
q8	2454	2160	2115	2115
q9	7783	7257	7227	7227
q10	4629	4542	4099	4099
q11	541	390	348	348
q12	739	734	526	526
q13	2974	3394	2807	2807
q14	289	275	256	256
q15	q16	679	692	613	613
q17	1301	1269	1248	1248
q18	7338	7029	6752	6752
q19	1092	1042	1082	1042
q20	2226	2198	1951	1951
q21	5269	4608	4402	4402
q22	536	449	402	402
Total cold run time: 57518 ms
Total hot run time: 51545 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 177910 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 ef8f1e8c0203485c5c14609b0217bc673afb3ec7, data reload: false

query5	4346	634	485	485
query6	484	217	208	208
query7	4990	596	349	349
query8	349	190	178	178
query9	8813	4167	4113	4113
query10	482	365	285	285
query11	5902	2305	2146	2146
query12	163	104	101	101
query13	1272	608	438	438
query14	6259	5299	4931	4931
query14_1	4226	4287	4241	4241
query15	212	204	177	177
query16	1077	487	446	446
query17	1122	696	559	559
query18	2618	451	340	340
query19	208	199	145	145
query20	114	107	102	102
query21	230	161	136	136
query22	13629	13604	13364	13364
query23	17429	16534	16146	16146
query23_1	16256	16238	16124	16124
query24	7635	1742	1274	1274
query24_1	1290	1277	1270	1270
query25	532	427	386	386
query26	1341	365	213	213
query27	2574	598	374	374
query28	4417	1994	1990	1990
query29	1091	639	486	486
query30	346	260	223	223
query31	1124	1104	972	972
query32	124	66	64	64
query33	546	313	251	251
query34	1223	1147	652	652
query35	782	777	678	678
query36	1171	1214	1097	1097
query37	157	113	95	95
query38	1904	1711	1660	1660
query39	887	877	877	877
query39_1	852	841	858	841
query40	256	165	145	145
query41	70	68	71	68
query42	93	93	92	92
query43	328	329	284	284
query44	1435	784	781	781
query45	200	195	181	181
query46	1058	1170	738	738
query47	2146	2052	1974	1974
query48	419	410	307	307
query49	596	429	312	312
query50	1046	419	344	344
query51	10791	10962	10669	10669
query52	90	123	76	76
query53	253	282	194	194
query54	290	236	227	227
query55	71	68	67	67
query56	300	280	292	280
query57	1335	1284	1191	1191
query58	273	254	253	253
query59	1588	1621	1436	1436
query60	298	267	265	265
query61	157	153	153	153
query62	580	491	434	434
query63	242	196	199	196
query64	2848	1049	846	846
query65	4704	4631	4657	4631
query66	1860	489	371	371
query67	29225	29196	29073	29073
query68	3257	1601	1029	1029
query69	449	325	268	268
query70	1075	978	972	972
query71	340	314	306	306
query72	3074	2545	2335	2335
query73	851	817	437	437
query74	5092	4922	4732	4732
query75	2541	2498	2131	2131
query76	2355	1172	764	764
query77	349	374	272	272
query78	11920	11728	11269	11269
query79	1400	1181	768	768
query80	638	570	456	456
query81	470	320	284	284
query82	606	160	121	121
query83	400	331	301	301
query84	276	152	134	134
query85	938	618	522	522
query86	411	312	285	285
query87	1827	1812	1766	1766
query88	3712	2778	2758	2758
query89	437	386	324	324
query90	2003	198	198	198
query91	206	190	165	165
query92	64	60	59	59
query93	1558	1602	974	974
query94	556	355	328	328
query95	806	523	579	523
query96	1066	819	356	356
query97	2644	2635	2525	2525
query98	214	206	202	202
query99	1078	1104	981	981
Total cold run time: 263701 ms
Total hot run time: 177910 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.09	0.05	0.05
query3	0.26	0.14	0.13
query4	1.62	0.17	0.14
query5	0.24	0.23	0.22
query6	1.24	1.07	1.03
query7	0.04	0.01	0.00
query8	0.06	0.03	0.04
query9	0.38	0.33	0.31
query10	0.57	0.58	0.52
query11	0.20	0.15	0.13
query12	0.19	0.14	0.15
query13	0.47	0.48	0.48
query14	1.03	1.00	1.02
query15	0.61	0.58	0.60
query16	0.32	0.33	0.31
query17	1.12	1.16	1.14
query18	0.23	0.21	0.20
query19	2.07	2.00	1.93
query20	0.02	0.01	0.02
query21	15.46	0.23	0.13
query22	4.91	0.05	0.05
query23	16.11	0.31	0.12
query24	2.90	0.42	0.33
query25	0.12	0.05	0.04
query26	0.78	0.21	0.16
query27	0.03	0.05	0.04
query28	3.49	0.94	0.55
query29	12.57	4.02	3.22
query30	0.27	0.15	0.17
query31	2.78	0.59	0.32
query32	3.21	0.59	0.48
query33	3.29	3.26	3.16
query34	15.63	4.23	3.51
query35	3.54	3.50	3.49
query36	0.55	0.44	0.42
query37	0.09	0.06	0.06
query38	0.06	0.04	0.04
query39	0.04	0.03	0.03
query40	0.19	0.17	0.15
query41	0.10	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.04	0.04
Total cold run time: 96.98 s
Total hot run time: 24.9 s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants