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