LCOV - code coverage report
Current view: top level - dashql-core/src/analyzer - function_calls.rs Coverage Total Hit
Test: DashQL 6e74948 Lines: 94.0 % 67 63
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : //! Identify function calls.
       2              : 
       3              : use super::state::AnalysisState;
       4              : use super::types::*;
       5              : use crate::error::{Error, Result};
       6              : use dashql_buffers::algebra::FunctionCallModifier;
       7              : use dashql_buffers::parser::{AttributeKey as K, KnownFunction, NodeType};
       8              : use dashql_parser::attrs;
       9              : use std::ops::Range;
      10              : 
      11         3589 : pub(super) fn visit(state: &mut AnalysisState, morsel: Range<usize>) -> Result<()> {
      12        78912 :     for node_id in morsel {
      13        78912 :         let node = &state.ast[node_id];
      14        78912 :         if node.node_type() != NodeType::OBJECT_SQL_FUNCTION_EXPRESSION {
      15        78539 :             continue;
      16          373 :         }
      17          373 :         let [star, all, distinct, variadic, over, within_group, name, args] = attrs!(state.children(node), [
      18              :             K::SQL_FUNCTION_ARGUMENTS_STAR,
      19              :             K::SQL_FUNCTION_ALL,
      20              :             K::SQL_FUNCTION_DISTINCT,
      21              :             K::SQL_FUNCTION_VARIADIC,
      22              :             K::SQL_FUNCTION_OVER,
      23              :             K::SQL_FUNCTION_WITHIN_GROUP,
      24              :             K::SQL_FUNCTION_NAME,
      25              :             K::SQL_FUNCTION_ARGUMENTS,
      26              :         ]);
      27          373 :         let mut modifiers = 0u8;
      28         2238 :         for (attr, modifier) in [
      29          373 :             (star, FunctionCallModifier::ARGS_STAR),
      30          373 :             (all, FunctionCallModifier::ARGS_ALL),
      31          373 :             (distinct, FunctionCallModifier::ARGS_DISTINCT),
      32          373 :             (variadic, FunctionCallModifier::VARIADIC),
      33          373 :             (over, FunctionCallModifier::OVER),
      34          373 :             (within_group, FunctionCallModifier::WITHIN_GROUP),
      35          373 :         ] {
      36         2238 :             if attr.is_some() {
      37          202 :                 modifiers |= modifier.0;
      38         2036 :             }
      39              :         }
      40              :         // The parser always emits a function name
      41          373 :         let mut function_name = FunctionName::Known(KnownFunction::CURRENT_TIME);
      42          373 :         if let Some(name) = name {
      43          373 :             match name.node_type() {
      44           38 :                 NodeType::ENUM_SQL_KNOWN_FUNCTION => {
      45           38 :                     function_name = FunctionName::Known(KnownFunction(name.children_begin_or_value() as u8));
      46           38 :                 }
      47          335 :                 NodeType::ARRAY => match state.read_qualified_function_name(Some(name)) {
      48          335 :                     Some(qualified) => function_name = FunctionName::Qualified(qualified),
      49              :                     // An unreadable qualified name fails the analysis (see docs/design/core_quirks.md)
      50            0 :                     None => return Err(Error::invalid_argument("bad optional access")),
      51              :                 },
      52            0 :                 _ => {}
      53              :             }
      54            0 :         }
      55          373 :         let mut arguments = FunctionArguments::None;
      56          373 :         if let Some(args) = args {
      57          137 :             let begin = state.out.function_arguments.len() as u32;
      58          137 :             let count = args.children_count();
      59          166 :             for i in 0..count {
      60          166 :                 let arg_node_id = args.children_begin_or_value() + i;
      61          166 :                 let mut arg = FunctionArgument {
      62          166 :                     ast_node_id: arg_node_id,
      63          166 :                     ..Default::default()
      64          166 :                 };
      65          166 :                 let arg_node = &state.ast[arg_node_id as usize];
      66          166 :                 if arg_node.node_type() != NodeType::OBJECT_SQL_FUNCTION_ARG {
      67           16 :                     arg.value_ast_node_id = arg_node_id;
      68           16 :                     state.out.function_arguments.push(arg);
      69           16 :                     continue;
      70          150 :                 }
      71          150 :                 let [value, name] = attrs!(state.children(arg_node), [K::SQL_FUNCTION_ARG_VALUE, K::SQL_FUNCTION_ARG_NAME]);
      72          150 :                 match value {
      73              :                     // Error recovery can leave an incomplete function argument
      74            0 :                     None => arg.value_ast_node_id = arg_node_id,
      75          150 :                     Some(value) => {
      76          150 :                         arg.value_ast_node_id = state.node_id(value);
      77          150 :                         if let Some(name) = name {
      78            3 :                             arg.name = Some(state.node_name(name));
      79          147 :                         }
      80              :                     }
      81              :                 }
      82          150 :                 state.out.function_arguments.push(arg);
      83              :             }
      84          137 :             arguments = FunctionArguments::Generic { begin, count };
      85          236 :         }
      86          373 :         let call = FunctionCall {
      87          373 :             function_name,
      88          373 :             function_call_modifiers: modifiers,
      89          373 :             arguments,
      90          373 :         };
      91          373 :         let span = *node.symbol_span();
      92          373 :         let expr = state.add_expression(node_id as u32, span, ExpressionInner::FunctionCall(call));
      93          373 :         state.expression_index[node_id] = Some(expr);
      94              :     }
      95         3589 :     Ok(())
      96         3589 : }
        

Generated by: LCOV version 2.0-1