Skip to content

Commit 92f646c

Browse files
authored
Add support for Arrow Time types in Substrait (#16558)
* Add support for Arrow Time types in Substrait This commit adds support for Arrow Time types Time32 and Time64 in Substrait plans. Resolves #16296 Resolves #16275 * Clean up test
1 parent 9bb309c commit 92f646c

File tree

5 files changed

+78
-45
lines changed

5 files changed

+78
-45
lines changed

datafusion/substrait/src/logical_plan/consumer/types.rs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use super::utils::{next_struct_field_name, DEFAULT_TIMEZONE};
18+
use super::utils::{from_substrait_precision, next_struct_field_name, DEFAULT_TIMEZONE};
1919
use super::SubstraitConsumer;
2020
#[allow(deprecated)]
2121
use crate::variation_const::{
@@ -27,7 +27,8 @@ use crate::variation_const::{
2727
INTERVAL_MONTH_DAY_NANO_TYPE_REF, INTERVAL_YEAR_MONTH_TYPE_REF,
2828
LARGE_CONTAINER_TYPE_VARIATION_REF, TIMESTAMP_MICRO_TYPE_VARIATION_REF,
2929
TIMESTAMP_MILLI_TYPE_VARIATION_REF, TIMESTAMP_NANO_TYPE_VARIATION_REF,
30-
TIMESTAMP_SECOND_TYPE_VARIATION_REF, UNSIGNED_INTEGER_TYPE_VARIATION_REF,
30+
TIMESTAMP_SECOND_TYPE_VARIATION_REF, TIME_32_TYPE_VARIATION_REF,
31+
TIME_64_TYPE_VARIATION_REF, UNSIGNED_INTEGER_TYPE_VARIATION_REF,
3132
VIEW_CONTAINER_TYPE_VARIATION_REF,
3233
};
3334
use datafusion::arrow::datatypes::{
@@ -107,29 +108,24 @@ pub fn from_substrait_type(
107108
}
108109
}
109110
r#type::Kind::PrecisionTimestamp(pts) => {
110-
let unit = match pts.precision {
111-
0 => Ok(TimeUnit::Second),
112-
3 => Ok(TimeUnit::Millisecond),
113-
6 => Ok(TimeUnit::Microsecond),
114-
9 => Ok(TimeUnit::Nanosecond),
115-
p => not_impl_err!(
116-
"Unsupported Substrait precision {p} for PrecisionTimestamp"
117-
),
118-
}?;
111+
let unit = from_substrait_precision(pts.precision, "PrecisionTimestamp")?;
119112
Ok(DataType::Timestamp(unit, None))
120113
}
121114
r#type::Kind::PrecisionTimestampTz(pts) => {
122-
let unit = match pts.precision {
123-
0 => Ok(TimeUnit::Second),
124-
3 => Ok(TimeUnit::Millisecond),
125-
6 => Ok(TimeUnit::Microsecond),
126-
9 => Ok(TimeUnit::Nanosecond),
127-
p => not_impl_err!(
128-
"Unsupported Substrait precision {p} for PrecisionTimestampTz"
129-
),
130-
}?;
115+
let unit =
116+
from_substrait_precision(pts.precision, "PrecisionTimestampTz")?;
131117
Ok(DataType::Timestamp(unit, Some(DEFAULT_TIMEZONE.into())))
132118
}
119+
r#type::Kind::PrecisionTime(pt) => {
120+
let time_unit = from_substrait_precision(pt.precision, "PrecisionTime")?;
121+
match pt.type_variation_reference {
122+
TIME_32_TYPE_VARIATION_REF => Ok(DataType::Time32(time_unit)),
123+
TIME_64_TYPE_VARIATION_REF => Ok(DataType::Time64(time_unit)),
124+
v => not_impl_err!(
125+
"Unsupported Substrait type variation {v} of type {s_kind:?}"
126+
),
127+
}
128+
}
133129
r#type::Kind::Date(date) => match date.type_variation_reference {
134130
DATE_32_TYPE_VARIATION_REF => Ok(DataType::Date32),
135131
DATE_64_TYPE_VARIATION_REF => Ok(DataType::Date64),
@@ -220,14 +216,9 @@ pub fn from_substrait_type(
220216
}
221217
DURATION_INTERVAL_DAY_TYPE_VARIATION_REF => {
222218
let duration_unit = match i.precision {
223-
Some(0) => Ok(TimeUnit::Second),
224-
Some(3) => Ok(TimeUnit::Millisecond),
225-
Some(6) => Ok(TimeUnit::Microsecond),
226-
Some(9) => Ok(TimeUnit::Nanosecond),
227-
p => {
228-
not_impl_err!(
229-
"Unsupported Substrait precision {p:?} for Duration"
230-
)
219+
Some(p) => from_substrait_precision(p, "Duration"),
220+
None => {
221+
not_impl_err!("Missing Substrait precision for Duration")
231222
}
232223
}?;
233224
Ok(DataType::Duration(duration_unit))

datafusion/substrait/src/logical_plan/consumer/utils.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// under the License.
1717

1818
use crate::logical_plan::consumer::SubstraitConsumer;
19-
use datafusion::arrow::datatypes::{DataType, Field, Schema, UnionFields};
19+
use datafusion::arrow::datatypes::{DataType, Field, Schema, TimeUnit, UnionFields};
2020
use datafusion::common::{
2121
exec_err, not_impl_err, substrait_datafusion_err, substrait_err, DFSchema,
2222
DFSchemaRef, TableReference,
@@ -476,6 +476,21 @@ pub async fn from_substrait_sorts(
476476
Ok(sorts)
477477
}
478478

479+
pub(crate) fn from_substrait_precision(
480+
precision: i32,
481+
type_name: &str,
482+
) -> datafusion::common::Result<TimeUnit> {
483+
match precision {
484+
0 => Ok(TimeUnit::Second),
485+
3 => Ok(TimeUnit::Millisecond),
486+
6 => Ok(TimeUnit::Microsecond),
487+
9 => Ok(TimeUnit::Nanosecond),
488+
precision => {
489+
not_impl_err!("Unsupported Substrait precision {precision}, for {type_name}")
490+
}
491+
}
492+
}
493+
479494
#[cfg(test)]
480495
pub(crate) mod tests {
481496
use super::make_renamed_schema;

datafusion/substrait/src/logical_plan/producer/types.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use crate::logical_plan::producer::to_substrait_precision;
1819
use crate::logical_plan::producer::utils::flatten_names;
1920
use crate::variation_const::{
2021
DATE_32_TYPE_VARIATION_REF, DATE_64_TYPE_VARIATION_REF,
2122
DECIMAL_128_TYPE_VARIATION_REF, DECIMAL_256_TYPE_VARIATION_REF,
2223
DEFAULT_CONTAINER_TYPE_VARIATION_REF, DEFAULT_INTERVAL_DAY_TYPE_VARIATION_REF,
2324
DEFAULT_TYPE_VARIATION_REF, DURATION_INTERVAL_DAY_TYPE_VARIATION_REF,
24-
LARGE_CONTAINER_TYPE_VARIATION_REF, UNSIGNED_INTEGER_TYPE_VARIATION_REF,
25+
LARGE_CONTAINER_TYPE_VARIATION_REF, TIME_32_TYPE_VARIATION_REF,
26+
TIME_64_TYPE_VARIATION_REF, UNSIGNED_INTEGER_TYPE_VARIATION_REF,
2527
VIEW_CONTAINER_TYPE_VARIATION_REF,
2628
};
27-
use datafusion::arrow::datatypes::{DataType, IntervalUnit, TimeUnit};
29+
use datafusion::arrow::datatypes::{DataType, IntervalUnit};
2830
use datafusion::common::{internal_err, not_impl_err, plan_err, DFSchemaRef};
2931
use substrait::proto::{r#type, NamedStruct};
3032

@@ -107,12 +109,7 @@ pub(crate) fn to_substrait_type(
107109
})),
108110
}),
109111
DataType::Timestamp(unit, tz) => {
110-
let precision = match unit {
111-
TimeUnit::Second => 0,
112-
TimeUnit::Millisecond => 3,
113-
TimeUnit::Microsecond => 6,
114-
TimeUnit::Nanosecond => 9,
115-
};
112+
let precision = to_substrait_precision(unit);
116113
let kind = match tz {
117114
None => r#type::Kind::PrecisionTimestamp(r#type::PrecisionTimestamp {
118115
type_variation_reference: DEFAULT_TYPE_VARIATION_REF,
@@ -132,6 +129,26 @@ pub(crate) fn to_substrait_type(
132129
};
133130
Ok(substrait::proto::Type { kind: Some(kind) })
134131
}
132+
DataType::Time32(unit) => {
133+
let precision = to_substrait_precision(unit);
134+
Ok(substrait::proto::Type {
135+
kind: Some(r#type::Kind::PrecisionTime(r#type::PrecisionTime {
136+
precision,
137+
type_variation_reference: TIME_32_TYPE_VARIATION_REF,
138+
nullability,
139+
})),
140+
})
141+
}
142+
DataType::Time64(unit) => {
143+
let precision = to_substrait_precision(unit);
144+
Ok(substrait::proto::Type {
145+
kind: Some(r#type::Kind::PrecisionTime(r#type::PrecisionTime {
146+
precision,
147+
type_variation_reference: TIME_64_TYPE_VARIATION_REF,
148+
nullability,
149+
})),
150+
})
151+
}
135152
DataType::Date32 => Ok(substrait::proto::Type {
136153
kind: Some(r#type::Kind::Date(r#type::Date {
137154
type_variation_reference: DATE_32_TYPE_VARIATION_REF,
@@ -173,12 +190,7 @@ pub(crate) fn to_substrait_type(
173190
}
174191
}
175192
DataType::Duration(duration_unit) => {
176-
let precision = match duration_unit {
177-
TimeUnit::Second => 0,
178-
TimeUnit::Millisecond => 3,
179-
TimeUnit::Microsecond => 6,
180-
TimeUnit::Nanosecond => 9,
181-
};
193+
let precision = to_substrait_precision(duration_unit);
182194
Ok(substrait::proto::Type {
183195
kind: Some(r#type::Kind::IntervalDay(r#type::IntervalDay {
184196
type_variation_reference: DURATION_INTERVAL_DAY_TYPE_VARIATION_REF,
@@ -335,7 +347,7 @@ mod tests {
335347
use crate::logical_plan::consumer::{
336348
from_substrait_named_struct, from_substrait_type_without_names,
337349
};
338-
use datafusion::arrow::datatypes::{Field, Fields, Schema};
350+
use datafusion::arrow::datatypes::{Field, Fields, Schema, TimeUnit};
339351
use datafusion::common::{DFSchema, Result};
340352
use std::sync::Arc;
341353

@@ -360,6 +372,10 @@ mod tests {
360372
round_trip_type(DataType::Timestamp(TimeUnit::Nanosecond, tz))?;
361373
}
362374

375+
round_trip_type(DataType::Time32(TimeUnit::Second))?;
376+
round_trip_type(DataType::Time32(TimeUnit::Millisecond))?;
377+
round_trip_type(DataType::Time64(TimeUnit::Microsecond))?;
378+
round_trip_type(DataType::Time64(TimeUnit::Nanosecond))?;
363379
round_trip_type(DataType::Date32)?;
364380
round_trip_type(DataType::Date64)?;
365381
round_trip_type(DataType::Binary)?;

datafusion/substrait/src/logical_plan/producer/utils.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// under the License.
1717

1818
use crate::logical_plan::producer::SubstraitProducer;
19-
use datafusion::arrow::datatypes::{DataType, Field};
19+
use datafusion::arrow::datatypes::{DataType, Field, TimeUnit};
2020
use datafusion::common::{plan_err, DFSchemaRef};
2121
use datafusion::logical_expr::SortExpr;
2222
use substrait::proto::sort_field::{SortDirection, SortKind};
@@ -76,3 +76,12 @@ pub(crate) fn substrait_sort_field(
7676
sort_kind: Some(SortKind::Direction(d as i32)),
7777
})
7878
}
79+
80+
pub(crate) fn to_substrait_precision(time_unit: &TimeUnit) -> i32 {
81+
match time_unit {
82+
TimeUnit::Second => 0,
83+
TimeUnit::Millisecond => 3,
84+
TimeUnit::Microsecond => 6,
85+
TimeUnit::Nanosecond => 9,
86+
}
87+
}

datafusion/substrait/src/variation_const.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ pub const TIMESTAMP_NANO_TYPE_VARIATION_REF: u32 = 3;
5050

5151
pub const DATE_32_TYPE_VARIATION_REF: u32 = 0;
5252
pub const DATE_64_TYPE_VARIATION_REF: u32 = 1;
53+
pub const TIME_32_TYPE_VARIATION_REF: u32 = 0;
54+
pub const TIME_64_TYPE_VARIATION_REF: u32 = 1;
5355
pub const DEFAULT_CONTAINER_TYPE_VARIATION_REF: u32 = 0;
5456
pub const LARGE_CONTAINER_TYPE_VARIATION_REF: u32 = 1;
5557
pub const VIEW_CONTAINER_TYPE_VARIATION_REF: u32 = 2;

0 commit comments

Comments
 (0)