sqlx_build_trust_sqlite/
value.rs

1use std::borrow::Cow;
2use std::ptr::NonNull;
3use std::slice::from_raw_parts;
4use std::str::from_utf8;
5use std::sync::Arc;
6
7use libsqlite3_sys::{
8    sqlite3_value, sqlite3_value_blob, sqlite3_value_bytes, sqlite3_value_double,
9    sqlite3_value_dup, sqlite3_value_free, sqlite3_value_int, sqlite3_value_int64,
10    sqlite3_value_type, SQLITE_NULL,
11};
12
13pub(crate) use sqlx_core::value::{Value, ValueRef};
14
15use crate::error::BoxDynError;
16use crate::type_info::DataType;
17use crate::{Sqlite, SqliteTypeInfo};
18
19enum SqliteValueData<'r> {
20    Value(&'r SqliteValue),
21}
22
23pub struct SqliteValueRef<'r>(SqliteValueData<'r>);
24
25impl<'r> SqliteValueRef<'r> {
26    pub(crate) fn value(value: &'r SqliteValue) -> Self {
27        Self(SqliteValueData::Value(value))
28    }
29
30    pub(super) fn int(&self) -> i32 {
31        match self.0 {
32            SqliteValueData::Value(v) => v.int(),
33        }
34    }
35
36    pub(super) fn int64(&self) -> i64 {
37        match self.0 {
38            SqliteValueData::Value(v) => v.int64(),
39        }
40    }
41
42    pub(super) fn double(&self) -> f64 {
43        match self.0 {
44            SqliteValueData::Value(v) => v.double(),
45        }
46    }
47
48    pub(super) fn blob(&self) -> &'r [u8] {
49        match self.0 {
50            SqliteValueData::Value(v) => v.blob(),
51        }
52    }
53
54    pub(super) fn text(&self) -> Result<&'r str, BoxDynError> {
55        match self.0 {
56            SqliteValueData::Value(v) => v.text(),
57        }
58    }
59}
60
61impl<'r> ValueRef<'r> for SqliteValueRef<'r> {
62    type Database = Sqlite;
63
64    fn to_owned(&self) -> SqliteValue {
65        match self.0 {
66            SqliteValueData::Value(v) => v.clone(),
67        }
68    }
69
70    fn type_info(&self) -> Cow<'_, SqliteTypeInfo> {
71        match self.0 {
72            SqliteValueData::Value(v) => v.type_info(),
73        }
74    }
75
76    fn is_null(&self) -> bool {
77        match self.0 {
78            SqliteValueData::Value(v) => v.is_null(),
79        }
80    }
81}
82
83#[derive(Clone)]
84pub struct SqliteValue {
85    pub(crate) handle: Arc<ValueHandle>,
86    pub(crate) type_info: SqliteTypeInfo,
87}
88
89pub(crate) struct ValueHandle(NonNull<sqlite3_value>);
90
91// SAFE: only protected value objects are stored in SqliteValue
92unsafe impl Send for ValueHandle {}
93unsafe impl Sync for ValueHandle {}
94
95impl SqliteValue {
96    pub(crate) unsafe fn new(value: *mut sqlite3_value, type_info: SqliteTypeInfo) -> Self {
97        debug_assert!(!value.is_null());
98
99        Self {
100            type_info,
101            handle: Arc::new(ValueHandle(NonNull::new_unchecked(sqlite3_value_dup(
102                value,
103            )))),
104        }
105    }
106
107    fn type_info_opt(&self) -> Option<SqliteTypeInfo> {
108        let dt = DataType::from_code(unsafe { sqlite3_value_type(self.handle.0.as_ptr()) });
109
110        if let DataType::Null = dt {
111            None
112        } else {
113            Some(SqliteTypeInfo(dt))
114        }
115    }
116
117    fn int(&self) -> i32 {
118        unsafe { sqlite3_value_int(self.handle.0.as_ptr()) }
119    }
120
121    fn int64(&self) -> i64 {
122        unsafe { sqlite3_value_int64(self.handle.0.as_ptr()) }
123    }
124
125    fn double(&self) -> f64 {
126        unsafe { sqlite3_value_double(self.handle.0.as_ptr()) }
127    }
128
129    fn blob(&self) -> &[u8] {
130        let len = unsafe { sqlite3_value_bytes(self.handle.0.as_ptr()) } as usize;
131
132        if len == 0 {
133            // empty blobs are NULL so just return an empty slice
134            return &[];
135        }
136
137        let ptr = unsafe { sqlite3_value_blob(self.handle.0.as_ptr()) } as *const u8;
138        debug_assert!(!ptr.is_null());
139
140        unsafe { from_raw_parts(ptr, len) }
141    }
142
143    fn text(&self) -> Result<&str, BoxDynError> {
144        Ok(from_utf8(self.blob())?)
145    }
146}
147
148impl Value for SqliteValue {
149    type Database = Sqlite;
150
151    fn as_ref(&self) -> SqliteValueRef<'_> {
152        SqliteValueRef::value(self)
153    }
154
155    fn type_info(&self) -> Cow<'_, SqliteTypeInfo> {
156        self.type_info_opt()
157            .map(Cow::Owned)
158            .unwrap_or(Cow::Borrowed(&self.type_info))
159    }
160
161    fn is_null(&self) -> bool {
162        unsafe { sqlite3_value_type(self.handle.0.as_ptr()) == SQLITE_NULL }
163    }
164}
165
166impl Drop for ValueHandle {
167    fn drop(&mut self) {
168        unsafe {
169            sqlite3_value_free(self.0.as_ptr());
170        }
171    }
172}
173
174// #[cfg(feature = "any")]
175// impl<'r> From<SqliteValueRef<'r>> for crate::any::AnyValueRef<'r> {
176//     #[inline]
177//     fn from(value: SqliteValueRef<'r>) -> Self {
178//         crate::any::AnyValueRef {
179//             type_info: value.type_info().clone().into_owned().into(),
180//             kind: crate::any::value::AnyValueRefKind::Sqlite(value),
181//         }
182//     }
183// }
184//
185// #[cfg(feature = "any")]
186// impl From<SqliteValue> for crate::any::AnyValue {
187//     #[inline]
188//     fn from(value: SqliteValue) -> Self {
189//         crate::any::AnyValue {
190//             type_info: value.type_info().clone().into_owned().into(),
191//             kind: crate::any::value::AnyValueKind::Sqlite(value),
192//         }
193//     }
194// }