Skip to main content

sql_fun_sqlast/sem/scalar_expr/
sql_value.rs

1use sql_fun_core::IVec;
2
3use crate::{
4    sem::{
5        AnalysisError, FromClause, FullName, ParseContext, SemScalarExpr, TypeReference, WithClause,
6    },
7    syn::{Opt, ScanToken, SqlValueFunctionOp},
8};
9
10use super::{AnalyzeScalarExpr, SemScalarExprNode};
11
12/// SQL value function
13#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
14pub enum SqlValueExpr {
15    /// `CURRENT_DATE()` SQL standard function
16    CurrentDate,
17    /// `CURRENT_TIME()` / `CURRENT_TIME(n)` SQL standard function
18    CurrentTime(Option<TimePrecision>),
19    /// `CURRENT_TIMESTAMP()` / `CURRENT_TIMESTAMP(n)` SQL standard function
20    CurrentTimestamp(Option<TimePrecision>),
21    /// `LOCALTIME` / `LOCALTIME(n)` SQL standard function
22    LocalTime(Option<TimePrecision>),
23    /// `LOCALTIMESTAMP` / `LOCALTIMESTAMP(n)` SQL standard function
24    LocalTimestamp(Option<TimePrecision>),
25    /// `CURRENT_USER` / `USER` / `CURRENT_ROLE` SQL standard function
26    CurrentUser,
27    /// `SESSION_USER`
28    SessionUser,
29    /// `CURRENT_SCHEMA` SQL standard function
30    CurrentSchema,
31    /// `CURRENT_CATALOG` SQL standard function
32    CurrentCatalog,
33}
34
35/// time precision typmod value
36#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
37pub struct TimePrecision(i32);
38
39impl TimePrecision {
40    fn from_typmod(typmod: i32) -> Self {
41        Self(typmod)
42    }
43}
44
45impl SemScalarExprNode for SqlValueExpr {
46    fn get_type(&self) -> Option<TypeReference> {
47        match self {
48            Self::CurrentDate => Some(TypeReference::concrete_type_ref(
49                &FullName::from_local_name("date"),
50                false,
51            )),
52            Self::CurrentTime(_) => Some(TypeReference::concrete_type_ref(
53                &FullName::from_local_name("timetz"),
54                false,
55            )),
56            Self::CurrentTimestamp(_) => Some(TypeReference::concrete_type_ref(
57                &FullName::from_local_name("timestamptz"),
58                false,
59            )),
60            Self::LocalTime(_) => Some(TypeReference::concrete_type_ref(
61                &FullName::from_local_name("time"),
62                false,
63            )),
64            Self::LocalTimestamp(_) => Some(TypeReference::concrete_type_ref(
65                &FullName::from_local_name("timestamp"),
66                false,
67            )),
68            Self::CurrentUser | Self::SessionUser | Self::CurrentSchema | Self::CurrentCatalog => {
69                Some(TypeReference::concrete_type_ref(
70                    &FullName::from_local_name("name"),
71                    false,
72                ))
73            }
74        }
75    }
76
77    fn is_not_null(&self) -> Option<bool> {
78        match self {
79            Self::CurrentSchema => Some(false),
80            _ => Some(true),
81        }
82    }
83}
84
85impl<TParseContext> AnalyzeScalarExpr<TParseContext, crate::syn::SqlValueFunction> for SqlValueExpr
86where
87    TParseContext: ParseContext,
88{
89    fn analyze_scalar_expr(
90        context: TParseContext,
91        _with_clause: &WithClause,
92        _from_clause: &FromClause,
93        syn: crate::syn::SqlValueFunction,
94        _tokens: &IVec<ScanToken>,
95    ) -> Result<(SemScalarExpr, TParseContext), AnalysisError> {
96        let Some(operator) = syn.get_op().as_inner() else {
97            AnalysisError::raise_unexpected_none("sqlvaluefunction.op")?
98        };
99
100        let node = match operator {
101            SqlValueFunctionOp::SvfopCurrentDate => Self::CurrentDate,
102            SqlValueFunctionOp::SvfopCurrentTime => Self::CurrentTime(None),
103            SqlValueFunctionOp::SvfopCurrentTimeN => {
104                let typmod = syn.get_typmod();
105                Self::CurrentTime(Some(TimePrecision::from_typmod(typmod)))
106            }
107            SqlValueFunctionOp::SvfopCurrentTimestamp => Self::CurrentTimestamp(None),
108            SqlValueFunctionOp::SvfopCurrentTimestampN => {
109                let typmod = syn.get_typmod();
110                Self::CurrentTimestamp(Some(TimePrecision::from_typmod(typmod)))
111            }
112            SqlValueFunctionOp::SvfopLocaltime => Self::LocalTime(None),
113            SqlValueFunctionOp::SvfopLocaltimeN => {
114                let typmod = syn.get_typmod();
115                Self::LocalTime(Some(TimePrecision::from_typmod(typmod)))
116            }
117            SqlValueFunctionOp::SvfopLocaltimestamp => Self::LocalTimestamp(None),
118            SqlValueFunctionOp::SvfopLocaltimestampN => {
119                let typmod = syn.get_typmod();
120                Self::LocalTimestamp(Some(TimePrecision::from_typmod(typmod)))
121            }
122            SqlValueFunctionOp::SvfopCurrentRole => Self::CurrentUser,
123            SqlValueFunctionOp::SvfopCurrentUser => Self::CurrentUser,
124            SqlValueFunctionOp::SvfopUser => Self::CurrentUser,
125            SqlValueFunctionOp::SvfopSessionUser => Self::SessionUser,
126            SqlValueFunctionOp::SvfopCurrentCatalog => Self::CurrentCatalog,
127            SqlValueFunctionOp::SvfopCurrentSchema => Self::CurrentSchema,
128            SqlValueFunctionOp::OptionNone | SqlValueFunctionOp::SqlvalueFunctionOpUndefined => {
129                AnalysisError::raise_unexpected_input("sqlvaluefunctionop value")?;
130                AnalysisError::never();
131            }
132        };
133        Ok((SemScalarExpr::SqlValue(node), context))
134    }
135}