Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions datafusion/optimizer/src/analyzer/type_coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,17 @@ fn extract_window_frame_target_type(col_type: &DataType) -> Result<DataType> {
Ok(DataType::Interval(IntervalUnit::MonthDayNano))
} else if let DataType::Dictionary(_, value_type) = col_type {
extract_window_frame_target_type(value_type)
} else if matches!(
col_type,
DataType::Binary | DataType::LargeBinary | DataType::BinaryView
) || matches!(col_type, DataType::FixedSizeBinary(_))
{
// Binary family types are only supported for "free" RANGE frames
// (bounds limited to UNBOUNDED PRECEDING / CURRENT ROW / UNBOUNDED
// FOLLOWING), since finite offset bounds require arithmetic on the
// order key. The coerce_window_frame function rejects finite offsets
// with a planning error.
Ok(DataType::Null)
} else {
internal_err!("Cannot run range queries on datatype: {col_type}")
}
Expand All @@ -1101,8 +1112,32 @@ fn coerce_window_frame(
.first()
.map(|s| s.expr.get_type(schema))
.transpose()?;
if let Some(col_type) = current_types {
extract_window_frame_target_type(&col_type)?
if let Some(ref col_type) = current_types {
// RANGE frames with binary ORDER BY keys only support
// "free" frames (UNBOUNDED PRECEDING / CURRENT ROW /
// UNBOUNDED FOLLOWING), since finite offset bounds require
// arithmetic on the order key (see #24327).
let is_binary = matches!(
col_type,
DataType::Binary
| DataType::LargeBinary
| DataType::BinaryView
) || matches!(col_type, DataType::FixedSizeBinary(_));
if is_binary {
let has_finite = |b: &WindowFrameBound| match b {
WindowFrameBound::Preceding(v)
| WindowFrameBound::Following(v) => !v.is_null(),
WindowFrameBound::CurrentRow => false,
};
if has_finite(&window_frame.start_bound)
|| has_finite(&window_frame.end_bound)
{
return plan_err!(
"RANGE frame with finite offset bounds is not supported for binary ORDER BY keys"
);
}
}
extract_window_frame_target_type(col_type)?
} else {
return internal_err!("ORDER BY column cannot be empty");
}
Expand Down