picodata_plugin/sql/
types.rs

1use crate::system;
2use abi_stable::std_types::{RString, RVec};
3use abi_stable::StableAbi;
4use tarantool::datetime::Datetime;
5use tarantool::decimal::Decimal;
6use tarantool::ffi::datetime::datetime;
7use tarantool::uuid::Uuid;
8
9/// *For internal usage, don't use it in your code*.
10#[derive(StableAbi)]
11#[repr(C)]
12pub struct RawDecimal {
13    pub digits: i32,
14    pub exponent: i32,
15    pub bits: u8,
16    pub lsu: [u16; tarantool::ffi::decimal::DECNUMUNITS as _],
17}
18
19impl From<RawDecimal> for tarantool::ffi::decimal::decNumber {
20    fn from(value: RawDecimal) -> Self {
21        tarantool::ffi::decimal::decNumber {
22            digits: value.digits,
23            exponent: value.exponent,
24            bits: value.bits,
25            lsu: value.lsu,
26        }
27    }
28}
29
30impl From<tarantool::ffi::decimal::decNumber> for RawDecimal {
31    fn from(value: tarantool::ffi::decimal::decNumber) -> Self {
32        RawDecimal {
33            digits: value.digits,
34            exponent: value.exponent,
35            bits: value.bits,
36            lsu: value.lsu,
37        }
38    }
39}
40
41/// *For internal usage, don't use it in your code*.
42#[derive(StableAbi)]
43#[repr(C)]
44pub struct RawDatetime {
45    pub epoch: f64,
46    pub nsec: i32,
47    pub tzoffset: i16,
48    pub tzindex: i16,
49}
50
51impl From<RawDatetime> for tarantool::ffi::datetime::datetime {
52    fn from(dt: RawDatetime) -> Self {
53        tarantool::ffi::datetime::datetime {
54            epoch: dt.epoch,
55            nsec: dt.nsec,
56            tzoffset: dt.tzoffset,
57            tzindex: dt.tzindex,
58        }
59    }
60}
61
62impl From<tarantool::ffi::datetime::datetime> for RawDatetime {
63    fn from(dt: datetime) -> Self {
64        Self {
65            epoch: dt.epoch,
66            nsec: dt.nsec,
67            tzoffset: dt.tzoffset,
68            tzindex: dt.tzindex,
69        }
70    }
71}
72
73/// *For internal usage, don't use it in your code*.
74#[derive(StableAbi)]
75#[repr(C)]
76pub enum SqlValueInner {
77    /// Boolean type.
78    Boolean(bool),
79    /// Fixed point type.
80    Decimal(RawDecimal),
81    /// Floating point type.
82    Double(f64),
83    /// Datetime type,
84    Datetime(RawDatetime),
85    /// Signed integer type.
86    Integer(i64),
87    /// SQL NULL ("unknown" in the terms of three-valued logic).
88    Null,
89    /// String type.
90    String(RString),
91    /// Unsigned integer type.
92    Unsigned(u64),
93    /// Tuple type
94    Array(RVec<SqlValue>),
95    /// Uuid type
96    Uuid([u8; 16]),
97}
98
99#[derive(StableAbi)]
100#[repr(C)]
101pub struct SqlValue(SqlValueInner);
102
103impl SqlValue {
104    /// *For internal usage, don't use it in your code*.
105    pub fn into_inner(self) -> SqlValueInner {
106        self.0
107    }
108
109    /// Create SQL value of a bool type.
110    pub fn boolean(b: bool) -> Self {
111        SqlValue(SqlValueInner::Boolean(b))
112    }
113
114    /// Create SQL value of a [tarantool::decimal::Decimal] type.
115    pub fn decimal(dec: tarantool::decimal::Decimal) -> Self {
116        let dec = dec.into_raw();
117        SqlValue(SqlValueInner::Decimal(RawDecimal::from(dec)))
118    }
119
120    /// Create SQL value of a double (64bit float) type.
121    pub fn double(d: f64) -> Self {
122        SqlValue(SqlValueInner::Double(d))
123    }
124
125    /// Create SQL value of a [`tarantool::datetime::Datetime`] type.
126    pub fn datetime(dt: tarantool::datetime::Datetime) -> Self {
127        SqlValue(SqlValueInner::Datetime(RawDatetime::from(dt.as_ffi_dt())))
128    }
129
130    /// Create SQL value of an integer type.
131    pub fn integer(i: i64) -> Self {
132        SqlValue(SqlValueInner::Integer(i))
133    }
134
135    /// Create SQL value of a NULL type.
136    pub fn null() -> Self {
137        SqlValue(SqlValueInner::Null)
138    }
139
140    /// Create SQL value of a string type.
141    pub fn string(s: impl Into<String>) -> Self {
142        SqlValue(SqlValueInner::String(RString::from(s.into())))
143    }
144
145    /// Create SQL value of an unsigned integer type.
146    pub fn unsigned(u: u64) -> Self {
147        SqlValue(SqlValueInner::Unsigned(u))
148    }
149
150    /// Create SQL value of an array type (array of SQL values).
151    pub fn array(arr: impl Into<Vec<Self>>) -> Self {
152        SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
153    }
154
155    /// Create SQL value of a [`system::tarantool::uuid::Uuid`] type.
156    pub fn uuid(uuid: system::tarantool::uuid::Uuid) -> Self {
157        SqlValue(SqlValueInner::Uuid(*uuid.as_bytes()))
158    }
159}
160
161impl From<bool> for SqlValue {
162    fn from(b: bool) -> Self {
163        SqlValue::boolean(b)
164    }
165}
166
167impl From<Decimal> for SqlValue {
168    fn from(dec: Decimal) -> Self {
169        SqlValue::decimal(dec)
170    }
171}
172
173macro_rules! impl_float {
174    ($t:ty) => {
175        impl From<$t> for SqlValue {
176            fn from(f: $t) -> Self {
177                SqlValue::double(f as f64)
178            }
179        }
180    };
181}
182
183impl_float!(f32);
184impl_float!(f64);
185
186impl From<Datetime> for SqlValue {
187    fn from(dt: Datetime) -> Self {
188        SqlValue::datetime(dt)
189    }
190}
191
192macro_rules! impl_int {
193    ($t:ty) => {
194        impl From<$t> for SqlValue {
195            fn from(i: $t) -> Self {
196                SqlValue::integer(i as i64)
197            }
198        }
199    };
200}
201
202impl_int!(i8);
203impl_int!(i16);
204impl_int!(i32);
205impl_int!(i64);
206impl_int!(isize);
207impl_int!(i128);
208
209impl<T: Into<SqlValue>> From<Option<T>> for SqlValue {
210    fn from(opt: Option<T>) -> Self {
211        match opt {
212            None => SqlValue::null(),
213            Some(t) => t.into(),
214        }
215    }
216}
217
218impl From<String> for SqlValue {
219    fn from(s: String) -> Self {
220        SqlValue::string(s)
221    }
222}
223
224impl From<&str> for SqlValue {
225    fn from(s: &str) -> Self {
226        SqlValue::string(s)
227    }
228}
229
230macro_rules! impl_uint {
231    ($t:ty) => {
232        impl From<$t> for SqlValue {
233            fn from(u: $t) -> Self {
234                SqlValue::unsigned(u as u64)
235            }
236        }
237    };
238}
239
240impl_uint!(u8);
241impl_uint!(u16);
242impl_uint!(u32);
243impl_uint!(u64);
244impl_uint!(usize);
245impl_uint!(u128);
246
247impl<T: Into<SqlValue>> From<Vec<T>> for SqlValue {
248    fn from(vec: Vec<T>) -> Self {
249        let array: Vec<_> = vec.into_iter().map(|el| el.into()).collect();
250        SqlValue::array(array)
251    }
252}
253
254impl<T: Into<SqlValue> + Clone> From<&[T]> for SqlValue {
255    fn from(slice: &[T]) -> Self {
256        let array: Vec<_> = slice.iter().map(|el| el.clone().into()).collect();
257        SqlValue::array(array)
258    }
259}
260
261impl<T: Into<SqlValue>, const N: usize> From<[T; N]> for SqlValue {
262    fn from(slice: [T; N]) -> Self {
263        let array: Vec<_> = slice.into_iter().map(|el| el.into()).collect();
264        SqlValue::array(array)
265    }
266}
267
268impl From<Uuid> for SqlValue {
269    fn from(uuid: Uuid) -> Self {
270        SqlValue::uuid(uuid)
271    }
272}