MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / extract_scalar_column

Function extract_scalar_column

nodedb-sql/src/planner/subquery.rs:397–455  ·  view source on GitHub ↗

Extract the projected column name from a scalar subquery. Handles aliased aggregates like `SELECT AVG(amount) AS avg_amount`. For unaliased aggregates, returns the canonical aggregate key emitted by the aggregate executor (e.g. `avg(amount)`, `count(*)`).

(query: &ast::Query)

Source from the content-addressed store, hash-verified

395/// For unaliased aggregates, returns the canonical aggregate key emitted by
396/// the aggregate executor (e.g. `avg(amount)`, `count(*)`).
397fn extract_scalar_column(query: &ast::Query) -> Option<String> {
398 let select = match &*query.body {
399 SetExpr::Select(s) => s,
400 _ => return None,
401 };
402 if select.projection.len() != 1 {
403 return None;
404 }
405 match &select.projection[0] {
406 ast::SelectItem::ExprWithAlias { alias, .. } => Some(normalize_ident(alias)),
407 ast::SelectItem::UnnamedExpr(expr) => match expr {
408 Expr::Identifier(ident) => Some(normalize_ident(ident)),
409 Expr::CompoundIdentifier(parts) if parts.len() >= 3 => {
410 // Schema-qualified: return None to propagate "unsupported" through convert_expr.
411 None
412 }
413 Expr::CompoundIdentifier(parts) if parts.len() == 2 => Some(normalize_ident(&parts[1])),
414 Expr::Function(func) => {
415 let func_name = func
416 .name
417 .0
418 .iter()
419 .map(|p| match p {
420 ast::ObjectNamePart::Identifier(ident) => normalize_ident(ident),
421 _ => String::new(),
422 })
423 .collect::<Vec<_>>()
424 .join(".")
425 .to_lowercase();
426 let arg = match &func.args {
427 ast::FunctionArguments::List(arg_list) => arg_list
428 .args
429 .first()
430 .and_then(|a| match a {
431 ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(
432 Expr::Identifier(ident),
433 )) => Some(normalize_ident(ident)),
434 ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(
435 Expr::CompoundIdentifier(parts),
436 )) if parts.len() >= 3 => None,
437 ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(
438 Expr::CompoundIdentifier(parts),
439 )) if parts.len() == 2 => Some(normalize_ident(&parts[1])),
440 ast::FunctionArg::Unnamed(
441 ast::FunctionArgExpr::Wildcard
442 | ast::FunctionArgExpr::QualifiedWildcard(_),
443 ) => Some("all".to_string()),
444 _ => None,
445 })
446 .unwrap_or_else(|| "*".to_string()),
447 _ => "*".to_string(),
448 };
449 Some(canonical_aggregate_key(&func_name, &arg))
450 }
451 _ => None,
452 },
453 _ => None,
454 }

Callers 1

try_plan_scalar_subqueryFunction · 0.85

Calls 7

normalize_identFunction · 0.85
canonical_aggregate_keyFunction · 0.85
joinMethod · 0.80
firstMethod · 0.80
to_stringMethod · 0.80
lenMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected