Skip to main content

sql_fun_sqlast/sem/data_source/
alias.rs

1use itertools::Itertools;
2
3use crate::{
4    sem::{AnalysisError, ColumnName, FullName, ParseContext},
5    syn::ListOpt,
6};
7
8#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
9pub struct AliasName(String);
10
11impl std::fmt::Display for AliasName {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        write!(f, "{}", self.0)
14    }
15}
16
17impl From<&str> for AliasName {
18    fn from(value: &str) -> Self {
19        Self(String::from(value))
20    }
21}
22
23impl AliasName {
24    pub fn as_str(&self) -> &str {
25        self.0.as_str()
26    }
27}
28
29/// alias name in from clause
30#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
31pub struct AliasSpec {
32    alias_name: AliasName,
33    derived_column_names: Vec<ColumnName>,
34}
35
36impl AliasSpec {
37    /// get alias name
38    #[must_use]
39    pub fn name(&self) -> &AliasName {
40        &self.alias_name
41    }
42
43    /// create alias spec from only local name
44    #[must_use]
45    pub fn from_local_name(local_name: &str) -> Self {
46        Self {
47            alias_name: AliasName(String::from(local_name)),
48            derived_column_names: Vec::new(),
49        }
50    }
51
52    /// analize Alias syn node
53    pub fn analyze<TParseContext>(
54        context: TParseContext,
55        rel_fullname: &FullName,
56        alias: &crate::syn::Alias,
57    ) -> Result<(Self, TParseContext), AnalysisError>
58    where
59        TParseContext: ParseContext,
60    {
61        let alias_name = alias.get_aliasname();
62        let alias_name = if alias_name.is_empty() {
63            rel_fullname.local_name()
64        } else {
65            alias_name
66        };
67        let col_names = if let Some(col_names) = alias.get_colnames().map(|v| v.as_string()) {
68            col_names
69                .iter()
70                .map(|v| ColumnName::from(v.get_sval()))
71                .collect()
72        } else {
73            Vec::default()
74        };
75        Ok((
76            Self {
77                alias_name: AliasName(alias_name),
78                derived_column_names: col_names,
79            },
80            context,
81        ))
82    }
83
84    /// analize Alias syn node without default alias name
85    pub fn analyze_without_relname<TParseContext>(
86        context: TParseContext,
87        alias: &crate::syn::Alias,
88    ) -> Result<(Self, TParseContext), AnalysisError>
89    where
90        TParseContext: ParseContext,
91    {
92        let alias_name = alias.get_aliasname();
93        if alias_name.is_empty() {
94            AnalysisError::raise_unexpected_none("alias.aliasname is empty")?;
95        }
96        let col_names = if let Some(col_names) = alias.get_colnames().map(|v| v.as_string()) {
97            col_names
98                .iter()
99                .map(|v| ColumnName::from(v.get_sval()))
100                .collect()
101        } else {
102            Vec::default()
103        };
104        Ok((
105            Self {
106                alias_name: AliasName(alias_name),
107                derived_column_names: col_names,
108            },
109            context,
110        ))
111    }
112
113    /// find column name from delived column list
114    #[must_use]
115    pub fn derived_column_index(&self, column: &ColumnName) -> Option<usize> {
116        if let Some((position, _)) = self
117            .derived_column_names
118            .iter()
119            .find_position(|n| *n == column)
120        {
121            Some(position)
122        } else {
123            None
124        }
125    }
126
127    /// get length of derived column list
128    #[must_use]
129    pub fn len_derived_column(&self) -> usize {
130        self.derived_column_names.len()
131    }
132}