Skip to content

Commit

Permalink
Implement Send for sql_type::Object and sql_type::Collection
Browse files Browse the repository at this point in the history
  • Loading branch information
kubo committed Mar 17, 2024
1 parent b279ee0 commit e98d639
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 67 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ New features:

* Add [`Row::column_info()`] to tell column names and types in [`RowValue::get()`]
* Change the lifetime parameter of [`ResultSet`] to `'static` when it is created by query methods of [`Connection`] or into_result_set methods of [`Statement`].
* `Send` is implemented for [`Object`] and [`Collection`] now.

Changes:

Expand Down Expand Up @@ -446,6 +447,7 @@ Incompatible changes:
[`Error::NoDataFound`]: https://www.jiubao.org/rust-oracle/oracle/enum.Error.html#variant.NoDataFound
[`Error::OutOfRange`]: https://www.jiubao.org/rust-oracle/oracle/enum.Error.html#variant.OutOfRange
[`FromSql::from_sql`]: https://www.jiubao.org/rust-oracle/oracle/sql_type/trait.FromSql.html#method.from_sql
[`Object`]: https://www.jiubao.org/rust-oracle/oracle/sql_type/struct.Object.html
[`ObjectType::attributes()`]: https://docs.rs/oracle/0.2.*/oracle/struct.ObjectType.html#method.attributes
[`ObjectType::name()`]: https://docs.rs/oracle/0.2.*/oracle/struct.ObjectType.html#method.name
[`ObjectType::new_collection()`]: https://docs.rs/oracle/0.2.*/oracle/struct.ObjectType.html#method.new_collection
Expand Down
7 changes: 4 additions & 3 deletions src/aq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ use crate::to_rust_slice;
use crate::Connection;
use crate::Context;
use crate::DpiMsgProps;
use crate::DpiObject;
use crate::DpiQueue;
use crate::Error;
use crate::Result;
Expand Down Expand Up @@ -173,12 +174,12 @@ impl Payload for Object {

fn get(props: &MsgProps<Self>) -> Result<Object> {
let objtype = props.payload_type.as_ref().ok_or(Error::NoDataFound)?;
let mut obj_handle = ptr::null_mut();
let mut obj_handle = DpiObject::null();
chkerr!(
props.ctxt(),
dpiMsgProps_getPayload(
props.handle.raw,
&mut obj_handle,
&mut obj_handle.raw,
ptr::null_mut(),
ptr::null_mut()
)
Expand All @@ -189,7 +190,7 @@ impl Payload for Object {
fn set(&self, props: &mut MsgProps<Self>) -> Result<()> {
chkerr!(
props.ctxt(),
dpiMsgProps_setPayloadObject(props.handle.raw, self.handle)
dpiMsgProps_setPayloadObject(props.handle.raw, self.handle())
);
props.payload_type = Some(self.object_type().clone());
Ok(())
Expand Down
41 changes: 36 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ pub type Result<T> = result::Result<T, Error>;

macro_rules! define_dpi_data_with_refcount {
($name:ident) => {
define_dpi_data_with_refcount!(__define_struct__, $name);
paste::item! {
unsafe impl Send for [<Dpi $name>] {}
unsafe impl Sync for [<Dpi $name>] {}
}
};

($name:ident, nosync) => {
define_dpi_data_with_refcount!(__define_struct__, $name);
paste::item! {
unsafe impl Send for [<Dpi $name>] {}
}
};

(__define_struct__, $name:ident) => {
paste::item! {
struct [<Dpi $name>] {
raw: *mut [<dpi $name>],
Expand All @@ -93,26 +108,39 @@ macro_rules! define_dpi_data_with_refcount {
[<Dpi $name>] { raw }
}

#[allow(dead_code)]
fn null() -> [<Dpi $name>] {
[<Dpi $name>] {
raw: ptr::null_mut(),
}
}

#[allow(dead_code)]
fn is_null(&self) -> bool {
self.raw.is_null()
}

pub(crate) fn raw(&self) -> *mut [<dpi $name>] {
self.raw
}
}

impl Clone for [<Dpi $name>] {
fn clone(&self) -> [<Dpi $name>] {
unsafe { [<dpi $name _addRef>](self.raw()) };
if !self.is_null() {
unsafe { [<dpi $name _addRef>](self.raw()) };
}
[<Dpi $name>]::new(self.raw())
}
}

impl Drop for [<Dpi $name>] {
fn drop(&mut self) {
unsafe { [<dpi $name _release>](self.raw()) };
if !self.is_null() {
unsafe { [<dpi $name _release>](self.raw()) };
}
}
}

unsafe impl Send for [<Dpi $name>] {}
unsafe impl Sync for [<Dpi $name>] {}
}
};
}
Expand All @@ -135,6 +163,9 @@ define_dpi_data_with_refcount!(ObjectAttr);
// define DpiQueue wrapping *mut dpiQueue.
define_dpi_data_with_refcount!(Queue);

// define DpiObject wrapping *mut dpiObject.
define_dpi_data_with_refcount!(Object, nosync);

trait AssertSend: Send {}
trait AssertSync: Sync {}

Expand Down
75 changes: 37 additions & 38 deletions src/sql_type/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use std::cmp;
use std::fmt;
use std::mem::{self, MaybeUninit};
use std::os::raw::c_char;
use std::ptr;
use std::sync::Arc;

use crate::binding::*;
Expand All @@ -29,8 +28,10 @@ use crate::sql_type::OracleType;
use crate::sql_type::ToSql;
use crate::to_rust_str;
use crate::util::write_literal;
use crate::AssertSend;
use crate::Connection;
use crate::Context;
use crate::DpiObject;
use crate::DpiObjectAttr;
use crate::DpiObjectType;
use crate::Error;
Expand Down Expand Up @@ -77,12 +78,12 @@ unsafe fn release_dpi_data(data: &dpiData, native_type_num: u32) {
/// Note: Methods in the type may be changed in future.
pub struct Collection {
conn: Conn,
pub(crate) handle: *mut dpiObject,
pub(crate) handle: DpiObject,
objtype: ObjectType,
}

impl Collection {
pub(crate) fn new(conn: Conn, handle: *mut dpiObject, objtype: ObjectType) -> Collection {
pub(crate) fn new(conn: Conn, handle: DpiObject, objtype: ObjectType) -> Collection {
Collection {
conn,
handle,
Expand All @@ -94,6 +95,10 @@ impl Collection {
self.conn.ctxt()
}

fn handle(&self) -> *mut dpiObject {
self.handle.raw
}

/// Returns type information.
pub fn object_type(&self) -> &ObjectType {
&self.objtype
Expand All @@ -106,7 +111,7 @@ impl Collection {
/// [OCICollSize()]: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-B8F6665F-12F1-43DB-A27E-82A2A655D701
pub fn size(&self) -> Result<i32> {
let mut size = 0;
chkerr!(self.ctxt(), dpiObject_getSize(self.handle, &mut size));
chkerr!(self.ctxt(), dpiObject_getSize(self.handle(), &mut size));
Ok(size)
}

Expand Down Expand Up @@ -257,7 +262,7 @@ impl Collection {
let mut exists = 0;
chkerr!(
self.ctxt(),
dpiObject_getFirstIndex(self.handle, &mut index, &mut exists)
dpiObject_getFirstIndex(self.handle(), &mut index, &mut exists)
);
if exists != 0 {
Ok(index)
Expand All @@ -274,7 +279,7 @@ impl Collection {
let mut exists = 0;
chkerr!(
self.ctxt(),
dpiObject_getLastIndex(self.handle, &mut index, &mut exists)
dpiObject_getLastIndex(self.handle(), &mut index, &mut exists)
);
if exists != 0 {
Ok(index)
Expand All @@ -291,7 +296,7 @@ impl Collection {
let mut exists = 0;
chkerr!(
self.ctxt(),
dpiObject_getNextIndex(self.handle, index, &mut next, &mut exists)
dpiObject_getNextIndex(self.handle(), index, &mut next, &mut exists)
);
if exists != 0 {
Ok(next)
Expand All @@ -308,7 +313,7 @@ impl Collection {
let mut exists = 0;
chkerr!(
self.ctxt(),
dpiObject_getPrevIndex(self.handle, index, &mut prev, &mut exists)
dpiObject_getPrevIndex(self.handle(), index, &mut prev, &mut exists)
);
if exists != 0 {
Ok(prev)
Expand All @@ -322,7 +327,7 @@ impl Collection {
let mut exists = 0;
chkerr!(
self.ctxt(),
dpiObject_getElementExistsByIndex(self.handle, index, &mut exists)
dpiObject_getElementExistsByIndex(self.handle(), index, &mut exists)
);
Ok(exists != 0)
}
Expand All @@ -349,7 +354,7 @@ impl Collection {
chkerr!(
self.ctxt(),
dpiObject_getElementValueByIndex(
self.handle,
self.handle(),
index,
native_type_num,
sql_value.data
Expand All @@ -370,7 +375,7 @@ impl Collection {
chkerr!(
self.ctxt(),
dpiObject_setElementValueByIndex(
self.handle,
self.handle(),
index,
sql_value.native_type_num(),
sql_value.data
Expand All @@ -387,7 +392,7 @@ impl Collection {
sql_value.set(value)?;
chkerr!(
self.ctxt(),
dpiObject_appendElement(self.handle, sql_value.native_type_num(), sql_value.data)
dpiObject_appendElement(self.handle(), sql_value.native_type_num(), sql_value.data)
);
Ok(())
}
Expand All @@ -398,7 +403,7 @@ impl Collection {
pub fn remove(&mut self, index: i32) -> Result<()> {
chkerr!(
self.ctxt(),
dpiObject_deleteElementByIndex(self.handle, index)
dpiObject_deleteElementByIndex(self.handle(), index)
);
Ok(())
}
Expand All @@ -408,21 +413,14 @@ impl Collection {
/// If the number of of elements to trim exceeds the current size
/// of the collection an error is returned.
pub fn trim(&mut self, len: usize) -> Result<()> {
chkerr!(self.ctxt(), dpiObject_trim(self.handle, len as u32));
chkerr!(self.ctxt(), dpiObject_trim(self.handle(), len as u32));
Ok(())
}
}

impl Clone for Collection {
fn clone(&self) -> Collection {
unsafe { dpiObject_addRef(self.handle) };
Collection::new(self.conn.clone(), self.handle, self.objtype.clone())
}
}

impl Drop for Collection {
fn drop(&mut self) {
let _ = unsafe { dpiObject_release(self.handle) };
Collection::new(self.conn.clone(), self.handle.clone(), self.objtype.clone())
}
}

Expand Down Expand Up @@ -481,6 +479,8 @@ impl fmt::Debug for Collection {
}
}

impl AssertSend for Collection {}

/// Oracle-specific object data type
///
/// ```no_run
Expand Down Expand Up @@ -510,12 +510,12 @@ impl fmt::Debug for Collection {
/// Note: Methods in the type may be changed in future.
pub struct Object {
conn: Conn,
pub(crate) handle: *mut dpiObject,
pub(crate) handle: DpiObject,
objtype: ObjectType,
}

impl Object {
pub(crate) fn new(conn: Conn, handle: *mut dpiObject, objtype: ObjectType) -> Object {
pub(crate) fn new(conn: Conn, handle: DpiObject, objtype: ObjectType) -> Object {
Object {
conn,
handle,
Expand All @@ -527,6 +527,10 @@ impl Object {
self.conn.ctxt()
}

pub(crate) fn handle(&self) -> *mut dpiObject {
self.handle.raw
}

/// Returns type information.
pub fn object_type(&self) -> &ObjectType {
&self.objtype
Expand Down Expand Up @@ -561,7 +565,7 @@ impl Object {
chkerr!(
self.ctxt(),
dpiObject_getAttributeValue(
self.handle,
self.handle(),
attr.handle.raw(),
native_type_num,
sql_value.data
Expand Down Expand Up @@ -591,7 +595,7 @@ impl Object {
chkerr!(
self.ctxt(),
dpiObject_setAttributeValue(
self.handle,
self.handle(),
attrtype.handle.raw(),
sql_value.native_type_num(),
sql_value.data
Expand All @@ -603,14 +607,7 @@ impl Object {

impl Clone for Object {
fn clone(&self) -> Object {
unsafe { dpiObject_addRef(self.handle) };
Object::new(self.conn.clone(), self.handle, self.objtype.clone())
}
}

impl Drop for Object {
fn drop(&mut self) {
let _ = unsafe { dpiObject_release(self.handle) };
Object::new(self.conn.clone(), self.handle.clone(), self.objtype.clone())
}
}

Expand Down Expand Up @@ -662,6 +659,8 @@ impl fmt::Debug for Object {
}
}

impl AssertSend for Object {}

/// Type information about Object or Collection data type
///
/// This is for not only Object type information but also
Expand Down Expand Up @@ -782,10 +781,10 @@ impl ObjectType {
)));
}
let conn = &self.internal.conn;
let mut handle = ptr::null_mut();
let mut handle = DpiObject::null();
chkerr!(
conn.ctxt(),
dpiObjectType_createObject(self.internal.handle.raw(), &mut handle)
dpiObjectType_createObject(self.internal.handle.raw(), &mut handle.raw)
);
Ok(Object::new(conn.clone(), handle, self.clone()))
}
Expand All @@ -800,10 +799,10 @@ impl ObjectType {
)));
}
let conn = &self.internal.conn;
let mut handle = ptr::null_mut();
let mut handle = DpiObject::null();
chkerr!(
conn.ctxt(),
dpiObjectType_createObject(self.internal.handle.raw(), &mut handle)
dpiObjectType_createObject(self.internal.handle.raw(), &mut handle.raw)
);
Ok(Collection::new(conn.clone(), handle, self.clone()))
}
Expand Down

0 comments on commit e98d639

Please sign in to comment.