Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
16 changes: 16 additions & 0 deletions doc/developer/testdrive.md
Original file line number Diff line number Diff line change
Expand Up @@ -943,5 +943,21 @@ SELECT mz_version_num() < 2601;

The `[version>=13000]` property allows running the action or query only when we are connected to a Materialize instance with a compatible version. The supported comparison operators are `>`, `>=`, `=`, `<=` and `<`. The version number is the same as returned from [`mz_version_num()`](https://materialize.com/docs/sql/functions/#system-information-func) and has the same format `XXXYYYZZ`, where `XX` is the major version, `YYY` is the minor version and `ZZ` is the patch version. So in the example we are only running the `SELECT 1` query if the Materialize instance is of version `v0.130.0` or higher. For lower versions no query is run and no comparison of results is performed subsequently.

You can bound the version above and below using the following syntax:

```
?[13500<=version<14300] SELECT 1;
1
```

You can use `<` or `<=` freely. The following are equivalent:

```
?[version<14300] SELECT 1;
1
?[14300>version] SELECT 1;
1
```

[confluent-arm]: https://github.com/confluentinc/common-docker/issues/117#issuecomment-948789717
[aws-creds]: https://github.com/MaterializeInc/i2/blob/main/doc/aws-access.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,18 @@ def validate(self) -> Testdrive:
Target cluster: quickstart


?[version>=13500] EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR MATERIALIZED VIEW explain_mv2;
?[version>=14300] EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR MATERIALIZED VIEW explain_mv2;
materialize.public.explain_mv2:
Filter (#1{y} = 7)
ReadStorage materialize.public.explain_item_t2

Source materialize.public.explain_item_t2
filter=((#1{y} = 7))

Target cluster: quickstart


?[13500<=version<14300] EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR MATERIALIZED VIEW explain_mv2;
materialize.public.explain_mv2:
Filter (#1 = 7)
ReadStorage materialize.public.explain_item_t2
Expand Down
2 changes: 1 addition & 1 deletion src/adapter/src/catalog/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,7 @@ impl CatalogState {
.variant
.index_by()
.into_iter()
.map(MirScalarExpr::Column)
.map(MirScalarExpr::column)
.collect(),
create_sql: index_sql(
index_item_name,
Expand Down
2 changes: 1 addition & 1 deletion src/adapter/src/catalog/builtin_table_updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ impl CatalogState {
.expect("missing sql information for index key")
.to_ast_string_simple();
let (field_number, expression) = match key {
MirScalarExpr::Column(col) => {
MirScalarExpr::Column(col, _) => {
(Datum::UInt64(u64::cast_from(*col + 1)), Datum::Null)
}
_ => (Datum::Null, Datum::String(&key_sql)),
Expand Down
4 changes: 2 additions & 2 deletions src/adapter/src/coord/peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl<T> PeekDataflowPlan<T> {
let key = typ
.default_key()
.into_iter()
.map(MirScalarExpr::Column)
.map(MirScalarExpr::column)
.collect::<Vec<_>>();
let (permutation, thinning) = permutation_for_arrangement(&key, arity);
Self {
Expand Down Expand Up @@ -397,7 +397,7 @@ pub fn create_fast_path_plan<T: Timestamp>(
if !preserves_order(&col.scalar_type) {
break;
}
let col_expr = MirScalarExpr::Column(idx);
let col_expr = MirScalarExpr::column(idx);

let Some((literal, _)) = filters
.iter()
Expand Down
2 changes: 1 addition & 1 deletion src/adapter/src/optimize/peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl<'s> Optimize<LocalMirPlan<Resolved<'s>>> for Optimizer {
let key = typ
.default_key()
.iter()
.map(|k| MirScalarExpr::Column(*k))
.map(|k| MirScalarExpr::column(*k))
.collect();

// The assembled dataflow contains a view and an index of that view.
Expand Down
2 changes: 1 addition & 1 deletion src/compute-types/src/plan/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ impl Context {
// All columns of the constant input will be part of the arrangement key.
let source_arrangement = (
(0..key.len())
.map(MirScalarExpr::Column)
.map(MirScalarExpr::column)
.collect::<Vec<_>>(),
(0..key.len()).collect::<Vec<_>>(),
Vec::<usize>::new(),
Expand Down
2 changes: 1 addition & 1 deletion src/compute-types/src/plan/reduce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ impl ReducePlan {
/// that key a single arrangement.
pub fn keys(&self, key_arity: usize, arity: usize) -> AvailableCollections {
let key = (0..key_arity)
.map(MirScalarExpr::Column)
.map(MirScalarExpr::column)
.collect::<Vec<_>>();
let (permutation, thinning) = permutation_for_arrangement(&key, arity);
AvailableCollections::new_arranged(vec![(key, permutation, thinning)], None)
Expand Down
2 changes: 1 addition & 1 deletion src/compute-types/src/plan/threshold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl ThresholdPlan {
// Arrange the input by all columns in order.
let mut all_columns = Vec::new();
for column in 0..arity {
all_columns.push(mz_expr::MirScalarExpr::Column(column));
all_columns.push(mz_expr::MirScalarExpr::column(column));
}
let (permutation, thinning) = permutation_for_arrangement(&all_columns, arity);
let ensure_arrangement = (all_columns, permutation, thinning);
Expand Down
2 changes: 1 addition & 1 deletion src/compute/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl PermutedRowPacker {
let (_, value) = permutation_for_arrangement(
&key.iter()
.cloned()
.map(MirScalarExpr::Column)
.map(MirScalarExpr::column)
.collect::<Vec<_>>(),
variant.desc().arity(),
);
Expand Down
2 changes: 1 addition & 1 deletion src/compute/src/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ where
) -> Self {
let mut keys = Vec::new();
for column in columns {
keys.push(MirScalarExpr::Column(column));
keys.push(MirScalarExpr::column(column));
}
Self::from_expressions(keys, arrangements)
}
Expand Down
8 changes: 4 additions & 4 deletions src/environmentd/tests/testdata/http/ws

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/expr-parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ mod scalar {
}

pub fn parse_column(input: ParseStream) -> Result {
Ok(MirScalarExpr::Column(parse_column_index(input)?))
Ok(MirScalarExpr::column(parse_column_index(input)?))
}

pub fn parse_column_index(input: ParseStream) -> syn::Result<usize> {
Expand Down
9 changes: 7 additions & 2 deletions src/expr-test-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub struct MirScalarExprDeserializeContext;
impl MirScalarExprDeserializeContext {
fn build_column(&self, token: Option<TokenTree>) -> Result<MirScalarExpr, String> {
if let Some(TokenTree::Literal(literal)) = token {
return Ok(MirScalarExpr::Column(
return Ok(MirScalarExpr::column(
literal
.to_string()
.parse::<usize>()
Expand Down Expand Up @@ -321,7 +321,12 @@ impl TestDeserializeContext for MirScalarExprDeserializeContext {
assert_eq!(map.len(), 1);
for (variant, data) in map.iter() {
match &variant[..] {
"Column" => return Some(format!("#{}", data.as_u64().unwrap())),
"Column" => {
return Some(format!(
"#{}",
data.as_array().unwrap()[0].as_u64().unwrap()
));
}
"Literal" => {
let column_type: ColumnType =
serde_json::from_value(data.as_array().unwrap()[1].clone()).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions src/expr/src/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,14 +302,14 @@ fn id_gen(expr: &MirRelationExpr) -> impl Iterator<Item = LocalId> + use<> {
impl ScalarOps for MirScalarExpr {
fn match_col_ref(&self) -> Option<usize> {
match self {
MirScalarExpr::Column(c) => Some(*c),
MirScalarExpr::Column(c, _name) => Some(*c),
_ => None,
}
}

fn references(&self, column: usize) -> bool {
match self {
MirScalarExpr::Column(c) => *c == column,
MirScalarExpr::Column(c, _name) => *c == column,
_ => false,
}
}
Expand Down
36 changes: 34 additions & 2 deletions src/expr/src/explain/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

use std::collections::BTreeMap;
use std::fmt;
use std::sync::Arc;

use mz_ore::soft_assert_eq_or_log;
use mz_ore::str::{Indent, IndentLike, StrExt, closure_to_display, separated};
use mz_ore::treat_as_equal::TreatAsEqual;
use mz_repr::explain::text::DisplayText;
use mz_repr::explain::{
CompactScalars, ExprHumanizer, HumanizedAnalyses, IndexUsageType, Indices,
Expand Down Expand Up @@ -1173,6 +1175,32 @@ where
}
}

// A column reference with a stored name.
// We defer to the inferred name, if available.
impl<'a, M> fmt::Display for HumanizedExpr<'a, (&usize, &Arc<str>), M>
where
M: HumanizerMode,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.cols {
// We have a name inferred for the column indexed by `self.expr`. Write `ident`.
Some(cols) if cols.len() > *self.expr.0 && !cols[*self.expr.0].is_empty() => {
// Note: using unchecked here is okay since we're directly
// converting to a string afterwards.
let ident = Ident::new_unchecked(cols[*self.expr.0].clone()); // TODO: try to avoid the `.clone()` here.
M::humanize_ident(*self.expr.0, ident, f)
}
// We don't have name inferred for this column.
_ => M::humanize_ident(
*self.expr.0,
Ident::new_unchecked(self.expr.1.to_string()),
f,
),
}
}
}

impl<'a, M> ScalarOps for HumanizedExpr<'a, MirScalarExpr, M> {
fn match_col_ref(&self) -> Option<usize> {
self.expr.match_col_ref()
Expand Down Expand Up @@ -1201,10 +1229,14 @@ where
use MirScalarExpr::*;

match self.expr {
Column(i) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation.
Column(i, TreatAsEqual(None)) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation (plain column reference).
self.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)
}
Literal(row, _) => {
// Delegate to the `HumanizedExpr<'a, _>` implementation.
self.child(row).fmt(f)
Expand Down
30 changes: 15 additions & 15 deletions src/expr/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ pub trait Interpreter {
/// Evaluate an entire expression, by delegating to the fine-grained methods on [Interpreter].
fn expr(&self, expr: &MirScalarExpr) -> Self::Summary {
match expr {
MirScalarExpr::Column(id) => self.column(*id),
MirScalarExpr::Column(id, _name) => self.column(*id),
MirScalarExpr::Literal(value, col_type) => self.literal(value, col_type),
MirScalarExpr::CallUnmaterializable(func) => self.unmaterializable(func),
MirScalarExpr::CallUnary { func, expr } => {
Expand Down Expand Up @@ -559,7 +559,7 @@ impl SpecialUnary {
func: UnaryFunc::TryParseMonotonicIso8601Timestamp(
crate::func::TryParseMonotonicIso8601Timestamp,
),
expr: Box::new(MirScalarExpr::Column(0)),
expr: Box::new(MirScalarExpr::column(0)),
};
let eval = |d| specs.eval_result(expr.eval(&[d], specs.arena));

Expand Down Expand Up @@ -1268,7 +1268,7 @@ mod tests {
any::<Index>()
.prop_map(move |idx| {
let id = idx.index(column_types.len());
(MirScalarExpr::Column(id), column_types[id].clone())
(MirScalarExpr::column(id), column_types[id].clone())
})
.boxed()
};
Expand Down Expand Up @@ -1443,8 +1443,8 @@ mod tests {
func: UnaryFunc::IsNull(IsNull),
expr: Box::new(CallBinary {
func: BinaryFunc::MulInt32,
expr1: Box::new(Column(0)),
expr2: Box::new(Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(MirScalarExpr::column(0)),
}),
},
),
Expand All @@ -1453,7 +1453,7 @@ mod tests {
1,
CallBinary {
func: BinaryFunc::Eq,
expr1: Box::new(Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(Literal(
Ok(Row::pack_slice(&[Datum::Int32(1727694505)])),
ScalarType::Int32.nullable(false),
Expand All @@ -1478,7 +1478,7 @@ mod tests {
let expr = MirScalarExpr::CallVariadic {
func: VariadicFunc::Concat,
exprs: vec![
MirScalarExpr::Column(0),
MirScalarExpr::column(0),
MirScalarExpr::literal_ok(Datum::String("a"), ScalarType::String),
MirScalarExpr::literal_ok(Datum::String("b"), ScalarType::String),
],
Expand Down Expand Up @@ -1510,7 +1510,7 @@ mod tests {
expr1: Box::new(period_ms.clone()),
expr2: Box::new(MirScalarExpr::CallBinary {
func: BinaryFunc::DivInt64,
expr1: Box::new(MirScalarExpr::Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(period_ms),
}),
}),
Expand Down Expand Up @@ -1568,7 +1568,7 @@ mod tests {
func: UnaryFunc::CastJsonbToNumeric(CastJsonbToNumeric(None)),
expr: Box::new(MirScalarExpr::CallBinary {
func: BinaryFunc::JsonbGetString,
expr1: Box::new(MirScalarExpr::Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(MirScalarExpr::Literal(
Ok(Row::pack_slice(&["ts".into()])),
ScalarType::String.nullable(false),
Expand Down Expand Up @@ -1607,7 +1607,7 @@ mod tests {
func: UnaryFunc::IsLikeMatch(IsLikeMatch(
crate::like_pattern::compile("%whatever%", true).unwrap(),
)),
expr: Box::new(MirScalarExpr::Column(0)),
expr: Box::new(MirScalarExpr::column(0)),
};

let relation = RelationType::new(vec![ScalarType::String.nullable(true)]);
Expand Down Expand Up @@ -1635,7 +1635,7 @@ mod tests {

let expr = MirScalarExpr::CallUnary {
func: UnaryFunc::TryParseMonotonicIso8601Timestamp(TryParseMonotonicIso8601Timestamp),
expr: Box::new(MirScalarExpr::Column(0)),
expr: Box::new(MirScalarExpr::column(0)),
};

let relation = RelationType::new(vec![ScalarType::String.nullable(true)]);
Expand Down Expand Up @@ -1721,7 +1721,7 @@ mod tests {

let expr = MirScalarExpr::CallBinary {
func: BinaryFunc::Gte,
expr1: Box::new(MirScalarExpr::Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(MirScalarExpr::CallUnmaterializable(
UnmaterializableFunc::MzNow,
)),
Expand Down Expand Up @@ -1761,13 +1761,13 @@ mod tests {

let expr = MirScalarExpr::CallBinary {
func: BinaryFunc::Gte,
expr1: Box::new(MirScalarExpr::Column(0)),
expr1: Box::new(MirScalarExpr::column(0)),
expr2: Box::new(MirScalarExpr::CallBinary {
func: BinaryFunc::AddInt64,
expr1: Box::new(MirScalarExpr::Column(1)),
expr1: Box::new(MirScalarExpr::column(1)),
expr2: Box::new(MirScalarExpr::CallUnary {
func: UnaryFunc::NegInt64(NegInt64),
expr: Box::new(MirScalarExpr::Column(3)),
expr: Box::new(MirScalarExpr::column(3)),
}),
}),
};
Expand Down
Loading