Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/expr/src/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use crate::{
};

pub use crate::explain::text::{
HumanizedExplain, HumanizedExpr, HumanizedNotice, HumanizerMode, fmt_text_constant_rows,
HumanizeDisplay, HumanizedExplain, HumanizedExpr, HumanizedNotice, HumanizerMode,
fmt_text_constant_rows,
};

mod json;
Expand Down
91 changes: 52 additions & 39 deletions src/expr/src/explain/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! `EXPLAIN ... AS TEXT` support for structures defined in this crate.

use std::collections::BTreeMap;
use std::fmt;
use std::fmt::{self, Display as _};
use std::sync::Arc;

use itertools::Itertools;
Expand All @@ -28,7 +28,7 @@ use mz_sql_parser::ast::Ident;
use crate::explain::{ExplainMultiPlan, ExplainSinglePlan};
use crate::{
AccessStrategy, AggregateExpr, EvalError, Id, JoinImplementation, JoinInputCharacteristics,
LocalId, MapFilterProject, MirRelationExpr, MirScalarExpr, RowSetFinishing,
LocalId, MapFilterProject, MirRelationExpr, MirScalarExpr, OptimizableExpr, RowSetFinishing,
};

impl<'a, T: 'a> DisplayText for ExplainSinglePlan<'a, T>
Expand Down Expand Up @@ -223,10 +223,11 @@ where
}
}

impl<'a, C, M> DisplayText<C> for HumanizedExpr<'a, MapFilterProject, M>
impl<'a, C, M, E> DisplayText<C> for HumanizedExpr<'a, MapFilterProject<E>, M>
where
C: AsMut<Indent>,
M: HumanizerMode,
E: OptimizableExpr + HumanizeDisplay,
{
fn fmt_text(&self, f: &mut fmt::Formatter<'_>, ctx: &mut C) -> fmt::Result {
let (scalars, predicates, outputs, input_arity) = (
Expand Down Expand Up @@ -258,7 +259,9 @@ where
}
}

impl<'a, M: HumanizerMode> HumanizedExpr<'a, MapFilterProject, M> {
impl<'a, M: HumanizerMode, E: OptimizableExpr + HumanizeDisplay>
HumanizedExpr<'a, MapFilterProject<E>, M>
{
/// Render an MFP using the default (concise) syntax.
pub fn fmt_default_text<T>(
&self,
Expand Down Expand Up @@ -1246,7 +1249,10 @@ where
}
}

impl<'a, M> ScalarOps for HumanizedExpr<'a, MirScalarExpr, M> {
impl<'a, T, M> ScalarOps for HumanizedExpr<'a, T, M>
where
T: ScalarOps,
{
fn match_col_ref(&self) -> Option<usize> {
self.expr.match_col_ref()
}
Expand All @@ -1256,57 +1262,54 @@ impl<'a, M> ScalarOps for HumanizedExpr<'a, MirScalarExpr, M> {
}
}

impl<'a, M> ScalarOps for HumanizedExpr<'a, usize, M> {
fn match_col_ref(&self) -> Option<usize> {
Some(*self.expr)
}

fn references(&self, col_ref: usize) -> bool {
col_ref == *self.expr
}
pub trait HumanizeDisplay: Sized {
fn humanize<'a, M: HumanizerMode>(
e: &HumanizedExpr<'a, Self, M>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result;
}

impl<'a, M> fmt::Display for HumanizedExpr<'a, MirScalarExpr, M>
where
M: HumanizerMode,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl HumanizeDisplay for MirScalarExpr {
fn humanize<'a, M: HumanizerMode>(
e: &HumanizedExpr<'a, MirScalarExpr, M>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
use MirScalarExpr::*;

match self.expr {
match e.expr {
Column(i, TreatAsEqual(None)) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation (plain column reference).
self.child(i).fmt(f)
e.child(i).fmt(f)
}
Column(i, TreatAsEqual(Some(name))) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation (with stored name information)
self.child(&(i, name)).fmt(f)
e.child(&(i, name)).fmt(f)
}
Literal(row, _) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation.
self.child(row).fmt(f)
e.child(row).fmt(f)
}
CallUnmaterializable(func) => write!(f, "{}()", func),
CallUnary { func, expr } => {
if let crate::UnaryFunc::Not(_) = *func {
if let CallUnary { func, expr } = expr.as_ref() {
if let Some(is) = func.is() {
let expr = self.child::<MirScalarExpr>(&*expr);
let expr = e.child::<MirScalarExpr>(&*expr);
return write!(f, "({}) IS NOT {}", expr, is);
}
}
}
if let Some(is) = func.is() {
let expr = self.child::<MirScalarExpr>(&*expr);
let expr = e.child::<MirScalarExpr>(&*expr);
write!(f, "({}) IS {}", expr, is)
} else {
let expr = self.child::<MirScalarExpr>(&*expr);
let expr = e.child::<MirScalarExpr>(&*expr);
write!(f, "{}({})", func, expr)
}
}
CallBinary { func, expr1, expr2 } => {
let expr1 = self.child::<MirScalarExpr>(&*expr1);
let expr2 = self.child::<MirScalarExpr>(&*expr2);
let expr1 = e.child::<MirScalarExpr>(&*expr1);
let expr2 = e.child::<MirScalarExpr>(&*expr2);
if func.is_infix_op() {
write!(f, "({} {} {})", expr1, func, expr2)
} else {
Expand All @@ -1317,55 +1320,65 @@ where
use crate::VariadicFunc::*;
match func {
CaseLiteral(cl) => {
let input = self.child::<MirScalarExpr>(&exprs[0]);
let input = e.child::<MirScalarExpr>(&exprs[0]);
write!(f, "case_lookup {}", input)?;
for entry in &cl.lookup {
let result = self.child::<MirScalarExpr>(&exprs[entry.expr_index]);
let result = e.child::<MirScalarExpr>(&exprs[entry.expr_index]);
write!(f, " when ")?;
self.mode.humanize_datum(entry.literal.unpack_first(), f)?;
e.mode.humanize_datum(entry.literal.unpack_first(), f)?;
write!(f, " then {}", result)?;
}
let els = self.child::<MirScalarExpr>(exprs.last().unwrap());
let els = e.child::<MirScalarExpr>(exprs.last().unwrap());
write!(f, " else {} end", els)
}
ArrayCreate(..) => {
let exprs = exprs.iter().map(|expr| self.child(expr));
let exprs = exprs.iter().map(|expr| e.child(expr));
let exprs = separated(", ", exprs);
write!(f, "array[{}]", exprs)
}
ListCreate(..) => {
let exprs = exprs.iter().map(|expr| self.child(expr));
let exprs = exprs.iter().map(|expr| e.child(expr));
let exprs = separated(", ", exprs);
write!(f, "list[{}]", exprs)
}
RecordCreate(..) => {
let exprs = exprs.iter().map(|expr| self.child(expr));
let exprs = exprs.iter().map(|expr| e.child(expr));
let exprs = separated(", ", exprs);
write!(f, "row({})", exprs)
}
func if func.is_infix_op() && exprs.len() > 1 => {
let exprs = exprs.iter().map(|expr| self.child(expr));
let exprs = exprs.iter().map(|expr| e.child(expr));
let func = format!(" {} ", func);
let exprs = separated(&func, exprs);
write!(f, "({})", exprs)
}
func => {
let exprs = exprs.iter().map(|expr| self.child(expr));
let exprs = exprs.iter().map(|expr| e.child(expr));
let exprs = separated(", ", exprs);
write!(f, "{}({})", func, exprs)
}
}
}
If { cond, then, els } => {
let cond = self.child::<MirScalarExpr>(&*cond);
let then = self.child::<MirScalarExpr>(&*then);
let els = self.child::<MirScalarExpr>(&*els);
let cond = e.child::<MirScalarExpr>(&*cond);
let then = e.child::<MirScalarExpr>(&*then);
let els = e.child::<MirScalarExpr>(&*els);
write!(f, "case when {} then {} else {} end", cond, then, els)
}
}
}
}

impl<'a, T, M> fmt::Display for HumanizedExpr<'a, T, M>
where
T: HumanizeDisplay,
M: HumanizerMode,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
T::humanize(self, f)
}
}

