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
use error::{SqlDiagnosticRecord, SqlResult};
use handle::SqlHandle;
use odbc_sys::*;
use std;
use std::string::FromUtf16Error;
pub fn decimal_digits(parameter_type: SqlDataType) -> SQLSMALLINT {
match parameter_type {
SQL_TIMESTAMP
| SQL_SS_TIMESTAMPOFFSET
| SQL_TIME
| SQL_DATETIME
| SQL_SS_TIME2
| SQL_EXT_TIMESTAMP
| SQL_EXT_TIME_OR_INTERVAL => 9,
_ => 0,
}
}
pub fn from_utf_16_null_terminated(mut slice: &[u16]) -> Result<String, FromUtf16Error> {
if let Some(&0) = slice.last() {
slice = &slice[..slice.len() - 1];
};
String::from_utf16(slice)
}
pub fn u32_to_bool(x: u32) -> bool {
match x {
1 => true,
0 => false,
_ => panic!("{} is not a valid boolean value (0/1)", x),
}
}
pub fn is_string_data_right_truncated<T: SqlHandle>(handle: &T, ret: SQLRETURN) -> SqlResult<bool> {
match ret {
SQL_SUCCESS | SQL_NO_DATA => Ok(false),
SQL_SUCCESS_WITH_INFO => {
let diagnostics = handle.diagnostics()?;
Ok(diagnostics
.iter()
.any(SqlDiagnosticRecord::is_string_data_right_truncated))
}
_ => panic!("Unexpected SQLRETURN: {:?}", ret),
}
}
pub trait VecCapacityExt {
fn reserve_capacity(&mut self, capacity: usize);
unsafe fn set_len_checked(&mut self, len: usize);
fn capacity_bytes(&self) -> usize;
fn remaining_capacity(&self) -> usize;
fn remaining_capacity_bytes(&self) -> usize;
}
impl<T> VecCapacityExt for Vec<T> {
fn reserve_capacity(&mut self, capacity: usize) {
let len = self.len();
if capacity > len {
self.reserve_exact(capacity - len);
}
}
unsafe fn set_len_checked(&mut self, len: usize) {
assert!(len <= self.capacity());
self.set_len(len);
}
fn capacity_bytes(&self) -> usize {
self.capacity() * std::mem::size_of::<T>()
}
fn remaining_capacity(&self) -> usize {
self.capacity() - self.len()
}
fn remaining_capacity_bytes(&self) -> usize {
self.remaining_capacity() * std::mem::size_of::<T>()
}
}
#[cfg(test)]
mod tests {
use std::sync::{Arc, RwLock};
use SqlHandle;
pub fn print_diagnostics<T: SqlHandle>(handle: &T) {
let diagnostics = handle.diagnostics().unwrap();
let mut iter = diagnostics.iter().peekable();
while let Some(detail) = iter.next() {
if iter.peek().is_some() {
println!("{}\n", detail);
} else {
println!("{}", detail);
}
}
}
pub fn print_diagnostics_async<T: SqlHandle>(handle: &Arc<RwLock<T>>) {
let lock = handle.read().unwrap();
print_diagnostics(&lock as &T);
}
}
#[cfg(test)]
pub use self::tests::*;