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    #[deprecated]
93    Unsigned(u64),
94    /// Tuple type
95    Array(RVec<SqlValue>),
96    /// Uuid type
97    Uuid([u8; 16]),
98}
99
100#[derive(StableAbi)]
101#[repr(C)]
102pub struct SqlValue(SqlValueInner);
103
104impl SqlValue {
105    /// *For internal usage, don't use it in your code*.
106    pub fn into_inner(self) -> SqlValueInner {
107        self.0
108    }
109
110    /// Create SQL value of a bool type.
111    pub fn boolean(b: bool) -> Self {
112        SqlValue(SqlValueInner::Boolean(b))
113    }
114
115    /// Create SQL value of a [tarantool::decimal::Decimal] type.
116    pub fn decimal(dec: tarantool::decimal::Decimal) -> Self {
117        let dec = dec.into_raw();
118        SqlValue(SqlValueInner::Decimal(RawDecimal::from(dec)))
119    }
120
121    /// Create SQL value of a double (64bit float) type.
122    pub fn double(d: f64) -> Self {
123        SqlValue(SqlValueInner::Double(d))
124    }
125
126    /// Create SQL value of a [`tarantool::datetime::Datetime`] type.
127    pub fn datetime(dt: tarantool::datetime::Datetime) -> Self {
128        SqlValue(SqlValueInner::Datetime(RawDatetime::from(dt.as_ffi_dt())))
129    }
130
131    /// Create SQL value of an integer type.
132    pub fn integer(i: i64) -> Self {
133        SqlValue(SqlValueInner::Integer(i))
134    }
135
136    /// Create SQL value of a NULL type.
137    pub fn null() -> Self {
138        SqlValue(SqlValueInner::Null)
139    }
140
141    /// Create SQL value of a string type.
142    pub fn string(s: impl Into<String>) -> Self {
143        SqlValue(SqlValueInner::String(RString::from(s.into())))
144    }
145
146    /// Create SQL value of an unsigned integer type.
147    #[deprecated]
148    #[allow(deprecated)]
149    pub fn unsigned(u: u64) -> Self {
150        SqlValue(SqlValueInner::Unsigned(u))
151    }
152
153    /// Create SQL value of an array type (array of SQL values).
154    pub fn array(arr: impl Into<Vec<Self>>) -> Self {
155        SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
156    }
157
158    /// Create SQL value of a [`system::tarantool::uuid::Uuid`] type.
159    pub fn uuid(uuid: system::tarantool::uuid::Uuid) -> Self {
160        SqlValue(SqlValueInner::Uuid(*uuid.as_bytes()))
161    }
162}
163
164impl From<bool> for SqlValue {
165    fn from(b: bool) -> Self {
166        SqlValue::boolean(b)
167    }
168}
169
170impl From<Decimal> for SqlValue {
171    fn from(dec: Decimal) -> Self {
172        SqlValue::decimal(dec)
173    }
174}
175
176macro_rules! impl_float {
177    ($t:ty) => {
178        impl From<$t> for SqlValue {
179            fn from(f: $t) -> Self {
180                SqlValue::double(f as f64)
181            }
182        }
183    };
184}
185
186impl_float!(f32);
187impl_float!(f64);
188
189impl From<Datetime> for SqlValue {
190    fn from(dt: Datetime) -> Self {
191        SqlValue::datetime(dt)
192    }
193}
194
195macro_rules! impl_int {
196    ($t:ty) => {
197        impl From<$t> for SqlValue {
198            fn from(i: $t) -> Self {
199                SqlValue::integer(i as i64)
200            }
201        }
202    };
203}
204
205impl_int!(i8);
206impl_int!(i16);
207impl_int!(i32);
208impl_int!(i64);
209impl_int!(isize);
210impl_int!(i128);
211
212impl_int!(u8);
213impl_int!(u16);
214impl_int!(u32);
215impl_int!(u64);
216impl_int!(usize);
217impl_int!(u128);
218
219impl<T: Into<SqlValue>> From<Option<T>> for SqlValue {
220    fn from(opt: Option<T>) -> Self {
221        match opt {
222            None => SqlValue::null(),
223            Some(t) => t.into(),
224        }
225    }
226}
227
228impl From<String> for SqlValue {
229    fn from(s: String) -> Self {
230        SqlValue::string(s)
231    }
232}
233
234impl From<&str> for SqlValue {
235    fn from(s: &str) -> Self {
236        SqlValue::string(s)
237    }
238}
239
240impl<T: Into<SqlValue>> From<Vec<T>> for SqlValue {
241    fn from(vec: Vec<T>) -> Self {
242        let array: Vec<_> = vec.into_iter().map(|el| el.into()).collect();
243        SqlValue::array(array)
244    }
245}
246
247impl<T: Into<SqlValue> + Clone> From<&[T]> for SqlValue {
248    fn from(slice: &[T]) -> Self {
249        let array: Vec<_> = slice.iter().map(|el| el.clone().into()).collect();
250        SqlValue::array(array)
251    }
252}
253
254impl<T: Into<SqlValue>, const N: usize> From<[T; N]> for SqlValue {
255    fn from(slice: [T; N]) -> Self {
256        let array: Vec<_> = slice.into_iter().map(|el| el.into()).collect();
257        SqlValue::array(array)
258    }
259}
260
261impl From<Uuid> for SqlValue {
262    fn from(uuid: Uuid) -> Self {
263        SqlValue::uuid(uuid)
264    }
265}