Skip to content

Commit 69c3786

Browse files
authored
Merge pull request #30884 from ggevay/typ-demand-literal-constr
Eliminate more `typ` and `arity` calls
2 parents f932a69 + 50072db commit 69c3786

File tree

6 files changed

+39
-26
lines changed

6 files changed

+39
-26
lines changed

src/compute-types/src/plan/lowering.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,6 @@ impl Context {
548548
equivalences,
549549
implementation,
550550
} => {
551-
let input_mapper = JoinInputMapper::new(inputs);
552-
553551
// Plan each of the join inputs independently.
554552
// The `plans` get surfaced upwards, and the `input_keys` should
555553
// be used as part of join planning / to validate the existing
@@ -564,6 +562,9 @@ impl Context {
564562
input_keys.push(keys);
565563
}
566564

565+
let input_mapper =
566+
JoinInputMapper::new_from_input_arities(input_arities.iter().copied());
567+
567568
// Extract temporal predicates as joins cannot currently absorb them.
568569
let (plan, missing) = match implementation {
569570
IndexedFilter(_coll_id, _idx_id, key, _val) => {

src/expr/src/linear.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ impl MapFilterProject {
329329
let (mfp, expr) = Self::extract_from_expression(input);
330330
(mfp.project(outputs.iter().cloned()), expr)
331331
}
332+
// TODO: The recursion is quadratic in the number of Map/Filter/Project operators due to
333+
// this call to `arity()`.
332334
x => (Self::new(x.arity()), x),
333335
}
334336
}

src/expr/src/relation.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ impl MirRelationExpr {
593593
/// Reports the column types of the relation given the column types of the
594594
/// input relations.
595595
///
596-
/// This method delegates to `try_col_with_input_cols`, panicing if an `Err`
596+
/// This method delegates to `try_col_with_input_cols`, panicking if an `Err`
597597
/// variant is returned.
598598
pub fn col_with_input_cols<'a, I>(&self, input_types: I) -> Vec<ColumnType>
599599
where
@@ -1792,22 +1792,21 @@ impl MirRelationExpr {
17921792
.unzip();
17931793
assert_eq!(keys_and_values.arity() - self.arity(), data.len());
17941794
self.let_in(id_gen, |_id_gen, get_keys| {
1795+
let get_keys_arity = get_keys.arity();
17951796
Ok(MirRelationExpr::join(
17961797
vec![
17971798
// all the missing keys (with count 1)
17981799
keys_and_values
1799-
.distinct_by((0..get_keys.arity()).collect())
1800+
.distinct_by((0..get_keys_arity).collect())
18001801
.negate()
18011802
.union(get_keys.clone().distinct()),
18021803
// join with keys to get the correct counts
18031804
get_keys.clone(),
18041805
],
1805-
(0..get_keys.arity())
1806-
.map(|i| vec![(0, i), (1, i)])
1807-
.collect(),
1806+
(0..get_keys_arity).map(|i| vec![(0, i), (1, i)]).collect(),
18081807
)
18091808
// get rid of the extra copies of columns from keys
1810-
.project((0..get_keys.arity()).collect())
1809+
.project((0..get_keys_arity).collect())
18111810
// This join is logically equivalent to
18121811
// `.map(<default_expr>)`, but using a join allows for
18131812
// potential predicate pushdown and elision in the

src/sql/src/plan/lowering.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,8 @@ impl HirScalarExpr {
13991399

14001400
// Record input arity here so that any group_keys that need to mutate get_inner
14011401
// don't add those columns to the aggregate input.
1402-
let input_arity = get_inner.typ().arity();
1402+
let input_type = get_inner.typ();
1403+
let input_arity = input_type.arity();
14031404
// The reduction that computes the window function must be keyed on the columns
14041405
// from the outer context, plus the expressions in the partition key. The current
14051406
// subquery will be 'executed' for every distinct row from the outer context so
@@ -1428,8 +1429,6 @@ impl HirScalarExpr {
14281429
}
14291430

14301431
get_inner.let_in(id_gen, |id_gen, mut get_inner| {
1431-
let input_type = get_inner.typ();
1432-
14331432
// Original columns of the relation
14341433
let fields: Box<_> = input_type
14351434
.column_types
@@ -1575,12 +1574,14 @@ impl HirScalarExpr {
15751574
let inner_arity = get_inner.arity();
15761575
let mut total_arity = inner_arity;
15771576
let mut join_inputs = vec![get_inner];
1577+
let mut join_input_arities = vec![inner_arity];
15781578
for (expr, subquery) in subqueries.into_iter() {
15791579
// Avoid lowering duplicated subqueries
15801580
if !subquery_map.contains_key(&expr) {
15811581
let subquery_arity = subquery.arity();
15821582
assert_eq!(subquery_arity, inner_arity + 1);
15831583
join_inputs.push(subquery);
1584+
join_input_arities.push(subquery_arity);
15841585
total_arity += subquery_arity;
15851586

15861587
// Column with the value of the subquery
@@ -1590,7 +1591,8 @@ impl HirScalarExpr {
15901591
// Each subquery projects all the columns of the outer context (distinct_inner)
15911592
// plus 1 column, containing the result of the subquery. Those columns must be
15921593
// joined with the outer/main relation (get_inner).
1593-
let input_mapper = mz_expr::JoinInputMapper::new(&join_inputs);
1594+
let input_mapper =
1595+
mz_expr::JoinInputMapper::new_from_input_arities(join_input_arities);
15941596
let equivalences = (0..inner_arity)
15951597
.map(|col| {
15961598
join_inputs

src/transform/src/demand.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl Demand {
176176
),
177177
MirRelationExpr::Map { input, scalars } => {
178178
let relation_type = relation_type.as_ref().unwrap();
179-
let arity = input.arity();
179+
let arity = relation_type.arity() - scalars.len();
180180
// contains columns whose supports have yet to be explored
181181
let mut new_columns = columns.clone();
182182
new_columns.retain(|c| *c >= arity);
@@ -219,7 +219,8 @@ impl Demand {
219219
for expr in exprs {
220220
expr.support_into(&mut columns);
221221
}
222-
columns.retain(|c| *c < input.arity());
222+
let arity = input.arity();
223+
columns.retain(|c| *c < arity);
223224
self.action(input, columns, gets)
224225
}
225226
MirRelationExpr::Filter { input, predicates } => {

src/transform/src/literal_constraints.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use mz_ore::collections::CollectionExt;
2929
use mz_ore::iter::IteratorExt;
3030
use mz_ore::stack::RecursionLimitError;
3131
use mz_ore::vec::swap_remove_multiple;
32-
use mz_repr::{GlobalId, Row};
32+
use mz_repr::{GlobalId, RelationType, Row};
3333

3434
use crate::canonicalize_mfp::CanonicalizeMfp;
3535
use crate::notice::IndexTooWideForLiteralConstraints;
@@ -70,7 +70,9 @@ impl LiteralConstraints {
7070
relation.try_visit_mut_children(|e| self.action(e, transform_ctx))?;
7171

7272
if let MirRelationExpr::Get {
73-
id: Id::Global(id), ..
73+
id: Id::Global(id),
74+
ref typ,
75+
..
7476
} = *relation
7577
{
7678
let orig_mfp = mfp.clone();
@@ -87,10 +89,11 @@ impl LiteralConstraints {
8789
mfp: &mut MapFilterProject,
8890
orig_mfp: &MapFilterProject,
8991
relation: &MirRelationExpr,
92+
relation_type: RelationType,
9093
) {
9194
// undo list_of_predicates_to_and_of_predicates, distribute_and_over_or, unary_and
9295
// (It undoes the latter 2 through `MirScalarExp::reduce`.)
93-
LiteralConstraints::canonicalize_predicates(mfp, relation);
96+
LiteralConstraints::canonicalize_predicates(mfp, relation, relation_type);
9497
// undo inline_literal_constraints
9598
mfp.optimize();
9699
// We can usually undo, but sometimes not (see comment on `distribute_and_over_or`),
@@ -109,14 +112,16 @@ impl LiteralConstraints {
109112
// todo: We might want to also call `canonicalize_equivalences`,
110113
// see near the end of literal_constraints.slt.
111114

115+
let inp_typ = typ.clone();
116+
112117
let key_val = Self::detect_literal_constraints(&mfp, id, transform_ctx);
113118

114119
match key_val {
115120
None => {
116121
// We didn't find a usable index, so no chance to remove literal constraints.
117122
// But, we might have removed contradicting OR args.
118123
if removed_contradicting_or_args {
119-
undo_preparation(&mut mfp, &orig_mfp, relation);
124+
undo_preparation(&mut mfp, &orig_mfp, relation, inp_typ);
120125
} else {
121126
// We didn't remove anything, so let's go with the original MFP.
122127
mfp = orig_mfp;
@@ -130,7 +135,7 @@ impl LiteralConstraints {
130135
{
131136
// We were able to remove the literal constraints or contradicting OR args,
132137
// so we would like to use this new MFP, so we try undoing the preparation.
133-
undo_preparation(&mut mfp, &orig_mfp, relation);
138+
undo_preparation(&mut mfp, &orig_mfp, relation, inp_typ.clone());
134139
} else {
135140
// We were not able to remove the literal constraint, so `mfp` is
136141
// equivalent to `orig_mfp`, but `orig_mfp` is often simpler (or the same).
@@ -140,7 +145,6 @@ impl LiteralConstraints {
140145
// We transform the Get into a semi-join with a constant collection.
141146

142147
let inp_id = id.clone();
143-
let inp_typ = relation.typ();
144148
let filter_list = MirRelationExpr::Constant {
145149
rows: Ok(possible_vals.iter().map(|val| (val.clone(), 1)).collect()),
146150
typ: mz_repr::RelationType {
@@ -164,10 +168,7 @@ impl LiteralConstraints {
164168
if possible_vals.is_empty() {
165169
// Even better than what we were hoping for: Found contradicting
166170
// literal constraints, so the whole relation is empty.
167-
*relation = MirRelationExpr::Constant {
168-
rows: Ok(Vec::new()),
169-
typ: relation.typ(),
170-
};
171+
relation.take_safely(Some(inp_typ));
171172
} else {
172173
// The common case: We need to build the join which is the main point of
173174
// this transform.
@@ -610,9 +611,16 @@ impl LiteralConstraints {
610611
}
611612

612613
/// Call [mz_expr::canonicalize::canonicalize_predicates] on each of the predicates in the MFP.
613-
fn canonicalize_predicates(mfp: &mut MapFilterProject, relation: &MirRelationExpr) {
614+
fn canonicalize_predicates(
615+
mfp: &mut MapFilterProject,
616+
relation: &MirRelationExpr,
617+
relation_type: RelationType,
618+
) {
614619
let (map, mut predicates, project) = mfp.as_map_filter_project();
615-
let typ_after_map = relation.clone().map(map.clone()).typ();
620+
let typ_after_map = relation
621+
.clone()
622+
.map(map.clone())
623+
.typ_with_input_types(&[relation_type]);
616624
canonicalize_predicates(&mut predicates, &typ_after_map.column_types);
617625
// Rebuild the MFP with the new predicates.
618626
*mfp = MapFilterProject::new(mfp.input_arity)

0 commit comments

Comments
 (0)