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 3855 : pub(super) fn visit(state: &mut AnalysisState, morsel: Range<usize>) -> Result<()> {
12 84087 : for node_id in morsel {
13 84087 : let node = &state.ast[node_id];
14 84087 : if node.node_type() != NodeType::OBJECT_SQL_FUNCTION_EXPRESSION {
15 83703 : continue;
16 384 : }
17 384 : 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 384 : let mut modifiers = 0u8;
28 2304 : for (attr, modifier) in [
29 384 : (star, FunctionCallModifier::ARGS_STAR),
30 384 : (all, FunctionCallModifier::ARGS_ALL),
31 384 : (distinct, FunctionCallModifier::ARGS_DISTINCT),
32 384 : (variadic, FunctionCallModifier::VARIADIC),
33 384 : (over, FunctionCallModifier::OVER),
34 384 : (within_group, FunctionCallModifier::WITHIN_GROUP),
35 384 : ] {
36 2304 : if attr.is_some() {
37 206 : modifiers |= modifier.0;
38 2098 : }
39 : }
40 : // The parser always emits a function name
41 384 : let mut function_name = FunctionName::Known(KnownFunction::CURRENT_TIME);
42 384 : if let Some(name) = name {
43 384 : match name.node_type() {
44 39 : NodeType::ENUM_SQL_KNOWN_FUNCTION => {
45 39 : function_name = FunctionName::Known(KnownFunction(name.children_begin_or_value() as u8));
46 39 : }
47 345 : NodeType::ARRAY => match state.read_qualified_function_name(Some(name)) {
48 345 : 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 384 : let mut arguments = FunctionArguments::None;
56 384 : if let Some(args) = args {
57 142 : let begin = state.out.function_arguments.len() as u32;
58 142 : let count = args.children_count();
59 171 : for i in 0..count {
60 171 : let arg_node_id = args.children_begin_or_value() + i;
61 171 : let mut arg = FunctionArgument {
62 171 : ast_node_id: arg_node_id,
63 171 : ..Default::default()
64 171 : };
65 171 : let arg_node = &state.ast[arg_node_id as usize];
66 171 : 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 155 : }
71 155 : let [value, name] = attrs!(state.children(arg_node), [K::SQL_FUNCTION_ARG_VALUE, K::SQL_FUNCTION_ARG_NAME]);
72 155 : match value {
73 : // Error recovery can leave an incomplete function argument
74 0 : None => arg.value_ast_node_id = arg_node_id,
75 155 : Some(value) => {
76 155 : arg.value_ast_node_id = state.node_id(value);
77 155 : if let Some(name) = name {
78 3 : arg.name = Some(state.node_name(name));
79 152 : }
80 : }
81 : }
82 155 : state.out.function_arguments.push(arg);
83 : }
84 142 : arguments = FunctionArguments::Generic { begin, count };
85 242 : }
86 384 : let call = FunctionCall {
87 384 : function_name,
88 384 : function_call_modifiers: modifiers,
89 384 : arguments,
90 384 : };
91 384 : let span = *node.symbol_span();
92 384 : let expr = state.add_expression(node_id as u32, span, ExpressionInner::FunctionCall(call));
93 384 : state.expression_index[node_id] = Some(expr);
94 : }
95 3855 : Ok(())
96 3855 : }
|