impl<'a, M> fmt::Display for HumanizedExpr<'a, AggregateExpr, M>
where
M: HumanizerMode,
Expand Down
4 changes: 1 addition & 3 deletions src/expr/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ use std::fmt::Debug;

use mz_repr::{Datum, ReprColumnType, ReprRelationType, ReprScalarType, Row, RowArena};

use crate::Eval;
use crate::scalar::func::variadic::And;
use crate::{
BinaryFunc, EvalError, MapFilterProject, MfpPlan, MirScalarExpr, UnaryFunc,
BinaryFunc, Eval, EvalError, MapFilterProject, MfpPlan, MirScalarExpr, UnaryFunc,
UnmaterializableFunc, VariadicFunc, func,
};

/// An inclusive range of non-null datum values.
#[derive(Clone, Eq, PartialEq, Debug)]
enum Values<'a> {
Expand Down
4 changes: 2 additions & 2 deletions src/expr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ pub use relation::{
};
pub use scalar::func::{self, BinaryFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc};
pub use scalar::{
Columns, Eval, EvalError, FilterCharacteristics, MirScalarExpr, ProtoDomainLimit,
ProtoEvalError, like_pattern,
Columns, Eval, EvalError, FilterCharacteristics, MirScalarExpr, OptimizableExpr,
ProtoDomainLimit, ProtoEvalError, like_pattern,
};

/// A [`MirRelationExpr`] that claims to have been optimized, e.g., by an
Expand Down
Loading
Loading