diesel/pg/connection/stmt/
mod.rs
1#![allow(unsafe_code)] extern crate pq_sys;
3
4use std::ffi::CString;
5use std::os::raw as libc;
6use std::ptr;
7
8use super::result::PgResult;
9use crate::pg::PgTypeMetadata;
10use crate::result::QueryResult;
11
12use super::raw::RawConnection;
13
14pub(crate) struct Statement {
15 name: CString,
16 param_formats: Vec<libc::c_int>,
17}
18
19impl Statement {
20 pub(super) fn execute(
21 &self,
22 raw_connection: &mut RawConnection,
23 param_data: &[Option<Vec<u8>>],
24 row_by_row: bool,
25 ) -> QueryResult<PgResult> {
26 let params_pointer = param_data
27 .iter()
28 .map(|data| {
29 data.as_ref()
30 .map(|d| d.as_ptr() as *const libc::c_char)
31 .unwrap_or(ptr::null())
32 })
33 .collect::<Vec<_>>();
34 let param_lengths = param_data
35 .iter()
36 .map(|data| data.as_ref().map(|d| d.len().try_into()).unwrap_or(Ok(0)))
37 .collect::<Result<Vec<_>, _>>()
38 .map_err(|e| crate::result::Error::SerializationError(Box::new(e)))?;
39 let param_count: libc::c_int = params_pointer
40 .len()
41 .try_into()
42 .map_err(|e| crate::result::Error::SerializationError(Box::new(e)))?;
43 unsafe {
44 raw_connection.send_query_prepared(
45 self.name.as_ptr(),
46 param_count,
47 params_pointer.as_ptr(),
48 param_lengths.as_ptr(),
49 self.param_formats.as_ptr(),
50 1,
51 )
52 }?;
53 if row_by_row {
54 raw_connection.enable_row_by_row_mode()?;
55 }
56 Ok(raw_connection.get_next_result()?.expect("Is never none"))
57 }
58
59 pub(super) fn prepare(
60 raw_connection: &mut RawConnection,
61 sql: &str,
62 name: Option<&str>,
63 param_types: &[PgTypeMetadata],
64 ) -> QueryResult<Self> {
65 let name = CString::new(name.unwrap_or(""))?;
66 let sql = CString::new(sql)?;
67 let param_types_vec = param_types
68 .iter()
69 .map(|x| x.oid())
70 .collect::<Result<Vec<_>, _>>()
71 .map_err(|e| crate::result::Error::SerializationError(Box::new(e)))?;
72
73 let internal_result = unsafe {
74 let param_count: libc::c_int = param_types
75 .len()
76 .try_into()
77 .map_err(|e| crate::result::Error::SerializationError(Box::new(e)))?;
78 raw_connection.prepare(
79 name.as_ptr(),
80 sql.as_ptr(),
81 param_count,
82 param_types_to_ptr(Some(¶m_types_vec)),
83 )
84 };
85 PgResult::new(internal_result?, raw_connection)?;
86
87 Ok(Statement {
88 name,
89 param_formats: vec![1; param_types.len()],
90 })
91 }
92}
93
94fn param_types_to_ptr(param_types: Option<&Vec<u32>>) -> *const pq_sys::Oid {
95 param_types
96 .map(|types| types.as_ptr())
97 .unwrap_or(ptr::null())
98}