Search before asking
Version
master (ddbaaab1388)
What's Wrong?
Doris writes year-zero DATETIME values to Parquet correctly, but cannot read its own file back — the values come back NULL.
be/src/core/data_type_serde/parquet_timestamp.h gates every Parquet timestamp read at year 1:
inlineconstexprint64_tMIN_DORIS_TIMESTAMP_MICROS = -62135596800000000LL; // 0001-01-01inlineconstexprint64_tMAX_DORIS_TIMESTAMP_MICROS = 253402300799999999LL; // 9999-12-31inline Status validate_parquet_timestamp_micros(int64_t timestamp_micros) {
if (timestamp_micros < MIN_DORIS_TIMESTAMP_MICROS || timestamp_micros > MAX_DORIS_TIMESTAMP_MICROS) {
returnStatus::DataQualityError(
"Parquet timestamp is outside the Doris 0001-9999 range: micros={}", timestamp_micros);
}
returnStatus::OK();
}But the DATETIME type itself starts at 0000-01-01, whose micros value is -62167219200000000 — below that bound. So the reader is stricter than the type it materialises into.
What You Expected?
A DATETIME value that Doris accepts, stores and exports should read back from Doris's own Parquet file.
How to Reproduce?
CREATETABLEdt0 (id INT, ts DATETIME(6)) DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES('replication_num'='1');
INSERT INTO dt0 VALUES (1,'0000-01-01 12:34:56'),(2,'0000-03-01 00:00:00'),
(3,'1969-12-31 23:59:59'),(4,'2024-01-01 12:00:00');
-- the type stores them fineSELECT id, CAST(ts AS STRING) FROM dt0 ORDER BY id;
-- 1 0000-01-01 12:34:56.000000-- 2 0000-03-01 00:00:00.000000-- 3 1969-12-31 23:59:59.000000-- 4 2024-01-01 12:00:00.000000SELECT*FROM dt0 ORDER BY id INTO OUTFILE 'file:///tmp/dtz/p_' FORMAT AS PARQUET;Read the file back with the local() TVF:
id ts_read
1 NULL <-- lost
2 NULL <-- lost
3 1969-12-31 23:59:59.000000
4 2024-01-01 12:00:00.000000
Note 0000-03-01 is also lost, so this is a plain range check, not a calendar edge case.
Anything Else?
The write side is correct: Spark reads the same year-zero timestamps out of a Doris-written Iceberg table without trouble (verified with apache/spark:4.0.0 against the Iceberg REST catalog — Spark returned 0000-01-01 12:34:56 for the row Doris returned NULL for). So only Doris's reader rejects them.
The constant name and the error text both say 0001-9999, so the bound may be deliberate. If so, the asymmetry is still worth resolving in one direction or the other:
- widen the reader to
0000-01-01 (-62167219200000000) to match the DATETIME range, or - reject year-zero timestamps on the write path too, so Doris never produces a file it cannot read.
Found while running Iceberg regression suites for #67366.
Are you willing to submit PR?
Code of Conduct
Search before asking
Version
master (
ddbaaab1388)What's Wrong?
Doris writes year-zero
DATETIMEvalues to Parquet correctly, but cannot read its own file back — the values come backNULL.be/src/core/data_type_serde/parquet_timestamp.hgates every Parquet timestamp read at year 1:But the DATETIME type itself starts at
0000-01-01, whose micros value is-62167219200000000— below that bound. So the reader is stricter than the type it materialises into.What You Expected?
A
DATETIMEvalue that Doris accepts, stores and exports should read back from Doris's own Parquet file.How to Reproduce?
Read the file back with the
local()TVF:Note
0000-03-01is also lost, so this is a plain range check, not a calendar edge case.Anything Else?
The write side is correct: Spark reads the same year-zero timestamps out of a Doris-written Iceberg table without trouble (verified with
apache/spark:4.0.0against the Iceberg REST catalog — Spark returned0000-01-01 12:34:56for the row Doris returnedNULLfor). So only Doris's reader rejects them.The constant name and the error text both say
0001-9999, so the bound may be deliberate. If so, the asymmetry is still worth resolving in one direction or the other:0000-01-01(-62167219200000000) to match the DATETIME range, orFound while running Iceberg regression suites for #67366.
Are you willing to submit PR?
Code of Conduct