diff --git a/odbc-api/src/cursor.rs b/odbc-api/src/cursor.rs index 1f891b14..6d9bdabf 100644 --- a/odbc-api/src/cursor.rs +++ b/odbc-api/src/cursor.rs @@ -4,7 +4,7 @@ use crate::{ buffers::Indicator, error::ExtendResult, handles::{AsStatementRef, CDataMut, SqlResult, State, Statement, StatementRef}, - parameter::{Binary, CElement, Text, VarCell, VarKind}, + parameter::{Binary, CElement, Text, VarCell, VarKind, WideText}, sleep::{wait_for, Sleep}, Error, ResultSetMetadata, }; @@ -120,7 +120,9 @@ impl<'s> CursorRow<'s> { } /// Retrieves arbitrary large character data from the row and stores it in the buffer. Column - /// index starts at `1`. + /// index starts at `1`. The used encoding is accordig to the ODBC standard determined by your + /// system local. Ultimatly the choice is up to the implementation of your ODBC driver, which + /// often defaults to always UTF-8. /// /// # Return /// @@ -130,6 +132,17 @@ impl<'s> CursorRow<'s> { self.get_variadic::(col_or_param_num, buf) } + /// Retrieves arbitrary large character data from the row and stores it in the buffer. Column + /// index starts at `1`. The used encoding is UTF-16. + /// + /// # Return + /// + /// `true` indicates that the value has not been `NULL` and the value has been placed in `buf`. + /// `false` indicates that the value is `NULL`. The buffer is cleared in that case. + pub fn get_wide_text(&mut self, col_or_param_num: u16, buf: &mut Vec) -> Result { + self.get_variadic::(col_or_param_num, buf) + } + /// Retrieves arbitrary large binary data from the row and stores it in the buffer. Column index /// starts at `1`. /// @@ -186,7 +199,7 @@ impl<'s> CursorRow<'s> { // Use an exponential strategy for increasing buffer size. buf.resize(old_len * 2, K::ZERO); let buf_extend = - &mut buf[(old_len - K::TERMINATING_ZEROES * size_of::())..]; + &mut buf[(old_len - K::TERMINATING_ZEROES)..]; target = VarCell::<&mut [K::Element], K>::from_buffer( buf_extend, Indicator::NoTotal, diff --git a/odbc-api/src/parameter.rs b/odbc-api/src/parameter.rs index 966c40b2..d9a83ac5 100644 --- a/odbc-api/src/parameter.rs +++ b/odbc-api/src/parameter.rs @@ -343,7 +343,7 @@ pub use self::{ varcell::{ Binary, Text, VarBinary, VarBinaryArray, VarBinaryBox, VarBinarySlice, VarBinarySliceMut, VarCell, VarChar, VarCharArray, VarCharBox, VarCharSlice, VarCharSliceMut, VarKind, - VarWCharArray, VarWCharBox, VarWCharSlice, VarWCharSliceMut, + VarWCharArray, VarWCharBox, VarWCharSlice, VarWCharSliceMut, WideText, }, }; diff --git a/odbc-api/tests/integration.rs b/odbc-api/tests/integration.rs index 87285c1c..870617ef 100644 --- a/odbc-api/tests/integration.rs +++ b/odbc-api/tests/integration.rs @@ -2294,6 +2294,33 @@ fn get_text(profile: &Profile) { assert_eq!(&b"Hello, World!"[..], &actual); } +/// Use get_text to retrieve a string. Use a buffer which is one terminating zero short to get the +/// entire value. +#[test_case(MSSQL; "Microsoft SQL Server")] +#[test_case(MARIADB; "Maria DB")] +#[test_case(SQLITE_3; "SQLite 3")] +#[test_case(POSTGRES; "PostgreSQL")] +fn get_wide_text(profile: &Profile) { + let table_name = table_name!(); + let (conn, table) = profile.given(&table_name, &["Varchar(50)"]).unwrap(); + conn.execute(&table.sql_insert(), &"Hello, World!".into_parameter()) + .unwrap(); + let mut cursor = conn + .execute(&format!("SELECT a FROM {table_name} ORDER BY id"), ()) + .unwrap() + .unwrap(); + + let mut row = cursor.next_row().unwrap().unwrap(); + // We want to hit an edge case there there has been a sign error then calculating buffer size + // with terminating zero. + let mut actual = Vec::with_capacity("Hello, World!".len() - 1); + let is_not_null = row.get_wide_text(1, &mut actual).unwrap(); + + let actual = U16String::from_vec(actual).to_string().unwrap(); + assert!(is_not_null); + assert_eq!("Hello, World!", &actual); +} + /// Use get_data to retrieve a binary data #[test_case(MSSQL; "Microsoft SQL Server")] #[test_case(MARIADB; "Maria DB")]