1use rudb_catalog::{Catalog, QualifiedName};
15use rudb_common::{Cancel, Memory, Result};
16use rudb_functions::TableFunction;
17use rudb_plan::{Node, NodeRef, Plan};
18
19use crate::cancel::Guarded;
20use crate::group::{Aggregate, Distinct};
21use crate::join::{CrossProduct, Join};
22use crate::operator::Operator;
23use crate::setop::SetOp;
24use crate::sort::Sort;
25use crate::source::{Dummy, FileScan, Scan, Series, Values};
26use crate::stream::{Filter, Limit, Project};
27use crate::topn::TopN;
28
29pub fn build<'a>(plan: &'a Plan, catalog: &'a Catalog) -> Result<Box<dyn Operator + 'a>> {
36 build_with(plan, catalog, &Cancel::new(), &Memory::unlimited())
37}
38
39pub fn build_with<'a>(
55 plan: &'a Plan,
56 catalog: &'a Catalog,
57 cancel: &Cancel,
58 memory: &Memory,
59) -> Result<Box<dyn Operator + 'a>> {
60 node(plan, catalog, cancel, memory, plan.root())
61}
62
63fn node<'a>(
64 plan: &'a Plan,
65 catalog: &'a Catalog,
66 cancel: &Cancel,
67 memory: &Memory,
68 reference: NodeRef,
69) -> Result<Box<dyn Operator + 'a>> {
70 let inner: Box<dyn Operator + 'a> = match *plan.node(reference) {
71 Node::Get { catalog: database, schema, table, index, columns, .. } => {
72 let name =
73 QualifiedName::new(plan.string(database), plan.string(schema), plan.string(table));
74 Box::new(Scan::new(plan, catalog.table(&name)?, index, columns)?)
75 }
76 Node::Dummy => Box::new(Dummy::new()),
77 Node::Values { index, columns, rows } => Box::new(Values::new(plan, index, columns, rows)?),
78 Node::TableFunction { index, function, args, columns } => {
79 match TableFunction::lookup(plan.string(function)) {
80 Some(function @ (TableFunction::ReadParquet | TableFunction::ReadCsv)) => {
81 Box::new(FileScan::new(plan, index, function, args, columns)?)
82 }
83 _ => Box::new(Series::new(plan, index, plan.string(function), args)?),
84 }
85 }
86 Node::Filter { input, predicate } => {
87 Box::new(Filter::new(plan, node(plan, catalog, cancel, memory, input)?, predicate)?)
88 }
89 Node::Project { input, index, exprs, names } => Box::new(Project::new(
90 plan,
91 node(plan, catalog, cancel, memory, input)?,
92 index,
93 exprs,
94 names,
95 )?),
96 Node::Aggregate { input, index, groups, aggregates } => Box::new(Aggregate::new(
97 plan,
98 node(plan, catalog, cancel, memory, input)?,
99 index,
100 groups,
101 aggregates,
102 memory,
103 )?),
104 Node::Sort { input, keys } => {
105 Box::new(Sort::new(plan, node(plan, catalog, cancel, memory, input)?, keys, memory))
106 }
107 Node::Limit { input, count, offset } => {
108 Box::new(Limit::new(node(plan, catalog, cancel, memory, input)?, count, offset))
109 }
110 Node::TopN { input, keys, count, offset } => Box::new(TopN::new(
111 plan,
112 node(plan, catalog, cancel, memory, input)?,
113 keys,
114 count,
115 offset,
116 memory,
117 )),
118 Node::Distinct { input, on } => {
119 Box::new(Distinct::new(plan, node(plan, catalog, cancel, memory, input)?, on, memory))
120 }
121 Node::Join { left, right, kind, conditions } => Box::new(Join::new(
122 plan,
123 node(plan, catalog, cancel, memory, left)?,
124 node(plan, catalog, cancel, memory, right)?,
125 kind,
126 conditions,
127 memory,
128 )),
129 Node::CrossProduct { left, right } => Box::new(CrossProduct::new(
130 node(plan, catalog, cancel, memory, left)?,
131 node(plan, catalog, cancel, memory, right)?,
132 memory,
133 )),
134 Node::SetOp { left, right, kind, all, index } => Box::new(SetOp::new(
135 node(plan, catalog, cancel, memory, left)?,
136 node(plan, catalog, cancel, memory, right)?,
137 kind,
138 all,
139 index,
140 memory,
141 )),
142 };
143 Ok(Box::new(Guarded::new(inner, cancel.clone())))
144}