MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / inline_expressions

Method inline_expressions

src/expr/src/linear.rs:1255–1317  ·  view source on GitHub ↗

This method inlines expressions with a single use. This method only inlines expressions; it does not delete expressions that are no longer referenced. The `remove_undemanded()` method does that, and should likely be used after this method. Inlining replaces column references when the referred-to item is either another column reference, or the only referrer of its referent. This is most common af

(&mut self)

Source from the content-addressed store, hash-verified

1253 /// );
1254 /// ```
1255 pub fn inline_expressions(&mut self) {
1256 // Local copy of input_arity to avoid borrowing `self` in closures.
1257 let input_arity = self.input_arity;
1258 // Reference counts track the number of places that a reference occurs.
1259 let mut reference_count = vec![0; input_arity + self.expressions.len()];
1260 // Increment reference counts for each use
1261 for expr in self.expressions.iter() {
1262 expr.visit_pre(&mut |e| {
1263 if let Some(i) = e.as_column() {
1264 reference_count[i] += 1;
1265 }
1266 });
1267 }
1268 for (_, pred) in self.predicates.iter() {
1269 pred.visit_pre(&mut |e| {
1270 if let Some(i) = e.as_column() {
1271 reference_count[i] += 1;
1272 }
1273 });
1274 }
1275 for proj in self.projection.iter() {
1276 reference_count[*proj] += 1;
1277 }
1278
1279 // Determine which expressions should be inlined because they reference temporal expressions.
1280 let mut is_temporal = vec![false; input_arity];
1281 for expr in self.expressions.iter() {
1282 // An express may contain a temporal expression, or reference a column containing such.
1283 is_temporal.push(
1284 OptimizableExpr::contains_temporal(expr)
1285 || expr.support().into_iter().any(|col| is_temporal[col]),
1286 );
1287 }
1288
1289 // Inline only those columns that 1. are expressions not inputs, and
1290 // 2a. are column references or literals or 2b. have a refcount of 1,
1291 // or 2c. reference temporal expressions (which cannot be evaluated).
1292 let mut should_inline = vec![false; reference_count.len()];
1293 for i in (input_arity..reference_count.len()).rev() {
1294 if let Some(c) = self.expressions[i - input_arity].as_column() {
1295 should_inline[i] = true;
1296 // The reference count of the referenced column should be
1297 // incremented with the number of references
1298 // `self.expressions[i - input_arity]` has.
1299 // Subtract 1 because `self.expressions[i - input_arity]` is
1300 // itself a reference.
1301 reference_count[c] += reference_count[i] - 1;
1302 } else {
1303 should_inline[i] = reference_count[i] == 1 || is_temporal[i];
1304 }
1305 }
1306 // Inline expressions per `should_inline`.
1307 self.perform_inlining(should_inline);
1308 // We can only inline column references in `self.projection`, but we should.
1309 for proj in self.projection.iter_mut() {
1310 if *proj >= self.input_arity {
1311 if let Some(i) = self.expressions[*proj - self.input_arity].as_column() {
1312 // TODO(mgree) !!! propagate name information to projection

Callers 1

optimizeMethod · 0.80

Calls 9

as_columnMethod · 0.80
anyMethod · 0.80
perform_inliningMethod · 0.80
iterMethod · 0.45
visit_preMethod · 0.45
pushMethod · 0.45
into_iterMethod · 0.45
supportMethod · 0.45
lenMethod · 0.45

Tested by

no test coverage detected