Skip to content

Commit df8a9a2

Browse files
adriangbclaude
andcommitted
docs: clarify resolve_against and the pass-through comparison
Address review: describe resolve_against as an action, and name the two column sets the merge compares instead of calling them sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 53a8458 commit df8a9a2

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

‎datafusion/optimizer/src/extract_leaf_expressions.rs‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -637,12 +637,13 @@ impl<'a> LeafExpressionExtractor<'a> {
637637
}
638638
}
639639

640-
/// The way `schema` names `col`, or `None` when `schema` does not hold it
641-
/// or the name is ambiguous.
640+
/// Resolves `col` against `schema` and returns it with the qualifier that
641+
/// `schema` gives the field. Returns `None` if `schema` does not hold `col`,
642+
/// or if the name is ambiguous in `schema`.
642643
///
643-
/// The result always carries the qualifier the schema gives the field, so
644-
/// two spellings of the same input column compare equal, and a column pushed
645-
/// into a projection reads as the input spells it.
644+
/// Two spellings of the same input column (a bare `c` and a qualified `t.c`)
645+
/// resolve to the same `Column`, so they compare equal. A column pushed into
646+
/// a projection this way uses the name that the input gives it.
646647
fn resolve_against(schema: &DFSchema, col: &Column) -> Option<Column> {
647648
schema
648649
.qualified_field_from_column(col)
@@ -716,11 +717,17 @@ fn build_extraction_projection_impl(
716717
// by alias expressions (e.g., CSE's __common_expr_N) exist in the output but
717718
// not the input, and cannot be added as pass-through Column references.
718719
//
719-
// Compare both sides in the input's spelling (see `resolve_against`).
720-
// Without this, a bare `c` and a qualified `t.c` do not match, and the
721-
// merged projection holds both, which `Projection::try_new` rejects as
722-
// ambiguous. Eliminating the empty side of a union makes this shape.
723-
// A same-name alias (`t.c AS c`) counts as a pass-through of `t.c`.
720+
// Resolve the pass-through columns of `existing` and the columns in
721+
// `columns_needed` against the input schema before comparing them (see
722+
// `resolve_against`). Without this, a bare `c` in one set and a
723+
// qualified `t.c` in the other do not match, so the merged projection
724+
// holds both, and `Projection::try_new` rejects it as ambiguous.
725+
//
726+
// This shape occurs when the optimizer removes the empty input of a
727+
// `UNION ALL` (for example `... UNION ALL SELECT ... WHERE 1 = 2`): the
728+
// projection that remains lists bare column names over a qualified
729+
// input. A same-name alias (`t.c AS c`) counts as a pass-through of
730+
// `t.c`.
724731
let input_schema = existing.input.schema();
725732
let existing_cols: IndexSet<Column> = existing
726733
.expr

0 commit comments

Comments
 (0)