Skip to main content

sql_fun_sqlast/sem/scalar_expr/
column_ref.rs

1mod cte_column_ref;
2mod invalid_column_ref;
3mod subquery_column_ref;
4mod table_column_ref;
5mod table_func_col_ref;
6mod view_column_ref;
7
8use sql_fun_core::IVec;
9
10pub use self::{
11    cte_column_ref::CteColumnRef,
12    invalid_column_ref::{
13        UndefinedAliasColumnRef, UnknownSourceColumnRef, UnknownTableFuncColumnRef,
14    },
15    subquery_column_ref::SubQueryColumnRef,
16    table_column_ref::TableColumnRef,
17    table_func_col_ref::TableFunctionColumnRef,
18    view_column_ref::ViewColumnRef,
19};
20
21use crate::{
22    sem::{
23        AnalysisError, AnalysisProblem, ColumnDefinition, ColumnName, FromClause, ParseContext,
24        SemScalarExpr, TypeReference, WithClause,
25        data_source::AliasName,
26        scalar_expr::{AnalyzeScalarExpr, SemScalarExprNode},
27    },
28    syn::{ListOpt, ScanToken},
29};
30
31trait ColumnReference {
32    fn get_type(&self) -> Option<TypeReference>;
33    fn is_not_null(&self) -> Option<bool>;
34    fn get_column_def(&self) -> &Option<ColumnDefinition>;
35    fn get_column_name(&self) -> &ColumnName;
36}
37
38/// Column reference
39#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
40pub enum ColumnReferenceExpr {
41    /// CTE column
42    CteColumn(CteColumnRef),
43    /// Table column
44    TableColumn(TableColumnRef),
45    /// View column
46    ViewColumn(ViewColumnRef),
47    /// table function result column
48    TableFuncColumn(TableFunctionColumnRef),
49    /// Sub-query column
50    SubQueryColumn(SubQueryColumnRef),
51
52    /// referenced alias not defined in from clause
53    UndefinedAlias(UndefinedAliasColumnRef),
54    /// table or view not found in source definition
55    UndefinedTableOrView(UnknownSourceColumnRef),
56    /// table function not found in source definition
57    UndefinedFunction(UnknownTableFuncColumnRef),
58    /// column not found
59    UndefinedColumn(ColumnName),
60    /// column name ambigous
61    AmbiguousColumnRef(ColumnName),
62}
63
64impl SemScalarExprNode for ColumnReferenceExpr {
65    fn get_type(&self) -> Option<TypeReference> {
66        self.get_type()
67    }
68
69    fn is_not_null(&self) -> Option<bool> {
70        self.is_not_null()
71    }
72}
73
74impl ColumnReferenceExpr {
75    /// get column type
76    #[must_use]
77    pub fn get_type(&self) -> Option<TypeReference> {
78        match self {
79            Self::CteColumn(r) => r.get_type(),
80            Self::TableColumn(r) => r.get_type(),
81            Self::ViewColumn(r) => r.get_type(),
82            Self::TableFuncColumn(r) => r.get_type(),
83            Self::SubQueryColumn(r) => r.get_type(),
84            Self::UndefinedAlias(r) => r.get_type(),
85            Self::UndefinedTableOrView(r) => r.get_type(),
86            Self::UndefinedFunction(r) => r.get_type(),
87            Self::UndefinedColumn(_) => None,
88            Self::AmbiguousColumnRef(_) => None,
89        }
90    }
91
92    /// get column is not null
93    #[must_use]
94    pub fn is_not_null(&self) -> Option<bool> {
95        match self {
96            Self::CteColumn(r) => r.is_not_null(),
97            Self::TableColumn(r) => r.is_not_null(),
98            Self::ViewColumn(r) => r.is_not_null(),
99            Self::TableFuncColumn(r) => r.is_not_null(),
100            Self::SubQueryColumn(r) => r.is_not_null(),
101            Self::UndefinedAlias(r) => r.is_not_null(),
102            Self::UndefinedTableOrView(r) => r.is_not_null(),
103            Self::UndefinedFunction(r) => r.is_not_null(),
104            Self::UndefinedColumn(_) => None,
105            Self::AmbiguousColumnRef(_) => None,
106        }
107    }
108
109    /// get column definition
110    #[must_use]
111    pub fn get_column_def(&self) -> &Option<ColumnDefinition> {
112        match self {
113            Self::CteColumn(r) => r.get_column_def(),
114            Self::TableColumn(r) => r.get_column_def(),
115            Self::ViewColumn(r) => r.get_column_def(),
116            Self::TableFuncColumn(r) => r.get_column_def(),
117            Self::SubQueryColumn(r) => r.get_column_def(),
118            Self::UndefinedAlias(r) => r.get_column_def(),
119            Self::UndefinedTableOrView(r) => r.get_column_def(),
120            Self::UndefinedFunction(r) => r.get_column_def(),
121            Self::UndefinedColumn(_) => &None,
122            Self::AmbiguousColumnRef(_) => &None,
123        }
124    }
125
126    /// get column name
127    #[must_use]
128    pub fn get_column_name(&self) -> &ColumnName {
129        match self {
130            Self::CteColumn(r) => r.get_column_name(),
131            Self::TableColumn(r) => r.get_column_name(),
132            Self::ViewColumn(r) => r.get_column_name(),
133            Self::TableFuncColumn(r) => r.get_column_name(),
134            Self::SubQueryColumn(r) => r.get_column_name(),
135            Self::UndefinedAlias(r) => r.get_column_name(),
136            Self::UndefinedTableOrView(r) => r.get_column_name(),
137            Self::UndefinedFunction(r) => r.get_column_name(),
138            Self::UndefinedColumn(c) => c,
139            Self::AmbiguousColumnRef(c) => c,
140        }
141    }
142
143    /// create undefined column reference instance
144    pub fn undefined_column_with_report<TParseContext>(
145        context: &mut TParseContext,
146        column: &ColumnName,
147    ) -> Result<SemScalarExpr, AnalysisError>
148    where
149        TParseContext: ParseContext,
150    {
151        context.report_problem(AnalysisProblem::column_not_found_in_source(column))?;
152        Ok(SemScalarExpr::ColumnRef(Self::UndefinedColumn(
153            column.clone(),
154        )))
155    }
156
157    /// create ambigous column reference instance
158    pub fn ambiguous_column_with_report<TParseContext>(
159        context: &mut TParseContext,
160        column: &ColumnName,
161    ) -> Result<SemScalarExpr, AnalysisError>
162    where
163        TParseContext: ParseContext,
164    {
165        context.report_problem(AnalysisProblem::ambiguous_column(column))?;
166        Ok(SemScalarExpr::ColumnRef(Self::AmbiguousColumnRef(
167            column.clone(),
168        )))
169    }
170
171    fn source_ref<TParseContext>(
172        mut context: TParseContext,
173        with_clause: &WithClause,
174        from_clause: &FromClause,
175        alias: &AliasName,
176        column: &ColumnName,
177    ) -> Result<(SemScalarExpr, TParseContext), AnalysisError>
178    where
179        TParseContext: ParseContext,
180    {
181        let Some((from_def, nullability)) = from_clause.resolve_alias(alias) else {
182            let scalar_expr =
183                UndefinedAliasColumnRef::new_with_report(&mut context, alias, column)?;
184            return Ok((scalar_expr, context));
185        };
186        from_def.create_column_ref(context, with_clause, alias, column, nullability)
187    }
188}
189
190impl<TParseContext> AnalyzeScalarExpr<TParseContext, crate::syn::ColumnRef> for ColumnReferenceExpr
191where
192    TParseContext: ParseContext,
193{
194    fn analyze_scalar_expr(
195        mut context: TParseContext,
196        with_clause: &WithClause,
197        from_clause: &FromClause,
198        syn: crate::syn::ColumnRef,
199        _tokens: &IVec<ScanToken>,
200    ) -> Result<(SemScalarExpr, TParseContext), AnalysisError> {
201        let Some(fields) = syn.get_fields().map(|v| v.as_string()) else {
202            AnalysisError::raise_unexpected_none("column_ref.fields")?
203        };
204
205        let fields: Vec<String> = fields.iter().map(crate::syn::String::get_sval).collect();
206        if fields.len() > 2 {
207            AnalysisError::raise_unexpected_input(&format!(
208                "unexpected len column_ref.fields {}",
209                fields.len()
210            ))?;
211        }
212
213        if fields.len() == 1 {
214            let column = ColumnName::from(fields[0].clone());
215
216            let Ok(find_alias_result) =
217                from_clause.find_alias_for_column(&column, &context, with_clause)
218            else {
219                let scalar_expr =
220                    ColumnReferenceExpr::ambiguous_column_with_report(&mut context, &column)?;
221                return Ok((scalar_expr, context));
222            };
223            let Some(alias) = find_alias_result else {
224                let scalar_expr =
225                    ColumnReferenceExpr::undefined_column_with_report(&mut context, &column)?;
226                return Ok((scalar_expr, context));
227            };
228            Self::source_ref(context, with_clause, from_clause, alias.name(), &column)
229        } else if fields.len() == 2 {
230            let alias = &fields[0];
231            let column = ColumnName::from(fields[1].clone());
232            Self::source_ref(
233                context,
234                with_clause,
235                from_clause,
236                &AliasName::from(alias.as_str()),
237                &column,
238            )
239        } else {
240            unreachable!()
241        }
242    }
243}