sql_fun_sqlast/sem/scalar_expr/
indirect.rs1mod array_index;
2mod array_slice;
3mod member_ref;
4
5use sql_fun_core::IVec;
6
7use crate::{
8 sem::{
9 AnalysisError, FromClause, ParseContext, SemScalarExpr, TypeReference, WithClause,
10 analyze_scaler_expr,
11 },
12 syn::{ListOpt, Opt, ScanToken},
13};
14
15use self::{array_index::ArrayIndex, array_slice::ArraySlice, member_ref::MemberRef};
16use super::{AnalyzeScalarExpr, SemScalarExprNode};
17
18#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
20pub enum IndirectionExpr {
21 ArrayIndex(Box<ArrayIndex>),
23 ArraySlice(Box<ArraySlice>),
25 MemberRef(Box<MemberRef>),
27}
28
29impl IndirectionExpr {
30 fn analyze_indicies<TParseContext>(
31 context: TParseContext,
32 with_clause: &WithClause,
33 from_clause: &FromClause,
34 arg: SemScalarExpr,
35 indicies: crate::syn::AIndices,
36 tokens: &IVec<ScanToken>,
37 ) -> Result<(Self, TParseContext), AnalysisError>
38 where
39 TParseContext: ParseContext,
40 {
41 if indicies.get_is_slice() {
42 ArraySlice::analyze_slice(context, with_clause, from_clause, arg, indicies, tokens)
43 } else {
44 ArrayIndex::analyze_index(context, with_clause, from_clause, arg, &indicies, tokens)
45 }
46 }
47}
48
49impl SemScalarExprNode for IndirectionExpr {
50 fn get_type(&self) -> Option<TypeReference> {
51 match &self {
52 IndirectionExpr::ArrayIndex(ind) => ind.item_type().clone(),
53 IndirectionExpr::ArraySlice(slice) => slice.array_type().clone(),
54 IndirectionExpr::MemberRef(mem_ref) => mem_ref.member_type().clone(),
55 }
56 }
57
58 fn is_not_null(&self) -> Option<bool> {
59 match &self {
60 IndirectionExpr::ArrayIndex(ind) => ind.array().is_not_null(),
61 IndirectionExpr::ArraySlice(slice) => slice.array_is_not_null(),
62 IndirectionExpr::MemberRef(mem_ref) => mem_ref.base_is_not_null(),
63 }
64 }
65}
66
67impl<TParseContext> AnalyzeScalarExpr<TParseContext, crate::syn::AIndirection> for IndirectionExpr
68where
69 TParseContext: ParseContext,
70{
71 fn analyze_scalar_expr(
72 mut context: TParseContext,
73 with_clause: &WithClause,
74 from_clause: &FromClause,
75 syn: crate::syn::AIndirection,
76 tokens: &IVec<ScanToken>,
77 ) -> Result<(SemScalarExpr, TParseContext), AnalysisError> {
78 let Some(arg) = syn.get_arg().as_inner() else {
79 AnalysisError::raise_unexpected_none("aindirection.arg")?
80 };
81
82 let Some(indirection) = syn.get_indirection().as_inner() else {
83 AnalysisError::raise_unexpected_none("aindirection.indirection")?
84 };
85 let (mut arg, new_context) =
86 analyze_scaler_expr(context, with_clause, from_clause, arg, tokens)?;
87 context = new_context;
88
89 for item in indirection {
90 if let Some(indicies) = item.as_a_indices().as_inner() {
91 let (new_arg, new_context) = Self::analyze_indicies(
92 context,
93 with_clause,
94 from_clause,
95 arg,
96 indicies,
97 tokens,
98 )?;
99 context = new_context;
100 arg = SemScalarExpr::Indirection(new_arg);
101 } else if let Some(member) = item.as_string().get_sval() {
102 arg = SemScalarExpr::Indirection(MemberRef::member_reference(
103 arg,
104 member,
105 &mut context,
106 )?);
107 } else {
108 AnalysisError::raise_unexpected_input(&format!("indirection item: {item:?}"))?;
109 }
110 }
111 Ok((arg, context))
112 }
113}