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
#![deny(missing_debug_implementations)]
#[allow(non_camel_case_types)]
pub mod data_type;
pub mod error;
pub use data_type::*;
use odbc_api::buffers::TextRowSet;
use odbc_api::handles::StatementImpl;
use odbc_api::{Cursor, CursorImpl, ResultSetMetadata};
use std::str::FromStr;
#[derive(Debug, Default)]
pub struct DmColumnDesc {
table_id: Option<usize>,
inner: Vec<DmColumnInner>,
}
#[derive(Debug)]
pub struct DmColumnInner {
_name: String,
_data_type: DataType,
}
impl DmColumnInner {
fn new(name: String, data_type: DataType) -> Self {
Self {
_name: name,
_data_type: data_type,
}
}
}
pub trait DmAdapter {
fn get_table_sql(table_name: &str) -> String;
fn get_table_desc(self) -> anyhow::Result<DmColumnDesc>;
}
impl DmAdapter for CursorImpl<StatementImpl<'_>> {
fn get_table_sql(table_name: &str) -> String {
format!(
r#"select a.name,a.type$ as data_type,a.id as table_id from SYSCOLUMNS as a left join SYSOBJECTS as b on a.id = b.id where b.name = '{}'"#,
table_name
)
}
fn get_table_desc(mut self) -> anyhow::Result<DmColumnDesc> {
let headers = self.column_names()?.collect::<Result<Vec<String>, _>>()?;
assert_eq!(headers, vec!["name", "data_type", "table_id"]);
let mut buffers = TextRowSet::for_cursor(1024, &mut self, Some(4096))?;
let mut row_set_cursor = self.bind_buffer(&mut buffers)?;
let mut table_desc = DmColumnDesc::default();
while let Some(batch) = row_set_cursor.fetch()? {
for row_index in 0..batch.num_rows() {
let num_cols = batch.num_cols();
assert_eq!(num_cols, headers.len());
let mut row_data: Vec<_> = (0..num_cols)
.map(|col_index| batch.at(col_index, row_index).unwrap_or(&[]))
.into_iter()
.map(String::from_utf8_lossy)
.collect();
table_desc.inner.push(DmColumnInner::new(
row_data.remove(0).to_string(),
DataType::from_str(row_data.remove(0).as_ref())?,
));
if table_desc.table_id.is_none() {
table_desc.table_id = Some(row_data.remove(0).parse::<usize>()?);
}
}
}
Ok(table_desc)
}
}