1use std::sync::Arc;
29
30use rudb_catalog::{Catalog, QualifiedName};
31use rudb_common::{Cancel, Memory, Result};
32use rudb_functions::TableFunction;
33use rudb_metrics::{Counters, Report};
34use rudb_pipeline::{Source, Watched};
35use rudb_plan::{Node, NodeRef, Plan, Shape};
36
37use crate::adapt::{Broken, Fed, Paired, Pulled, Streamed};
38use crate::cancel::Guarded;
39use crate::gather::{Gather, Keep};
40use crate::group::{Aggregate, Distinct};
41use crate::join::{CrossProduct, Gathered, Join};
42use crate::operator::Operator;
43use crate::schema::Schema;
44use crate::setop::SetOp;
45use crate::sort::Sort;
46use crate::source::{Dummy, FileScan, Scan, Series, Values};
47use crate::strategies::Strategies;
48use crate::stream::{Filter, Limit, Project};
49use crate::topn::TopN;
50
51pub fn build<'a>(plan: &'a Plan, catalog: &'a Catalog) -> Result<Box<dyn Operator + 'a>> {
58 build_with(plan, catalog, &Cancel::new(), &Memory::unlimited())
59}
60
61pub fn build_with<'a>(
81 plan: &'a Plan,
82 catalog: &'a Catalog,
83 cancel: &Cancel,
84 memory: &Memory,
85) -> Result<Box<dyn Operator + 'a>> {
86 build_measured(plan, catalog, cancel, memory, &Report::new())
87}
88
89pub fn build_measured<'a>(
99 plan: &'a Plan,
100 catalog: &'a Catalog,
101 cancel: &Cancel,
102 memory: &Memory,
103 report: &Report,
104) -> Result<Box<dyn Operator + 'a>> {
105 let shape = Shape::of(plan);
106 for pipeline in shape.all() {
107 report.pipeline(pipeline);
108 for waits_for in shape.waits_for(pipeline) {
109 report.depends(pipeline, *waits_for);
110 }
111 }
112 let building = Building { plan, catalog, cancel, memory, report, shape };
113 building.node(plan.root())
114}
115
116struct Building<'a, 'b> {
118 plan: &'a Plan,
119 catalog: &'a Catalog,
120 cancel: &'b Cancel,
121 memory: &'b Memory,
122 report: &'b Report,
123 shape: Shape,
124}
125
126impl<'a> Building<'a, '_> {
127 fn gathered(&self, node: NodeRef) -> u32 {
139 self.shape.gathered(node).expect("a node with two inputs has a second operator")
140 }
141
142 fn watch(&self, id: u32, pipeline: u32, kind: &str, detail: Option<&str>) -> Arc<Counters> {
143 let counters = Counters::new(id, pipeline, kind).reference();
144 let counters = match detail {
145 Some(detail) => counters.detailed(detail),
146 None => counters,
147 };
148 self.report.watch(counters)
149 }
150
151 fn node(&self, reference: NodeRef) -> Result<Box<dyn Operator + 'a>> {
152 let plan = self.plan;
153 let memory = self.memory;
154 let id = self.shape.operator(reference);
155 let pipeline = self.shape.pipeline(reference);
156 let inner: Box<dyn Operator + 'a> = match *plan.node(reference) {
157 Node::Get { catalog: database, schema, table, index, columns, .. } => {
158 let name = QualifiedName::new(
159 plan.string(database),
160 plan.string(schema),
161 plan.string(table),
162 );
163 let scan = Scan::new(plan, self.catalog.table(&name)?, index, columns)?;
164 let schema = scan.schema().clone();
165 let counters = self.watch(id, pipeline, "Scan", Some(plan.string(table)));
166 pulled(Watched::new(scan, counters), schema)
167 }
168 Node::Dummy => {
169 let dummy = Dummy::new();
170 let schema = dummy.schema().clone();
171 pulled(Watched::new(dummy, self.watch(id, pipeline, "Dummy", None)), schema)
172 }
173 Node::Values { index, columns, rows } => {
174 let values = Values::new(plan, index, columns, rows)?;
175 let schema = values.schema().clone();
176 pulled(Watched::new(values, self.watch(id, pipeline, "Values", None)), schema)
177 }
178 Node::TableFunction { index, function, args, options, settings, columns } => {
179 let name = plan.string(function);
180 match TableFunction::lookup(name) {
181 Some(function @ (TableFunction::ReadParquet | TableFunction::ReadCsv)) => {
182 let scan =
183 FileScan::new(plan, index, function, args, options, settings, columns)?;
184 let schema = scan.schema().clone();
185 let counters = self.watch(id, pipeline, "FileScan", Some(name));
186 pulled(Watched::new(scan, counters), schema)
187 }
188 Some(TableFunction::RudbStrategies) => {
189 let table = Strategies::new(plan, index, columns)?;
190 let schema = table.schema().clone();
191 let counters = self.watch(id, pipeline, "Strategies", None);
192 pulled(Watched::new(table, counters), schema)
193 }
194 _ => {
195 let series = Series::new(plan, index, name, args)?;
196 let schema = series.schema().clone();
197 let counters = self.watch(id, pipeline, "Series", Some(name));
198 pulled(Watched::new(series, counters), schema)
199 }
200 }
201 }
202 Node::Filter { input, predicate } => {
203 let input = self.node(input)?;
204 let schema = input.schema().clone();
205 let filter = Filter::new(plan, predicate, &schema)?;
206 let counters = self.watch(id, pipeline, "Filter", None);
207 Box::new(Streamed::new(input, Watched::new(filter, counters), schema))
208 }
209 Node::Project { input, index, exprs, names } => {
210 let input = self.node(input)?;
211 let project = Project::new(plan, input.schema(), index, exprs, names)?;
212 let schema = project.schema().clone();
213 let counters = self.watch(id, pipeline, "Project", None);
214 Box::new(Streamed::new(input, Watched::new(project, counters), schema))
215 }
216 Node::Aggregate { input, index, groups, aggregates } => {
217 let input = self.node(input)?;
218 let (aggregate, out) =
219 Aggregate::new(plan, input.schema(), index, groups, aggregates, memory)?;
220 let schema = aggregate.schema().clone();
221 let counters = self.watch(id, pipeline, "Aggregate", None);
222 let made = Arc::clone(&counters);
223 let driver = self.report.driving(pipeline);
224 Box::new(Broken::new(
225 input,
226 Watched::new(aggregate, counters),
227 driver,
228 out,
229 made,
230 schema,
231 ))
232 }
233 Node::Sort { input, keys } => {
234 let input = self.node(input)?;
235 let schema = input.schema().clone();
236 let (sort, out) = Sort::new(plan, &schema, keys, memory)?;
237 let counters = self.watch(id, pipeline, "Sort", None);
238 let made = Arc::clone(&counters);
239 let driver = self.report.driving(pipeline);
240 Box::new(Broken::new(
241 input,
242 Watched::new(sort, counters),
243 driver,
244 out,
245 made,
246 schema,
247 ))
248 }
249 Node::Limit { input, count, offset } => {
250 let input = self.node(input)?;
251 let schema = input.schema().clone();
252 let limit = Limit::new(count, offset);
253 let counters = self.watch(id, pipeline, "Limit", None);
254 Box::new(Streamed::new(input, Watched::new(limit, counters), schema))
255 }
256 Node::TopN { input, keys, count, offset } => {
257 let input = self.node(input)?;
258 let schema = input.schema().clone();
259 let (top, out) = TopN::new(plan, &schema, keys, count, offset, memory)?;
260 let counters = self.watch(id, pipeline, "TopN", None);
261 let made = Arc::clone(&counters);
262 let driver = self.report.driving(pipeline);
263 Box::new(Broken::new(input, Watched::new(top, counters), driver, out, made, schema))
264 }
265 Node::Distinct { input, on } => {
266 let input = self.node(input)?;
267 let schema = input.schema().clone();
268 let (distinct, out) = Distinct::new(plan, &schema, on, memory)?;
269 let counters = self.watch(id, pipeline, "Distinct", None);
270 let made = Arc::clone(&counters);
271 let driver = self.report.driving(pipeline);
272 Box::new(Broken::new(
273 input,
274 Watched::new(distinct, counters),
275 driver,
276 out,
277 made,
278 schema,
279 ))
280 }
281 Node::Join { left, right, kind, conditions } => {
282 let gather_id = self.gathered(reference);
288 let gathering = self.shape.pipeline(right);
289 let right = self.node(right)?;
290 let left = self.node(left)?;
291 let (gather, gathered) = Gather::new(memory);
292 let side = Gathered { schema: right.schema(), rows: gathered };
293 let (join, out) =
294 Join::new(plan, left.schema(), side, kind, conditions, self.cancel, memory);
295 let schema = join.schema().clone();
296 let kept = self.watch(gather_id, gathering, "Gather", None);
297 let counters = self.watch(id, pipeline, "Join", None);
298 let made = Arc::clone(&counters);
299 Box::new(Paired::new(
300 right,
301 Watched::new(gather, kept),
302 self.report.driving(gathering),
303 left,
304 Watched::new(join, counters),
305 self.report.driving(pipeline),
306 out,
307 made,
308 schema,
309 ))
310 }
311 Node::CrossProduct { left, right } => {
312 let keep_id = self.gathered(reference);
317 let aside = self.shape.pipeline(right);
318 let right = self.node(right)?;
319 let left = self.node(left)?;
320 let (keep, kept) = Keep::new(memory);
321 let cross = CrossProduct::new(left.schema(), right.schema(), kept);
322 let schema = cross.schema().clone();
323 let held = self.watch(keep_id, aside, "Keep", None);
324 let counters = self.watch(id, pipeline, "CrossProduct", None);
325 Box::new(Fed::new(
326 right,
327 Watched::new(keep, held),
328 self.report.driving(aside),
329 Streamed::new(left, Watched::new(cross, counters), schema),
330 ))
331 }
332 Node::SetOp { left, right, kind, all, index } => {
333 let gather_id = self.gathered(reference);
336 let counting = self.shape.pipeline(right);
337 let right = self.node(right)?;
338 let left = self.node(left)?;
339 let (gather, gathered) = Gather::new(memory);
340 let (setop, out) = SetOp::new(left.schema(), gathered, kind, all, index, memory);
341 let schema = setop.schema().clone();
342 let kept = self.watch(gather_id, counting, "Gather", None);
343 let counters = self.watch(id, pipeline, "SetOp", None);
344 let made = Arc::clone(&counters);
345 Box::new(Paired::new(
346 right,
347 Watched::new(gather, kept),
348 self.report.driving(counting),
349 left,
350 Watched::new(setop, counters),
351 self.report.driving(pipeline),
352 out,
353 made,
354 schema,
355 ))
356 }
357 };
358 Ok(Box::new(Guarded::new(inner, self.cancel.clone())))
359 }
360}
361
362fn pulled<'a, S: Source + 'a>(source: S, schema: Schema) -> Box<dyn Operator + 'a> {
369 Box::new(Pulled::new(source, schema))
370}