Skip to main content

sql_fun_sqlast/sem/names/
ope.rs

1use std::fmt::Display;
2
3use crate::{
4    sem::{AnalysisError, ParseContext, error::ProblemLikeError},
5    syn::{ListOpt, NodeListOpt},
6};
7
8use super::SchemaName;
9
10/// operator name with schema(optional)
11#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
12pub struct ValidOperatorName {
13    schema_name: Option<SchemaName>,
14    op_name: String,
15}
16
17impl Display for ValidOperatorName {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        if let Some(schema_name) = &self.schema_name {
20            write!(f, "{schema_name}",)?;
21        }
22        write!(f, "{}", self.op_name)?;
23        Ok(())
24    }
25}
26
27impl ValidOperatorName {
28    /// create from [`crate::syn::NodeListOpt`]
29    pub fn try_from(value: NodeListOpt) -> Result<Option<Self>, ProblemLikeError> {
30        let Some(items) = value.map_values(|v| v.as_string().get_sval()) else {
31            return Ok(None);
32        };
33        if items.is_empty() || items.len() >= 2 {
34            Err(ProblemLikeError::invalid_operator_name(items))?
35        } else if items.len() == 1 {
36            Ok(Some(ValidOperatorName {
37                schema_name: None,
38                op_name: items[0].clone(),
39            }))
40        } else {
41            Ok(Some(ValidOperatorName {
42                schema_name: Some(SchemaName::from(items[0].as_str())),
43                op_name: items[1].clone(),
44            }))
45        }
46    }
47
48    /// create instance for test
49    #[cfg(test)]
50    pub fn new(operator_name: &str) -> Self {
51        Self {
52            schema_name: None,
53            op_name: String::from(operator_name),
54        }
55    }
56}
57
58/// Operator name
59#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
60pub enum OperatorName {
61    /// accepted operator name
62    Valid(ValidOperatorName),
63    /// non acceptable operator name
64    Invalid,
65}
66
67impl OperatorName {
68    /// accept operator name or report problem
69    pub fn try_from_report<TParseContext: ParseContext>(
70        value: NodeListOpt,
71        context: &mut TParseContext,
72    ) -> Result<Option<Self>, AnalysisError> {
73        let result = ValidOperatorName::try_from(value);
74        match result {
75            Ok(Some(v)) => Ok(Some(Self::Valid(v))),
76            Ok(None) => Ok(None),
77            Err(e) => {
78                e.report_problem_to(context)?;
79                Ok(Some(Self::Invalid))
80            }
81        }
82    }
83
84    /// operator name is valid
85    #[must_use]
86    pub fn is_valid(&self) -> bool {
87        matches!(self, Self::Valid(_))
88    }
89
90    /// get name of operator, require vaild
91    #[must_use]
92    pub fn to_name_string(&self) -> String {
93        match self {
94            Self::Valid(v) => v.to_string(),
95            _ => panic!("invalid name"),
96        }
97    }
98}