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};
36use rudb_seam::Settings;
37
38use crate::adapt::{Broken, Fed, Paired, Pulled, Streamed};
39use crate::cancel::Guarded;
40use crate::gather::{Gather, Keep};
41use crate::group::{Aggregate, Distinct};
42use crate::join::{CrossProduct, Gathered, Join};
43use crate::operator::Operator;
44use crate::schema::Schema;
45use crate::setop::SetOp;
46use crate::sort::Sort;
47use crate::source::{Dummy, FileScan, Scan, Series, Values};
48use crate::strategies::Strategies;
49use crate::stream::{Filter, Limit, Project};
50use crate::topn::TopN;
51
52pub fn build<'a>(plan: &'a Plan, catalog: &'a Catalog) -> Result<Box<dyn Operator + 'a>> {
62 build_with(plan, catalog, &Cancel::new(), &Memory::unlimited(), &Settings::new())
63}
64
65pub fn build_with<'a>(
90 plan: &'a Plan,
91 catalog: &'a Catalog,
92 cancel: &Cancel,
93 memory: &Memory,
94 seams: &Settings,
95) -> Result<Box<dyn Operator + 'a>> {
96 build_measured(plan, catalog, cancel, memory, seams, &Report::new())
97}
98
99pub fn build_measured<'a>(
109 plan: &'a Plan,
110 catalog: &'a Catalog,
111 cancel: &Cancel,
112 memory: &Memory,
113 seams: &Settings,
114 report: &Report,
115) -> Result<Box<dyn Operator + 'a>> {
116 let shape = Shape::of(plan);
117 for pipeline in shape.all() {
118 report.pipeline(pipeline);
119 for waits_for in shape.waits_for(pipeline) {
120 report.depends(pipeline, *waits_for);
121 }
122 }
123 let building = Building { plan, catalog, cancel, memory, seams, report, shape };
124 building.node(plan.root())
125}
126
127struct Building<'a, 'b> {
129 plan: &'a Plan,
130 catalog: &'a Catalog,
131 cancel: &'b Cancel,
132 memory: &'b Memory,
133 seams: &'b Settings,
134 report: &'b Report,
135 shape: Shape,
136}
137
138impl<'a> Building<'a, '_> {
139 fn gathered(&self, node: NodeRef) -> u32 {
151 self.shape.gathered(node).expect("a node with two inputs has a second operator")
152 }
153
154 fn watch(&self, id: u32, pipeline: u32, kind: &str, detail: Option<&str>) -> Arc<Counters> {
155 let counters = Counters::new(id, pipeline, kind).reference();
156 let counters = match detail {
157 Some(detail) => counters.detailed(detail),
158 None => counters,
159 };
160 self.report.watch(counters)
161 }
162
163 fn node(&self, reference: NodeRef) -> Result<Box<dyn Operator + 'a>> {
164 let plan = self.plan;
165 let memory = self.memory;
166 let id = self.shape.operator(reference);
167 let pipeline = self.shape.pipeline(reference);
168 let inner: Box<dyn Operator + 'a> = match *plan.node(reference) {
169 Node::Get { catalog: database, schema, table, index, columns, .. } => {
170 let name = QualifiedName::new(
171 plan.string(database),
172 plan.string(schema),
173 plan.string(table),
174 );
175 let scan = Scan::new(plan, self.catalog.table(&name)?, index, columns)?;
176 let schema = scan.schema().clone();
177 let counters = self.watch(id, pipeline, "Scan", Some(plan.string(table)));
178 pulled(Watched::new(scan, counters), schema)
179 }
180 Node::Dummy => {
181 let dummy = Dummy::new();
182 let schema = dummy.schema().clone();
183 pulled(Watched::new(dummy, self.watch(id, pipeline, "Dummy", None)), schema)
184 }
185 Node::Values { index, columns, rows } => {
186 let values = Values::new(plan, index, columns, rows)?;
187 let schema = values.schema().clone();
188 pulled(Watched::new(values, self.watch(id, pipeline, "Values", None)), schema)
189 }
190 Node::TableFunction { index, function, args, options, settings, columns } => {
191 let name = plan.string(function);
192 match TableFunction::lookup(name) {
193 Some(function @ (TableFunction::ReadParquet | TableFunction::ReadCsv)) => {
194 let scan =
195 FileScan::new(plan, index, function, args, options, settings, columns)?;
196 let schema = scan.schema().clone();
197 let counters = self.watch(id, pipeline, "FileScan", Some(name));
198 pulled(Watched::new(scan, counters), schema)
199 }
200 Some(TableFunction::RudbStrategies) => {
201 let table = Strategies::new(plan, index, columns)?;
202 let schema = table.schema().clone();
203 let counters = self.watch(id, pipeline, "Strategies", None);
204 pulled(Watched::new(table, counters), schema)
205 }
206 _ => {
207 let series = Series::new(plan, index, name, args)?;
208 let schema = series.schema().clone();
209 let counters = self.watch(id, pipeline, "Series", Some(name));
210 pulled(Watched::new(series, counters), schema)
211 }
212 }
213 }
214 Node::Filter { input, predicate } => {
215 let input = self.node(input)?;
216 let schema = input.schema().clone();
217 let filter = Filter::new(plan, reference, predicate, &schema, self.seams)?;
218 let counters = self.watch(id, pipeline, "Filter", None);
219 Box::new(Streamed::new(input, Watched::new(filter, counters), schema))
220 }
221 Node::Project { input, index, exprs, names } => {
222 let input = self.node(input)?;
223 let project = Project::new(plan, input.schema(), index, exprs, names)?;
224 let schema = project.schema().clone();
225 let counters = self.watch(id, pipeline, "Project", None);
226 Box::new(Streamed::new(input, Watched::new(project, counters), schema))
227 }
228 Node::Aggregate { input, index, groups, aggregates } => {
229 let input = self.node(input)?;
230 let (aggregate, out) =
231 Aggregate::new(plan, input.schema(), index, groups, aggregates, memory)?;
232 let schema = aggregate.schema().clone();
233 let counters = self.watch(id, pipeline, "Aggregate", None);
234 let made = Arc::clone(&counters);
235 let driver = self.report.driving(pipeline);
236 Box::new(Broken::new(
237 input,
238 Watched::new(aggregate, counters),
239 driver,
240 out,
241 made,
242 schema,
243 ))
244 }
245 Node::Sort { input, keys } => {
246 let input = self.node(input)?;
247 let schema = input.schema().clone();
248 let (sort, out) = Sort::new(plan, &schema, keys, memory)?;
249 let counters = self.watch(id, pipeline, "Sort", None);
250 let made = Arc::clone(&counters);
251 let driver = self.report.driving(pipeline);
252 Box::new(Broken::new(
253 input,
254 Watched::new(sort, counters),
255 driver,
256 out,
257 made,
258 schema,
259 ))
260 }
261 Node::Limit { input, count, offset } => {
262 let input = self.node(input)?;
263 let schema = input.schema().clone();
264 let limit = Limit::new(count, offset);
265 let counters = self.watch(id, pipeline, "Limit", None);
266 Box::new(Streamed::new(input, Watched::new(limit, counters), schema))
267 }
268 Node::TopN { input, keys, count, offset } => {
269 let input = self.node(input)?;
270 let schema = input.schema().clone();
271 let (top, out) = TopN::new(plan, &schema, keys, count, offset, memory)?;
272 let counters = self.watch(id, pipeline, "TopN", None);
273 let made = Arc::clone(&counters);
274 let driver = self.report.driving(pipeline);
275 Box::new(Broken::new(input, Watched::new(top, counters), driver, out, made, schema))
276 }
277 Node::Distinct { input, on } => {
278 let input = self.node(input)?;
279 let schema = input.schema().clone();
280 let (distinct, out) = Distinct::new(plan, &schema, on, memory)?;
281 let counters = self.watch(id, pipeline, "Distinct", None);
282 let made = Arc::clone(&counters);
283 let driver = self.report.driving(pipeline);
284 Box::new(Broken::new(
285 input,
286 Watched::new(distinct, counters),
287 driver,
288 out,
289 made,
290 schema,
291 ))
292 }
293 Node::Join { left, right, kind, conditions } => {
294 let gather_id = self.gathered(reference);
300 let gathering = self.shape.pipeline(right);
301 let right = self.node(right)?;
302 let left = self.node(left)?;
303 let (gather, gathered) = Gather::new(memory);
304 let side = Gathered { schema: right.schema(), rows: gathered };
305 let (join, out) =
306 Join::new(plan, left.schema(), side, kind, conditions, self.cancel, memory);
307 let schema = join.schema().clone();
308 let kept = self.watch(gather_id, gathering, "Gather", None);
309 let counters = self.watch(id, pipeline, "Join", None);
310 let made = Arc::clone(&counters);
311 Box::new(Paired::new(
312 right,
313 Watched::new(gather, kept),
314 self.report.driving(gathering),
315 left,
316 Watched::new(join, counters),
317 self.report.driving(pipeline),
318 out,
319 made,
320 schema,
321 ))
322 }
323 Node::CrossProduct { left, right } => {
324 let keep_id = self.gathered(reference);
329 let aside = self.shape.pipeline(right);
330 let right = self.node(right)?;
331 let left = self.node(left)?;
332 let (keep, kept) = Keep::new(memory);
333 let cross = CrossProduct::new(left.schema(), right.schema(), kept);
334 let schema = cross.schema().clone();
335 let held = self.watch(keep_id, aside, "Keep", None);
336 let counters = self.watch(id, pipeline, "CrossProduct", None);
337 Box::new(Fed::new(
338 right,
339 Watched::new(keep, held),
340 self.report.driving(aside),
341 Streamed::new(left, Watched::new(cross, counters), schema),
342 ))
343 }
344 Node::SetOp { left, right, kind, all, index } => {
345 let gather_id = self.gathered(reference);
348 let counting = self.shape.pipeline(right);
349 let right = self.node(right)?;
350 let left = self.node(left)?;
351 let (gather, gathered) = Gather::new(memory);
352 let (setop, out) = SetOp::new(left.schema(), gathered, kind, all, index, memory);
353 let schema = setop.schema().clone();
354 let kept = self.watch(gather_id, counting, "Gather", None);
355 let counters = self.watch(id, pipeline, "SetOp", None);
356 let made = Arc::clone(&counters);
357 Box::new(Paired::new(
358 right,
359 Watched::new(gather, kept),
360 self.report.driving(counting),
361 left,
362 Watched::new(setop, counters),
363 self.report.driving(pipeline),
364 out,
365 made,
366 schema,
367 ))
368 }
369 };
370 Ok(Box::new(Guarded::new(inner, self.cancel.clone())))
371 }
372}
373
374fn pulled<'a, S: Source + 'a>(source: S, schema: Schema) -> Box<dyn Operator + 'a> {
381 Box::new(Pulled::new(source, schema))
382}