(&mut self, expr: &mut Expr<Aug>)
| 6375 | } |
| 6376 | |
| 6377 | fn visit_expr_mut(&mut self, expr: &mut Expr<Aug>) { |
| 6378 | let (disallowed_context, func) = match expr { |
| 6379 | Expr::Case { .. } => (Some("CASE"), None), |
| 6380 | Expr::HomogenizingFunction { |
| 6381 | function: HomogenizingFunction::Coalesce, |
| 6382 | .. |
| 6383 | } => (Some("COALESCE"), None), |
| 6384 | Expr::Function(func) if self.in_select_item => { |
| 6385 | // If we're in a SELECT list, replace table functions with a uuid identifier |
| 6386 | // and save the table func so it can be planned elsewhere. |
| 6387 | let mut table_func = None; |
| 6388 | if let Ok(item) = self.scx.get_item_by_resolved_name(&func.name) { |
| 6389 | if let Ok(Func::Table { .. }) = item.func() { |
| 6390 | if let Some(context) = self.table_disallowed_context.last() { |
| 6391 | self.err = Some(sql_err!( |
| 6392 | "table functions are not allowed in {} (function {})", |
| 6393 | context, |
| 6394 | func.name |
| 6395 | )); |
| 6396 | return; |
| 6397 | } |
| 6398 | table_func = Some(func.clone()); |
| 6399 | } |
| 6400 | } |
| 6401 | // Since we will descend into the table func below, don't add its own disallow |
| 6402 | // context here, instead use visit_function to set that. |
| 6403 | (None, table_func) |
| 6404 | } |
| 6405 | _ => (None, None), |
| 6406 | }; |
| 6407 | if let Some(func) = func { |
| 6408 | // Since we are trading out expr, we need to visit the table func here. |
| 6409 | visit_mut::visit_expr_mut(self, expr); |
| 6410 | // Don't attempt to replace table functions with unsupported syntax. |
| 6411 | if let Function { |
| 6412 | name: _, |
| 6413 | args: _, |
| 6414 | filter: None, |
| 6415 | over: None, |
| 6416 | distinct: false, |
| 6417 | } = &func |
| 6418 | { |
| 6419 | // Identical table functions can be de-duplicated. |
| 6420 | let unique_id = self.id_gen.allocate_id(); |
| 6421 | let id = self |
| 6422 | .tables |
| 6423 | .entry(func) |
| 6424 | .or_insert_with(|| format!("table_func_{unique_id}")); |
| 6425 | // We know this is okay because id is is 11 characters + <=20 characters, which is |
| 6426 | // less than our max length. |
| 6427 | *expr = Expr::Identifier(vec![Ident::new_unchecked(id.clone())]); |
| 6428 | } |
| 6429 | } |
| 6430 | if let Some(context) = disallowed_context { |
| 6431 | self.table_disallowed_context.push(context); |
| 6432 | } |
| 6433 | |
| 6434 | visit_mut::visit_expr_mut(self, expr); |
no test coverage detected