You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CREATETABLEt (a duration);
This feature is not implemented: Unsupported SQL type Custom(ObjectName([Identifier(Ident { value: "duration", quote_style: None, span: Span(Location(1,19)..Location(1,27)) })]), [])
but you can indirectly create a table with a duration column type
> CREATE TABLE t ASSELECT'2023-03-15T15:00:20.000000123'::timestamp-'2023-01-20T23:00:00.000000099'::timestamp;
0 row(s) fetched.
Elapsed 0.009 seconds.
> SHOW COLUMNS FROM t;
+---------------+--------------+------------+-------------------------------------------------------------------------------+----------------------+-------------+
| table_catalog | table_schema | table_name | column_name | data_type | is_nullable |
+---------------+--------------+------------+-------------------------------------------------------------------------------+----------------------+-------------+
| datafusion | public | t | Utf8("2023-03-15T15:00:20.000000123") - Utf8("2023-01-20T23:00:00.000000099") | Duration(Nanosecond) | NO |
+---------------+--------------+------------+-------------------------------------------------------------------------------+----------------------+-------------+1 row(s) fetched.
Elapsed 0.010 seconds.
and as shown above, some expressions return a duration.
One solution would be for Datafusion to stop using Duration and stick to Interval. There has been recent work to add more support for Durations, so I don't think this is desirable:
The other solution would be to add suport for casting Arrow Duration types to Substrait. There's probably multiple approaches to this:
Use INTERVAL_COMPOUND<P> (or maybe INTERVAL_DAY<P> is enough). This would be a lossy conversion, because the round trip would look like Arrow Duration -> Substrait Interval -> Arrow Interval.
Use some type of user defined type, STRUCT, or NSTRUCT.
If you follow a couple of GH links it brings you here: apache/arrow#40695. The specific use case is where arrow is both the source and destination, so it's OK to roundtrip the type through an opaque UDT. However, one of Datafusion's stated goals is "Use DataFusion to create plans to run on other systems" (https://docs.rs/datafusion-substrait/latest/datafusion_substrait/) which wouldn't work that well with UDT unless the other system understood the UDT we created.
I think using a type variation reference as you did in #16503 is a good solution to this. I see that this is a similar approach taken for the DataType::Decimal128 and DataType::Decimal256 types, so it seems consistent with what we are already doing
Activity
jkosh44 commentedon Jun 6, 2025
take
jkosh44 commentedon Jun 6, 2025
The query that fails looks like
Subtracting two timestamps returns a duration type.
There is no duration type in substrait (https://substrait.io/types/type_classes/), so the cast from arrow to substrate fails:
datafusion/datafusion/substrait/src/logical_plan/producer/types.rs
Lines 30 to 289 in 4cf1148
Interestingly, Duration doesn't really seem to be a fully supported data type by Datafusion. It's not listed as a supported SQL datatype: https://datafusion.apache.org/user-guide/sql/data_types.html#date-time-types. You can't directly create a table with a duration column type:
but you can indirectly create a table with a duration column type
and as shown above, some expressions return a duration.
One solution would be for Datafusion to stop using Duration and stick to Interval. There has been recent work to add more support for Durations, so I don't think this is desirable:
AVGfor durations #15458The other solution would be to add suport for casting Arrow Duration types to Substrait. There's probably multiple approaches to this:
INTERVAL_COMPOUND<P>(or maybeINTERVAL_DAY<P>is enough). This would be a lossy conversion, because the round trip would look like Arrow Duration -> Substrait Interval -> Arrow Interval.STRUCT, orNSTRUCT.jkosh44 commentedon Jun 6, 2025
Of course, yet another solution would be to add the Duration type to substrait, but they'd need to be interested in doing that.
jkosh44 commentedon Jun 7, 2025
The arrow C++ substrait library also doesn't support Durations, but they have a comment about using UDTs to support them: https://github.com/apache/arrow/blob/1d169cc90f65be6ee0bb1fcc03b4f22cf99be897/cpp/src/arrow/engine/substrait/type_internal.cc#L444-L445.
If you follow a couple of GH links it brings you here: apache/arrow#40695. The specific use case is where arrow is both the source and destination, so it's OK to roundtrip the type through an opaque UDT. However, one of Datafusion's stated goals is "Use DataFusion to create plans to run on other systems" (https://docs.rs/datafusion-substrait/latest/datafusion_substrait/) which wouldn't work that well with UDT unless the other system understood the UDT we created.
Add support for Arrow Duration type in Substrait
Add support for Arrow Duration type in Substrait
Add support for Arrow Duration type in Substrait
Add support for Arrow Duration type in Substrait
Add support for Arrow Duration type in Substrait
gabotechs commentedon Jun 24, 2025
I think using a type variation reference as you did in #16503 is a good solution to this. I see that this is a similar approach taken for the
DataType::Decimal128andDataType::Decimal256types, so it seems consistent with what we are already doingAdd support for Arrow Duration type in Substrait (apache#16503)