sql_fun_sqlast/sem/scalar_expr/
sub_link.rs1use 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#[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}