in datafusion/expr/src/expr.rs [1307:1565]
fn create_name(e: &Expr) -> Result<String> {
match e {
Expr::Alias(Alias { name, .. }) => Ok(name.clone()),
Expr::Column(c) => Ok(c.flat_name()),
Expr::OuterReferenceColumn(_, c) => Ok(format!("outer_ref({})", c.flat_name())),
Expr::ScalarVariable(_, variable_names) => Ok(variable_names.join(".")),
Expr::Literal(value) => Ok(format!("{value:?}")),
Expr::BinaryExpr(binary_expr) => {
let left = create_name(binary_expr.left.as_ref())?;
let right = create_name(binary_expr.right.as_ref())?;
Ok(format!("{} {} {}", left, binary_expr.op, right))
}
Expr::Like(Like {
negated,
expr,
pattern,
escape_char,
case_insensitive,
}) => {
let s = format!(
"{} {}{} {} {}",
expr,
if *negated { "NOT " } else { "" },
if *case_insensitive { "ILIKE" } else { "LIKE" },
pattern,
if let Some(char) = escape_char {
format!("CHAR '{char}'")
} else {
"".to_string()
}
);
Ok(s)
}
Expr::SimilarTo(Like {
negated,
expr,
pattern,
escape_char,
case_insensitive: _,
}) => {
let s = format!(
"{} {} {} {}",
expr,
if *negated {
"NOT SIMILAR TO"
} else {
"SIMILAR TO"
},
pattern,
if let Some(char) = escape_char {
format!("CHAR '{char}'")
} else {
"".to_string()
}
);
Ok(s)
}
Expr::Case(case) => {
let mut name = "CASE ".to_string();
if let Some(e) = &case.expr {
let e = create_name(e)?;
let _ = write!(name, "{e} ");
}
for (w, t) in &case.when_then_expr {
let when = create_name(w)?;
let then = create_name(t)?;
let _ = write!(name, "WHEN {when} THEN {then} ");
}
if let Some(e) = &case.else_expr {
let e = create_name(e)?;
let _ = write!(name, "ELSE {e} ");
}
name += "END";
Ok(name)
}
Expr::Cast(Cast { expr, .. }) => {
// CAST does not change the expression name
create_name(expr)
}
Expr::TryCast(TryCast { expr, .. }) => {
// CAST does not change the expression name
create_name(expr)
}
Expr::Not(expr) => {
let expr = create_name(expr)?;
Ok(format!("NOT {expr}"))
}
Expr::Negative(expr) => {
let expr = create_name(expr)?;
Ok(format!("(- {expr})"))
}
Expr::IsNull(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS NULL"))
}
Expr::IsNotNull(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS NOT NULL"))
}
Expr::IsTrue(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS TRUE"))
}
Expr::IsFalse(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS FALSE"))
}
Expr::IsUnknown(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS UNKNOWN"))
}
Expr::IsNotTrue(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS NOT TRUE"))
}
Expr::IsNotFalse(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS NOT FALSE"))
}
Expr::IsNotUnknown(expr) => {
let expr = create_name(expr)?;
Ok(format!("{expr} IS NOT UNKNOWN"))
}
Expr::Exists(Exists { negated: true, .. }) => Ok("NOT EXISTS".to_string()),
Expr::Exists(Exists { negated: false, .. }) => Ok("EXISTS".to_string()),
Expr::InSubquery(InSubquery { negated: true, .. }) => Ok("NOT IN".to_string()),
Expr::InSubquery(InSubquery { negated: false, .. }) => Ok("IN".to_string()),
Expr::ScalarSubquery(subquery) => {
Ok(subquery.subquery.schema().field(0).name().clone())
}
Expr::GetIndexedField(GetIndexedField { expr, field }) => {
let expr = create_name(expr)?;
match field {
GetFieldAccess::NamedStructField { name } => {
Ok(format!("{expr}[{name}]"))
}
GetFieldAccess::ListIndex { key } => {
let key = create_name(key)?;
Ok(format!("{expr}[{key}]"))
}
GetFieldAccess::ListRange { start, stop } => {
let start = create_name(start)?;
let stop = create_name(stop)?;
Ok(format!("{expr}[{start}:{stop}]"))
}
}
}
Expr::ScalarFunction(func) => {
create_function_name(&func.fun.to_string(), false, &func.args)
}
Expr::ScalarUDF(ScalarUDF { fun, args }) => {
create_function_name(&fun.name, false, args)
}
Expr::WindowFunction(WindowFunction {
fun,
args,
window_frame,
partition_by,
order_by,
}) => {
let mut parts: Vec<String> =
vec![create_function_name(&fun.to_string(), false, args)?];
if !partition_by.is_empty() {
parts.push(format!("PARTITION BY [{}]", expr_vec_fmt!(partition_by)));
}
if !order_by.is_empty() {
parts.push(format!("ORDER BY [{}]", expr_vec_fmt!(order_by)));
}
parts.push(format!("{window_frame}"));
Ok(parts.join(" "))
}
Expr::AggregateFunction(AggregateFunction {
fun,
distinct,
args,
filter,
order_by,
}) => {
let mut name = create_function_name(&fun.to_string(), *distinct, args)?;
if let Some(fe) = filter {
name = format!("{name} FILTER (WHERE {fe})");
};
if let Some(order_by) = order_by {
name = format!("{name} ORDER BY [{}]", expr_vec_fmt!(order_by));
};
Ok(name)
}
Expr::AggregateUDF(AggregateUDF {
fun,
args,
filter,
order_by,
}) => {
let mut names = Vec::with_capacity(args.len());
for e in args {
names.push(create_name(e)?);
}
let mut info = String::new();
if let Some(fe) = filter {
info += &format!(" FILTER (WHERE {fe})");
}
if let Some(ob) = order_by {
info += &format!(" ORDER BY ([{}])", expr_vec_fmt!(ob));
}
Ok(format!("{}({}){}", fun.name, names.join(","), info))
}
Expr::GroupingSet(grouping_set) => match grouping_set {
GroupingSet::Rollup(exprs) => {
Ok(format!("ROLLUP ({})", create_names(exprs.as_slice())?))
}
GroupingSet::Cube(exprs) => {
Ok(format!("CUBE ({})", create_names(exprs.as_slice())?))
}
GroupingSet::GroupingSets(lists_of_exprs) => {
let mut list_of_names = vec![];
for exprs in lists_of_exprs {
list_of_names.push(format!("({})", create_names(exprs.as_slice())?));
}
Ok(format!("GROUPING SETS ({})", list_of_names.join(", ")))
}
},
Expr::InList(InList {
expr,
list,
negated,
}) => {
let expr = create_name(expr)?;
let list = list.iter().map(create_name);
if *negated {
Ok(format!("{expr} NOT IN ({list:?})"))
} else {
Ok(format!("{expr} IN ({list:?})"))
}
}
Expr::Between(Between {
expr,
negated,
low,
high,
}) => {
let expr = create_name(expr)?;
let low = create_name(low)?;
let high = create_name(high)?;
if *negated {
Ok(format!("{expr} NOT BETWEEN {low} AND {high}"))
} else {
Ok(format!("{expr} BETWEEN {low} AND {high}"))
}
}
Expr::Sort { .. } => Err(DataFusionError::Internal(
"Create name does not support sort expression".to_string(),
)),
Expr::Wildcard => Ok("*".to_string()),
Expr::QualifiedWildcard { .. } => Err(DataFusionError::Internal(
"Create name does not support qualified wildcard".to_string(),
)),
Expr::Placeholder(Placeholder { id, .. }) => Ok((*id).to_string()),
}
}