Skip to content

Commit ce907c0

Browse files
authored
Merge pull request #124 from Embucket/df55-alias-single-field
Avoid resolving aliased expression fields twice
2 parents 3ba51ea + 9655ca8 commit ce907c0

1 file changed

Lines changed: 51 additions & 5 deletions

File tree

‎datafusion/expr/src/expr_schema.rs‎

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -520,15 +520,13 @@ impl ExprSchemable for Expr {
520520
metadata,
521521
..
522522
}) => {
523-
let mut combined_metadata = expr.metadata(schema)?;
523+
let field = expr.to_field(schema)?.1;
524+
let mut combined_metadata = FieldMetadata::from(field.metadata());
524525
if let Some(metadata) = metadata {
525526
combined_metadata.extend(metadata.clone());
526527
}
527528

528-
Ok(expr
529-
.to_field(schema)
530-
.map(|(_, f)| f)?
531-
.with_field_metadata(&combined_metadata))
529+
Ok(field.with_field_metadata(&combined_metadata))
532530
}
533531
Expr::Negative(expr) => expr.to_field(schema).map(|(_, f)| f),
534532
Expr::Column(c) => schema.field_from_column(c).map(Arc::clone),
@@ -1150,6 +1148,54 @@ mod tests {
11501148
assert_eq!(expr.metadata(&schema).unwrap(), alias_metadata);
11511149
}
11521150

1151+
#[test]
1152+
fn test_nested_alias_resolves_child_field_once() -> Result<()> {
1153+
#[derive(Debug)]
1154+
struct CountingSchema {
1155+
field: FieldRef,
1156+
lookups: std::cell::Cell<usize>,
1157+
}
1158+
1159+
impl ExprSchema for CountingSchema {
1160+
fn nullable(&self, _col: &Column) -> Result<bool> {
1161+
Ok(self.field.is_nullable())
1162+
}
1163+
1164+
fn field_from_column(&self, _col: &Column) -> Result<&FieldRef> {
1165+
self.lookups.set(self.lookups.get() + 1);
1166+
Ok(&self.field)
1167+
}
1168+
}
1169+
1170+
let schema = CountingSchema {
1171+
field: Arc::new(Field::new("value", DataType::Int32, false).with_metadata(
1172+
HashMap::from([
1173+
("override".to_string(), "base".to_string()),
1174+
("keep".to_string(), "base".to_string()),
1175+
]),
1176+
)),
1177+
lookups: std::cell::Cell::new(0),
1178+
};
1179+
let mut expr = col("value");
1180+
for index in 0..12 {
1181+
let Expr::Alias(alias) = expr.alias(format!("alias_{index}")) else {
1182+
unreachable!();
1183+
};
1184+
expr = Expr::Alias(alias.with_metadata(Some(FieldMetadata::from(
1185+
HashMap::from([("override".to_string(), index.to_string())]),
1186+
))));
1187+
}
1188+
1189+
let field = expr.to_field(&schema)?.1;
1190+
assert_eq!(schema.lookups.get(), 1);
1191+
assert_eq!(field.name(), "alias_11");
1192+
assert_eq!(field.data_type(), &DataType::Int32);
1193+
assert!(!field.is_nullable());
1194+
assert_eq!(field.metadata().get("override"), Some(&"11".to_string()));
1195+
assert_eq!(field.metadata().get("keep"), Some(&"base".to_string()));
1196+
Ok(())
1197+
}
1198+
11531199
#[test]
11541200
fn test_expr_placeholder() {
11551201
let schema = MockExprSchema::new();

0 commit comments

Comments
 (0)