Skip to main content

nodedb_sql/planner/
union.rs

1//! UNION / UNION ALL planning.
2
3use sqlparser::ast::{self, SetExpr, SetOperator, SetQuantifier};
4
5use crate::error::{Result, SqlError};
6use crate::functions::registry::FunctionRegistry;
7use crate::types::*;
8
9/// Plan a UNION / UNION ALL / INTERSECT / EXCEPT operation.
10pub fn plan_set_operation(
11    op: &SetOperator,
12    left: &SetExpr,
13    right: &SetExpr,
14    quantifier: &SetQuantifier,
15    catalog: &dyn SqlCatalog,
16    functions: &FunctionRegistry,
17) -> Result<SqlPlan> {
18    let left_plan = plan_set_expr(left, catalog, functions)?;
19    let right_plan = plan_set_expr(right, catalog, functions)?;
20
21    match op {
22        SetOperator::Union => {
23            let distinct = matches!(quantifier, SetQuantifier::Distinct | SetQuantifier::None);
24            Ok(SqlPlan::Union {
25                inputs: vec![left_plan, right_plan],
26                distinct,
27            })
28        }
29        SetOperator::Intersect => {
30            let all = matches!(quantifier, SetQuantifier::All);
31            Ok(SqlPlan::Intersect {
32                left: Box::new(left_plan),
33                right: Box::new(right_plan),
34                all,
35            })
36        }
37        SetOperator::Except => {
38            let all = matches!(quantifier, SetQuantifier::All);
39            Ok(SqlPlan::Except {
40                left: Box::new(left_plan),
41                right: Box::new(right_plan),
42                all,
43            })
44        }
45        _ => Err(SqlError::Unsupported {
46            detail: format!("set operation: {op}"),
47        }),
48    }
49}
50
51fn plan_set_expr(
52    expr: &SetExpr,
53    catalog: &dyn SqlCatalog,
54    functions: &FunctionRegistry,
55) -> Result<SqlPlan> {
56    match expr {
57        SetExpr::Select(select) => {
58            // Wrap in a dummy Query to reuse plan_query.
59            let query = ast::Query {
60                with: None,
61                body: Box::new(SetExpr::Select(select.clone())),
62                order_by: None,
63                limit_clause: None,
64                fetch: None,
65                locks: Vec::new(),
66                for_clause: None,
67                settings: None,
68                format_clause: None,
69                pipe_operators: Vec::new(),
70            };
71            super::select::plan_query(&query, catalog, functions)
72        }
73        SetExpr::SetOperation {
74            op,
75            left,
76            right,
77            set_quantifier,
78        } => plan_set_operation(op, left, right, set_quantifier, catalog, functions),
79        _ => Err(SqlError::Unsupported {
80            detail: format!("set expression: {expr}"),
81        }),
82    }
83}