This is an automated email from the ASF dual-hosted git repository.
Mryange pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 4ab7cc02461 [fix](function) support TIMESTAMPDIFF MICROSECOND in
nereids (#63365)
4ab7cc02461 is described below
commit 4ab7cc024611e53d9317c2a1e64f265af46e2913
Author: Mryange <[email protected]>
AuthorDate: Thu May 21 12:07:33 2026 +0800
[fix](function) support TIMESTAMPDIFF MICROSECOND in nereids (#63365)
### What problem does this PR solve?
Nereids rejects `TIMESTAMPDIFF(MICROSECOND, ...)` during analysis.
The executable path already exists through `MicroSecondsDiff`, but the
FE binder cannot reach it because:
- `Interval.TimeUnit` does not define a standalone `MICROSECOND`
- `DatetimeFunctionBinder` only routes `TIMESTAMPDIFF` up to `SECOND`
As a result, queries such as `TIMESTAMPDIFF(MICROSECOND, MIN(t),
MAX(t))` fail even for valid `DATETIMEV2(6)` inputs.
---
.../rules/analysis/DatetimeFunctionBinder.java | 5 +++-
.../trees/expressions/literal/Interval.java | 1 +
.../rules/analysis/DatetimeFunctionBinderTest.java | 10 ++++++++
.../data/nereids_syntax_p0/test_timestampdiff.out | 6 +++++
.../nereids_syntax_p0/test_timestampdiff.groovy | 28 ++++++++++++++++++++++
5 files changed, 49 insertions(+), 1 deletion(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
index c93f151cf0c..4e1a768bd97 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java
@@ -55,6 +55,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecondSub
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursAdd;
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff;
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub;
+import
org.apache.doris.nereids.trees.expressions.functions.scalar.MicroSecondsDiff;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecondAdd;
@@ -301,9 +302,11 @@ public class DatetimeFunctionBinder {
return new MinutesDiff(end, start);
case SECOND:
return new SecondsDiff(end, start);
+ case MICROSECOND:
+ return new MicroSecondsDiff(end, start);
default:
throw new AnalysisException("Unsupported time stamp diff time
unit: " + unit
- + ", supported time unit:
YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND");
+ + ", supported time unit:
YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND/MICROSECOND");
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
index 275e0f74fe1..f490c225c44 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java
@@ -106,6 +106,7 @@ public class Interval extends Expression implements
UnaryExpression, AlwaysNotNu
MINUTE_SECOND("MINUTE_SECOND", false, 200),
MINUTE_MICROSECOND("MINUTE_MICROSECOND", false, 200),
SECOND("SECOND", true, 100),
+ MICROSECOND("MICROSECOND", true, 0),
SECOND_MICROSECOND("SECOND_MICROSECOND", true, 100);
private final String description;
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java
index 81f24ed878b..a63e4a3e628 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinderTest.java
@@ -42,6 +42,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.HourFloor;
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursAdd;
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff;
import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub;
+import
org.apache.doris.nereids.trees.expressions.functions.scalar.MicroSecondsDiff;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd;
@@ -110,6 +111,8 @@ public class DatetimeFunctionBinderTest {
TinyIntType.INSTANCE, false, ImmutableList.of());
private final SlotReference secondUnit = new SlotReference(new ExprId(-1),
"SECOND",
TinyIntType.INSTANCE, false, ImmutableList.of());
+ private final SlotReference microsecondUnit = new SlotReference(new
ExprId(-1), "MICROSECOND",
+ TinyIntType.INSTANCE, false, ImmutableList.of());
private final SlotReference invalidUnit = new SlotReference(new
ExprId(-1), "INVALID",
TinyIntType.INSTANCE, false, ImmutableList.of());
@@ -172,6 +175,13 @@ public class DatetimeFunctionBinderTest {
Assertions.assertEquals(dateTimeV2Literal2, result.child(0));
Assertions.assertEquals(dateTimeV2Literal1, result.child(1));
+ timeDiff = new UnboundFunction(functionName, ImmutableList.of(
+ microsecondUnit, dateTimeV2Literal1, dateTimeV2Literal2));
+ result = DatetimeFunctionBinder.INSTANCE.bind(timeDiff);
+ Assertions.assertInstanceOf(MicroSecondsDiff.class, result);
+ Assertions.assertEquals(dateTimeV2Literal2, result.child(0));
+ Assertions.assertEquals(dateTimeV2Literal1, result.child(1));
+
Assertions.assertThrowsExactly(AnalysisException.class,
() -> DatetimeFunctionBinder.INSTANCE.bind(
new UnboundFunction(functionName,
ImmutableList.of(invalidUnit,
diff --git a/regression-test/data/nereids_syntax_p0/test_timestampdiff.out
b/regression-test/data/nereids_syntax_p0/test_timestampdiff.out
index 0e2dd6a5375..15623515ed4 100644
--- a/regression-test/data/nereids_syntax_p0/test_timestampdiff.out
+++ b/regression-test/data/nereids_syntax_p0/test_timestampdiff.out
@@ -17,3 +17,9 @@
-- !select --
40
+-- !select --
+876543
+
+-- !select --
+2024-01-01T10:00:00.999999 2024-01-01T10:00:00.123456 876543
+
diff --git a/regression-test/suites/nereids_syntax_p0/test_timestampdiff.groovy
b/regression-test/suites/nereids_syntax_p0/test_timestampdiff.groovy
index 34500732e22..0a3e563bd7f 100644
--- a/regression-test/suites/nereids_syntax_p0/test_timestampdiff.groovy
+++ b/regression-test/suites/nereids_syntax_p0/test_timestampdiff.groovy
@@ -37,4 +37,32 @@ suite("test_timestampdiff") {
qt_select """
SELECT TIMESTAMPDIFF(second,'2003-02-03 11:00:00','2003-02-03
11:00:40');
"""
+
+ qt_select """
+ SELECT TIMESTAMPDIFF(microsecond,
+ CAST('2024-01-01 10:00:00.123456' AS DATETIMEV2(6)),
+ CAST('2024-01-01 10:00:00.999999' AS DATETIMEV2(6)));
+ """
+
+ sql """drop table if exists test_timestampdiff_microsecond"""
+ sql """
+ create table test_timestampdiff_microsecond (
+ id int,
+ t datetimev2(6)
+ )
+ duplicate key(id)
+ distributed by hash(id) buckets 1
+ properties("replication_num" = "1");
+ """
+
+ sql """
+ insert into test_timestampdiff_microsecond values
+ (1, '2024-01-01 10:00:00.123456'),
+ (2, '2024-01-01 10:00:00.999999');
+ """
+
+ qt_select """
+ SELECT MAX(t), MIN(t), TIMESTAMPDIFF(MICROSECOND, MIN(t), MAX(t))
+ FROM test_timestampdiff_microsecond;
+ """
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]