picodata_plugin/sql/
types.rs1use 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#[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#[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#[derive(StableAbi)]
75#[repr(C)]
76pub enum SqlValueInner {
77 Boolean(bool),
79 Decimal(RawDecimal),
81 Double(f64),
83 Datetime(RawDatetime),
85 Integer(i64),
87 Null,
89 String(RString),
91 #[deprecated]
93 Unsigned(u64),
94 Array(RVec<SqlValue>),
96 Uuid([u8; 16]),
98}
99
100#[derive(StableAbi)]
101#[repr(C)]
102pub struct SqlValue(SqlValueInner);
103
104impl SqlValue {
105 pub fn into_inner(self) -> SqlValueInner {
107 self.0
108 }
109
110 pub fn boolean(b: bool) -> Self {
112 SqlValue(SqlValueInner::Boolean(b))
113 }
114
115 pub fn decimal(dec: tarantool::decimal::Decimal) -> Self {
117 let dec = dec.into_raw();
118 SqlValue(SqlValueInner::Decimal(RawDecimal::from(dec)))
119 }
120
121 pub fn double(d: f64) -> Self {
123 SqlValue(SqlValueInner::Double(d))
124 }
125
126 pub fn datetime(dt: tarantool::datetime::Datetime) -> Self {
128 SqlValue(SqlValueInner::Datetime(RawDatetime::from(dt.as_ffi_dt())))
129 }
130
131 pub fn integer(i: i64) -> Self {
133 SqlValue(SqlValueInner::Integer(i))
134 }
135
136 pub fn null() -> Self {
138 SqlValue(SqlValueInner::Null)
139 }
140
141 pub fn string(s: impl Into<String>) -> Self {
143 SqlValue(SqlValueInner::String(RString::from(s.into())))
144 }
145
146 #[deprecated]
148 #[allow(deprecated)]
149 pub fn unsigned(u: u64) -> Self {
150 SqlValue(SqlValueInner::Unsigned(u))
151 }
152
153 pub fn array(arr: impl Into<Vec<Self>>) -> Self {
155 SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
156 }
157
158 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}