risingwave_frontend/optimizer/rule/
apply_union_transpose_rule.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use itertools::Itertools;
16
17use super::prelude::{PlanRef, *};
18use crate::optimizer::plan_node::{LogicalApply, LogicalUnion, PlanTreeNode, PlanTreeNodeBinary};
19
20/// Transpose `LogicalApply` and `LogicalUnion`.
21///
22/// Before:
23///
24/// ```text
25///     LogicalApply
26///    /            \
27///  Domain      LogicalUnion
28///                /      \
29///               T1     T2
30/// ```
31///
32/// After:
33///
34/// ```text
35///           LogicalUnion
36///         /            \
37///  LogicalApply     LogicalApply
38///   /      \           /      \
39/// Domain   T1        Domain   T2
40/// ```
41pub struct ApplyUnionTransposeRule {}
42impl Rule<Logical> for ApplyUnionTransposeRule {
43    fn apply(&self, plan: PlanRef) -> Option<PlanRef> {
44        let apply: &LogicalApply = plan.as_logical_apply()?;
45        if apply.max_one_row() {
46            return None;
47        }
48        let left = apply.left();
49        let right = apply.right();
50        let union: &LogicalUnion = right.as_logical_union()?;
51
52        let new_inputs = union
53            .inputs()
54            .into_iter()
55            .map(|input| apply.clone_with_left_right(left.clone(), input).into())
56            .collect_vec();
57        Some(union.clone_with_inputs(&new_inputs))
58    }
59}
60
61impl ApplyUnionTransposeRule {
62    pub fn create() -> BoxedRule {
63        Box::new(ApplyUnionTransposeRule {})
64    }
65}