Skip to main content

sql_fun_sqlast/sem/data_source/
rows_fun.rs

1use sql_fun_core::IVec;
2
3use crate::{
4    sem::{
5        AliasSpec, AnalysisError, AnalysisProblem, ColumnCollection, DataSource, FromClause,
6        FullName, Nullable, ParseContext, SemScalarExpr, WithClause, analyze_scaler_expr,
7        data_source::AliasName, type_system::ArgumentBindingCollection,
8    },
9    syn::{ListOpt, Opt, ScanToken},
10};
11
12/// row functions
13#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
14pub struct DataSourceRowFunctions {
15    alias: AliasSpec,
16    functions: IVec<DataSourceRowsFromFunc>,
17}
18
19impl DataSourceRowFunctions {
20    pub(super) fn resolve_alias<'a>(
21        &self,
22        data_source: &'a DataSource,
23        name: &AliasName,
24    ) -> Option<(&'a DataSource, Nullable)> {
25        if self.alias.name() == name {
26            Some((data_source, false))
27        } else {
28            None
29        }
30    }
31
32    pub(super) fn new(functions: &IVec<DataSourceRowsFromFunc>, alias: &AliasSpec) -> Self {
33        Self {
34            functions: functions.clone(),
35            alias: alias.clone(),
36        }
37    }
38
39    /// get alias name
40    #[must_use]
41    pub fn get_aliases(&self) -> Vec<AliasSpec> {
42        vec![self.alias.clone()]
43    }
44}
45
46/// rows from function
47#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
48pub enum DataSourceRowsFromFunc {
49    /// resolved table function call
50    FuncCall(FullName, Vec<SemScalarExpr>, ColumnCollection),
51    /// undefined table function call
52    UndefinedFuncCall(FullName, Vec<SemScalarExpr>),
53}
54
55impl DataSourceRowsFromFunc {
56    /// analyze `FuncCall` node in RangeFunction.functions
57    pub fn analyze_func_call<TParseContext>(
58        mut context: TParseContext,
59        with_clause: &WithClause,
60        from_clause: &FromClause,
61        func_call: crate::syn::FuncCall,
62        tokens: &IVec<ScanToken>,
63    ) -> Result<(Self, TParseContext), AnalysisError>
64    where
65        TParseContext: ParseContext,
66    {
67        let fun_name = FullName::try_from(func_call.get_funcname())?;
68        let Some(args) = func_call.get_args().as_inner() else {
69            AnalysisError::raise_unexpected_none("func_call.args")?
70        };
71        let mut arg_exprs = Vec::new();
72        let mut arg_types = ArgumentBindingCollection::default();
73        for arg in args {
74            let (arg, new_context) =
75                analyze_scaler_expr(context, with_clause, from_clause, arg, tokens)?;
76            context = new_context;
77            arg_types.push(arg.get_type());
78            arg_exprs.push(arg);
79        }
80
81        if let Some(overloads) = context.get_function_by_name(&fun_name) {
82            let Some(overload) = overloads.resolve_overload(&mut context, &arg_types) else {
83                context.report_problem(AnalysisProblem::function_overload_resolution_failed(
84                    &fun_name, &arg_types,
85                ))?;
86                return Ok((Self::UndefinedFuncCall(fun_name, arg_exprs), context));
87            };
88            let columns = overload.returning_table();
89            let resolved_fun_name = context.resolve_function_name_with_search_path(&fun_name);
90            Ok((
91                Self::FuncCall(resolved_fun_name, arg_exprs, columns),
92                context,
93            ))
94        } else {
95            context.report_problem(AnalysisProblem::table_function_not_found(&fun_name))?;
96            Ok((Self::UndefinedFuncCall(fun_name, arg_exprs), context))
97        }
98    }
99
100    /// analyze Node in RangeFunction.functions
101    pub fn analyze_node<TParseContext>(
102        context: TParseContext,
103        with_clause: &WithClause,
104        from_clause: &FromClause,
105        function: crate::syn::Node,
106        tokens: &IVec<ScanToken>,
107    ) -> Result<(Self, TParseContext), AnalysisError>
108    where
109        TParseContext: ParseContext,
110    {
111        if let Some(func_call) = function.as_func_call().as_inner() {
112            Self::analyze_func_call(context, with_clause, from_clause, func_call, tokens)
113        } else if let Some(_sqlvf) = function.as_sqlvalue_function().as_inner() {
114            todo!()
115        } else {
116            AnalysisError::raise_unexpected_input(
117                "RangeFunction.functions contains unexpected node",
118            )
119        }
120    }
121}