rusqlite/
raw_statement.rs1use super::ffi;
2use super::StatementStatus;
3use crate::util::ParamIndexCache;
4use crate::util::SqliteMallocString;
5use std::ffi::{c_int, CStr};
6use std::ptr;
7#[cfg(feature = "cache")]
8use std::sync::Arc;
9
10#[derive(Debug)]
12pub struct RawStatement {
13 ptr: *mut ffi::sqlite3_stmt,
14 cache: ParamIndexCache,
16 #[cfg(feature = "cache")]
27 statement_cache_key: Option<Arc<str>>,
28}
29
30impl RawStatement {
31 #[inline]
32 pub unsafe fn new(stmt: *mut ffi::sqlite3_stmt) -> Self {
33 Self {
34 ptr: stmt,
35 cache: ParamIndexCache::default(),
36 #[cfg(feature = "cache")]
37 statement_cache_key: None,
38 }
39 }
40
41 #[inline]
42 pub fn is_null(&self) -> bool {
43 self.ptr.is_null()
44 }
45
46 #[inline]
47 #[cfg(feature = "cache")]
48 pub(crate) fn set_statement_cache_key(&mut self, p: impl Into<Arc<str>>) {
49 self.statement_cache_key = Some(p.into());
50 }
51
52 #[inline]
53 #[cfg(feature = "cache")]
54 pub(crate) fn statement_cache_key(&self) -> Option<Arc<str>> {
55 self.statement_cache_key.clone()
56 }
57
58 #[inline]
59 pub unsafe fn ptr(&self) -> *mut ffi::sqlite3_stmt {
60 self.ptr
61 }
62
63 #[inline]
64 pub fn column_count(&self) -> usize {
65 unsafe { ffi::sqlite3_column_count(self.ptr) as usize }
67 }
68
69 #[inline]
70 pub fn column_type(&self, idx: usize) -> c_int {
71 unsafe { ffi::sqlite3_column_type(self.ptr, idx as c_int) }
72 }
73
74 #[inline]
75 #[cfg(feature = "column_metadata")]
76 pub fn column_database_name(&self, idx: usize) -> Option<&CStr> {
77 unsafe {
78 let db_name = ffi::sqlite3_column_database_name(self.ptr, idx as c_int);
79 if db_name.is_null() {
80 None
81 } else {
82 Some(CStr::from_ptr(db_name))
83 }
84 }
85 }
86
87 #[inline]
88 #[cfg(feature = "column_metadata")]
89 pub fn column_table_name(&self, idx: usize) -> Option<&CStr> {
90 unsafe {
91 let tbl_name = ffi::sqlite3_column_table_name(self.ptr, idx as c_int);
92 if tbl_name.is_null() {
93 None
94 } else {
95 Some(CStr::from_ptr(tbl_name))
96 }
97 }
98 }
99
100 #[inline]
101 #[cfg(feature = "column_metadata")]
102 pub fn column_origin_name(&self, idx: usize) -> Option<&CStr> {
103 unsafe {
104 let origin_name = ffi::sqlite3_column_origin_name(self.ptr, idx as c_int);
105 if origin_name.is_null() {
106 None
107 } else {
108 Some(CStr::from_ptr(origin_name))
109 }
110 }
111 }
112
113 #[inline]
114 #[cfg(feature = "column_decltype")]
115 pub fn column_decltype(&self, idx: usize) -> Option<&CStr> {
116 unsafe {
117 let decltype = ffi::sqlite3_column_decltype(self.ptr, idx as c_int);
118 if decltype.is_null() {
119 None
120 } else {
121 Some(CStr::from_ptr(decltype))
122 }
123 }
124 }
125
126 #[inline]
127 pub fn column_name(&self, idx: usize) -> Option<&CStr> {
128 let idx = idx as c_int;
129 if idx < 0 || idx >= self.column_count() as c_int {
130 return None;
131 }
132 unsafe {
133 let ptr = ffi::sqlite3_column_name(self.ptr, idx);
134 assert!(
137 !ptr.is_null(),
138 "Null pointer from sqlite3_column_name: Out of memory?"
139 );
140 Some(CStr::from_ptr(ptr))
141 }
142 }
143
144 #[inline]
145 #[cfg(not(feature = "unlock_notify"))]
146 pub fn step(&self) -> c_int {
147 unsafe { ffi::sqlite3_step(self.ptr) }
148 }
149
150 #[cfg(feature = "unlock_notify")]
151 pub fn step(&self) -> c_int {
152 use crate::unlock_notify;
153 let mut db = ptr::null_mut::<ffi::sqlite3>();
154 loop {
155 unsafe {
156 let mut rc = ffi::sqlite3_step(self.ptr);
157 if (rc & 0xff) != ffi::SQLITE_LOCKED {
162 break rc;
163 }
164 if db.is_null() {
165 db = ffi::sqlite3_db_handle(self.ptr);
166 }
167 if !unlock_notify::is_locked(db, rc) {
168 break rc;
169 }
170 rc = unlock_notify::wait_for_unlock_notify(db);
171 if rc != ffi::SQLITE_OK {
172 break rc;
173 }
174 self.reset();
175 }
176 }
177 }
178
179 #[inline]
180 pub fn reset(&self) -> c_int {
181 unsafe { ffi::sqlite3_reset(self.ptr) }
182 }
183
184 #[inline]
185 pub fn bind_parameter_count(&self) -> usize {
186 unsafe { ffi::sqlite3_bind_parameter_count(self.ptr) as usize }
187 }
188
189 #[inline]
190 pub fn bind_parameter_index(&self, name: &str) -> Option<usize> {
191 self.cache.get_or_insert_with(name, |param_cstr| {
192 let r = unsafe { ffi::sqlite3_bind_parameter_index(self.ptr, param_cstr.as_ptr()) };
193 match r {
194 0 => None,
195 i => Some(i as usize),
196 }
197 })
198 }
199
200 #[inline]
201 pub fn bind_parameter_name(&self, index: i32) -> Option<&CStr> {
202 unsafe {
203 let name = ffi::sqlite3_bind_parameter_name(self.ptr, index);
204 if name.is_null() {
205 None
206 } else {
207 Some(CStr::from_ptr(name))
208 }
209 }
210 }
211
212 #[inline]
213 pub fn clear_bindings(&mut self) {
214 unsafe {
215 ffi::sqlite3_clear_bindings(self.ptr);
216 } }
218
219 #[inline]
220 pub fn sql(&self) -> Option<&CStr> {
221 if self.ptr.is_null() {
222 None
223 } else {
224 Some(unsafe { CStr::from_ptr(ffi::sqlite3_sql(self.ptr)) })
225 }
226 }
227
228 #[inline]
229 pub fn finalize(mut self) -> c_int {
230 self.finalize_()
231 }
232
233 #[inline]
234 fn finalize_(&mut self) -> c_int {
235 let r = unsafe { ffi::sqlite3_finalize(self.ptr) };
236 self.ptr = ptr::null_mut();
237 r
238 }
239
240 #[inline]
242 pub fn readonly(&self) -> bool {
243 unsafe { ffi::sqlite3_stmt_readonly(self.ptr) != 0 }
244 }
245
246 #[inline]
247 pub(crate) fn expanded_sql(&self) -> Option<SqliteMallocString> {
248 unsafe { expanded_sql(self.ptr) }
249 }
250
251 #[inline]
252 pub fn get_status(&self, status: StatementStatus, reset: bool) -> i32 {
253 unsafe { stmt_status(self.ptr, status, reset) }
254 }
255
256 #[inline]
257 pub fn is_explain(&self) -> i32 {
258 unsafe { ffi::sqlite3_stmt_isexplain(self.ptr) }
259 }
260
261 }
263
264#[inline]
265pub(crate) unsafe fn expanded_sql(ptr: *mut ffi::sqlite3_stmt) -> Option<SqliteMallocString> {
266 SqliteMallocString::from_raw(ffi::sqlite3_expanded_sql(ptr))
267}
268#[inline]
269pub(crate) unsafe fn stmt_status(
270 ptr: *mut ffi::sqlite3_stmt,
271 status: StatementStatus,
272 reset: bool,
273) -> i32 {
274 assert!(!ptr.is_null());
275 ffi::sqlite3_stmt_status(ptr, status as i32, reset as i32)
276}
277
278impl Drop for RawStatement {
279 fn drop(&mut self) {
280 self.finalize_();
281 }
282}