我正在Rust中使用混合列类型的odbc_api
从sql数据库中读取一些数据。但是,我注意到表中具有varchar(max)
的字段无法从表中返回。我认为这与TextRowSet
字符串缓冲区大小有关,但即使我将值从4 KiB更改为更高的限制,我仍然无法收到varchar列。一切构建都没有警告或错误。
代码:
use anyhow::Error;
use odbc_api::{buffers::TextRowSet, Cursor, Environment, ResultSetMetadata};
use std::io;
const BATCH_SIZE: usize = 100;
fn main() -> Result<(), Error>
{
// Write sql query to stdout
let out = io::stdout();
let mut writer = csv::Writer::from_writer(out);
// Establish environment
let environment = Environment::new()?;
let connection_string = "
Driver={ODBC Driver 17 for SQL Server};
Server=my_server;
db=my_db;
trusted_connection=yes;
";
let conn = environment.connect_with_connection_string(connection_string)?;
// Set up query and execute
let qry = "select top 10 * from my_tbl";
match conn.execute(&qry, ())
{
Err(e) => println!("{}", e),
Ok(Some(mut cursor)) => {
// Write column names to stdout
let headline: Vec<String> = cursor.column_names()?.collect::<Result<_,_>>()?;
writer.write_record(headline)?;
// Use schema in cursor to initialize a text buffer large enough to hold the largest
// possible strings for each column to an upper limit of 4Kib.
let mut buffers = TextRowSet::for_cursor(BATCH_SIZE, &mut cursor, Some(4096))?;
// Bind the buffer to the cursor. It will now be filled with every call to fetch.
let mut row_set_cursor = cursor.bind_buffer(&mut buffers)?;
// Iterate over batches
while let Some(batch) = row_set_cursor.fetch()?
{
// Within a batch, iterate over every row
for row_index in 0..batch.num_rows()
{
//println!("{}", row_index);
let record = (0..batch.num_cols()).map(|col_index| {
batch.at(col_index, row_index)
.unwrap()
});
// Writes row as csv
writer.write_record(record)?;
}
}
},
Ok(None) => {
eprintln!("Query came back empty. No output created.");
}
}
Ok(())
}
odbc_api文档:https://docs.rs/odbc-api/latest/odbc_api/
**破解解决方案编辑:**
因此,通过转到源表并将字段varchar(max)
修改为varchar(255)
,我有效地解决了这个问题。有人能解释一下这里发生了什么吗?
Microsoft SQL Server报告类型为VARCHAR(max)
的列的元素大小为0
。文本缓冲区为每个字段分配刚好足够的内存用于终止零,同时保持在指定的上限之下。由于我是odbc-api
的作者,我在阅读了你的问题后发布的0.50.2
版本中修复了它。