Skip to content

Commit

Permalink
implement CData for WideText VarCells
Browse files Browse the repository at this point in the history
  • Loading branch information
pacman82 committed Apr 14, 2023
1 parent 99b5588 commit c4c51e6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 27 deletions.
10 changes: 4 additions & 6 deletions odbc-api/src/cursor.rs
Expand Up @@ -487,7 +487,7 @@ where

/// Unbinds the buffer from the underlying statement handle. Potential usecases for this
/// function include.
///
///
/// 1. Binding a different buffer to the "same" cursor after letting it point to the next result
/// set obtained with [self::more_results`].
/// 2. Reusing the same buffer with a different statement.
Expand Down Expand Up @@ -515,8 +515,7 @@ where
C: AsStatementRef,
{
fn drop(&mut self) {
if let Err(e) = unbind_buffer_from_cursor(&mut self.cursor)
{
if let Err(e) = unbind_buffer_from_cursor(&mut self.cursor) {
// Avoid panicking, if we already have a panic. We don't want to mask the original
// error.
if !panicking() {
Expand Down Expand Up @@ -714,8 +713,7 @@ where
C: AsStatementRef,
{
fn drop(&mut self) {
if let Err(e) = unbind_buffer_from_cursor(&mut self.cursor)
{
if let Err(e) = unbind_buffer_from_cursor(&mut self.cursor) {
// Avoid panicking, if we already have a panic. We don't want to mask the original
// error.
if !panicking() {
Expand All @@ -733,4 +731,4 @@ fn unbind_buffer_from_cursor(cursor: &mut impl AsStatementRef) -> Result<(), Err
stmt.unbind_cols().into_result(&stmt)?;
stmt.unset_num_rows_fetched().into_result(&stmt)?;
Ok(())
}
}
12 changes: 6 additions & 6 deletions odbc-api/src/handles/statement.rs
Expand Up @@ -11,13 +11,13 @@ use super::{
};
use odbc_sys::{
Desc, FreeStmtOption, HDbc, HStmt, Handle, HandleType, Len, ParamType, Pointer, SQLBindCol,
SQLBindParameter, SQLCloseCursor, SQLDescribeParam, SQLExecute, SQLFetch,
SQLFreeStmt, SQLGetData, SQLMoreResults, SQLNumParams, SQLNumResultCols, SQLParamData,
SQLPutData, SQLRowCount, SqlDataType, SqlReturn, StatementAttribute, IS_POINTER,
SQLBindParameter, SQLCloseCursor, SQLDescribeParam, SQLExecute, SQLFetch, SQLFreeStmt,
SQLGetData, SQLMoreResults, SQLNumParams, SQLNumResultCols, SQLParamData, SQLPutData,
SQLRowCount, SqlDataType, SqlReturn, StatementAttribute, IS_POINTER,
};
use std::{ffi::c_void, marker::PhantomData, mem::ManuallyDrop, ptr::null_mut};

#[cfg(feature="odbc_version_3_80")]
#[cfg(feature = "odbc_version_3_80")]
use odbc_sys::SQLCompleteAsync;

#[cfg(feature = "narrow")]
Expand Down Expand Up @@ -243,7 +243,7 @@ pub trait Statement: AsHandle {
}

/// Unsets the integer set by [`Self::set_num_rows_fetched`].
///
///
/// This being a seperate method from [`Self::set_num_rows_fetched` allows us to write us
/// cleanup code with less `unsafe` statements since this operation is always safe.
fn unset_num_rows_fetched(&mut self) -> SqlResult<()> {
Expand Down Expand Up @@ -885,7 +885,7 @@ pub trait Statement: AsHandle {
/// to notification mode) the driver manager has not notified the application.
///
/// See: <https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlcompleteasync-function>
#[cfg(feature="odbc_version_3_80")]
#[cfg(feature = "odbc_version_3_80")]
fn complete_async(&mut self, function_name: &'static str) -> SqlResult<SqlResult<()>> {
let mut ret = SqlReturn::ERROR;
unsafe {
Expand Down
7 changes: 5 additions & 2 deletions odbc-api/src/into_parameter.rs
@@ -1,9 +1,12 @@
use widestring::U16Str;

use crate::{
buffers::Indicator,
fixed_sized::Pod,
parameter::{InputParameter, VarBinaryBox, VarBinarySlice, VarCharBox, VarCharSlice, VarWCharSlice},
Nullable, buffers::Indicator,
parameter::{
InputParameter, VarBinaryBox, VarBinarySlice, VarCharBox, VarCharSlice, VarWCharSlice,
},
Nullable,
};

/// An instance can be consumed and to create a parameter which can be bound to a statement during
Expand Down
24 changes: 13 additions & 11 deletions odbc-api/src/parameter/varcell.rs
Expand Up @@ -318,7 +318,7 @@ where

unsafe impl<B, K> CData for VarCell<B, K>
where
B: Borrow<[u8]>,
B: Borrow<[K::Element]>,
K: VarKind,
{
fn cdata_type(&self) -> CDataType {
Expand All @@ -337,13 +337,15 @@ where
// This is the maximum buffer length, but it is NOT the length of an instance of Self due to
// the missing size of the indicator value. As such the buffer length can not be used to
// correctly index a columnar buffer of Self.
self.buffer.borrow().len().try_into().unwrap()
(self.buffer.borrow().len() * size_of::<K::Element>())
.try_into()
.unwrap()
}
}

impl<B, K> HasDataType for VarCell<B, K>
where
B: Borrow<[u8]>,
B: Borrow<[K::Element]>,
K: VarKind,
{
fn data_type(&self) -> DataType {
Expand All @@ -353,7 +355,7 @@ where

unsafe impl<B, K> CDataMut for VarCell<B, K>
where
B: BorrowMut<[u8]>,
B: BorrowMut<[K::Element]>,
K: VarKind,
{
fn mut_indicator_ptr(&mut self) -> *mut isize {
Expand Down Expand Up @@ -510,16 +512,16 @@ where
// because erroneous but still safe implementation of these traits could cause invalid memory access
// down the road. E.g. think about returning a different slice with a different length for borrow
// and borrow_mut.
unsafe impl<K: VarKind> CElement for VarCell<&'_ [u8], K> {}
unsafe impl<K: VarKind> CElement for VarCell<&'_ [K::Element], K> {}

unsafe impl<const LENGTH: usize, K: VarKind> CElement for VarCell<[u8; LENGTH], K> {}
unsafe impl<const LENGTH: usize, K: VarKind> OutputParameter for VarCell<[u8; LENGTH], K> {}
unsafe impl<const LENGTH: usize, K: VarKind> CElement for VarCell<[K::Element; LENGTH], K> {}
unsafe impl<const LENGTH: usize, K: VarKind> OutputParameter for VarCell<[K::Element; LENGTH], K> {}

unsafe impl<K: VarKind> CElement for VarCell<&'_ mut [u8], K> {}
unsafe impl<K: VarKind> OutputParameter for VarCell<&'_ mut [u8], K> {}
unsafe impl<K: VarKind> CElement for VarCell<&'_ mut [K::Element], K> {}
unsafe impl<K: VarKind> OutputParameter for VarCell<&'_ mut [K::Element], K> {}

unsafe impl<K: VarKind> CElement for VarCell<Box<[u8]>, K> {}
unsafe impl<K: VarKind> OutputParameter for VarCell<Box<[u8]>, K> {}
unsafe impl<K: VarKind> CElement for VarCell<Box<[K::Element]>, K> {}
unsafe impl<K: VarKind> OutputParameter for VarCell<Box<[K::Element]>, K> {}

#[cfg(test)]
mod tests {
Expand Down
3 changes: 1 addition & 2 deletions odbc-api/tests/integration.rs
Expand Up @@ -1453,8 +1453,7 @@ fn bind_u16str_parameter_to_char(profile: &Profile) {
let insert_sql = table.sql_insert();

let hello = U16String::from_str("Hello");
conn.execute(&insert_sql, &hello.into_parameter())
.unwrap();
conn.execute(&insert_sql, &hello.into_parameter()).unwrap();

let actual = table.content_as_string(&conn);
assert_eq!("Hello", &actual);
Expand Down

0 comments on commit c4c51e6

Please sign in to comment.