Skip to content

Commit c397b43

Browse files
committed
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
1 parent fcb193b commit c397b43

File tree

5 files changed

+79
-45
lines changed

5 files changed

+79
-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: 32 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,11 @@ 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))?;
379+
round_trip_type(DataType::Date64)?;
363380
round_trip_type(DataType::Date32)?;
364381
round_trip_type(DataType::Date64)?;
365382
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)