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 : }
|