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, Slice, seams_of};
36use rudb_seam::Settings;
37
38use crate::adapt::{Broken, Fed, Paired, Pulled, Streamed};
39use crate::cancel::Guarded;
40use crate::fetch::Fetch;
41use crate::gather::{Gather, Keep};
42use crate::group::{Aggregate, Distinct};
43use crate::join::{CrossProduct, Gathered, Join};
44use crate::operator::Operator;
45use crate::register::registries;
46use crate::schema::Schema;
47use crate::setop::SetOp;
48use crate::sort::Sort;
49use crate::source::{Dummy, FileScan, Scan, Series, Values};
50use crate::strategies::Strategies;
51use crate::stream::{Filter, Limit, Project};
52use crate::topn::TopN;
53
54pub fn build<'a>(plan: &'a Plan, catalog: &'a Catalog) -> Result<Box<dyn Operator + 'a>> {
64 build_with(plan, catalog, &Cancel::new(), &Memory::unlimited(), &Settings::new())
65}
66
67pub fn build_with<'a>(
92 plan: &'a Plan,
93 catalog: &'a Catalog,
94 cancel: &Cancel,
95 memory: &Memory,
96 seams: &Settings,
97) -> Result<Box<dyn Operator + 'a>> {
98 build_measured(plan, catalog, cancel, memory, seams, &Report::new())
99}
100
101pub fn build_measured<'a>(
111 plan: &'a Plan,
112 catalog: &'a Catalog,
113 cancel: &Cancel,
114 memory: &Memory,
115 seams: &Settings,
116 report: &Report,
117) -> Result<Box<dyn Operator + 'a>> {
118 let shape = Shape::of(plan);
119 for pipeline in shape.all() {
120 report.pipeline(pipeline);
121 for waits_for in shape.waits_for(pipeline) {
122 report.depends(pipeline, *waits_for);
123 }
124 }
125 let building = Building { plan, catalog, cancel, memory, seams, report, shape };
126 building.node(plan.root())
127}
128
129struct Building<'a, 'b> {
131 plan: &'a Plan,
132 catalog: &'a Catalog,
133 cancel: &'b Cancel,
134 memory: &'b Memory,
135 seams: &'b Settings,
136 report: &'b Report,
137 shape: Shape,
138}
139
140impl<'a> Building<'a, '_> {
141 fn gathered(&self, node: NodeRef) -> u32 {
147 self.shape.gathered(node).expect("a node with two inputs has a second operator")
148 }
149
150 fn watch(
165 &self,
166 node: NodeRef,
167 id: u32,
168 pipeline: u32,
169 kind: &str,
170 detail: Option<&str>,
171 ) -> Arc<Counters> {
172 let mut counters = Counters::new(id, pipeline, kind);
173 if let Some(detail) = detail {
174 counters = counters.detailed(detail);
175 }
176 for seam in seams_of(self.plan.node(node)) {
177 if let Some(running) = registries().running(*seam, self.seams) {
178 counters = counters.chose(seam.name(), &running.name, running.is_reference);
179 }
180 }
181 self.report.watch(counters)
182 }
183
184 fn aggregate(
185 &self,
186 reference: NodeRef,
187 input: NodeRef,
188 index: u32,
189 groups: Slice,
190 aggregates: Slice,
191 max_groups: Option<usize>,
192 ) -> Result<Box<dyn Operator + 'a>> {
193 let child = self.node(input)?;
194 let (aggregate, out) =
195 Aggregate::new(self.plan, child.schema(), index, groups, aggregates, self.memory)?;
196 let aggregate = match max_groups {
197 Some(limit) => aggregate.limit_groups(limit),
198 None => aggregate,
199 };
200 let schema = aggregate.schema().clone();
201 let id = self.shape.operator(reference);
202 let pipeline = self.shape.pipeline(reference);
203 let counters = self.watch(reference, id, pipeline, "Aggregate", None);
204 let made = Arc::clone(&counters);
205 let driver = self.report.driving(pipeline);
206 Ok(Box::new(Broken::new(
207 child,
208 Watched::new(aggregate, counters),
209 driver,
210 out,
211 made,
212 schema,
213 )))
214 }
215
216 fn node(&self, reference: NodeRef) -> Result<Box<dyn Operator + 'a>> {
217 let plan = self.plan;
218 let memory = self.memory;
219 let id = self.shape.operator(reference);
220 let pipeline = self.shape.pipeline(reference);
221 let inner: Box<dyn Operator + 'a> = match *plan.node(reference) {
222 Node::Get { catalog: database, schema, table, index, columns, .. } => {
223 let name = QualifiedName::new(
224 plan.string(database),
225 plan.string(schema),
226 plan.string(table),
227 );
228 let scan = Scan::new(plan, self.catalog.table(&name)?, index, columns)?;
229 let schema = scan.schema().clone();
230 let counters =
231 self.watch(reference, id, pipeline, "Scan", Some(plan.string(table)));
232 pulled(Watched::new(scan, counters), schema)
233 }
234 Node::Dummy => {
235 let dummy = Dummy::new();
236 let schema = dummy.schema().clone();
237 pulled(
238 Watched::new(dummy, self.watch(reference, id, pipeline, "Dummy", None)),
239 schema,
240 )
241 }
242 Node::Values { index, columns, rows } => {
243 let values = Values::new(plan, index, columns, rows)?;
244 let schema = values.schema().clone();
245 pulled(
246 Watched::new(values, self.watch(reference, id, pipeline, "Values", None)),
247 schema,
248 )
249 }
250 Node::TableFunction { index, function, args, options, settings, columns } => {
251 let name = plan.string(function);
252 match TableFunction::lookup(name) {
253 Some(function @ (TableFunction::ReadParquet | TableFunction::ReadCsv)) => {
254 let counters = self.watch(reference, id, pipeline, "FileScan", Some(name));
255 let scan =
256 FileScan::new(plan, index, function, args, options, settings, columns)?
257 .watched(counters.clone());
258 let schema = scan.schema().clone();
259 pulled(Watched::new(scan, counters), schema)
260 }
261 Some(TableFunction::RudbStrategies) => {
262 let table = Strategies::new(plan, index, columns)?;
263 let schema = table.schema().clone();
264 let counters = self.watch(reference, id, pipeline, "Strategies", None);
265 pulled(Watched::new(table, counters), schema)
266 }
267 _ => {
268 let series = Series::new(plan, index, name, args)?;
269 let schema = series.schema().clone();
270 let counters = self.watch(reference, id, pipeline, "Series", Some(name));
271 pulled(Watched::new(series, counters), schema)
272 }
273 }
274 }
275 Node::Fetch { input, index, args, columns, row } => {
276 let input = self.node(input)?;
277 let counters = self.watch(reference, id, pipeline, "Fetch", None);
278 let fetch = Fetch::new(plan, input.schema(), index, args, columns, row)?
279 .watched(counters.clone());
280 let schema = fetch.schema().clone();
281 Box::new(Streamed::new(input, Watched::new(fetch, counters), schema))
282 }
283 Node::Filter { input, predicate } => {
284 let input = self.node(input)?;
285 let schema = input.schema().clone();
286 let filter = Filter::new(plan, reference, predicate, &schema, self.seams)?;
287 let counters = self.watch(reference, id, pipeline, "Filter", None);
288 Box::new(Streamed::new(input, Watched::new(filter, counters), schema))
289 }
290 Node::Project { input, index, exprs, names } => {
291 let input = self.node(input)?;
292 let project = Project::new(plan, input.schema(), index, exprs, names)?;
293 let schema = project.schema().clone();
294 let counters = self.watch(reference, id, pipeline, "Project", None);
295 Box::new(Streamed::new(input, Watched::new(project, counters), schema))
296 }
297 Node::Aggregate { input, index, groups, aggregates } => {
298 self.aggregate(reference, input, index, groups, aggregates, None)?
299 }
300 Node::Sort { input, keys } => {
301 let input = self.node(input)?;
302 let schema = input.schema().clone();
303 let (sort, out) = Sort::new(plan, &schema, keys, memory)?;
304 let counters = self.watch(reference, id, pipeline, "Sort", None);
305 let made = Arc::clone(&counters);
306 let driver = self.report.driving(pipeline);
307 Box::new(Broken::new(
308 input,
309 Watched::new(sort, counters),
310 driver,
311 out,
312 made,
313 schema,
314 ))
315 }
316 Node::Limit { input, count, offset } => {
317 let max_groups = count
318 .and_then(|count| count.checked_add(offset))
319 .and_then(|count| usize::try_from(count).ok());
320 let input = match (plan.node(input).clone(), max_groups) {
321 (
322 Node::Aggregate { input: below, index, groups, aggregates },
323 Some(max_groups),
324 ) => {
325 self.aggregate(input, below, index, groups, aggregates, Some(max_groups))?
326 }
327 _ => self.node(input)?,
328 };
329 let schema = input.schema().clone();
330 let limit = Limit::new(count, offset);
331 let counters = self.watch(reference, id, pipeline, "Limit", None);
332 Box::new(Streamed::new(input, Watched::new(limit, counters), schema))
333 }
334 Node::TopN { input, keys, count, offset } => {
335 let input = self.node(input)?;
336 let schema = input.schema().clone();
337 let (top, out) = TopN::new(plan, &schema, keys, count, offset, memory)?;
338 let counters = self.watch(reference, id, pipeline, "TopN", None);
339 let made = Arc::clone(&counters);
340 let driver = self.report.driving(pipeline);
341 Box::new(Broken::new(input, Watched::new(top, counters), driver, out, made, schema))
342 }
343 Node::Distinct { input, on } => {
344 let input = self.node(input)?;
345 let schema = input.schema().clone();
346 let (distinct, out) = Distinct::new(plan, &schema, on, memory)?;
347 let counters = self.watch(reference, id, pipeline, "Distinct", None);
348 let made = Arc::clone(&counters);
349 let driver = self.report.driving(pipeline);
350 Box::new(Broken::new(
351 input,
352 Watched::new(distinct, counters),
353 driver,
354 out,
355 made,
356 schema,
357 ))
358 }
359 Node::Join { left, right, kind, conditions } => {
360 let gather_id = self.gathered(reference);
366 let gathering = self.shape.pipeline(right);
367 let right = self.node(right)?;
368 let left = self.node(left)?;
369 let (gather, gathered) = Gather::new(memory);
370 let side = Gathered { schema: right.schema(), rows: gathered };
371 let (join, out) =
372 Join::new(plan, left.schema(), side, kind, conditions, self.cancel, memory);
373 let schema = join.schema().clone();
374 let kept = self.watch(reference, gather_id, gathering, "Gather", None);
375 let counters = self.watch(reference, id, pipeline, "Join", None);
376 let made = Arc::clone(&counters);
377 Box::new(Paired::new(
378 right,
379 Watched::new(gather, kept),
380 self.report.driving(gathering),
381 left,
382 Watched::new(join, counters),
383 self.report.driving(pipeline),
384 out,
385 made,
386 schema,
387 ))
388 }
389 Node::CrossProduct { left, right } => {
390 let keep_id = self.gathered(reference);
395 let aside = self.shape.pipeline(right);
396 let right = self.node(right)?;
397 let left = self.node(left)?;
398 let (keep, kept) = Keep::new(memory);
399 let cross = CrossProduct::new(left.schema(), right.schema(), kept);
400 let schema = cross.schema().clone();
401 let held = self.watch(reference, keep_id, aside, "Keep", None);
402 let counters = self.watch(reference, id, pipeline, "CrossProduct", None);
403 Box::new(Fed::new(
404 right,
405 Watched::new(keep, held),
406 self.report.driving(aside),
407 Streamed::new(left, Watched::new(cross, counters), schema),
408 ))
409 }
410 Node::SetOp { left, right, kind, all, index } => {
411 let gather_id = self.gathered(reference);
414 let counting = self.shape.pipeline(right);
415 let right = self.node(right)?;
416 let left = self.node(left)?;
417 let (gather, gathered) = Gather::new(memory);
418 let (setop, out) = SetOp::new(left.schema(), gathered, kind, all, index, memory);
419 let schema = setop.schema().clone();
420 let kept = self.watch(reference, gather_id, counting, "Gather", None);
421 let counters = self.watch(reference, id, pipeline, "SetOp", None);
422 let made = Arc::clone(&counters);
423 Box::new(Paired::new(
424 right,
425 Watched::new(gather, kept),
426 self.report.driving(counting),
427 left,
428 Watched::new(setop, counters),
429 self.report.driving(pipeline),
430 out,
431 made,
432 schema,
433 ))
434 }
435 };
436 Ok(Box::new(Guarded::new(inner, self.cancel.clone())))
437 }
438}
439
440fn pulled<'a, S: Source + 'a>(source: S, schema: Schema) -> Box<dyn Operator + 'a> {
447 Box::new(Pulled::new(source, schema))
448}