1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
extern crate libsqlite3_sys as ffi;
use std::cell::Ref;
use std::ptr::NonNull;
use std::{slice, str};
use crate::sqlite::SqliteType;
use super::row::PrivateSqliteRow;
#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct SqliteValue<'row, 'stmt, 'query> {
_row: Ref<'row, PrivateSqliteRow<'stmt, 'query>>,
value: NonNull<ffi::sqlite3_value>,
}
#[repr(transparent)]
pub(super) struct OwnedSqliteValue {
pub(super) value: NonNull<ffi::sqlite3_value>,
}
impl Drop for OwnedSqliteValue {
fn drop(&mut self) {
unsafe { ffi::sqlite3_value_free(self.value.as_ptr()) }
}
}
impl<'row, 'stmt, 'query> SqliteValue<'row, 'stmt, 'query> {
pub(super) fn new(
row: Ref<'row, PrivateSqliteRow<'stmt, 'query>>,
col_idx: i32,
) -> Option<SqliteValue<'row, 'stmt, 'query>> {
let value = match &*row {
PrivateSqliteRow::Direct(stmt) => stmt.column_value(col_idx)?,
PrivateSqliteRow::Duplicated { values, .. } => {
values.get(col_idx as usize).and_then(|v| v.as_ref())?.value
}
};
let ret = Self { _row: row, value };
if ret.value_type().is_none() {
None
} else {
Some(ret)
}
}
pub(crate) fn parse_string<'value, R>(&'value self, f: impl FnOnce(&'value str) -> R) -> R {
let s = unsafe {
let ptr = ffi::sqlite3_value_text(self.value.as_ptr());
let len = ffi::sqlite3_value_bytes(self.value.as_ptr());
let bytes = slice::from_raw_parts(ptr as *const u8, len as usize);
str::from_utf8_unchecked(bytes)
};
f(s)
}
pub(crate) fn read_text(&self) -> &str {
self.parse_string(|s| s)
}
pub(crate) fn read_blob(&self) -> &[u8] {
unsafe {
let ptr = ffi::sqlite3_value_blob(self.value.as_ptr());
let len = ffi::sqlite3_value_bytes(self.value.as_ptr());
if len == 0 {
&[]
} else {
slice::from_raw_parts(ptr as *const u8, len as usize)
}
}
}
pub(crate) fn read_integer(&self) -> i32 {
unsafe { ffi::sqlite3_value_int(self.value.as_ptr()) }
}
pub(crate) fn read_long(&self) -> i64 {
unsafe { ffi::sqlite3_value_int64(self.value.as_ptr()) }
}
pub(crate) fn read_double(&self) -> f64 {
unsafe { ffi::sqlite3_value_double(self.value.as_ptr()) }
}
pub fn value_type(&self) -> Option<SqliteType> {
let tpe = unsafe { ffi::sqlite3_value_type(self.value.as_ptr()) };
match tpe {
ffi::SQLITE_TEXT => Some(SqliteType::Text),
ffi::SQLITE_INTEGER => Some(SqliteType::Long),
ffi::SQLITE_FLOAT => Some(SqliteType::Double),
ffi::SQLITE_BLOB => Some(SqliteType::Binary),
ffi::SQLITE_NULL => None,
_ => unreachable!(
"Sqlite's documentation state that this case ({}) is not reachable. \
If you ever see this error message please open an issue at \
https://github.com/diesel-rs/diesel.",
tpe
),
}
}
}
impl OwnedSqliteValue {
pub(super) fn copy_from_ptr(ptr: NonNull<ffi::sqlite3_value>) -> Option<OwnedSqliteValue> {
let tpe = unsafe { ffi::sqlite3_value_type(ptr.as_ptr()) };
if ffi::SQLITE_NULL == tpe {
return None;
}
let value = unsafe { ffi::sqlite3_value_dup(ptr.as_ptr()) };
Some(Self {
value: NonNull::new(value)?,
})
}
pub(super) fn duplicate(&self) -> OwnedSqliteValue {
let value = unsafe { ffi::sqlite3_value_dup(self.value.as_ptr()) };
let value = NonNull::new(value).expect(
"Sqlite documentation states this returns only null if value is null \
or OOM. If you ever see this panic message please open an issue at \
https://github.com/diesel-rs/diesel.",
);
OwnedSqliteValue { value }
}
}