sql_type/
type_.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use alloc::{
14    borrow::Cow,
15    fmt::{Display, Write},
16    sync::Arc,
17    vec::Vec,
18};
19use sql_parse::Span;
20
21/// Canonical base type of a type
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum BaseType {
24    /// There are no constraint of the value
25    Any,
26    /// The value must be boolean
27    Bool,
28    /// The value must be a binary blob
29    Bytes,
30    Date,
31    DateTime,
32    /// The value must be some kind of float
33    Float,
34    /// The value must be some kind of integer
35    Integer,
36    String,
37    Time,
38    TimeStamp,
39}
40
41impl Display for BaseType {
42    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
43        match self {
44            BaseType::Any => f.write_str("any"),
45            BaseType::Bool => f.write_str("bool"),
46            BaseType::Bytes => f.write_str("bytes"),
47            BaseType::Date => f.write_str("date"),
48            BaseType::DateTime => f.write_str("datetime"),
49            BaseType::Float => f.write_str("float"),
50            BaseType::Integer => f.write_str("integer"),
51            BaseType::String => f.write_str("string"),
52            BaseType::Time => f.write_str("time"),
53            BaseType::TimeStamp => f.write_str("timestamp"),
54        }
55    }
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum ArgType {
60    Normal,
61    ListHack,
62}
63
64/// Represent the type of a value
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum Type<'a> {
67    // This type is used internally and should not escape to the user
68    #[doc(hidden)]
69    Args(BaseType, Arc<Vec<(usize, ArgType, Span)>>),
70    Base(BaseType),
71    Enum(Arc<Vec<Cow<'a, str>>>),
72    F32,
73    F64,
74    I16,
75    I32,
76    I64,
77    I8,
78    Invalid,
79    JSON,
80    Set(Arc<Vec<Cow<'a, str>>>),
81    U16,
82    U32,
83    U64,
84    U8,
85    // This type is used internally and should not escape to the user
86    #[doc(hidden)]
87    Null,
88}
89
90impl<'a> Display for Type<'a> {
91    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
92        match self {
93            Type::Args(t, a) => {
94                write!(f, "args({t}")?;
95                for (a, _, _) in a.iter() {
96                    write!(f, ", {a}")?;
97                }
98                f.write_char(')')
99            }
100            Type::Base(t) => t.fmt(f),
101            Type::F32 => f.write_str("f32"),
102            Type::F64 => f.write_str("f64"),
103            Type::I16 => f.write_str("i16"),
104            Type::I32 => f.write_str("i32"),
105            Type::I64 => f.write_str("i64"),
106            Type::I8 => f.write_str("i8"),
107            Type::Invalid => f.write_str("invalid"),
108            Type::JSON => f.write_str("json"),
109            Type::U16 => f.write_str("u16"),
110            Type::U32 => f.write_str("u32"),
111            Type::U64 => f.write_str("u64"),
112            Type::U8 => f.write_str("u8"),
113            Type::Null => f.write_str("null"),
114            Type::Enum(v) => {
115                f.write_str("enum(")?;
116                for (i, v) in v.iter().enumerate() {
117                    if i != 0 {
118                        f.write_str(", ")?;
119                    }
120                    write!(f, "'{v}'")?
121                }
122                f.write_char(')')
123            }
124            Type::Set(v) => {
125                f.write_str("set(")?;
126                for (i, v) in v.iter().enumerate() {
127                    if i != 0 {
128                        f.write_str(", ")?;
129                    }
130                    write!(f, "'{v}'")?
131                }
132                f.write_char(')')
133            }
134        }
135    }
136}
137
138impl<'a> Type<'a> {
139    /// Compute the canonical base type
140    pub fn base(&self) -> BaseType {
141        match self {
142            Type::Args(t, _) => *t,
143            Type::Base(t) => *t,
144            Type::Enum(_) => BaseType::String,
145            Type::F32 => BaseType::Float,
146            Type::F64 => BaseType::Float,
147            Type::I16 => BaseType::Integer,
148            Type::I32 => BaseType::Integer,
149            Type::I64 => BaseType::Integer,
150            Type::I8 => BaseType::Integer,
151            Type::Invalid => BaseType::Any,
152            Type::JSON => BaseType::Any,
153            Type::Null => BaseType::Any,
154            Type::Set(_) => BaseType::String,
155            Type::U16 => BaseType::Integer,
156            Type::U32 => BaseType::Integer,
157            Type::U64 => BaseType::Integer,
158            Type::U8 => BaseType::Integer,
159        }
160    }
161}
162
163impl<'a> From<BaseType> for Type<'a> {
164    fn from(t: BaseType) -> Self {
165        Type::Base(t)
166    }
167}
168
169/// Represent a type with not_null information
170#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct FullType<'a> {
172    pub t: Type<'a>,
173    pub not_null: bool,
174    pub list_hack: bool,
175}
176
177impl<'a> FullType<'a> {
178    pub(crate) fn new(t: impl Into<Type<'a>>, not_null: bool) -> Self {
179        Self {
180            t: t.into(),
181            not_null,
182            list_hack: false,
183        }
184    }
185
186    /// Construct a new invalid type
187    pub fn invalid() -> Self {
188        Self {
189            t: Type::Invalid,
190            not_null: false,
191            list_hack: false,
192        }
193    }
194}
195
196impl<'a> core::ops::Deref for FullType<'a> {
197    type Target = Type<'a>;
198
199    fn deref(&self) -> &Self::Target {
200        &self.t
201    }
202}
203
204impl<'a> Display for FullType<'a> {
205    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
206        self.t.fmt(f)?;
207        if self.list_hack {
208            f.write_str(" list_hack")?;
209        }
210        if self.not_null {
211            f.write_str(" not null")?;
212        }
213        Ok(())
214    }
215}