Skip to content

[fix](arrow) encode DATE in the proleptic Gregorian calendar at format boundaries - #67449

Draft
morningman wants to merge 3 commits into
apache:masterfrom
morningman:wt-adbc-67366
Draft

[fix](arrow) encode DATE in the proleptic Gregorian calendar at format boundaries#67449
morningman wants to merge 3 commits into
apache:masterfrom
morningman:wt-adbc-67366

Conversation

@morningman

@morningmanmorningman commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close#67366
Issue Number: close#67447

Problem Summary:

Doris follows MySQL's calendar, in which year 0 is not a leap year: 0000-02-29
does not exist and calc_daynr() therefore numbers 0000-01-01 .. 0000-02-28 one
day ahead of the proleptic Gregorian calendar. Arrow date32, Parquet DATE, ORC
DATE and the Iceberg specification all define their day ordinal in the proleptic
Gregorian calendar, where year 0 IS a leap year; the two numberings coincide only
from 0000-03-01 onwards.

1. The DATE ordinal at every format boundary (#67366). Each boundary added or
subtracted the epoch day number directly, so all 59 dates in the year-zero window
were shipped one day late: 0000-01-01 left Doris as -719527, which Arrow renders
as 0000-01-02, while the MySQL protocol -- which carries year/month/day verbatim
and never needs a calendar -- reported 0000-01-01 for the same value. New helpers
daynr_to_epoch_days() / epoch_days_to_daynr() now carry every such conversion:
Arrow date32/date64 read and write (which Parquet export shares), the Parquet
DATE reader, and the ORC DATE reader and writer. Both compile to branchless
code. The ORC reader passes the file's ordinal straight through instead of
laundering it through date_day_offset_dict, which also removes a silent fallback
that decoded any out-of-dictionary value as 1900-01-01; the Arrow date32 reader
now checks the result of get_date_from_daynr() instead of discarding it.

2. The Iceberg partition transforms (#67366). They were derived from
datetime_diff(), which rounds towards zero, while Iceberg floors
(DateTimeUtil.convertDays/convertMicros evaluate one unit later for a negative
input and then subtract one). Every pre-1970 value not exactly on a unit boundary
got the wrong partition: 1969-12-31 23:59:59 landed in the same day and hour
partition as 1970-01-01 00:00:00, and year()/month() reported 0 and -6 for
1969-06-15 where Iceberg requires -1 and -7. year, month, day, hour and
bucket are rewritten for both DATE and TIMESTAMP; human_hour() floors as well,
and human_year() zero-pads like TransformUtil.humanYear. bucket(n, ts) now
hashes the full microsecond value the specification defines instead of whole
seconds times a million.

3. Year-zero DATETIME on the Parquet read path (#67447).MIN_DORIS_TIMESTAMP_MICROS
was a whole year narrower than the type it materialises into (year 0 has 366 days,
not 365) and was applied to the raw instant before the timezone offset, so a
DATETIME Doris accepts, stores and exports could not be read back out of Doris's own
file, and a non-UTC session timezone lost representable values at both ends. The
shared helper now keeps only a coarse format-level guard; the exact civil range is
enforced per target type after conversion. append_datetimev2_from_epoch_micros()
goes through epoch_days_to_daynr() as well. TIMESTAMPTZ shares the storage and the
helper and gains the same range.

4. ORC DATE statistics.format_v2's ORC reader converted DATE stripe statistics
through date_day_offset_dict, and those zone maps have exactly one consumer:
OrcReader::get_aggregate_result, which answers a pushed-down MIN/MAX from
statistics without reading a row. On the default path MIN(d) therefore reported
1900-01-01 for a file whose smallest row is 0000-01-01 -- a value present in no
row. The bounds are now decoded with the row decoder's conversion, and a bound with
no Doris DATE disables the statistics so MIN/MAX falls back to a row scan.

5. FE partition-range rendering.IcebergPartitionUtils rendered MTMV
partition-range bounds with the pattern letter y (year-of-era), so the ordinal
-719528 the day transform now emits for 0000-01-01 rendered as 0001-01-01
and collided with the range of the real 0001-01-01 partition.

Verified against cctz over all 3,652,424 representable Doris dates, and against the
Apache Iceberg reference implementation (iceberg-api 1.10.1, after reproducing the
specification's own Appendix B test vector 2017-11-16 -> -653330422). The Iceberg
regression suite writes identical boundary rows from Doris and from Spark into two
identically partitioned tables and compares the resulting partition metadata, so the
transforms are checked against the reference implementation end to end rather than
against Doris's own expectations.

Release note

Doris now encodes and decodes DATE and year-zero DATETIME at file and wire
boundaries the way the format specifications define them. This changes behaviour:

  • DATE, year zero. Arrow date32/date64, Parquet DATE and ORC DATE
    written by Doris encode 0000-01-01 as -719528 instead of -719527. Files
    written by an older Doris read back one day later than before (0000-01-01 comes
    back as 0000-01-02), except an old-encoded 0000-02-28 (ordinal -719469),
    which is the proleptic-only 0000-02-29 and has no Doris DATE: an ORC scan fails,
    a Parquet scan fails in strict mode and returns NULL otherwise, and Arrow input
    fails. Rewrite such files from the source table to repair them.
  • Arrow input.date32 input (stream load format=arrow, the ADBC catalog, the
    remote-Doris catalog, the Paimon native reader, Python UDTFs) now reports an
    out-of-range day instead of silently storing a zero date. Federating an older and a
    newer Doris through the remote-Doris catalog shifts year-zero dates by one day in
    the mixed-version window, and fails on an old-encoded 0000-02-28.
  • ORC/Parquet errors. An ORC DATE ordinal outside 0000-01-01 .. 9999-12-31, or
    equal to the proleptic-only 0000-02-29, now fails the scan instead of silently
    decoding as 1900-01-01. The message carries the offending value and the column
    name and no longer names the wrong format.
  • Iceberg partitions.year, month, day, hour and bucket now floor
    towards negative infinity and use the proleptic ordinal, so pre-1970 and year-zero
    rows land in the partitions the specification defines (1969-12-31 23:59:59 is
    hour -1, not 0). bucket(n, ts) hashes the full microsecond value, so a DATETIME
    with a non-zero sub-second part routes to a different (and now Spark-compatible)
    bucket. A year partition directory is zero-padded (..._year=0000). Data files
    and manifests written by an older Doris keep the old values, so filtered scans in
    Doris and in Spark keep skipping those rows until the files are rewritten: run
    rewrite_data_files after every BE has been upgraded. During a rolling upgrade old
    and new BEs write both variants into the same table.
  • Pushed-down MIN/MAX over ORC DATE now agrees with the rows of the same file.
  • Year-zero DATETIME/TIMESTAMPTZ in Parquet is read back instead of becoming
    NULL (or failing in strict mode), including under a non-UTC session timezone.
  • MTMV partition-range view of an Iceberg table with year-zero day/hour
    partitions renders 0000-01-01 instead of 0001-01-01.

Check List (For Author)

  • Test: Regression test + Unit Test + Manual test
    • BE UT: data_type_datev2_serde_calendar_test,
      data_type_datetimev2_serde_calendar_test, data_type_serde_parquet_test,
      vdatetime_value_test (all 3,652,424 representable dates against cctz, ordinal
      and civil date), partition_transformers_test, orc_reader_test
    • FE UT: IcebergPartitionUtilsTest
    • Regression: export_p0/outfile/test_outfile_date_year_zero,
      export_p0/outfile/test_outfile_datetime_year_zero,
      arrow_flight_sql_p0/test_date_year_zero,
      external_table_p0/iceberg/write/test_iceberg_write_partition_epoch_boundary
    • Manual: local cluster, OUTFILE round trip over file:// and local(), three
      session timezones, INSERT ... SELECT from the exported file
  • Behavior changed: Yes (see the Release note)
  • Does this need documentation: No (no in-repo or website document describes the DATE
    ordinal encoding, the DATETIME lower bound of the Parquet reader, or the Iceberg
    transform arithmetic)

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

morningmanand others added 3 commits September 3, 2026 00:11
…t boundaries
### What problem does this PR solve?
Issue Number: closeapache#67366
Problem Summary:
Doris follows MySQL's calendar, in which year 0 is not a leap year: 0000-02-29
does not exist and calc_daynr() therefore numbers 0000-01-01 .. 0000-02-28 one
day ahead of the proleptic Gregorian calendar. Arrow date32, Parquet DATE, ORC
DATE and the Iceberg spec all define their day ordinal in the proleptic
Gregorian calendar, where year 0 IS a leap year, and the two numberings coincide
only from 0000-03-01 onwards.
Every format boundary subtracted or added the epoch day number directly, so all
59 dates in 0000-01-01 .. 0000-02-28 were shipped one day late: 0000-01-01 left
Doris as -719527, which Arrow renders as 0000-01-02, while the MySQL protocol --
which carries year/month/day verbatim and never needs a calendar -- reported
0000-01-01 for the same value.
Add daynr_to_epoch_days()/epoch_days_to_daynr() and route the boundaries through
them: Arrow date32/date64 read and write (which Parquet export shares), the
Parquet DATE reader, and the ORC DATE reader and writer. Both helpers compile to
branchless code, so the write path costs two extra instructions and the read
path is absorbed by the following get_date_from_daynr(). The ORC reader now
passes the file's day value straight through instead of laundering it through
date_day_offset_dict, which also removes a silent fallback that decoded any
out-of-dictionary value as 1900-01-01. The Arrow date32 reader now checks the
result of get_date_from_daynr() instead of discarding it, and 0000-02-29 -- which
exists in the proleptic Gregorian calendar but not in Doris -- is rejected rather
than silently decoding as 0000-02-28.
The Iceberg partition transforms had a second, independent defect: they were
derived from datetime_diff(), which rounds towards zero, while Iceberg floors
(DateTimeUtil.convertDays/convertMicros evaluate one unit later for a negative
input and then subtract one). Every pre-1970 value that was not exactly on a unit
boundary got the wrong partition -- 1969-12-31 23:59:59 landed in the same day and
hour partition as 1970-01-01 00:00:00, and year()/month() reported 0 and -6 for
1969-06-15 where Iceberg requires -1 and -7. Rewrite year, month, day, hour and
bucket for both DATE and TIMESTAMP, and make human_hour() floor as well so a
negative hour ordinal renders as 1969-12-31-23 rather than 1970-01-01--1.
Verified against cctz over all 3,652,424 representable Doris dates, and against
the Apache Iceberg reference implementation (iceberg-api 1.10.1, after
reproducing the spec's own Appendix B test vector 2017-11-16 -> -653330422).
A new regression suite writes identical boundary rows from Doris and from Spark
into two identically partitioned Iceberg tables and compares the resulting
partition metadata, so the transforms are checked against the reference
implementation end to end rather than against Doris's own expectations.
### Release note
DATE values in 0000-01-01 .. 0000-02-28 now cross every file and wire boundary
with the proleptic Gregorian day ordinal the format specifications require:
- Arrow date32/date64, Parquet DATE and ORC DATE written by Doris encode
0000-01-01 as -719528 instead of -719527. Files written by an older Doris are
read one day later than before (0000-01-01 comes back as 0000-01-02), except
for an old-encoded 0000-02-28 (ordinal -719469), which is the proleptic-only
0000-02-29 and has no Doris DATE: an ORC scan fails, a Parquet scan fails in
strict mode and returns NULL otherwise, and Arrow input fails. Rewrite such
files from the source table to repair them.
- Arrow date32 input (stream load `format=arrow`, the ADBC catalog, the
remote-Doris catalog, the Paimon native reader, Python UDTFs) now reports an
out-of-range day instead of silently storing a zero date.
- Federating an older and a newer Doris through the remote-Doris catalog shifts
year-zero dates by one day in the mixed-version window, and fails on an
old-encoded 0000-02-28.
- An ORC DATE ordinal outside 0000-01-01 .. 9999-12-31, or equal to the
proleptic-only 0000-02-29, now fails the scan instead of silently decoding as
1900-01-01.
- Iceberg `year`, `month`, `day`, `hour` and `bucket` partition values now floor
towards negative infinity and use the proleptic ordinal, so pre-1970 and
year-zero rows land in the partitions the Iceberg specification defines
(1969-12-31 23:59:59 is hour -1, not 0). Data files and manifests written by an
older Doris keep the old values, so filtered scans in Doris and in Spark keep
skipping those rows until the files are rewritten; run `rewrite_data_files`
after every BE has been upgraded. During a rolling upgrade old and new BEs
write both variants into the same table.
### Check List (For Author)
- Test: Regression test + Unit Test
- BE UT: data_type_datev2_serde_calendar_test, vdatetime_value_test (all
3,652,424 representable dates against cctz), partition_transformers_test,
orc_reader_test
- Regression: export_p0/outfile/test_outfile_date_year_zero,
arrow_flight_sql_p0/test_date_year_zero,
external_table_p0/iceberg/write/test_iceberg_write_partition_epoch_boundary
- Behavior changed: Yes (see the Release note: the file/wire encoding of 59
year-zero DATE values and the Iceberg pre-1970 partition values change)
- Does this need documentation: No (no in-repo or website document describes the
DATE ordinal encoding or the Iceberg transform arithmetic)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPwhYhsSio1HYk2kFnx7KY
### What problem does this PR solve?
Issue Number: closeapache#67447
Related PR: apache#67449
Problem Summary:
Doris DATETIME starts at 0000-01-01 00:00:00, but the Parquet reader gated every
timestamp at 0001-01-01, so a value Doris accepts, stores and exports could not be read
back out of Doris's own file. Two independent defects sat behind that.
MIN_DORIS_TIMESTAMP_MICROS was a whole year narrower than the type it materialises into:
0000-01-01 is 366 days below 0001-01-01, not 365, because year 0 IS a leap year in the
proleptic Gregorian calendar that Parquet timestamps are defined in. The bound was also
applied to the raw instant, before the timezone offset, so it lost representable values
at both ends -- east of UTC a local 0001-01-01 00:00:00 is an instant below the civil
minimum, and west of it a local 9999-12-31 23:59:59.999999 is one above the maximum.
What stays in the shared helper is only a coarse guard (one day of slack, more than any
real offset), keeping the unit-overflow and malformed-INT96 checks format-level; the
exact civil range is now enforced per target type after the conversion.
append_datetimev2_from_epoch_micros() then added calc_daynr(1970, 1, 1) straight to a
proleptic Gregorian day ordinal. Doris follows MySQL's calendar, in which year 0 is not
a leap year, so the two numberings disagree over 0000-01-01 .. 0000-02-28: 0000-01-01
computed daynr 0 and was rejected outright, and the rest of that window would have
decoded one day early. Route it through epoch_days_to_daynr(), the helper the DATE
reader already uses, which also rejects the proleptic-only 0000-02-29 rather than
colliding it with 0000-02-28.
TIMESTAMPTZ shares the same storage and the same helper, and both its error text and the
type's own comment still advertised a year-one floor.
The legacy scanner's zero-date compatibility for genuinely unrepresentable values is left
alone: after this change year zero no longer reaches that path at all.
A new SerDe test checks every representable day of year zero against cctz rather than
against Doris's own day arithmetic, plus the two offset edges, INT96, the millis unit,
plain, dictionary, decoded-value and raw-predicate materialization, and TIMESTAMPTZ.
Reverting the three source files turns 12 of these red and leaves the two
"still rejects out-of-range" cases green, so they cannot pass vacuously.
End to end on a local cluster: the extended Iceberg suite now compares timestamp values,
not just partition tuples, against Spark 4.0.0 in both directions (Doris-written read by
both engines, Spark-written read by Doris) -- Iceberg `timestamp` is not adjusted to UTC,
so it exercises the civil path. The OUTFILE round trip was verified over file:// plus
local(), the reproduction from the report, across three session timezones including the
two that straddle the range edges, plus the counts, the ORC control and INSERT ... SELECT.
That run also showed the legacy scanner (enable_file_scanner_v2=false) returns NULL for
any pre-epoch timestamp with a sub-second part, year zero or not, because it truncates a
negative epoch value towards zero instead of flooring it. That is a separate defect in a
path this change does not touch, so the new suite deliberately does not assert the two
scanners agree.
### Release note
Doris can now read back the year-zero DATETIME values it accepts, stores and
exports:
- The Parquet reader accepted no timestamp below 0001-01-01, so a DATETIME in
0000-01-01 .. 0000-12-31 written by Doris itself came back as NULL (or failed
in strict mode). It is now read correctly, and the civil range is enforced
after the timezone offset instead of before it, which also recovers the values
at both ends of the range that a non-UTC session timezone used to lose.
- The 0000-01-01 .. 0000-02-28 window decoded one day early and 0000-01-01 was
rejected outright, because a proleptic Gregorian day ordinal was added to
Doris's MySQL day number; both now decode correctly, and the proleptic-only
0000-02-29 is rejected instead of colliding with 0000-02-28.
- TIMESTAMPTZ shares the same storage and helper and gains the same range.
### Check List (For Author)
- Test: Regression test + Unit Test
- BE UT: data_type_datetimev2_serde_calendar_test (every representable day of
year zero against cctz, both offset edges, INT96, the millis unit, plain,
dictionary, decoded-value and raw-predicate materialization, TIMESTAMPTZ),
data_type_serde_parquet_test
- Regression: export_p0/outfile/test_outfile_datetime_year_zero,
external_table_p0/iceberg/write/test_iceberg_write_partition_epoch_boundary
- Manual: local cluster, OUTFILE round trip over file:// and local(), three
session timezones, INSERT ... SELECT from the exported file
- Behavior changed: Yes (see the Release note: year-zero DATETIME/TIMESTAMPTZ
values that used to read back as NULL are now returned)
- Does this need documentation: No (no document states the DATETIME lower bound
of the Parquet read path)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPwhYhsSio1HYk2kFnx7KY
### What problem does this PR solve?
Issue Number: closeapache#67366
Related PR: apache#67449
Problem Summary:
Review follow-up on apache#67449. The two commits before this one moved the DATE row
decoders onto the proleptic Gregorian ordinal but left three consumers of the
same ordinal behind, and the Iceberg transforms kept one pre-existing defect.
format_v2's ORC reader still converted DATE stripe statistics through
`date_day_offset_dict`, whose out-of-table fallback is the old
`1900-01-01 + (value + 25567)` arithmetic. Those zone maps have exactly one
consumer, `OrcReader::get_aggregate_result`, which answers a pushed-down
MIN/MAX from statistics without reading a row, so on the default path
(`enable_file_scanner_v2` and `enable_push_down_no_group_agg`) `MIN(d)`
reported 1900-01-01 for a file whose smallest row is 0000-01-01 -- a value
present in no row at all. Decode the bounds with the same conversion the rows
use and return false when a bound has no Doris DATE, which makes the reader fall
back to a normal row scan.
`ReadMapDecimalDateWithCenturyBoundary` pinned that dictionary fallback: it wrote
the ORC ordinal -719530 and expected 1900-01-01, which the new decoder rejects.
Point the fixture at 0000-01-01, the smallest representable DATE, and add a
dedicated test that the three unrepresentable shapes (-719530, the proleptic-only
-719469 and 2932897) fail the scan.
Iceberg's `bucket` over a timestamp hashes the full microsecond value
(iceberg-api `Bucket.BucketLong` over `BucketUtil.hash(long)`), but Doris hashed
whole seconds times a million, so a DATETIME(6) row landed in a different bucket
than the same row written by Spark and bucket pruning skipped the Doris-written
file. `human_year()` did not zero-pad, so a year-zero row's partition directory
was `..._year=0` where Spark writes `..._year=0000`.
On the FE side, `IcebergPartitionUtils` rendered MTMV partition-range bounds with
the pattern letter `y` (year-of-era), so the ordinal -719528 the `day` transform
now emits for 0000-01-01 rendered as 0001-01-01 and collided with the range of
the real 0001-01-01 partition.
The `ExpressionEstimation` hunk from the first commit is reverted: DATE/DATETIME
column statistics are `yyyyMMddHHmmss` numbers, but `getDatetimeFromLong()` reads
them as epoch seconds, so every value is >= 101000000 and the year-zero
correction could never fire. The real defect (the encoding mismatch) predates
this PR and belongs in its own change with its own test.
Also in this commit: the shared out-of-range message no longer says "Parquet" for
an ORC file and now carries the offending value, the ORC and Arrow callers
prepend the column name, the epoch-day constants are derived from the daynr
domain instead of typed out, the Arrow date64 branch spells its contract like the
date32 one, and `epoch_date()`/`epoch_datetime()` plus their two cast includes
are deleted (no caller left).
### Release note
- A pushed-down `MIN(date_col)` / `MAX(date_col)` over an ORC file now agrees
with the rows. It previously answered from stripe statistics decoded in Doris's
own calendar, so a file containing 0000-01-01 .. 0000-02-28 reported a bound
that no row holds (1900-01-01 for 0000-01-01).
- Iceberg `bucket(n, ts)` now hashes the full microsecond value, as the Iceberg
specification requires. A `DATETIME` column with a non-zero sub-second part
routes to a different (and now Spark-compatible) bucket than before; existing
files keep their old bucket values until they are rewritten.
- An Iceberg `year` partition directory is zero-padded (`..._year=0000`), which
is what Spark writes. Only the directory name changes; the manifest value is
unaffected.
- The MTMV partition-range view of an Iceberg table with year-zero `day`/`hour`
partitions renders 0000-01-01 instead of 0001-01-01.
- An unrepresentable DATE in a Parquet or ORC file is now reported with the
offending value and the column name, and no longer names the wrong format.
### Check List (For Author)
- Test: Regression test + Unit Test
- BE UT: orc_reader_test (year-zero rows, a null row, the three rejected
ordinals, MIN/MAX against the row decode, and the statistics fallback),
data_type_datev2_serde_calendar_test (the Parquet/ORC decoded-value entry
point, strict and null-on-failure), partition_transformers_test
(microsecond buckets, the zero-padded human year), vdatetime_value_test
- FE UT: IcebergPartitionUtilsTest (year-zero day and hour ranges)
- Regression: the ORC half of
external_table_p0/iceberg/write/test_iceberg_write_partition_epoch_boundary
compares a pushed-down MIN/MAX with the rows of the same file
- Behavior changed: Yes (see the Release note)
- Does this need documentation: No
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPwhYhsSio1HYk2kFnx7KY
@morningman

Copy link
Copy Markdown
ContributorAuthor

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16935 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 980f5764e3c75744068fdb6057c88f052c960485, data reload: false
------ Round 1 ----------------------------------
============================================
q1	17590	3009	3035	3009
q2	2075	250	238	238
q3	10241	880	518	518
q4	4670	249	207	207
q5	7672	566	392	392
q6	140	116	95	95
q7	526	514	389	389
q8	9243	971	910	910
q9	3588	2379	2405	2379
q10	6487	834	717	717
q11	398	197	189	189
q12	612	259	200	200
q13	18143	1526	1174	1174
q14	159	151	138	138
q15	q16	451	395	374	374
q17	1401	913	821	821
q18	3066	2237	2206	2206
q19	1272	907	787	787
q20	378	285	199	199
q21	5599	1758	1840	1758
q22	330	271	235	235
Total cold run time: 94041 ms
Total hot run time: 16935 ms
----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3399	3341	3321	3321
q2	513	437	370	370
q3	2243	2762	2195	2195
q4	1177	1161	885	885
q5	2173	2073	2077	2073
q6	171	125	87	87
q7	1013	899	850	850
q8	1598	1444	1398	1398
q9	3144	3105	3083	3083
q10	1833	1763	1602	1602
q11	371	269	253	253
q12	455	431	344	344
q13	1454	1509	1132	1132
q14	164	164	161	161
q15	q16	390	394	357	357
q17	3585	3356	3231	3231
q18	4769	4338	4724	4338
q19	860	898	865	865
q20	1010	949	825	825
q21	3707	3008	3232	3008
q22	394	348	318	318
Total cold run time: 34423 ms
Total hot run time: 30696 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82064 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 980f5764e3c75744068fdb6057c88f052c960485, data reload: false
query5	4245	411	340	340
query6	396	142	125	125
query7	4929	425	237	237
query8	291	128	119	119
query9	8682	2876	2881	2876
query10	370	222	184	184
query11	5401	1052	912	912
query12	119	69	68	68
query13	1190	432	334	334
query14	6089	2187	2090	2090
query14_1	1977	1954	1935	1935
query15	176	119	110	110
query16	925	366	354	354
query17	811	458	362	362
query18	2340	324	245	245
query19	164	143	113	113
query20	73	68	68	68
query21	203	99	88	88
query22	5373	5374	5350	5350
query23	6639	6054	5934	5934
query23_1	6168	5946	5985	5946
query24	7292	1123	778	778
query24_1	800	780	778	778
query25	438	305	261	261
query26	1228	227	129	129
query27	2803	423	263	263
query28	4662	1502	1508	1502
query29	934	455	371	371
query30	253	150	135	135
query31	816	392	328	328
query32	126	73	81	73
query33	460	225	188	188
query34	1002	859	470	470
query35	388	399	342	342
query36	580	571	536	536
query37	123	80	70	70
query38	1004	845	803	803
query39	480	486	457	457
query39_1	450	470	476	470
query40	200	94	79	79
query41	62	57	57	57
query42	81	75	79	75
query43	243	251	213	213
query44	1027	557	563	557
query45	116	105	139	105
query46	784	867	541	541
query47	770	737	709	709
query48	316	314	230	230
query49	536	233	177	177
query50	771	264	198	198
query51	8093	8148	8234	8148
query52	69	68	59	59
query53	200	193	150	150
query54	244	178	218	178
query55	88	59	55	55
query56	198	168	188	168
query57	667	656	654	654
query58	204	176	163	163
query59	1230	1229	1087	1087
query60	230	175	170	170
query61	114	122	116	116
query62	359	200	180	180
query63	172	145	151	145
query64	2755	685	619	619
query65	1602	1562	1613	1562
query66	1830	276	212	212
query67	9837	9710	9681	9681
query68	2743	1182	771	771
query69	352	225	192	192
query70	663	628	635	628
query71	258	168	166	166
query72	2297	1770	1564	1564
query73	671	547	341	341
query74	1575	1218	1120	1120
query75	1167	1094	951	951
query76	2288	754	586	586
query77	258	268	215	215
query78	3919	3624	3182	3182
query79	2881	796	609	609
query80	1585	329	274	274
query81	505	156	133	133
query82	634	131	100	100
query83	285	209	194	194
query84	319	115	90	90
query85	838	360	300	300
query86	482	177	168	168
query87	999	967	868	868
query88	2896	2127	2089	2089
query89	296	197	172	172
query90	1987	126	126	126
query91	132	123	103	103
query92	85	72	71	71
query93	1730	1097	726	726
query94	642	249	217	217
query95	518	318	231	231
query96	818	589	275	275
query97	1062	1023	971	971
query98	167	133	132	132
query99	417	351	316	316
Total cold run time: 178099 ms
Total hot run time: 82064 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.63 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 980f5764e3c75744068fdb6057c88f052c960485, data reload: false
query1	0.01	0.00	0.00
query2	0.08	0.04	0.04
query3	0.24	0.11	0.11
query4	1.60	0.10	0.10
query5	0.18	0.16	0.16
query6	1.25	0.66	0.68
query7	0.04	0.01	0.00
query8	0.04	0.03	0.03
query9	0.28	0.21	0.21
query10	0.34	0.34	0.33
query11	0.16	0.12	0.11
query12	0.16	0.12	0.12
query13	0.30	0.30	0.31
query14	0.45	0.44	0.43
query15	0.36	0.34	0.35
query16	0.23	0.22	0.23
query17	0.72	0.74	0.73
query18	0.17	0.17	0.18
query19	1.22	1.15	1.10
query20	0.01	0.01	0.01
query21	15.44	0.15	0.11
query22	5.10	0.04	0.04
query23	16.17	0.25	0.11
query24	3.06	0.31	0.26
query25	0.12	0.04	0.04
query26	0.79	0.17	0.12
query27	0.03	0.02	0.03
query28	3.59	0.52	0.27
query29	12.51	3.18	2.55
query30	0.25	0.11	0.12
query31	2.78	0.35	0.17
query32	3.57	0.31	0.23
query33	1.40	1.52	1.44
query34	15.37	2.23	1.76
query35	1.74	1.71	1.71
query36	0.46	0.30	0.28
query37	0.05	0.04	0.04
query38	0.04	0.03	0.03
query39	0.03	0.02	0.02
query40	0.11	0.08	0.08
query41	0.07	0.03	0.02
query42	0.03	0.02	0.03
query43	0.03	0.03	0.03
Total cold run time: 90.58 s
Total hot run time: 14.63 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage `` 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 75.00% (33/44) 🎉

Increment coverage report
Complete coverage report

CategoryCoverage
Function Coverage76.08% (34618/45504)
Line Coverage61.18% (390837/638838)
Region Coverage57.25% (327800/572530)
Branch Coverage58.07% (149608/257654)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.00% (0/11) 🎉
Increment coverage report
Complete coverage report

@morningman
morningman marked this pull request as draft September 3, 2026 13:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@morningman@hello-stephen