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 Unsigned(u64),
93 Array(RVec<SqlValue>),
95 Uuid([u8; 16]),
97}
98
99#[derive(StableAbi)]
100#[repr(C)]
101pub struct SqlValue(SqlValueInner);
102
103impl SqlValue {
104 pub fn into_inner(self) -> SqlValueInner {
106 self.0
107 }
108
109 pub fn boolean(b: bool) -> Self {
111 SqlValue(SqlValueInner::Boolean(b))
112 }
113
114 pub fn decimal(dec: tarantool::decimal::Decimal) -> Self {
116 let dec = dec.into_raw();
117 SqlValue(SqlValueInner::Decimal(RawDecimal::from(dec)))
118 }
119
120 pub fn double(d: f64) -> Self {
122 SqlValue(SqlValueInner::Double(d))
123 }
124
125 pub fn datetime(dt: tarantool::datetime::Datetime) -> Self {
127 SqlValue(SqlValueInner::Datetime(RawDatetime::from(dt.as_ffi_dt())))
128 }
129
130 pub fn integer(i: i64) -> Self {
132 SqlValue(SqlValueInner::Integer(i))
133 }
134
135 pub fn null() -> Self {
137 SqlValue(SqlValueInner::Null)
138 }
139
140 pub fn string(s: impl Into<String>) -> Self {
142 SqlValue(SqlValueInner::String(RString::from(s.into())))
143 }
144
145 pub fn unsigned(u: u64) -> Self {
147 SqlValue(SqlValueInner::Unsigned(u))
148 }
149
150 pub fn array(arr: impl Into<Vec<Self>>) -> Self {
152 SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
153 }
154
155 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}