1use crate::extensions::Extensions;
19use crate::logical_plan::producer::{
20 from_aggregate, from_aggregate_function, from_alias, from_between, from_binary_expr,
21 from_case, from_cast, from_column, from_distinct, from_empty_relation, from_exists,
22 from_filter, from_higher_order_function, from_in_list, from_in_subquery, from_join,
23 from_lambda, from_lambda_variable, from_like, from_limit, from_literal,
24 from_placeholder, from_projection, from_repartition, from_scalar_function,
25 from_scalar_subquery, from_set_comparison, from_sort, from_subquery_alias,
26 from_table_scan, from_try_cast, from_unary_expr, from_union, from_values,
27 from_window, from_window_function, to_substrait_rel, to_substrait_rex,
28 to_substrait_type_from_field,
29};
30use datafusion::arrow::datatypes::FieldRef;
31use datafusion::common::{
32 Column, DFSchemaRef, HashMap, ScalarValue, not_impl_err, substrait_err,
33};
34use datafusion::execution::SessionState;
35use datafusion::execution::registry::SerializerRegistry;
36use datafusion::logical_expr::Subquery;
37use datafusion::logical_expr::expr::{
38 Alias, Exists, InList, InSubquery, Lambda, LambdaVariable, Placeholder,
39 SetComparison, WindowFunction,
40};
41use datafusion::logical_expr::{
42 Aggregate, Between, BinaryExpr, Case, Cast, Distinct, EmptyRelation, Expr, Extension,
43 Filter, Join, Like, Limit, LogicalPlan, Projection, Repartition, Sort, SubqueryAlias,
44 TableScan, TryCast, Union, Values, Window, expr,
45};
46use pbjson_types::Any as ProtoAny;
47use substrait::proto::aggregate_rel::Measure;
48use substrait::proto::rel::RelType;
49use substrait::proto::{
50 Expression, ExtensionLeafRel, ExtensionMultiRel, ExtensionSingleRel, Rel,
51};
52
53pub trait SubstraitProducer: Send + Sync + Sized {
152 fn register_function(&mut self, signature: String) -> u32;
160
161 fn register_type(&mut self, name: String) -> u32;
169
170 fn get_extensions(self) -> Extensions;
173
174 fn handle_plan(
180 &mut self,
181 plan: &LogicalPlan,
182 ) -> datafusion::common::Result<Box<Rel>> {
183 to_substrait_rel(self, plan)
184 }
185
186 fn handle_projection(
187 &mut self,
188 plan: &Projection,
189 ) -> datafusion::common::Result<Box<Rel>> {
190 from_projection(self, plan)
191 }
192
193 fn handle_filter(&mut self, plan: &Filter) -> datafusion::common::Result<Box<Rel>> {
194 from_filter(self, plan)
195 }
196
197 fn handle_window(&mut self, plan: &Window) -> datafusion::common::Result<Box<Rel>> {
198 from_window(self, plan)
199 }
200
201 fn handle_aggregate(
202 &mut self,
203 plan: &Aggregate,
204 ) -> datafusion::common::Result<Box<Rel>> {
205 from_aggregate(self, plan)
206 }
207
208 fn handle_sort(&mut self, plan: &Sort) -> datafusion::common::Result<Box<Rel>> {
209 from_sort(self, plan)
210 }
211
212 fn handle_join(&mut self, plan: &Join) -> datafusion::common::Result<Box<Rel>> {
213 from_join(self, plan)
214 }
215
216 fn handle_repartition(
217 &mut self,
218 plan: &Repartition,
219 ) -> datafusion::common::Result<Box<Rel>> {
220 from_repartition(self, plan)
221 }
222
223 fn handle_union(&mut self, plan: &Union) -> datafusion::common::Result<Box<Rel>> {
224 from_union(self, plan)
225 }
226
227 fn handle_table_scan(
228 &mut self,
229 plan: &TableScan,
230 ) -> datafusion::common::Result<Box<Rel>> {
231 from_table_scan(self, plan)
232 }
233
234 fn handle_empty_relation(
235 &mut self,
236 plan: &EmptyRelation,
237 ) -> datafusion::common::Result<Box<Rel>> {
238 from_empty_relation(self, plan)
239 }
240
241 fn handle_subquery_alias(
242 &mut self,
243 plan: &SubqueryAlias,
244 ) -> datafusion::common::Result<Box<Rel>> {
245 from_subquery_alias(self, plan)
246 }
247
248 fn handle_limit(&mut self, plan: &Limit) -> datafusion::common::Result<Box<Rel>> {
249 from_limit(self, plan)
250 }
251
252 fn handle_values(&mut self, plan: &Values) -> datafusion::common::Result<Box<Rel>> {
253 from_values(self, plan)
254 }
255
256 fn handle_distinct(
257 &mut self,
258 plan: &Distinct,
259 ) -> datafusion::common::Result<Box<Rel>> {
260 from_distinct(self, plan)
261 }
262
263 fn handle_extension(
264 &mut self,
265 _plan: &Extension,
266 ) -> datafusion::common::Result<Box<Rel>> {
267 substrait_err!(
268 "Specify handling for LogicalPlan::Extension by implementing the SubstraitProducer trait"
269 )
270 }
271
272 fn handle_expr(
278 &mut self,
279 expr: &Expr,
280 schema: &DFSchemaRef,
281 ) -> datafusion::common::Result<Expression> {
282 to_substrait_rex(self, expr, schema)
283 }
284
285 fn handle_alias(
286 &mut self,
287 alias: &Alias,
288 schema: &DFSchemaRef,
289 ) -> datafusion::common::Result<Expression> {
290 from_alias(self, alias, schema)
291 }
292
293 fn handle_column(
294 &mut self,
295 column: &Column,
296 schema: &DFSchemaRef,
297 ) -> datafusion::common::Result<Expression> {
298 from_column(column, schema)
299 }
300
301 fn handle_literal(
302 &mut self,
303 value: &ScalarValue,
304 ) -> datafusion::common::Result<Expression> {
305 from_literal(self, value)
306 }
307
308 fn handle_binary_expr(
309 &mut self,
310 expr: &BinaryExpr,
311 schema: &DFSchemaRef,
312 ) -> datafusion::common::Result<Expression> {
313 from_binary_expr(self, expr, schema)
314 }
315
316 fn handle_like(
317 &mut self,
318 like: &Like,
319 schema: &DFSchemaRef,
320 ) -> datafusion::common::Result<Expression> {
321 from_like(self, like, schema)
322 }
323
324 fn handle_unary_expr(
326 &mut self,
327 expr: &Expr,
328 schema: &DFSchemaRef,
329 ) -> datafusion::common::Result<Expression> {
330 from_unary_expr(self, expr, schema)
331 }
332
333 fn handle_between(
334 &mut self,
335 between: &Between,
336 schema: &DFSchemaRef,
337 ) -> datafusion::common::Result<Expression> {
338 from_between(self, between, schema)
339 }
340
341 fn handle_case(
342 &mut self,
343 case: &Case,
344 schema: &DFSchemaRef,
345 ) -> datafusion::common::Result<Expression> {
346 from_case(self, case, schema)
347 }
348
349 fn handle_cast(
350 &mut self,
351 cast: &Cast,
352 schema: &DFSchemaRef,
353 ) -> datafusion::common::Result<Expression> {
354 from_cast(self, cast, schema)
355 }
356
357 fn handle_try_cast(
358 &mut self,
359 cast: &TryCast,
360 schema: &DFSchemaRef,
361 ) -> datafusion::common::Result<Expression> {
362 from_try_cast(self, cast, schema)
363 }
364
365 fn handle_scalar_function(
366 &mut self,
367 scalar_fn: &expr::ScalarFunction,
368 schema: &DFSchemaRef,
369 ) -> datafusion::common::Result<Expression> {
370 from_scalar_function(self, scalar_fn, schema)
371 }
372
373 fn handle_higher_order_function(
374 &mut self,
375 scalar_fn: &expr::HigherOrderFunction,
376 schema: &DFSchemaRef,
377 ) -> datafusion::common::Result<Expression> {
378 from_higher_order_function(self, scalar_fn, schema)
379 }
380
381 fn handle_aggregate_function(
382 &mut self,
383 agg_fn: &expr::AggregateFunction,
384 schema: &DFSchemaRef,
385 ) -> datafusion::common::Result<Measure> {
386 from_aggregate_function(self, agg_fn, schema)
387 }
388
389 fn handle_window_function(
390 &mut self,
391 window_fn: &WindowFunction,
392 schema: &DFSchemaRef,
393 ) -> datafusion::common::Result<Expression> {
394 from_window_function(self, window_fn, schema)
395 }
396
397 fn handle_in_list(
398 &mut self,
399 in_list: &InList,
400 schema: &DFSchemaRef,
401 ) -> datafusion::common::Result<Expression> {
402 from_in_list(self, in_list, schema)
403 }
404
405 fn handle_in_subquery(
406 &mut self,
407 in_subquery: &InSubquery,
408 schema: &DFSchemaRef,
409 ) -> datafusion::common::Result<Expression> {
410 from_in_subquery(self, in_subquery, schema)
411 }
412
413 fn handle_set_comparison(
414 &mut self,
415 set_comparison: &SetComparison,
416 schema: &DFSchemaRef,
417 ) -> datafusion::common::Result<Expression> {
418 from_set_comparison(self, set_comparison, schema)
419 }
420 fn handle_scalar_subquery(
421 &mut self,
422 subquery: &Subquery,
423 schema: &DFSchemaRef,
424 ) -> datafusion::common::Result<Expression> {
425 from_scalar_subquery(self, subquery, schema)
426 }
427
428 fn handle_exists(
429 &mut self,
430 exists: &Exists,
431 schema: &DFSchemaRef,
432 ) -> datafusion::common::Result<Expression> {
433 from_exists(self, exists, schema)
434 }
435
436 fn handle_placeholder(
437 &mut self,
438 placeholder: &Placeholder,
439 _schema: &DFSchemaRef,
440 ) -> datafusion::common::Result<Expression> {
441 from_placeholder(self, placeholder)
442 }
443
444 fn handle_lambda(
445 &mut self,
446 lambda: &Lambda,
447 schema: &DFSchemaRef,
448 ) -> datafusion::common::Result<Expression> {
449 from_lambda(self, lambda, schema)
450 }
451
452 fn handle_lambda_variable(
453 &mut self,
454 lambda_variable: &LambdaVariable,
455 schema: &DFSchemaRef,
456 ) -> datafusion::common::Result<Expression> {
457 from_lambda_variable(self, lambda_variable, schema)
458 }
459
460 fn push_lambda_parameters(
466 &mut self,
467 _lambda_parameters: Vec<FieldRef>,
468 ) -> datafusion::common::Result<()> {
469 not_impl_err!("SubstraitProducer::push_lambda_parameters")
470 }
471
472 fn pop_lambda_parameters(&mut self) -> datafusion::common::Result<()> {
476 not_impl_err!("SubstraitProducer::pop_lambda_parameters")
477 }
478
479 fn lambda_variable(&self, _name: &str) -> datafusion::common::Result<(u32, i32)> {
484 not_impl_err!("SubstraitProducer::lambda_variable")
485 }
486
487 fn lambda_parameter_type(
491 &self,
492 _name: &str,
493 ) -> datafusion::common::Result<substrait::proto::Type> {
494 not_impl_err!("SubstraitProducer::lambda_parameter_type")
495 }
496}
497
498pub struct DefaultSubstraitProducer<'a> {
499 extensions: Extensions,
500 serializer_registry: &'a dyn SerializerRegistry,
501 lambda_producer: DefaultSubstraitLambdaProducer,
502}
503
504impl<'a> DefaultSubstraitProducer<'a> {
505 pub fn new(state: &'a SessionState) -> Self {
506 DefaultSubstraitProducer {
507 extensions: Extensions::default(),
508 serializer_registry: state.serializer_registry().as_ref(),
509 lambda_producer: DefaultSubstraitLambdaProducer::new(),
510 }
511 }
512}
513
514impl SubstraitProducer for DefaultSubstraitProducer<'_> {
515 fn register_function(&mut self, fn_name: String) -> u32 {
516 self.extensions.register_function(&fn_name)
517 }
518
519 fn register_type(&mut self, type_name: String) -> u32 {
520 self.extensions.register_type(&type_name)
521 }
522
523 fn get_extensions(self) -> Extensions {
524 self.extensions
525 }
526
527 fn handle_extension(
528 &mut self,
529 plan: &Extension,
530 ) -> datafusion::common::Result<Box<Rel>> {
531 let extension_bytes = self
532 .serializer_registry
533 .serialize_logical_plan(plan.node.as_ref())?;
534 let detail = ProtoAny {
535 type_url: plan.node.name().to_string(),
536 value: extension_bytes.into(),
537 };
538 let mut inputs_rel = plan
539 .node
540 .inputs()
541 .into_iter()
542 .map(|plan| self.handle_plan(plan))
543 .collect::<datafusion::common::Result<Vec<_>>>()?;
544 let rel_type = match inputs_rel.len() {
545 0 => RelType::ExtensionLeaf(ExtensionLeafRel {
546 common: None,
547 detail: Some(detail),
548 }),
549 1 => RelType::ExtensionSingle(Box::new(ExtensionSingleRel {
550 common: None,
551 detail: Some(detail),
552 input: Some(inputs_rel.pop().unwrap()),
553 })),
554 _ => RelType::ExtensionMulti(ExtensionMultiRel {
555 common: None,
556 detail: Some(detail),
557 inputs: inputs_rel.into_iter().map(|r| *r).collect(),
558 }),
559 };
560 Ok(Box::new(Rel {
561 rel_type: Some(rel_type),
562 }))
563 }
564
565 fn push_lambda_parameters(
566 &mut self,
567 lambda_parameters: Vec<FieldRef>,
568 ) -> datafusion::common::Result<()> {
569 let lambda_parameters_map = lambda_parameters_map(self, lambda_parameters)?;
570
571 self.lambda_producer
572 .push_lambda_parameters(lambda_parameters_map);
573
574 Ok(())
575 }
576
577 fn pop_lambda_parameters(&mut self) -> datafusion::common::Result<()> {
578 self.lambda_producer.pop_lambda_parameters()
579 }
580
581 fn lambda_variable(&self, name: &str) -> datafusion::common::Result<(u32, i32)> {
582 self.lambda_producer.lambda_variable(name)
583 }
584
585 fn lambda_parameter_type(
586 &self,
587 name: &str,
588 ) -> datafusion::common::Result<substrait::proto::Type> {
589 self.lambda_producer.lambda_parameter_type(name)
590 }
591}
592
593pub struct DefaultSubstraitLambdaProducer {
597 lambdas_variables: Vec<HashMap<String, (usize, substrait::proto::Type)>>,
598}
599
600impl Default for DefaultSubstraitLambdaProducer {
601 fn default() -> Self {
602 Self::new()
603 }
604}
605
606impl DefaultSubstraitLambdaProducer {
607 pub fn new() -> Self {
608 Self {
609 lambdas_variables: Vec::new(),
610 }
611 }
612
613 pub fn push_lambda_parameters(
615 &mut self,
616 lambda_parameters: HashMap<String, (usize, substrait::proto::Type)>,
617 ) {
618 self.lambdas_variables.push(lambda_parameters);
619 }
620
621 pub fn pop_lambda_parameters(&mut self) -> datafusion::common::Result<()> {
622 match self.lambdas_variables.pop() {
623 Some(_) => Ok(()),
624 None => substrait_err!("no lambda_parameters to pop"),
625 }
626 }
627
628 pub fn lambda_variable(&self, name: &str) -> datafusion::common::Result<(u32, i32)> {
629 for (steps_out, lambda_parameters) in
630 self.lambdas_variables.iter().rev().enumerate()
631 {
632 if let Some((field_idx, _type)) = lambda_parameters.get(name) {
633 return Ok((steps_out as u32, *field_idx as i32));
634 }
635 }
636
637 substrait_err!("unknown lambda variable {name}")
638 }
639
640 pub fn lambda_parameter_type(
641 &self,
642 name: &str,
643 ) -> datafusion::common::Result<substrait::proto::Type> {
644 for lambda_parameters in self.lambdas_variables.iter().rev() {
645 if let Some((_field_idx, type_)) = lambda_parameters.get(name) {
646 return Ok(type_.clone());
647 }
648 }
649
650 substrait_err!("unknown lambda variable {name}")
651 }
652}
653
654pub fn lambda_parameters_map(
656 producer: &mut impl SubstraitProducer,
657 lambda_parameters: Vec<FieldRef>,
658) -> datafusion::common::Result<HashMap<String, (usize, substrait::proto::Type)>> {
659 lambda_parameters
660 .into_iter()
661 .enumerate()
662 .map(|(field_idx, field)| {
663 Ok((
664 field.name().clone(),
665 (field_idx, to_substrait_type_from_field(producer, &field)?),
666 ))
667 })
668 .collect::<datafusion::common::Result<_>>()
669}