Skip to content
Open
Show file tree
Hide file tree
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
37 changes: 22 additions & 15 deletions datafusion/expr/src/expr_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub trait ExprSchemable {
fn nullable(&self, input_schema: &dyn ExprSchema) -> Result<bool>;

/// Given a schema, return the expr's optional metadata
#[deprecated(since = "52.0.0", note = "Use to_field() and extract metadata via FieldMetadata::from(field.metadata()) instead")]
fn metadata(&self, schema: &dyn ExprSchema) -> Result<FieldMetadata>;

/// Convert to a field with respect to a schema
Expand Down Expand Up @@ -489,7 +490,7 @@ impl ExprSchemable for Expr {
}) => {
let field = expr.to_field(schema).map(|(_, f)| f.as_ref().clone())?;

let mut combined_metadata = expr.metadata(schema)?;
let mut combined_metadata = FieldMetadata::from(field.metadata());
if let Some(metadata) = metadata {
combined_metadata.extend(metadata.clone());
}
Expand Down Expand Up @@ -1080,17 +1081,15 @@ mod tests {
.with_data_type(DataType::Int32)
.with_metadata(meta.clone());

let (_, field) = expr.to_field(&schema).unwrap();
let metadata = FieldMetadata::from(field.metadata());
// col, alias, and cast should be metadata-preserving
assert_eq!(meta, expr.metadata(&schema).unwrap());
assert_eq!(meta, expr.clone().alias("bar").metadata(&schema).unwrap());
assert_eq!(
meta,
expr.clone()
.cast_to(&DataType::Int64, &schema)
.unwrap()
.metadata(&schema)
.unwrap()
);
assert_eq!(meta, metadata);
let (_, bar_field) = expr.clone().alias("bar").to_field(&schema).unwrap();
assert_eq!(meta, FieldMetadata::from(bar_field.metadata()));
let casted_expr = expr.clone().cast_to(&DataType::Int64, &schema).unwrap();
let (_, casted_field) = casted_expr.to_field(&schema).unwrap();
assert_eq!(meta, FieldMetadata::from(casted_field.metadata()));

let schema = DFSchema::from_unqualified_fields(
vec![meta.add_to_field(Field::new("foo", DataType::Int32, true))].into(),
Expand All @@ -1099,15 +1098,17 @@ mod tests {
.unwrap();

// verify to_field method populates metadata
assert_eq!(meta, expr.metadata(&schema).unwrap());
let (_, expr_field) = expr.to_field(&schema).unwrap();
assert_eq!(meta, FieldMetadata::from(expr_field.metadata()));

// outer ref constructed by `out_ref_col_with_metadata` should be metadata-preserving
let outer_ref = out_ref_col_with_metadata(
DataType::Int32,
meta.to_hashmap(),
Column::from_name("foo"),
);
assert_eq!(meta, outer_ref.metadata(&schema).unwrap());
let (_, outer_field) = outer_ref.to_field(&schema).unwrap();
assert_eq!(meta, FieldMetadata::from(outer_field.metadata()));
}

#[test]
Expand All @@ -1131,14 +1132,20 @@ mod tests {
expr.data_type_and_nullable(&schema).unwrap(),
(DataType::Utf8, true)
);
assert_eq!(placeholder_meta, expr.metadata(&schema).unwrap());
let metadata = expr
.to_field(&schema)
.map(|(_, field)| FieldMetadata::from(field.metadata()));
assert_eq!(placeholder_meta, metadata.unwrap());

let expr_alias = expr.alias("a placeholder by any other name");
assert_eq!(
expr_alias.data_type_and_nullable(&schema).unwrap(),
(DataType::Utf8, true)
);
assert_eq!(placeholder_meta, expr_alias.metadata(&schema).unwrap());
let metadata = expr_alias
.to_field(&schema)
.map(|(_, field)| FieldMetadata::from(field.metadata()));
assert_eq!(placeholder_meta, metadata.unwrap());

// Non-nullable placeholder field should remain non-nullable
let expr = Expr::Placeholder(Placeholder::new_with_field(
Expand Down
4 changes: 3 additions & 1 deletion datafusion/expr/src/logical_plan/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,9 @@ impl LogicalPlanBuilder {
let mut common_metadata: Option<FieldMetadata> = None;
for (i, row) in values.iter().enumerate() {
let value = &row[j];
let metadata = value.metadata(&schema)?;
let metadata = value
.to_field(&schema)
.map(|(_, field)| FieldMetadata::from(field.metadata()))?;
if let Some(ref cm) = common_metadata {
if &metadata != cm {
return plan_err!("Inconsistent metadata across values list at row {i} column {j}. Was {:?} but found {:?}", cm, metadata);
Expand Down