Skip to content

Commit

Permalink
Improve performance of fetching numeric types when number column defi…
Browse files Browse the repository at this point in the history
…nition is out of range of i64.

See #89 (comment)
  • Loading branch information
kubo committed Oct 28, 2024
1 parent bf51e95 commit 0c49553
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
8 changes: 8 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

## 0.6.3 (2024-XX-XX)

Internal Changes:

* Update ODPI-C to 5.3.0. (see [ODPI-C release notes])
* Improve performance of fetching numeric types when number column definition is out of range of i64.
See https://github.com/kubo/rust-oracle/issues/89#issuecomment-2435662861

## 0.6.2 (2024-06-26)

Fixed Issues:
Expand Down
33 changes: 18 additions & 15 deletions src/sql_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0)
//-----------------------------------------------------------------------------

use std::borrow::Cow;
use std::convert::TryInto;
use std::fmt;
use std::os::raw::c_char;
use std::ptr;
use std::rc::Rc;
use std::slice;
use std::str;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -87,7 +89,7 @@ macro_rules! define_fn_to_int {
NativeType::Char |
NativeType::Clob |
NativeType::Number =>
Ok(self.get_string()?.parse()?),
Ok(self.get_cow_str()?.parse()?),
_ =>
self.invalid_conversion_to_rust_type(stringify!($type))
}
Expand Down Expand Up @@ -443,10 +445,10 @@ impl SqlValue<'_> {
}
}

fn get_string(&self) -> Result<String> {
fn get_cow_str(&self) -> Result<Cow<str>> {
match self.native_type {
NativeType::Char | NativeType::Number => self.get_string_unchecked(),
NativeType::Clob => self.get_clob_as_string_unchecked(),
NativeType::Char | NativeType::Number => self.get_cow_str_unchecked(),
NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.into()),
_ => self.invalid_conversion_to_rust_type("String"),
}
}
Expand Down Expand Up @@ -486,11 +488,12 @@ impl SqlValue<'_> {
/// Gets the SQL value as utf8 string. The native_type must be
/// NativeType::Char or NativeType::Number. Otherwise, this may cause access
/// violation.
fn get_string_unchecked(&self) -> Result<String> {
fn get_cow_str_unchecked(&self) -> Result<Cow<str>> {
self.check_not_null()?;
unsafe {
let bytes = dpiData_getBytes(self.data()?);
Ok(to_rust_str((*bytes).ptr, (*bytes).length))
let s = slice::from_raw_parts((*bytes).ptr as *mut u8, (*bytes).length as usize);
Ok(String::from_utf8_lossy(s))
}
}

Expand Down Expand Up @@ -905,7 +908,7 @@ impl SqlValue<'_> {
NativeType::Float => flt_to_int!(self.get_f32_unchecked()?, f32, i64),
NativeType::Double => flt_to_int!(self.get_f64_unchecked()?, f64, i64),
NativeType::Char | NativeType::Clob | NativeType::Number => {
Ok(self.get_string()?.parse()?)
Ok(self.get_cow_str()?.parse()?)
}
_ => self.invalid_conversion_to_rust_type("i64"),
}
Expand Down Expand Up @@ -937,7 +940,7 @@ impl SqlValue<'_> {
NativeType::Float => flt_to_int!(self.get_f32_unchecked()?, f32, u64),
NativeType::Double => flt_to_int!(self.get_f64_unchecked()?, f64, u64),
NativeType::Char | NativeType::Clob | NativeType::Number => {
Ok(self.get_string()?.parse()?)
Ok(self.get_cow_str()?.parse()?)
}
_ => self.invalid_conversion_to_rust_type("u64"),
}
Expand All @@ -952,7 +955,7 @@ impl SqlValue<'_> {
NativeType::Float => self.get_f32_unchecked(),
NativeType::Double => Ok(self.get_f64_unchecked()? as f32),
NativeType::Char | NativeType::Clob | NativeType::Number => {
Ok(self.get_string()?.parse()?)
Ok(self.get_cow_str()?.parse()?)
}
_ => self.invalid_conversion_to_rust_type("f32"),
}
Expand All @@ -967,7 +970,7 @@ impl SqlValue<'_> {
NativeType::Float => Ok(self.get_f32_unchecked()? as f64),
NativeType::Double => self.get_f64_unchecked(),
NativeType::Char | NativeType::Clob | NativeType::Number => {
Ok(self.get_string()?.parse()?)
Ok(self.get_cow_str()?.parse()?)
}
_ => self.invalid_conversion_to_rust_type("f64"),
}
Expand All @@ -980,7 +983,7 @@ impl SqlValue<'_> {
NativeType::UInt64 => Ok(self.get_u64_unchecked()?.to_string()),
NativeType::Float => Ok(self.get_f32_unchecked()?.to_string()),
NativeType::Double => Ok(self.get_f64_unchecked()?.to_string()),
NativeType::Char | NativeType::Number => self.get_string_unchecked(),
NativeType::Char | NativeType::Number => Ok(self.get_cow_str_unchecked()?.into()),
NativeType::Raw => self.get_raw_as_hex_string_unchecked(),
NativeType::Timestamp => Ok(self.get_timestamp_unchecked()?.to_string()),
NativeType::IntervalDS => Ok(self.get_interval_ds_unchecked()?.to_string()),
Expand Down Expand Up @@ -1009,7 +1012,7 @@ impl SqlValue<'_> {
match self.native_type {
NativeType::Raw => self.get_raw_unchecked(),
NativeType::Blob => self.get_blob_unchecked(),
NativeType::Char | NativeType::Clob => Ok(parse_str_into_raw(&self.get_string()?)?),
NativeType::Char | NativeType::Clob => Ok(parse_str_into_raw(&self.get_cow_str()?)?),
_ => self.invalid_conversion_to_rust_type("raw"),
}
}
Expand All @@ -1019,7 +1022,7 @@ impl SqlValue<'_> {
pub(crate) fn to_timestamp(&self) -> Result<Timestamp> {
match self.native_type {
NativeType::Timestamp => self.get_timestamp_unchecked(),
NativeType::Char | NativeType::Clob => Ok(self.get_string()?.parse()?),
NativeType::Char | NativeType::Clob => Ok(self.get_cow_str()?.parse()?),
_ => self.invalid_conversion_to_rust_type("Timestamp"),
}
}
Expand All @@ -1029,7 +1032,7 @@ impl SqlValue<'_> {
pub(crate) fn to_interval_ds(&self) -> Result<IntervalDS> {
match self.native_type {
NativeType::IntervalDS => self.get_interval_ds_unchecked(),
NativeType::Char | NativeType::Clob => Ok(self.get_string()?.parse()?),
NativeType::Char | NativeType::Clob => Ok(self.get_cow_str()?.parse()?),
_ => self.invalid_conversion_to_rust_type("IntervalDS"),
}
}
Expand All @@ -1039,7 +1042,7 @@ impl SqlValue<'_> {
pub(crate) fn to_interval_ym(&self) -> Result<IntervalYM> {
match self.native_type {
NativeType::IntervalYM => self.get_interval_ym_unchecked(),
NativeType::Char | NativeType::Clob => Ok(self.get_string()?.parse()?),
NativeType::Char | NativeType::Clob => Ok(self.get_cow_str()?.parse()?),
_ => self.invalid_conversion_to_rust_type("IntervalYM"),
}
}
Expand Down

0 comments on commit 0c49553

Please sign in to comment.