Skip to content

Commit bad7348

Browse files
committed
remove specialize logic
1 parent f585136 commit bad7348

File tree

4 files changed

+51
-28
lines changed

4 files changed

+51
-28
lines changed

datafusion/common/src/types/builtin.rs

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

18+
use arrow_schema::TimeUnit;
19+
1820
use crate::types::{LogicalTypeRef, NativeType};
1921
use std::sync::{Arc, LazyLock};
2022

@@ -47,3 +49,11 @@ singleton!(LOGICAL_FLOAT64, logical_float64, Float64);
4749
singleton!(LOGICAL_DATE, logical_date, Date);
4850
singleton!(LOGICAL_BINARY, logical_binary, Binary);
4951
singleton!(LOGICAL_STRING, logical_string, String);
52+
53+
// TODO: Extend macro
54+
// TODO: Should we use LOGICAL_TIMESTAMP_NANO to distinguish unit and timzeone?
55+
static LOGICAL_TIMESTAMP: LazyLock<LogicalTypeRef> =
56+
LazyLock::new(|| Arc::new(NativeType::Timestamp(TimeUnit::Nanosecond, None)));
57+
pub fn logical_timestamp() -> LogicalTypeRef {
58+
Arc::clone(&LOGICAL_TIMESTAMP)
59+
}

datafusion/expr-common/src/signature.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ use std::num::NonZeroUsize;
2424

2525
use crate::type_coercion::aggregates::NUMERICS;
2626
use arrow::datatypes::{DataType, IntervalUnit, TimeUnit};
27-
use datafusion_common::types::{LogicalType, LogicalTypeRef, NativeType};
28-
use datafusion_common::Result;
27+
use datafusion_common::types::{
28+
logical_timestamp, LogicalType, LogicalTypeRef, NativeType,
29+
};
30+
use datafusion_common::{not_impl_err, Result};
2931
use indexmap::IndexSet;
3032
use itertools::Itertools;
3133

@@ -230,24 +232,40 @@ impl Display for TypeSignatureClass {
230232
}
231233

232234
impl TypeSignatureClass {
233-
/// Return the default casted type for the given `TypeSignatureClass`
234-
/// We return the largest common type for the given `TypeSignatureClass`
235+
/// Returns the default cast type for the given `TypeSignatureClass`.
236+
/// Be cautious to avoid adding specialized logic here, as this function is public and intended for general use.
235237
pub fn default_casted_type(
236238
&self,
237239
logical_type: &NativeType,
238-
data_type: &DataType,
240+
origin_type: &DataType,
239241
) -> Result<DataType> {
240-
Ok(match self {
241-
// TODO: Able to elimnate this special case?
242-
// Not consistent with Postgres and DuckDB but to avoid regression we implicit cast string to timestamp
243-
TypeSignatureClass::Timestamp if logical_type == &NativeType::String => {
244-
DataType::Timestamp(TimeUnit::Nanosecond, None)
245-
}
242+
match self {
246243
TypeSignatureClass::Native(logical_type) => {
247-
return logical_type.native().default_cast_for(data_type)
244+
logical_type.native().default_cast_for(origin_type)
245+
}
246+
// If the given type is already a timestamp, we don't change the unit and timezone
247+
TypeSignatureClass::Timestamp if logical_type.is_timestamp() => {
248+
Ok(origin_type.to_owned())
249+
}
250+
TypeSignatureClass::Timestamp => {
251+
// TODO: Consider allowing the user to specify the default timestamp type instead of having it predefined in DataFusion when we have such use case
252+
// Use default timestamp type with nanosecond precision and no timezone
253+
logical_timestamp().default_cast_for(origin_type)
254+
}
255+
TypeSignatureClass::Date if logical_type.is_date() => {
256+
Ok(origin_type.to_owned())
248257
}
249-
_ => data_type.clone(),
250-
})
258+
TypeSignatureClass::Time if logical_type.is_time() => {
259+
Ok(origin_type.to_owned())
260+
}
261+
TypeSignatureClass::Interval if logical_type.is_interval() => {
262+
Ok(origin_type.to_owned())
263+
}
264+
TypeSignatureClass::Duration if logical_type.is_duration() => {
265+
Ok(origin_type.to_owned())
266+
}
267+
_ => not_impl_err!("Other cases are not implemented yet"),
268+
}
251269
}
252270
}
253271

datafusion/expr/src/type_coercion/functions.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -605,21 +605,14 @@ fn get_valid_types(
605605
target_type: &TypeSignatureClass,
606606
logical_type: &NativeType,
607607
) -> bool {
608+
if logical_type == &NativeType::Null {
609+
return true;
610+
}
611+
608612
match target_type {
609613
TypeSignatureClass::Native(t) if t.native() == logical_type => {
610614
true
611615
}
612-
TypeSignatureClass::Native(_)
613-
if logical_type == &NativeType::Null =>
614-
{
615-
true
616-
}
617-
// Not consistent with Postgres and DuckDB but to avoid regression we implicit cast string to timestamp
618-
TypeSignatureClass::Timestamp
619-
if logical_type == &NativeType::String =>
620-
{
621-
true
622-
}
623616
TypeSignatureClass::Timestamp if logical_type.is_timestamp() => {
624617
true
625618
}
@@ -636,8 +629,7 @@ fn get_valid_types(
636629
}
637630
}
638631

639-
if is_matched_type(&param.desired_type, &current_logical_type)
640-
|| param
632+
if is_matched_type(&param.desired_type, &current_logical_type) || param
641633
.allowed_casts
642634
.iter()
643635
.any(|t| is_matched_type(t, &current_logical_type))

datafusion/functions/src/datetime/date_part.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ impl DatePartFunc {
102102
},
103103
Coercion {
104104
desired_type: TypeSignatureClass::Timestamp,
105-
allowed_casts: vec![],
105+
// Not consistent with Postgres and DuckDB but to avoid regression we implicit cast string to timestamp
106+
allowed_casts: vec![TypeSignatureClass::Native(
107+
logical_string(),
108+
)],
106109
},
107110
]),
108111
TypeSignature::CoercibleV2(vec![

0 commit comments

Comments
 (0)