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 pub fn unsigned(u: u64) -> Self {
149 SqlValue(SqlValueInner::Unsigned(u))
150 }
151
152 pub fn array(arr: impl Into<Vec<Self>>) -> Self {
154 SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
155 }
156
157 pub fn uuid(uuid: system::tarantool::uuid::Uuid) -> Self {
159 SqlValue(SqlValueInner::Uuid(*uuid.as_bytes()))
160 }
161}
162
163impl From<bool> for SqlValue {
164 fn from(b: bool) -> Self {
165 SqlValue::boolean(b)
166 }
167}
168
169impl From<Decimal> for SqlValue {
170 fn from(dec: Decimal) -> Self {
171 SqlValue::decimal(dec)
172 }
173}
174
175macro_rules! impl_float {
176 ($t:ty) => {
177 impl From<$t> for SqlValue {
178 fn from(f: $t) -> Self {
179 SqlValue::double(f as f64)
180 }
181 }
182 };
183}
184
185impl_float!(f32);
186impl_float!(f64);
187
188impl From<Datetime> for SqlValue {
189 fn from(dt: Datetime) -> Self {
190 SqlValue::datetime(dt)
191 }
192}
193
194macro_rules! impl_int {
195 ($t:ty) => {
196 impl From<$t> for SqlValue {
197 fn from(i: $t) -> Self {
198 SqlValue::integer(i as i64)
199 }
200 }
201 };
202}
203
204impl_int!(i8);
205impl_int!(i16);
206impl_int!(i32);
207impl_int!(i64);
208impl_int!(isize);
209impl_int!(i128);
210
211impl_int!(u8);
212impl_int!(u16);
213impl_int!(u32);
214impl_int!(u64);
215impl_int!(usize);
216impl_int!(u128);
217
218impl<T: Into<SqlValue>> From<Option<T>> for SqlValue {
219 fn from(opt: Option<T>) -> Self {
220 match opt {
221 None => SqlValue::null(),
222 Some(t) => t.into(),
223 }
224 }
225}
226
227impl From<String> for SqlValue {
228 fn from(s: String) -> Self {
229 SqlValue::string(s)
230 }
231}
232
233impl From<&str> for SqlValue {
234 fn from(s: &str) -> Self {
235 SqlValue::string(s)
236 }
237}
238
239impl<T: Into<SqlValue>> From<Vec<T>> for SqlValue {
240 fn from(vec: Vec<T>) -> Self {
241 let array: Vec<_> = vec.into_iter().map(|el| el.into()).collect();
242 SqlValue::array(array)
243 }
244}
245
246impl<T: Into<SqlValue> + Clone> From<&[T]> for SqlValue {
247 fn from(slice: &[T]) -> Self {
248 let array: Vec<_> = slice.iter().map(|el| el.clone().into()).collect();
249 SqlValue::array(array)
250 }
251}
252
253impl<T: Into<SqlValue>, const N: usize> From<[T; N]> for SqlValue {
254 fn from(slice: [T; N]) -> Self {
255 let array: Vec<_> = slice.into_iter().map(|el| el.into()).collect();
256 SqlValue::array(array)
257 }
258}
259
260impl From<Uuid> for SqlValue {
261 fn from(uuid: Uuid) -> Self {
262 SqlValue::uuid(uuid)
263 }
264}