Skip to main content

sql_fun_sqlast/sem/scalar_expr/
sub_link.rs

1use sql_fun_core::IVec;
2
3use crate::{
4    AstAndContextPair,
5    sem::{
6        AnalysisError, FromClause, ParseContext, SelectStatement, SemScalarExpr, TypeReference,
7        WithClause, analyze_select,
8    },
9    syn::{Opt, ScanToken},
10};
11
12use super::{AnalyzeScalarExpr, SemScalarExprNode};
13
14/// Sub-query expression
15#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
16pub struct SubLinkExpr {
17    subselect: Box<SelectStatement>,
18    type_ref: TypeReference,
19}
20
21impl SemScalarExprNode for SubLinkExpr {
22    fn get_type(&self) -> Option<TypeReference> {
23        Some(self.type_ref.clone())
24    }
25
26    fn is_not_null(&self) -> Option<bool> {
27        Some(false)
28    }
29}
30
31impl<TParseContext> AnalyzeScalarExpr<TParseContext, crate::syn::SubLink> for SubLinkExpr
32where
33    TParseContext: ParseContext,
34{
35    fn analyze_scalar_expr(
36        mut context: TParseContext,
37        _with_clause: &WithClause,
38        _from_clause: &FromClause,
39        syn: crate::syn::SubLink,
40        tokens: &IVec<ScanToken>,
41    ) -> Result<(SemScalarExpr, TParseContext), AnalysisError> {
42        let Some(subselect) = syn.get_subselect().as_select_stmt().as_inner() else {
43            AnalysisError::raise_unexpected_none("sublink.subselect")?
44        };
45        let AstAndContextPair(select_stmt, new_context) =
46            analyze_select(context, subselect, tokens)?;
47        context = new_context;
48        let Some(select_stmt) = select_stmt.into_select_statemtnt() else {
49            AnalysisError::raise_unexpected_none("select_statemnt")?
50        };
51
52        let type_ref = select_stmt.returning_composite_type()?;
53
54        Ok((
55            SemScalarExpr::SubLink(Self {
56                subselect: Box::new(select_stmt),
57                type_ref,
58            }),
59            context,
60        ))
61    }
62}