Skip to content

Commit

Permalink
odbcsv new parameter max-str-len
Browse files Browse the repository at this point in the history
  • Loading branch information
pacman82 committed Mar 6, 2021
1 parent 4e4ff30 commit cfd1025
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* `TextColumn` is now generic over its character type. The type alias `CharColumn` for
`TextColumn<u8>` can serve as a drop in replacement for the previous iteration of `TextColumn`.
* `AnyColumnBuffer` has a new variant called `WText` holding a UTF-16 `TextColumn<u16>` or `WCharColumn`.
* `TextRowSet::for_cursor` has a new parameter `max_str_limit` to designate the upper limit for column buffer size.
* `TextRowSet::for_cursor` has a new parameter `max_str_len` to designate the upper limit for column buffer size.
* Add `TextRowSet::indicator_at` to allow checking for truncation of strings.

## 0.17.0
Expand Down
3 changes: 1 addition & 2 deletions odbc-api/src/buffers/text_column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,7 @@ impl<C> TextColumn<C> {
new_value[..max_copy_length].clone_from_slice(&old_value[..max_copy_length]);
}
Indicator::Length(num_bytes_len) => {
let num_bytes_to_copy =
min(num_bytes_len / size_of::<C>(), max_copy_length);
let num_bytes_to_copy = min(num_bytes_len / size_of::<C>(), max_copy_length);
new_value[..num_bytes_to_copy].copy_from_slice(&old_value[..num_bytes_to_copy]);
}
}
Expand Down
6 changes: 3 additions & 3 deletions odbc-api/src/buffers/text_row_set.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Indicator, text_column::TextColumn};
use super::{text_column::TextColumn, Indicator};
use crate::{handles::Statement, Cursor, Error, ParameterCollection, RowSetBuffer};
use std::{
cmp::min,
Expand Down Expand Up @@ -109,7 +109,7 @@ impl TextRowSet {
pub fn for_cursor(
batch_size: u32,
cursor: &impl Cursor,
max_str_limit: Option<usize>,
max_str_len: Option<usize>,
) -> Result<TextRowSet, Error> {
let num_cols = cursor.num_result_cols()?;
let buffers = (1..(num_cols + 1))
Expand All @@ -122,7 +122,7 @@ impl TextRowSet {
cursor.col_display_size(col_index as u16)? as usize
};
// Apply upper bound if specified
let max_str_len = max_str_limit
let max_str_len = max_str_len
.map(|limit| min(limit, reported_len))
.unwrap_or(reported_len);
Ok(TextColumn::new(batch_size as usize, max_str_len))
Expand Down
9 changes: 8 additions & 1 deletion odbc-api/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ use test_case::test_case;

use common::{cursor_to_string, setup_empty_table, SingleColumnRowSetBuffer, ENV};

use odbc_api::{ColumnDescription, Cursor, DataType, IntoParameter, Nullability, Nullable, U16String, buffers::{AnyColumnView, AnyColumnViewMut, BufferDescription, BufferKind, ColumnarRowSet, Indicator, TextRowSet}, parameter::VarChar32};
use odbc_api::{
buffers::{
AnyColumnView, AnyColumnViewMut, BufferDescription, BufferKind, ColumnarRowSet, Indicator,
TextRowSet,
},
parameter::VarChar32,
ColumnDescription, Cursor, DataType, IntoParameter, Nullability, Nullable, U16String,
};
use std::{iter, thread};

const MSSQL: &str =
Expand Down
4 changes: 4 additions & 0 deletions odbcsv/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.3.15

* New optional parameter `max-str-len` can be used to limit memory consumption.

## 0.3.14

* Insert now logs batch number and rows
Expand Down
7 changes: 6 additions & 1 deletion odbcsv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ struct QueryOpt {
/// but require more memory during execution.
#[structopt(long, default_value = "5000")]
batch_size: u32,
/// Maximum string length in bytes. If ommitted no limit is applied and the ODBC driver is taken
/// for its word regarding the maximum length of the columns.
#[structopt(long, short = "m")]
max_str_len: Option<usize>,
/// Path to the output csv file the returned values are going to be written to. If omitted the
/// csv is going to be printed to standard out.
#[structopt(long, short = "o")]
Expand Down Expand Up @@ -187,6 +191,7 @@ fn query(environment: &Environment, opt: &QueryOpt) -> Result<(), Error> {
parameters,
query,
batch_size,
max_str_len,
} = opt;

// If an output file has been specified write to it, otherwise use stdout instead.
Expand Down Expand Up @@ -214,7 +219,7 @@ fn query(environment: &Environment, opt: &QueryOpt) -> Result<(), Error> {
let headline: Vec<String> = cursor.column_names()?.collect::<Result<_, _>>()?;
writer.write_record(headline)?;

let mut buffers = TextRowSet::for_cursor(*batch_size, &cursor, None)?;
let mut buffers = TextRowSet::for_cursor(*batch_size, &cursor, *max_str_len)?;
let mut row_set_cursor = cursor.bind_buffer(&mut buffers)?;

// Use this number to count the batches. Only used for logging.
Expand Down
24 changes: 24 additions & 0 deletions odbcsv/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ fn query_mssql() {
.stdout(csv);
}

#[test]
fn max_str_len() {
let csv = "title,year\n\
Jura,1993\n\
2001,1968\n\
Inte,\n\
";

Command::cargo_bin("odbcsv")
.unwrap()
.args(&[
"-vvvv",
"query",
"--max-str-len",
"4",
"--connection-string",
MSSQL,
"SELECT title, year from Movies",
])
.assert()
.success()
.stdout(csv);
}

#[test]
fn placeholders() {
let csv = "title\n\
Expand Down

0 comments on commit cfd1025

Please sign in to comment.