sqlx_core_oldapi/sqlite/
value.rs

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