risingwave_frontend/planner/
set_operation.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 risingwave_common::util::column_index_mapping::ColIndexMapping;
16
17use crate::binder::{BoundSetExpr, BoundSetOperation};
18use crate::error::Result;
19use crate::optimizer::plan_node::{
20    LogicalExcept, LogicalIntersect, LogicalPlanRef as PlanRef, LogicalProject, LogicalUnion,
21};
22use crate::planner::Planner;
23
24impl Planner {
25    pub(super) fn plan_set_operation(
26        &mut self,
27        op: BoundSetOperation,
28        all: bool,
29        corresponding_col_indices: Option<(ColIndexMapping, ColIndexMapping)>,
30        left: BoundSetExpr,
31        right: BoundSetExpr,
32    ) -> Result<PlanRef> {
33        let left = self.plan_set_expr(left, vec![], &[])?;
34        let right = self.plan_set_expr(right, vec![], &[])?;
35
36        // Map the corresponding columns
37        let (left, right) = if let Some((mapping_l, mapping_r)) = corresponding_col_indices {
38            (
39                LogicalProject::with_mapping(left, mapping_l).into(),
40                LogicalProject::with_mapping(right, mapping_r).into(),
41            )
42        } else {
43            (left, right)
44        };
45
46        match op {
47            BoundSetOperation::Union => Ok(LogicalUnion::create(all, vec![left, right])),
48            BoundSetOperation::Intersect => Ok(LogicalIntersect::create(all, vec![left, right])),
49            BoundSetOperation::Except => Ok(LogicalExcept::create(all, vec![left, right])),
50        }
51    }
52}