1use std::os::raw::{c_int, c_void};
4#[cfg(feature = "array")]
5use std::rc::Rc;
6
7use crate::ffi;
8use crate::ffi::sqlite3_context;
9
10use crate::str_for_sqlite;
11use crate::types::{ToSqlOutput, ValueRef};
12#[cfg(feature = "array")]
13use crate::vtab::array::{free_array, ARRAY_TYPE};
14
15#[inline]
19pub(super) unsafe fn set_result(ctx: *mut sqlite3_context, result: &ToSqlOutput<'_>) {
20 let value = match *result {
21 ToSqlOutput::Borrowed(v) => v,
22 ToSqlOutput::Owned(ref v) => ValueRef::from(v),
23
24 #[cfg(feature = "blob")]
25 ToSqlOutput::ZeroBlob(len) => {
26 return ffi::sqlite3_result_zeroblob(ctx, len);
27 }
28 #[cfg(feature = "array")]
29 ToSqlOutput::Array(ref a) => {
30 return ffi::sqlite3_result_pointer(
31 ctx,
32 Rc::into_raw(a.clone()) as *mut c_void,
33 ARRAY_TYPE,
34 Some(free_array),
35 );
36 }
37 };
38
39 match value {
40 ValueRef::Null => ffi::sqlite3_result_null(ctx),
41 ValueRef::Integer(i) => ffi::sqlite3_result_int64(ctx, i),
42 ValueRef::Real(r) => ffi::sqlite3_result_double(ctx, r),
43 ValueRef::Text(s) => {
44 let length = s.len();
45 if length > c_int::max_value() as usize {
46 ffi::sqlite3_result_error_toobig(ctx);
47 } else {
48 let (c_str, len, destructor) = match str_for_sqlite(s) {
49 Ok(c_str) => c_str,
50 Err(_) => return ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE),
52 };
53 ffi::sqlite3_result_text(ctx, c_str, len, destructor);
54 }
55 }
56 ValueRef::Blob(b) => {
57 let length = b.len();
58 if length > c_int::max_value() as usize {
59 ffi::sqlite3_result_error_toobig(ctx);
60 } else if length == 0 {
61 ffi::sqlite3_result_zeroblob(ctx, 0)
62 } else {
63 ffi::sqlite3_result_blob(
64 ctx,
65 b.as_ptr() as *const c_void,
66 length as c_int,
67 ffi::SQLITE_TRANSIENT(),
68 );
69 }
70 }
71 }
72}