Defines a built-in table function from a static SQL SELECT statement. The SQL statement should use the standard parameter syntax (`$1`, `$2`, ...) to refer to the inputs to the function; see sql_impl_func for an example. The number of parameters in the SQL expression must exactly match the number of parameters in the built-in's declaration. There is no support for variadic functions. As this is
(
sql: &'static str,
feature_flag: Option<&'static vars::FeatureFlag>,
)
| 436 | // table function. The SELECT's projection's names are used and should be |
| 437 | // aliased if needed. |
| 438 | fn sql_impl_table_func_inner( |
| 439 | sql: &'static str, |
| 440 | feature_flag: Option<&'static vars::FeatureFlag>, |
| 441 | ) -> Operation<TableFuncPlan> { |
| 442 | let query = match mz_sql_parser::parser::parse_statements(sql) |
| 443 | .expect("static function definition failed to parse") |
| 444 | .expect_element(|| "static function definition must have exactly one statement") |
| 445 | .ast |
| 446 | { |
| 447 | Statement::Select(SelectStatement { query, as_of: None }) => query, |
| 448 | _ => panic!("static function definition expected SELECT statement"), |
| 449 | }; |
| 450 | let invoke = move |qcx: &QueryContext, types: Vec<SqlScalarType>| { |
| 451 | // Reconstruct an expression context where the parameter types are |
| 452 | // bound to the types of the expressions in `args`. |
| 453 | let mut scx = qcx.scx.clone(); |
| 454 | scx.param_types = RefCell::new( |
| 455 | types |
| 456 | .into_iter() |
| 457 | .enumerate() |
| 458 | .map(|(i, ty)| (i + 1, ty)) |
| 459 | .collect(), |
| 460 | ); |
| 461 | let mut qcx = QueryContext::root(&scx, qcx.lifetime); |
| 462 | |
| 463 | let query = query.clone(); |
| 464 | let (mut query, new_ids) = names::resolve(qcx.scx.catalog, query)?; |
| 465 | scx.sql_impl_resolved_ids |
| 466 | .lock() |
| 467 | .expect("planning is single-threaded") |
| 468 | .extend_from(&new_ids); |
| 469 | transform_ast::transform(&scx, &mut query)?; |
| 470 | |
| 471 | query::plan_nested_query(&mut qcx, &query) |
| 472 | }; |
| 473 | |
| 474 | Operation::variadic(move |ecx, args| { |
| 475 | if let Some(feature_flag) = feature_flag { |
| 476 | ecx.require_feature_flag(feature_flag)?; |
| 477 | } |
| 478 | let types = args.iter().map(|arg| ecx.scalar_type(arg)).collect(); |
| 479 | let (mut expr, scope) = invoke(ecx.qcx, types)?; |
| 480 | expr.splice_parameters(&args, 0); |
| 481 | Ok(TableFuncPlan { |
| 482 | imp: TableFuncImpl::Expr(expr), |
| 483 | column_names: scope.column_names().cloned().collect(), |
| 484 | }) |
| 485 | }) |
| 486 | } |
| 487 | |
| 488 | /// Implements a table function using SQL. |
| 489 | /// |
no test coverage detected