odbc_safe/handles/
hstmt.rs1use super::*;
2use sys::*;
3use std::marker::PhantomData;
4use std::ptr::{null, null_mut};
5use std::thread::panicking;
6
7#[derive(Debug)]
8pub struct HStmt<'con> {
9 parent: PhantomData<&'con HDbc<'con>>,
11 handle: SQLHSTMT,
13}
14
15impl<'con, 'param> Drop for HStmt<'con> {
16 fn drop(&mut self) {
17 unsafe {
18 match SQLFreeHandle(SQL_HANDLE_STMT, self.handle as SQLHANDLE) {
19 SQL_SUCCESS => (),
20 other => {
21 if !panicking() {
22 panic!("Unexepected return value of SQLFreeHandle: {:?}.", other)
23 }
24 }
25 }
26 }
27 }
28}
29
30unsafe impl<'env, 'param> Handle for HStmt<'env> {
31 const HANDLE_TYPE: HandleType = SQL_HANDLE_STMT;
32
33 fn handle(&self) -> SQLHANDLE {
34 self.handle as SQLHANDLE
35 }
36}
37
38impl<'env, 'param> HStmt<'env> {
39 pub fn as_raw(&self) -> SQLHSTMT {
40 self.handle
41 }
42
43 pub fn allocate(parent: &HDbc) -> Return<Self> {
45 let mut out = null_mut();
46 unsafe {
47 let result: Return<()> = SQLAllocHandle(SQL_HANDLE_STMT, parent.handle(), &mut out)
48 .into();
49 result.map(|()| {
50 HStmt {
51 parent: PhantomData,
52 handle: out as SQLHSTMT,
53 }
54 })
55 }
56 }
57
58 pub fn exec_direct<T>(&mut self, statement_text: &T) -> ReturnOption<()>
59 where
60 T: SqlStr + ?Sized,
61 {
62 unsafe {
63 SQLExecDirect(
64 self.handle,
65 statement_text.as_text_ptr(),
66 statement_text.text_length_int(),
67 ).into()
68 }
69 }
70
71 pub fn num_result_cols(&self) -> Return<SQLSMALLINT> {
72 let mut out: SQLSMALLINT = 0;
73 let ret = unsafe { SQLNumResultCols(self.handle, &mut out) };
74 let ret: Return<()> = ret.into();
75 ret.map(|()| out)
76 }
77
78 pub fn affected_row_count(&self) -> Return<SQLLEN> {
79 let mut out: SQLLEN = 0;
80 let ret = unsafe { SQLRowCount(self.handle, &mut out) };
81 let ret: Return<()> = ret.into();
82 ret.map(|()| out)
83 }
84
85 pub fn fetch(&mut self) -> ReturnOption<()> {
86 unsafe { SQLFetch(self.handle).into() }
87 }
88
89 pub fn get_data<T>(
90 &mut self,
91 col_or_param_num: SQLUSMALLINT,
92 target: &mut T,
93 ) -> ReturnOption<Indicator>
94 where
95 T: CDataType + ?Sized,
96 {
97 let mut str_len_or_ind = 0;
98 let ret: ReturnOption<()> = unsafe {
99 SQLGetData(
100 self.handle,
101 col_or_param_num,
102 T::c_data_type(),
103 target.mut_sql_ptr(),
104 target.buffer_len(),
105 &mut str_len_or_ind,
106 ).into()
107 };
108 ret.map(|()| str_len_or_ind.into())
109 }
110
111 pub fn close_cursor(&mut self) -> Return<()> {
112 unsafe { SQLCloseCursor(self.handle).into() }
113 }
114
115 pub unsafe fn bind_input_parameter<T>(
119 &mut self,
120 parameter_number: SQLUSMALLINT,
121 parameter_type: DataType,
122 value: &T,
123 indicator: Option<&SQLLEN>
124 ) -> Return<()>
125 where
126 T: CDataType + ?Sized,
127 {
128 let indicator: *const SQLLEN = match indicator {
129 Some(indicator) => {
130 assert!(*indicator <= value.buffer_len(), "Indicator cannot be larger than buffer length.");
131 indicator
132 }
133 None => null(),
134 };
135 SQLBindParameter(
136 self.handle,
137 parameter_number,
138 SQL_PARAM_INPUT,
139 T::c_data_type(),
140 parameter_type.sql_data_type(),
141 parameter_type.column_size(),
142 parameter_type.decimal_digits(),
143 value.sql_ptr() as SQLPOINTER,
144 0,
145 indicator as *mut SQLLEN,
146 ).into()
147 }
148
149 pub fn prepare<T>(&mut self, statement_text: &T) -> Return<()>
150 where
151 T: SqlStr + ?Sized,
152 {
153 unsafe {
154 SQLPrepare(
155 self.handle,
156 statement_text.as_text_ptr(),
157 statement_text.text_length_int(),
158 ).into()
159 }
160 }
161
162 pub fn reset_parameters(&mut self) -> Return<()> {
163 unsafe { SQLFreeStmt(self.handle, SQL_RESET_PARAMS).into() }
164 }
165
166 pub fn execute(&mut self) -> ReturnOption<()> {
167 unsafe { SQLExecute(self.handle).into() }
168 }
169
170 pub fn reset_columns(&mut self) -> Return<()> {
172 unsafe { SQLFreeStmt(self.handle, SQL_UNBIND).into() }
173 }
174
175 pub unsafe fn bind_col<T>(
179 &mut self,
180 column_number: SQLUSMALLINT,
181 value: &mut T,
182 indicator: Option<&mut SQLLEN>,
183 ) -> Return<()>
184 where
185 T: CDataType + ?Sized,
186 {
187 let indicator: *mut SQLLEN = match indicator {
188 Some(indicator) => indicator,
189 None => null_mut(),
190 };
191 SQLBindCol(
192 self.handle,
193 column_number,
194 T::c_data_type(),
195 value.mut_sql_ptr(),
196 value.buffer_len(),
197 indicator,
198 ).into()
199 }
200
201 pub fn describe_col<T>(
202 &mut self,
203 column_number: SQLUSMALLINT,
204 column_name: &mut T,
205 column_name_indicator: &mut SQLSMALLINT,
206 data_type: &mut SqlDataType,
207 column_size: &mut SQLULEN,
208 decimal_digits: &mut SQLSMALLINT,
209 nullable: &mut Nullable,
210 ) -> Return<()>
211 where
212 T: OutputBuffer + ?Sized,
213 {
214 unsafe {
215 SQLDescribeCol(
216 self.handle,
217 column_number,
218 column_name.mut_buf_ptr(),
219 column_name.buf_len(),
220 column_name_indicator,
221 data_type,
222 column_size,
223 decimal_digits,
224 nullable,
225 ).into()
226 }
227 }
228}