Skip to content

Commit 74ed9ba

Browse files
committed
Display qualifiers in EXPLAIN
Sometimes we display qualifiers in plan's Display, e.g. for `Column`, but sometimes not. This adds qualifiers to output for `SubqueryAlias` and in `LogicalPlan::display_indent_schema`. Qualifiers are sometimes necessary to understand the plan semantics, especially when dealing with duplicate names, e.g. in joins.
1 parent d2f8fa5 commit 74ed9ba

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

datafusion/expr/src/expr.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3456,7 +3456,12 @@ pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
34563456
impl Display for Expr {
34573457
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
34583458
match self {
3459-
Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
3459+
Expr::Alias(Alias { expr, relation, name, .. }) => {
3460+
match relation {
3461+
None => write!(f, "{expr} AS {name}"),
3462+
Some(relation) => write!(f, "{expr} AS {relation}.{name}"),
3463+
}
3464+
},
34603465
Expr::Column(c) => write!(f, "{c}"),
34613466
Expr::OuterReferenceColumn(_, c) => {
34623467
write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")

datafusion/expr/src/logical_plan/display.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::dml::CopyTo;
3131
use arrow::datatypes::Schema;
3232
use datafusion_common::display::GraphvizBuilder;
3333
use datafusion_common::tree_node::{TreeNodeRecursion, TreeNodeVisitor};
34-
use datafusion_common::{Column, DataFusionError};
34+
use datafusion_common::{Column, DFSchema, DataFusionError};
3535
use serde_json::json;
3636

3737
/// Formats plans with a single line per node. For example:
@@ -75,7 +75,7 @@ impl<'n> TreeNodeVisitor<'n> for IndentVisitor<'_, '_> {
7575
write!(
7676
self.f,
7777
" {}",
78-
display_schema(&plan.schema().as_ref().to_owned().into())
78+
display_df_schema(&plan.schema().as_ref())
7979
)?;
8080
}
8181

@@ -92,7 +92,7 @@ impl<'n> TreeNodeVisitor<'n> for IndentVisitor<'_, '_> {
9292
}
9393
}
9494

95-
/// Print the schema in a compact representation to `buf`
95+
/// Print the schema in a compact representation
9696
///
9797
/// For example: `foo:Utf8` if `foo` can not be null, and
9898
/// `foo:Utf8;N` if `foo` is nullable.
@@ -135,6 +135,38 @@ pub fn display_schema(schema: &Schema) -> impl fmt::Display + '_ {
135135
Wrapper(schema)
136136
}
137137

138+
/// Print the schema in a compact representation.
139+
/// Similar to `display_schema`, but includes field qualifiers if any.
140+
pub fn display_df_schema(schema: &DFSchema) -> impl fmt::Display + '_ {
141+
struct Wrapper<'a>(&'a DFSchema);
142+
143+
impl fmt::Display for Wrapper<'_> {
144+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145+
write!(f, "[")?;
146+
for (idx, (qualifier, field)) in self.0.iter().enumerate() {
147+
if idx > 0 {
148+
write!(f, ", ")?;
149+
}
150+
let nullable_str = if field.is_nullable() { ";N" } else { "" };
151+
write!(
152+
f,
153+
"{}{}:{:?}{}",
154+
if let Some(q) = qualifier {
155+
format!("{q}.")
156+
} else {
157+
"".to_string()
158+
},
159+
field.name(),
160+
field.data_type(),
161+
nullable_str
162+
)?;
163+
}
164+
write!(f, "]")
165+
}
166+
}
167+
Wrapper(schema)
168+
}
169+
138170
/// Formats plans for graphical display using the `DOT` language. This
139171
/// format can be visualized using software from
140172
/// [`graphviz`](https://graphviz.org/)

0 commit comments

Comments
 (0)