sqlx_core_oldapi/sqlite/
value.rs1use 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
90unsafe 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 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}