This is an automated email from the ASF dual-hosted git repository.
andygrove pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-comet.git
The following commit(s) were added to refs/heads/main by this push:
new 268849c0cb feat: add `make_interval` support (codegen dispatch +
native) (#5039)
268849c0cb is described below
commit 268849c0cb52c471b205e1dbbb81af98465fc024
Author: Peter Lee <[email protected]>
AuthorDate: Thu Aug 6 19:31:19 2026 +0800
feat: add `make_interval` support (codegen dispatch + native) (#5039)
---
docs/source/user-guide/latest/expressions.md | 4 +-
native/Cargo.lock | 1 +
native/spark-expr/Cargo.toml | 1 +
native/spark-expr/src/comet_scalar_funcs.rs | 7 +-
.../spark-expr/src/datetime_funcs/make_interval.rs | 87 ++++++++++++++++++++++
native/spark-expr/src/datetime_funcs/mod.rs | 2 +
native/spark-expr/src/lib.rs | 5 +-
.../org/apache/comet/serde/QueryPlanSerde.scala | 1 +
.../scala/org/apache/comet/serde/datetime.scala | 37 ++++++++-
.../expressions/datetime/make_interval.sql | 67 +++++++++++++++++
.../expressions/datetime/make_interval_ansi.sql | 41 ++++++++++
.../datetime/make_interval_dispatch.sql | 49 ++++++++++++
.../datetime/make_interval_dispatch_ansi.sql | 48 ++++++++++++
.../expressions/datetime/try_make_interval.sql | 39 ++++++++++
.../CometDatetimeExpressionBenchmark.scala | 55 ++++++++++++++
15 files changed, 436 insertions(+), 8 deletions(-)
diff --git a/docs/source/user-guide/latest/expressions.md
b/docs/source/user-guide/latest/expressions.md
index fd4324babc..192eae807e 100644
--- a/docs/source/user-guide/latest/expressions.md
+++ b/docs/source/user-guide/latest/expressions.md
@@ -277,7 +277,7 @@ The type-name conversion functions (`bigint`, `binary`,
`boolean`, `date`, `deci
| `localtimestamp` | ✅ | — | |
| `make_date` | ✅ | Native | |
| `make_dt_interval` | ✅ | Codegen dispatch | |
-| `make_interval` | 🔜 | — | Produces legacy CalendarInterval; tracked by
[#5061](https://github.com/apache/datafusion-comet/issues/5061) |
+| `make_interval` | ✅ | Hybrid | Routes through the JVM codegen dispatcher by
default; intervals outside Arrow's nanosecond range are tracked by
[#5279](https://github.com/apache/datafusion-comet/issues/5279); the native
path is opt-in via allowIncompatible
([details](compatibility/expressions/datetime.md)) |
| `make_time` | 🔜 | — | Spark 4.1 TIME type; tracked by
[#4288](https://github.com/apache/datafusion-comet/issues/4288) |
| `make_timestamp` | ✅ | Hybrid | |
| `make_timestamp_ltz` | ✅ | — | 2-arg TIME form falls back |
@@ -308,7 +308,7 @@ The type-name conversion functions (`bigint`, `binary`,
`boolean`, `date`, `deci
| `to_unix_timestamp` | ✅ | Hybrid | |
| `to_utc_timestamp` | ✅ | Hybrid | Routes through the JVM codegen dispatcher
by default (handles all timezone forms); the native path is opt-in via
allowIncompatible ([details](compatibility/expressions/datetime.md)) |
| `trunc` | ✅ | Hybrid | |
-| `try_make_interval` | 🔜 | — | Produces legacy CalendarInterval; tracked by
[#5061](https://github.com/apache/datafusion-comet/issues/5061) |
+| `try_make_interval` | ✅ | — | Rewrites to `MakeInterval`; same support as
`make_interval` (Spark 4.0+) |
| `try_make_timestamp` | ✅ | — | |
| `try_to_date` | ✅ | — | Rewrites to `Cast`/`GetTimestamp` before Comet sees
the plan; same support as `to_date` |
| `try_to_time` | 🔜 | — | Spark 4.1 TIME type; tracked by
[#4288](https://github.com/apache/datafusion-comet/issues/4288) |
diff --git a/native/Cargo.lock b/native/Cargo.lock
index eeaa9da5ce..ae8a2f7be7 100644
--- a/native/Cargo.lock
+++ b/native/Cargo.lock
@@ -2066,6 +2066,7 @@ dependencies = [
"datafusion",
"datafusion-comet-common",
"datafusion-comet-jni-bridge",
+ "datafusion-spark",
"futures",
"jni 0.22.4",
"num",
diff --git a/native/spark-expr/Cargo.toml b/native/spark-expr/Cargo.toml
index 2333d2f0e6..6faa9fec4e 100644
--- a/native/spark-expr/Cargo.toml
+++ b/native/spark-expr/Cargo.toml
@@ -30,6 +30,7 @@ edition = { workspace = true }
arrow = { workspace = true }
chrono = { workspace = true }
datafusion = { workspace = true }
+datafusion-spark = { workspace = true }
chrono-tz = { workspace = true }
num = { workspace = true }
regex = { workspace = true }
diff --git a/native/spark-expr/src/comet_scalar_funcs.rs
b/native/spark-expr/src/comet_scalar_funcs.rs
index 50732959c8..e90e01de95 100644
--- a/native/spark-expr/src/comet_scalar_funcs.rs
+++ b/native/spark-expr/src/comet_scalar_funcs.rs
@@ -28,8 +28,8 @@ use crate::{
spark_isnan, spark_lpad, spark_make_decimal, spark_month_name,
spark_read_side_padding,
spark_round, spark_rpad, spark_to_time, spark_unhex, spark_unscaled_value,
EvalMode,
SparkArrayPositionFunc, SparkArraySlice, SparkArraysOverlap,
SparkContains, SparkDateDiff,
- SparkDateFromUnixDate, SparkDateTrunc, SparkFlatten, SparkMakeDate,
SparkMakeTime,
- SparkNextDay, SparkSecondsToTimestamp, SparkSizeFunc,
+ SparkDateFromUnixDate, SparkDateTrunc, SparkFlatten, SparkMakeDate,
SparkMakeInterval,
+ SparkMakeTime, SparkNextDay, SparkSecondsToTimestamp, SparkSizeFunc,
};
use arrow::datatypes::DataType;
use datafusion::common::{DataFusionError, Result as DataFusionResult};
@@ -250,6 +250,9 @@ pub fn create_comet_physical_fun_with_eval_mode(
"make_date" => Ok(Arc::new(ScalarUDF::new_from_impl(SparkMakeDate::new(
fail_on_error,
)))),
+ "make_interval" =>
Ok(Arc::new(ScalarUDF::new_from_impl(SparkMakeInterval::new(
+ fail_on_error,
+ )))),
"next_day" => Ok(Arc::new(ScalarUDF::new_from_impl(SparkNextDay::new(
fail_on_error,
)))),
diff --git a/native/spark-expr/src/datetime_funcs/make_interval.rs
b/native/spark-expr/src/datetime_funcs/make_interval.rs
new file mode 100644
index 0000000000..9f7b21ca2a
--- /dev/null
+++ b/native/spark-expr/src/datetime_funcs/make_interval.rs
@@ -0,0 +1,87 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::arithmetic_overflow_error;
+use arrow::array::Array;
+use arrow::datatypes::DataType;
+use datafusion::common::Result;
+use datafusion::logical_expr::{ColumnarValue, ScalarFunctionArgs,
ScalarUDFImpl, Signature};
+use datafusion_spark::function::datetime::make_interval::SparkMakeInterval as
DataFusionMakeInterval;
+
+#[derive(Debug, PartialEq, Eq, Hash)]
+pub struct SparkMakeInterval {
+ inner: DataFusionMakeInterval,
+ fail_on_error: bool,
+}
+
+impl SparkMakeInterval {
+ pub fn new(fail_on_error: bool) -> Self {
+ Self {
+ inner: DataFusionMakeInterval::new(),
+ fail_on_error,
+ }
+ }
+}
+
+impl ScalarUDFImpl for SparkMakeInterval {
+ fn name(&self) -> &str {
+ self.inner.name()
+ }
+
+ fn signature(&self) -> &Signature {
+ self.inner.signature()
+ }
+
+ fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
+ self.inner.return_type(arg_types)
+ }
+
+ fn invoke_with_args(&self, args: ScalarFunctionArgs) ->
Result<ColumnarValue> {
+ let inputs = if self.fail_on_error {
+ Some(args.args.clone())
+ } else {
+ None
+ };
+ let result = self.inner.invoke_with_args(args)?;
+
+ if let Some(inputs) = inputs {
+ let inputs_are_valid = |i| {
+ inputs.iter().all(|input| match input {
+ ColumnarValue::Array(values) => values.is_valid(i),
+ ColumnarValue::Scalar(value) => !value.is_null(),
+ })
+ };
+ let overflow = match &result {
+ ColumnarValue::Array(values) =>
values.nulls().is_some_and(|nulls| {
+ nulls.null_count() != 0
+ && nulls
+ .iter()
+ .enumerate()
+ .any(|(i, is_valid)| !is_valid &&
inputs_are_valid(i))
+ }),
+ ColumnarValue::Scalar(value) => value.is_null() &&
inputs_are_valid(0),
+ };
+ if overflow {
+ // Spark identifies the integer or long operation that
overflowed. The native
+ // wrapper only sees the result null mask, so it can only
report interval overflow.
+ return Err(arithmetic_overflow_error("interval").into());
+ }
+ }
+
+ Ok(result)
+ }
+}
diff --git a/native/spark-expr/src/datetime_funcs/mod.rs
b/native/spark-expr/src/datetime_funcs/mod.rs
index 37c5fa5dd2..05530f29c2 100644
--- a/native/spark-expr/src/datetime_funcs/mod.rs
+++ b/native/spark-expr/src/datetime_funcs/mod.rs
@@ -22,6 +22,7 @@ mod day_month_name;
mod extract_date_part;
mod hours;
mod make_date;
+mod make_interval;
mod make_time;
mod next_day;
mod seconds_to_timestamp;
@@ -38,6 +39,7 @@ pub use extract_date_part::SparkMinute;
pub use extract_date_part::SparkSecond;
pub use hours::SparkHoursTransform;
pub use make_date::SparkMakeDate;
+pub use make_interval::SparkMakeInterval;
pub use make_time::SparkMakeTime;
pub use next_day::SparkNextDay;
pub use seconds_to_timestamp::SparkSecondsToTimestamp;
diff --git a/native/spark-expr/src/lib.rs b/native/spark-expr/src/lib.rs
index 42ab43361a..2b5c29befc 100644
--- a/native/spark-expr/src/lib.rs
+++ b/native/spark-expr/src/lib.rs
@@ -77,8 +77,9 @@ pub use comet_scalar_funcs::{
pub use csv_funcs::*;
pub use datetime_funcs::{
spark_day_name, spark_month_name, spark_to_time, SparkDateDiff,
SparkDateFromUnixDate,
- SparkDateTrunc, SparkHour, SparkHoursTransform, SparkMakeDate,
SparkMakeTime, SparkMinute,
- SparkNextDay, SparkSecond, SparkSecondsToTimestamp, SparkUnixTimestamp,
TimestampTruncExpr,
+ SparkDateTrunc, SparkHour, SparkHoursTransform, SparkMakeDate,
SparkMakeInterval,
+ SparkMakeTime, SparkMinute, SparkNextDay, SparkSecond,
SparkSecondsToTimestamp,
+ SparkUnixTimestamp, TimestampTruncExpr,
};
pub use error::{decimal_overflow_error, SparkError, SparkErrorWithContext,
SparkResult};
pub use hash_funcs::*;
diff --git a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
index 4299eb14ba..85601a9e0c 100644
--- a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
@@ -303,6 +303,7 @@ object QueryPlanSerde extends Logging with CometExprShim
with CometTypeShim {
classOf[MakeTimestamp] -> CometMakeTimestamp,
classOf[MakeYMInterval] -> CometMakeYMInterval,
classOf[MakeDTInterval] -> CometMakeDTInterval,
+ classOf[MakeInterval] -> CometMakeInterval,
classOf[MultiplyDTInterval] -> CometMultiplyDTInterval,
classOf[TimestampAdd] -> CometTimestampAdd,
classOf[TimestampDiff] -> CometTimestampDiff,
diff --git a/spark/src/main/scala/org/apache/comet/serde/datetime.scala
b/spark/src/main/scala/org/apache/comet/serde/datetime.scala
index 946c34a857..a74a158e97 100644
--- a/spark/src/main/scala/org/apache/comet/serde/datetime.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/datetime.scala
@@ -21,9 +21,9 @@ package org.apache.comet.serde
import java.util.Locale
-import org.apache.spark.sql.catalyst.expressions.{AddMonths, Attribute,
ConvertTimezone, DateAdd, DateDiff, DateFormatClass, DateFromUnixDate, DateSub,
DayOfMonth, DayOfWeek, DayOfYear, Days, Expression, FromUTCTimestamp,
GetDateField, GetTimestamp, Hour, Hours, LastDay, Literal, MakeDate,
MakeDTInterval, MakeTimestamp, MakeYMInterval, MicrosToTimestamp,
MillisToTimestamp, Minute, Month, MonthsBetween, MultiplyDTInterval, NextDay,
PreciseTimestampConversion, Quarter, Second, SecondsToTim [...]
+import org.apache.spark.sql.catalyst.expressions.{AddMonths, Attribute, Cast,
ConvertTimezone, DateAdd, DateDiff, DateFormatClass, DateFromUnixDate, DateSub,
DayOfMonth, DayOfWeek, DayOfYear, Days, Expression, FromUTCTimestamp,
GetDateField, GetTimestamp, Hour, Hours, LastDay, Literal, MakeDate,
MakeDTInterval, MakeInterval, MakeTimestamp, MakeYMInterval, MicrosToTimestamp,
MillisToTimestamp, Minute, Month, MonthsBetween, MultiplyDTInterval, NextDay,
PreciseTimestampConversion, Quarter, [...]
import org.apache.spark.sql.internal.SQLConf
-import org.apache.spark.sql.types.{DataType, DateType, DoubleType, FloatType,
IntegerType, LongType, StringType, TimestampNTZType, TimestampType}
+import org.apache.spark.sql.types.{CalendarIntervalType, DataType, DateType,
DoubleType, FloatType, IntegerType, LongType, StringType, TimestampNTZType,
TimestampType}
import org.apache.spark.unsafe.types.UTF8String
import org.apache.comet.CometConf
@@ -963,6 +963,39 @@ object CometMakeYMInterval extends
CometCodegenDispatch[MakeYMInterval]
object CometMakeDTInterval extends CometCodegenDispatch[MakeDTInterval]
+object CometMakeInterval extends CometExpressionSerde[MakeInterval] with
CodegenDispatchFallback {
+ private val incompatReason =
+ "The native implementation converts seconds to `Float64`, which can lose
microsecond" +
+ " precision, and stores time in nanoseconds, which overflows for large
time components" +
+ " (hours, minutes, seconds) that Spark can represent."
+
+ override def getCompatibleNotes(): Seq[String] = Seq(
+ "Both the default JVM codegen-dispatch path and the native path currently
limit the" +
+ " elapsed-time component to about 292 years in either direction. This
only affects" +
+ " extreme intervals and is tracked in" +
+ " [#5279](https://github.com/apache/datafusion-comet/issues/5279).")
+
+ override def getIncompatibleReasons(): Seq[String] = Seq(incompatReason)
+
+ override def getSupportLevel(expr: MakeInterval): SupportLevel =
+ Incompatible(Some(incompatReason))
+
+ override def convert(
+ expr: MakeInterval,
+ inputs: Seq[Attribute],
+ binding: Boolean): Option[Expr] = {
+ // The explicit return type skips DataFusion's registry coercion, but its
kernel needs Float64.
+ val children = expr.children.updated(6, Cast(expr.secs, DoubleType))
+ val childExprs = children.map(exprToProtoInternal(_, inputs, binding))
+ val optExpr = scalarFunctionExprToProtoWithReturnType(
+ "make_interval",
+ CalendarIntervalType,
+ expr.failOnError,
+ childExprs: _*)
+ optExpr
+ }
+}
+
object CometMultiplyDTInterval extends CometCodegenDispatch[MultiplyDTInterval]
object CometTimestampAdd extends CometCodegenDispatch[TimestampAdd]
diff --git
a/spark/src/test/resources/sql-tests/expressions/datetime/make_interval.sql
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval.sql
new file mode 100644
index 0000000000..952a9085ee
--- /dev/null
+++ b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval.sql
@@ -0,0 +1,67 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- Config: spark.comet.expression.MakeInterval.allowIncompatible=true
+
+statement
+CREATE TABLE test_make_interval(
+ years int,
+ months int,
+ weeks int,
+ days int,
+ hours int,
+ mins int,
+ secs decimal(18, 6)) USING parquet
+
+statement
+INSERT INTO test_make_interval VALUES
+ (1, 2, 3, 4, 5, 6, 7.123456),
+ (0, 1, 0, 1, 0, 0, 100.000001),
+ (-1, -2, -1, -1, -1, -1, -1.500000),
+ (NULL, 1, 2, 3, 4, 5, 6.000000),
+ (2, NULL, 2, 3, 4, 5, 6.000000),
+ (3, 1, 2, 3, 4, 5, NULL),
+ (-2147483648, 0, 0, 0, 0, 0, 0.000000)
+
+query
+SELECT make_interval(years, months, weeks, days, hours, mins, secs)
+FROM test_make_interval
+ORDER BY years
+
+query
+SELECT make_interval(1, 2), make_interval(3), make_interval()
+
+query
+SELECT make_interval(0, 1, 0, 1, 0, 0, 100.000001)
+
+query
+SELECT make_interval(2147483647)
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5131)
+SELECT make_interval(1, 2, 3, 4, 0, 0, 123456789012.123456)
+
+query
+SELECT make_interval(0, 0, 0, 0, 0, 0, 999999999.999999)
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5131)
+SELECT make_interval(0, 0, 0, 0, 0, 0, 999999999.000001)
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5131)
+SELECT make_interval(0, 0, 0, 0, 2562048)
+
+query
+SELECT make_interval(0, 0, 0, 0, 0, 0, 1234567890123456789)
diff --git
a/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_ansi.sql
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_ansi.sql
new file mode 100644
index 0000000000..175b9ecd08
--- /dev/null
+++
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_ansi.sql
@@ -0,0 +1,41 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- Native ANSI execution must preserve Spark's overflow exception.
+-- Config: spark.sql.ansi.enabled=true
+-- Config: spark.comet.expression.MakeInterval.allowIncompatible=true
+
+statement
+CREATE TABLE test_make_interval_ansi(years int) USING parquet
+
+statement
+INSERT INTO test_make_interval_ansi VALUES (NULL)
+
+query
+SELECT make_interval(1, 2, 3, 4, 5, 6, 7.123456)
+
+query
+SELECT make_interval(years) FROM test_make_interval_ansi
+
+query expect_error(overflow. If necessary set)
+SELECT make_interval(2147483647)
+
+query expect_error(overflow. If necessary set)
+SELECT make_interval(0, 0, 2147483647)
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5131)
+SELECT make_interval(0, 0, 0, 0, 2562048)
diff --git
a/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch.sql
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch.sql
new file mode 100644
index 0000000000..ee2d5e8160
--- /dev/null
+++
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch.sql
@@ -0,0 +1,49 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- With allowIncompatible unset, MakeInterval uses Spark's JVM codegen
dispatcher.
+
+statement
+CREATE TABLE test_make_interval_dispatch(
+ years int,
+ months int,
+ weeks int,
+ days int,
+ hours int,
+ mins int,
+ secs decimal(18, 6)) USING parquet
+
+statement
+INSERT INTO test_make_interval_dispatch VALUES
+ (1, 2, 3, 4, 5, 6, 7.123456),
+ (0, 1, 0, 1, 0, 0, 100.000001),
+ (-1, -2, -1, -1, -1, -1, -1.500000),
+ (NULL, 1, 2, 3, 4, 5, 6.000000),
+ (2, NULL, 2, 3, 4, 5, 6.000000),
+ (3, 1, 2, 3, 4, 5, NULL),
+ (0, 0, 0, 0, 2562048, 0, 0.000000)
+
+query
+SELECT make_interval(years, months, weeks, days, hours, mins, secs)
+FROM test_make_interval_dispatch
+WHERE hours != 2562048
+ORDER BY years
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5279)
+SELECT make_interval(0, 0, 0, 0, hours)
+FROM test_make_interval_dispatch
+WHERE hours = 2562048
diff --git
a/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch_ansi.sql
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch_ansi.sql
new file mode 100644
index 0000000000..f199a8fb66
--- /dev/null
+++
b/spark/src/test/resources/sql-tests/expressions/datetime/make_interval_dispatch_ansi.sql
@@ -0,0 +1,48 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- Config: spark.sql.ansi.enabled=true
+
+statement
+CREATE TABLE test_make_interval_dispatch_ansi(years int, weeks int, hours int)
USING parquet
+
+statement
+INSERT INTO test_make_interval_dispatch_ansi VALUES
+ (1, 0, 5),
+ (2147483647, 0, 0),
+ (0, 2147483647, 0),
+ (0, 0, 2562048)
+
+query
+SELECT make_interval(years, 0, weeks, 0, hours)
+FROM test_make_interval_dispatch_ansi
+WHERE years = 1
+
+query expect_error(overflow. If necessary set)
+SELECT make_interval(years)
+FROM test_make_interval_dispatch_ansi
+WHERE years = 2147483647
+
+query expect_error(overflow. If necessary set)
+SELECT make_interval(0, 0, weeks)
+FROM test_make_interval_dispatch_ansi
+WHERE weeks = 2147483647
+
+query ignore(https://github.com/apache/datafusion-comet/issues/5279)
+SELECT make_interval(0, 0, 0, 0, hours)
+FROM test_make_interval_dispatch_ansi
+WHERE hours = 2562048
diff --git
a/spark/src/test/resources/sql-tests/expressions/datetime/try_make_interval.sql
b/spark/src/test/resources/sql-tests/expressions/datetime/try_make_interval.sql
new file mode 100644
index 0000000000..5e481cb9ff
--- /dev/null
+++
b/spark/src/test/resources/sql-tests/expressions/datetime/try_make_interval.sql
@@ -0,0 +1,39 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- MinSparkVersion: 4.0
+-- ConfigMatrix: spark.sql.ansi.enabled=true,false
+
+statement
+CREATE TABLE test_try_make_interval(
+ years int,
+ months int,
+ weeks int,
+ days int,
+ hours int,
+ mins int,
+ secs decimal(18, 6)) USING parquet
+
+statement
+INSERT INTO test_try_make_interval VALUES
+ (1, 2, 3, 4, 5, 6, 7.123456),
+ (2147483647, 0, 0, 0, 0, 0, 0.000000)
+
+query
+SELECT try_make_interval(years, months, weeks, days, hours, mins, secs)
+FROM test_try_make_interval
+ORDER BY years
diff --git
a/spark/src/test/scala/org/apache/spark/sql/benchmark/CometDatetimeExpressionBenchmark.scala
b/spark/src/test/scala/org/apache/spark/sql/benchmark/CometDatetimeExpressionBenchmark.scala
index 224f2ad344..a9d5b35e17 100644
---
a/spark/src/test/scala/org/apache/spark/sql/benchmark/CometDatetimeExpressionBenchmark.scala
+++
b/spark/src/test/scala/org/apache/spark/sql/benchmark/CometDatetimeExpressionBenchmark.scala
@@ -19,9 +19,12 @@
package org.apache.spark.sql.benchmark
+import org.apache.spark.benchmark.Benchmark
import
org.apache.spark.sql.catalyst.util.DateTimeTestUtils.{withDefaultTimeZone, LA}
import org.apache.spark.sql.internal.SQLConf
+import org.apache.comet.CometConf
+
// spotless:off
/**
* Benchmark to measure Comet execution performance. To run this benchmark:
@@ -131,6 +134,54 @@ object CometDatetimeExpressionBenchmark extends
CometBenchmarkBase {
}
}
+ def makeIntervalBenchmark(values: Int): Unit = {
+ withTempPath { dir =>
+ withTempTable("parquetV1Table") {
+ prepareTable(
+ dir,
+ spark.sql(s"""SELECT
+ | CAST(ABS(value) % 10 AS INT) AS y,
+ | CAST(ABS(value) % 12 AS INT) AS mo,
+ | CAST(ABS(value) % 4 AS INT) AS w,
+ | CAST(ABS(value) % 28 AS INT) AS d,
+ | CAST(ABS(value) % 24 AS INT) AS h,
+ | CAST(ABS(value) % 60 AS INT) AS mi,
+ | CAST(ABS(value) % 60 AS DECIMAL(18, 6)) AS s
+ |FROM $tbl""".stripMargin))
+
+ val query = "SELECT make_interval(y, mo, w, d, h, mi, s) FROM
parquetV1Table"
+ def consumeIntervals(): Unit = {
+
spark.sql(query).queryExecution.toRdd.foreachPartition(_.foreach(_.getInterval(0)))
+ }
+ val benchmark = new Benchmark("MakeInterval", values, output = output)
+ val cometConfigs = Map(
+ CometConf.COMET_ENABLED.key -> "true",
+ CometConf.COMET_EXEC_ENABLED.key -> "true",
+ "spark.sql.optimizer.excludedRules" ->
+ "org.apache.spark.sql.catalyst.optimizer.ConstantFolding")
+
+ benchmark.addCase("Spark") { _ =>
+ withSQLConf(CometConf.COMET_ENABLED.key -> "false") {
+ consumeIntervals()
+ }
+ }
+ benchmark.addCase("Comet (codegen dispatch)") { _ =>
+ withSQLConf(cometConfigs.toSeq: _*) {
+ consumeIntervals()
+ }
+ }
+ benchmark.addCase("Comet (native)") { _ =>
+ val configs =
+ cometConfigs ++
Map(CometConf.getExprAllowIncompatConfigKey("MakeInterval") -> "true")
+ withSQLConf(configs.toSeq: _*) {
+ consumeIntervals()
+ }
+ }
+ benchmark.run()
+ }
+ }
+ }
+
override def runCometBenchmark(mainArgs: Array[String]): Unit = {
val values = 1024 * 1024;
@@ -167,6 +218,10 @@ object CometDatetimeExpressionBenchmark extends
CometBenchmarkBase {
makeTimeBenchmark(v)
}
}
+
+ runBenchmarkWithTable("MakeInterval", values) { v =>
+ makeIntervalBenchmark(v)
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]