1use rudb_catalog::{Catalog, QualifiedName};
15use rudb_common::Result;
16use rudb_functions::TableFunction;
17use rudb_plan::{Node, NodeRef, Plan};
18
19use crate::group::{Aggregate, Distinct};
20use crate::join::{CrossProduct, Join};
21use crate::operator::Operator;
22use crate::setop::SetOp;
23use crate::sort::Sort;
24use crate::source::{Dummy, FileScan, Scan, Series, Values};
25use crate::stream::{Filter, Limit, Project};
26
27pub fn build<'a>(plan: &'a Plan, catalog: &'a Catalog) -> Result<Box<dyn Operator + 'a>> {
34 node(plan, catalog, plan.root())
35}
36
37fn node<'a>(
38 plan: &'a Plan,
39 catalog: &'a Catalog,
40 reference: NodeRef,
41) -> Result<Box<dyn Operator + 'a>> {
42 Ok(match *plan.node(reference) {
43 Node::Get { catalog: database, schema, table, index, columns, .. } => {
44 let name =
45 QualifiedName::new(plan.string(database), plan.string(schema), plan.string(table));
46 Box::new(Scan::new(plan, catalog.table(&name)?, index, columns)?)
47 }
48 Node::Dummy => Box::new(Dummy::new()),
49 Node::Values { index, columns, rows } => Box::new(Values::new(plan, index, columns, rows)?),
50 Node::TableFunction { index, function, args, columns } => {
51 match TableFunction::lookup(plan.string(function)) {
52 Some(function @ (TableFunction::ReadParquet | TableFunction::ReadCsv)) => {
53 Box::new(FileScan::new(plan, index, function, args, columns)?)
54 }
55 _ => Box::new(Series::new(plan, index, plan.string(function), args)?),
56 }
57 }
58 Node::Filter { input, predicate } => {
59 Box::new(Filter::new(plan, node(plan, catalog, input)?, predicate)?)
60 }
61 Node::Project { input, index, exprs, names } => {
62 Box::new(Project::new(plan, node(plan, catalog, input)?, index, exprs, names)?)
63 }
64 Node::Aggregate { input, index, groups, aggregates } => {
65 Box::new(Aggregate::new(plan, node(plan, catalog, input)?, index, groups, aggregates)?)
66 }
67 Node::Sort { input, keys } => Box::new(Sort::new(plan, node(plan, catalog, input)?, keys)),
68 Node::Limit { input, count, offset } => {
69 Box::new(Limit::new(node(plan, catalog, input)?, count, offset))
70 }
71 Node::Distinct { input, on } => {
72 Box::new(Distinct::new(plan, node(plan, catalog, input)?, on))
73 }
74 Node::Join { left, right, kind, conditions } => Box::new(Join::new(
75 plan,
76 node(plan, catalog, left)?,
77 node(plan, catalog, right)?,
78 kind,
79 conditions,
80 )),
81 Node::CrossProduct { left, right } => {
82 Box::new(CrossProduct::new(node(plan, catalog, left)?, node(plan, catalog, right)?))
83 }
84 Node::SetOp { left, right, kind, all, index } => Box::new(SetOp::new(
85 node(plan, catalog, left)?,
86 node(plan, catalog, right)?,
87 kind,
88 all,
89 index,
90 )),
91 })
92}