This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 8f912890df1 branch-4.0: [fix](be) Support TIMESTAMPTZ in TopN runtime
predicate #63220 (#63236)
8f912890df1 is described below
commit 8f912890df1fc3c3e5dc84c856e39e7774c18773
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri May 15 21:08:29 2026 -0700
branch-4.0: [fix](be) Support TIMESTAMPTZ in TopN runtime predicate #63220
(#63236)
Cherry-picked from #63220
Co-authored-by: TengJianPing <[email protected]>
---
be/src/runtime/runtime_predicate.cpp | 2 +-
.../timestamptz/test_timestamptz_sort.out | 104 ++++++++++++++++
.../timestamptz/test_timestamptz_sort.groovy | 134 +++++++++++++++++++++
3 files changed, 239 insertions(+), 1 deletion(-)
diff --git a/be/src/runtime/runtime_predicate.cpp
b/be/src/runtime/runtime_predicate.cpp
index 0b28df34665..36e3e6cd5e6 100644
--- a/be/src/runtime/runtime_predicate.cpp
+++ b/be/src/runtime/runtime_predicate.cpp
@@ -78,7 +78,7 @@ Status RuntimePredicate::init_target(
bool RuntimePredicate::_init(PrimitiveType type) {
return is_int_or_bool(type) || is_decimal(type) || is_string_type(type) ||
is_date_type(type) ||
- is_time_type(type) || is_ip(type) || is_varbinary(type);
+ is_time_type(type) || is_timestamptz_type(type) || is_ip(type) ||
is_varbinary(type);
}
Status RuntimePredicate::update(const Field& value) {
diff --git
a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_sort.out
b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_sort.out
index 41766708c9f..6b8b08de986 100644
--- a/regression-test/data/datatype_p0/timestamptz/test_timestamptz_sort.out
+++ b/regression-test/data/datatype_p0/timestamptz/test_timestamptz_sort.out
@@ -16,3 +16,107 @@
-- !sort_offset_limit --
3 2020-01-01 07:59:59+08:00
+-- !big_topn_asc --
+0 1970-01-01 08:00:00+08:00
+1 1970-01-01 08:00:01+08:00
+2 1970-01-01 08:00:02+08:00
+3 1970-01-01 08:00:03+08:00
+4 1970-01-01 08:00:04+08:00
+5 1970-01-01 08:00:05+08:00
+6 1970-01-01 08:00:06+08:00
+7 1970-01-01 08:00:07+08:00
+8 1970-01-01 08:00:08+08:00
+9 1970-01-01 08:00:09+08:00
+
+-- !big_topn_desc --
+9999 1970-01-01 10:46:39+08:00
+9998 1970-01-01 10:46:38+08:00
+9997 1970-01-01 10:46:37+08:00
+9996 1970-01-01 10:46:36+08:00
+9995 1970-01-01 10:46:35+08:00
+9994 1970-01-01 10:46:34+08:00
+9993 1970-01-01 10:46:33+08:00
+9992 1970-01-01 10:46:32+08:00
+9991 1970-01-01 10:46:31+08:00
+9990 1970-01-01 10:46:30+08:00
+
+-- !big_topn_offset --
+50 1970-01-01 08:00:50+08:00
+51 1970-01-01 08:00:51+08:00
+52 1970-01-01 08:00:52+08:00
+53 1970-01-01 08:00:53+08:00
+54 1970-01-01 08:00:54+08:00
+55 1970-01-01 08:00:55+08:00
+56 1970-01-01 08:00:56+08:00
+57 1970-01-01 08:00:57+08:00
+58 1970-01-01 08:00:58+08:00
+59 1970-01-01 08:00:59+08:00
+
+-- !big_count --
+10000
+
+-- !mixed_asc --
+5 2020-01-01 00:00:00+08:00
+8 2020-01-01 07:59:59+08:00
+6 2020-01-01 08:00:00+08:00
+2 2020-01-01 12:00:00+08:00
+4 2020-01-01 14:30:00+08:00
+
+-- !mixed_desc --
+10 2020-06-02 01:00:00+08:00
+9 2020-06-01 15:00:00+08:00
+3 2020-01-02 01:00:00+08:00
+1 2020-01-01 20:00:00+08:00
+7 2020-01-01 16:00:00+08:00
+
+-- !big_null_asc_first --
+0 \N
+97 \N
+194 \N
+291 \N
+388 \N
+485 \N
+582 \N
+679 \N
+776 \N
+873 \N
+
+-- !big_null_asc_last --
+1 1970-01-01 08:00:01+08:00
+2 1970-01-01 08:00:02+08:00
+3 1970-01-01 08:00:03+08:00
+4 1970-01-01 08:00:04+08:00
+5 1970-01-01 08:00:05+08:00
+6 1970-01-01 08:00:06+08:00
+7 1970-01-01 08:00:07+08:00
+8 1970-01-01 08:00:08+08:00
+9 1970-01-01 08:00:09+08:00
+10 1970-01-01 08:00:10+08:00
+
+-- !big_null_desc_first --
+0 \N
+97 \N
+194 \N
+291 \N
+388 \N
+485 \N
+582 \N
+679 \N
+776 \N
+873 \N
+
+-- !big_null_desc_last --
+9999 1970-01-01 10:46:39+08:00
+9998 1970-01-01 10:46:38+08:00
+9997 1970-01-01 10:46:37+08:00
+9996 1970-01-01 10:46:36+08:00
+9995 1970-01-01 10:46:35+08:00
+9994 1970-01-01 10:46:34+08:00
+9993 1970-01-01 10:46:33+08:00
+9992 1970-01-01 10:46:32+08:00
+9990 1970-01-01 10:46:30+08:00
+9989 1970-01-01 10:46:29+08:00
+
+-- !big_null_count --
+10000 9896
+
diff --git
a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_sort.groovy
b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_sort.groovy
index b88e16b82ba..6fd7e806d3e 100644
---
a/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_sort.groovy
+++
b/regression-test/suites/datatype_p0/timestamptz/test_timestamptz_sort.groovy
@@ -50,4 +50,138 @@ suite("test_timestamptz_sort") {
qt_sort_offset_limit """
select * from timestamptz_sort_test order by tz asc limit 1 offset 1;
"""
+
+ // Exercise BE topn runtime predicate on TIMESTAMPTZ.
+ // topn_filter_ratio is amplified so that the FE generates a TopnFilter
targeting the OlapScan
+ // regardless of row-count statistics; without TIMESTAMPTZ support in
RuntimePredicate this
+ // query throws "meet invalid type, type=TIMESTAMPTZ" on the BE.
+ sql " set topn_filter_ratio = 1000000; "
+
+ // Larger dataset to exercise the BE topn runtime predicate over many
segments / pages,
+ // so that the threshold tightens repeatedly and storage-layer pruning
kicks in.
+ sql """ DROP TABLE IF EXISTS timestamptz_sort_big; """
+ sql """
+ CREATE TABLE timestamptz_sort_big (id INT, tz timestamptz)
+ DISTRIBUTED BY HASH(id) BUCKETS 4
+ PROPERTIES ("replication_num" = "1");
+ """
+ sql """
+ INSERT INTO timestamptz_sort_big
+ SELECT
+ cast(number as INT),
+ cast(from_unixtime(number) as timestamptz)
+ FROM numbers("number" = "10000");
+ """
+
+ // The plan must actually contain the TopN runtime predicate (TOPN OPT on
OlapScanNode);
+ // otherwise the BE path under test is dormant and the query trivially
passes for the wrong
+ // reason. We assert it on both asc and desc so flipping the order is also
covered.
+ explain {
+ sql "select * from timestamptz_sort_big order by tz asc, id asc limit
10;"
+ contains("TOPN OPT:")
+ }
+ explain {
+ sql "select * from timestamptz_sort_big order by tz desc, id asc limit
10;"
+ contains("TOPN OPT:")
+ }
+
+ qt_big_topn_asc """
+ select * from timestamptz_sort_big order by tz asc, id asc limit 10;
+ """
+
+ qt_big_topn_desc """
+ select * from timestamptz_sort_big order by tz desc, id asc limit 10;
+ """
+
+ qt_big_topn_offset """
+ select * from timestamptz_sort_big order by tz asc, id asc limit 10
offset 50;
+ """
+
+ qt_big_count """
+ select count(*) from timestamptz_sort_big;
+ """
+
+ // Mixed timezones: verify TopN orders by the absolute UTC instant, not
the local display.
+ // Two pairs deliberately share local clock time but differ by offset; the
+00:00 row is the
+ // *later* instant for the noon pair, and the +08:00 row is the *later*
instant for the midnight
+ // pair. The sort must reflect the actual instant, not the local string.
+ sql """ DROP TABLE IF EXISTS timestamptz_sort_mixed; """
+ sql """
+ CREATE TABLE timestamptz_sort_mixed (id INT, tz timestamptz)
+ DISTRIBUTED BY HASH(id) BUCKETS 4
+ PROPERTIES ("replication_num" = "1");
+ """
+ sql """
+ insert into timestamptz_sort_mixed values
+ (1, cast("2020-01-01 12:00:00 +00:00" as timestamptz)),
+ (2, cast("2020-01-01 12:00:00 +08:00" as timestamptz)),
+ (3, cast("2020-01-01 12:00:00 -05:00" as timestamptz)),
+ (4, cast("2020-01-01 12:00:00 +05:30" as timestamptz)),
+ (5, cast("2020-01-01 00:00:00 +08:00" as timestamptz)),
+ (6, cast("2020-01-01 00:00:00 +00:00" as timestamptz)),
+ (7, cast("2020-01-01 00:00:00 -08:00" as timestamptz)),
+ (8, cast("2019-12-31 23:59:59 +00:00" as timestamptz)),
+ (9, cast("2020-06-01 12:00:00 +05:00" as timestamptz)),
+ (10, cast("2020-06-01 12:00:00 -05:00" as timestamptz));
+ """
+
+ explain {
+ sql "select * from timestamptz_sort_mixed order by tz asc, id asc
limit 5;"
+ contains("TOPN OPT:")
+ }
+
+ qt_mixed_asc """
+ select * from timestamptz_sort_mixed order by tz asc, id asc limit 5;
+ """
+
+ qt_mixed_desc """
+ select * from timestamptz_sort_mixed order by tz desc, id asc limit 5;
+ """
+
+ // Combined large-scale + nullable: 10k rows with periodic NULLs scattered
through, exercising
+ // the topn runtime predicate together with NULLS FIRST / NULLS LAST
semantics over many pages.
+ sql """ DROP TABLE IF EXISTS timestamptz_sort_big_null; """
+ sql """
+ CREATE TABLE timestamptz_sort_big_null (id INT, tz timestamptz NULL)
+ DISTRIBUTED BY HASH(id) BUCKETS 4
+ PROPERTIES ("replication_num" = "1");
+ """
+ sql """
+ INSERT INTO timestamptz_sort_big_null
+ SELECT
+ cast(number as INT),
+ case when number % 97 = 0 then null
+ else cast(from_unixtime(number) as timestamptz)
+ end
+ FROM numbers("number" = "10000");
+ """
+
+ explain {
+ sql "select * from timestamptz_sort_big_null order by tz asc nulls
first, id asc limit 10;"
+ contains("TOPN OPT:")
+ }
+ explain {
+ sql "select * from timestamptz_sort_big_null order by tz asc nulls
last, id asc limit 10;"
+ contains("TOPN OPT:")
+ }
+
+ qt_big_null_asc_first """
+ select * from timestamptz_sort_big_null order by tz asc nulls first,
id asc limit 10;
+ """
+
+ qt_big_null_asc_last """
+ select * from timestamptz_sort_big_null order by tz asc nulls last, id
asc limit 10;
+ """
+
+ qt_big_null_desc_first """
+ select * from timestamptz_sort_big_null order by tz desc nulls first,
id asc limit 10;
+ """
+
+ qt_big_null_desc_last """
+ select * from timestamptz_sort_big_null order by tz desc nulls last,
id asc limit 10;
+ """
+
+ qt_big_null_count """
+ select count(*), count(tz) from timestamptz_sort_big_null;
+ """
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]