MCPcopy Create free account
hub / github.com/apache/datafusion / requalify_sides_if_needed

Function requalify_sides_if_needed

datafusion/expr/src/logical_plan/builder.rs:1775–1835  ·  view source on GitHub ↗

(Re)qualify the sides of a join if needed, i.e. if the columns from one side would otherwise conflict with the columns from the other. This is especially useful for queries that come as Substrait, since Substrait doesn't currently allow specifying aliases, neither for columns nor for tables. DataFusion requires columns to be uniquely identifiable, in some places (see e.g. DFSchema::check_names).

(
    left: LogicalPlanBuilder,
    right: LogicalPlanBuilder,
)

Source from the content-addressed store, hash-verified

1773/// - The requalified or original right logical plan
1774/// - If a requalification was needed or not
1775pub fn requalify_sides_if_needed(
1776 left: LogicalPlanBuilder,
1777 right: LogicalPlanBuilder,
1778) -> Result<(LogicalPlanBuilder, LogicalPlanBuilder, bool)> {
1779 let left_cols = left.schema().columns();
1780 let right_cols = right.schema().columns();
1781
1782 // Requalify if merging the schemas would cause an error during join.
1783 // This can happen in several cases:
1784 // 1. Duplicate qualified fields: both sides have same relation.name
1785 // 2. Duplicate unqualified fields: both sides have same unqualified name
1786 // 3. Ambiguous reference: one side qualified, other unqualified, same name
1787 //
1788 // Implementation note: This uses a simple O(n*m) nested loop rather than
1789 // a HashMap-based O(n+m) approach. The nested loop is preferred because:
1790 // - Schemas are typically small (in TPCH benchmark, max is 16 columns),
1791 // so n*m is negligible
1792 // - Early return on first conflict makes common case very fast
1793 // - Code is simpler and easier to reason about
1794 // - Called only during plan construction, not in execution hot path
1795 for l in &left_cols {
1796 for r in &right_cols {
1797 if l.name != r.name {
1798 continue;
1799 }
1800
1801 // Same name - check if this would cause a conflict
1802 match (&l.relation, &r.relation) {
1803 // Both qualified with same relation - duplicate qualified field
1804 (Some(l_rel), Some(r_rel)) if l_rel == r_rel => {
1805 return Ok((
1806 left.alias(TableReference::bare("left"))?,
1807 right.alias(TableReference::bare("right"))?,
1808 true,
1809 ));
1810 }
1811 // Both unqualified - duplicate unqualified field
1812 (None, None) => {
1813 return Ok((
1814 left.alias(TableReference::bare("left"))?,
1815 right.alias(TableReference::bare("right"))?,
1816 true,
1817 ));
1818 }
1819 // One qualified, one not - ambiguous reference
1820 (Some(_), None) | (None, Some(_)) => {
1821 return Ok((
1822 left.alias(TableReference::bare("left"))?,
1823 right.alias(TableReference::bare("right"))?,
1824 true,
1825 ));
1826 }
1827 // Different qualifiers - OK, no conflict
1828 _ => {}
1829 }
1830 }
1831 }
1832

Callers 4

intersect_or_exceptMethod · 0.85
from_join_relFunction · 0.85
from_cross_relFunction · 0.85

Calls 3

columnsMethod · 0.80
schemaMethod · 0.45
aliasMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…