Closed raymclee closed 1 year ago
How about the following sample code.
I'll add methods creating various Collection
iterators later. One of them is same with the collection::Values
iterator bellow except the visibility of collection::Values::new
.
use oracle::sql_type::{Collection, OracleType};
use oracle::{Connection, Result};
fn main() -> Result<()> {
let conn = Connection::connect("odpic", "welcome", "")?;
// See https://github.com/oracle/odpi/blob/v4.4.1/test/sql/SetupTest.sql#L489-L492
let objtype = conn.object_type("PKG_TESTSTRINGARRAYS.UDT_STRINGLIST")?;
// See https://github.com/oracle/odpi/blob/v4.4.1/test/sql/SetupTest.sql#L553-L561
let mut stmt = conn
.statement("begin pkg_TestStringArrays.TestIndexBy(:1); end;")
.build()?;
stmt.execute(&[&OracleType::Object(objtype)])?;
let coll: Collection = stmt.bind_value(1)?;
let vec: Vec<String> = collection::Values::new(&coll).collect::<Result<Vec<_>>>()?;
assert_eq!(vec[0], "First element".to_string());
assert_eq!(vec[1], "Second element".to_string());
assert_eq!(vec[2], "Third element".to_string());
assert_eq!(vec[3], "Fourth element".to_string());
Ok(())
}
mod collection {
use oracle::sql_type::{Collection, FromSql};
use oracle::{Error, Result};
use std::marker::PhantomData;
fn next_item<T>(coll: &Collection, index: Option<i32>) -> Result<Option<(i32, T)>>
where
T: FromSql,
{
let new_idx_result = if let Some(idx) = index {
coll.next_index(idx)
} else {
coll.first_index()
};
match new_idx_result {
Ok(new_idx) => {
let obj = coll.get(new_idx)?;
Ok(Some((new_idx, obj)))
}
Err(Error::NoDataFound) => Ok(None),
Err(err) => Err(err),
}
}
pub struct Values<'a, T> {
coll: &'a Collection,
index: Option<i32>,
phantom: PhantomData<T>,
}
impl<'a, T> Values<'a, T> {
pub fn new(coll: &Collection) -> Values<T> {
Values {
coll,
index: None,
phantom: PhantomData,
}
}
}
impl<'a, T> Iterator for Values<'a, T>
where
T: FromSql,
{
type Item = Result<T>;
fn next(&mut self) -> Option<Result<T>> {
match next_item(self.coll, self.index) {
Ok(Some((idx, value))) => {
self.index = Some(idx);
Some(Ok(value))
}
Ok(None) => None,
Err(err) => Some(Err(err)),
}
}
}
}
How about the following sample code. I'll add methods creating various
Collection
iterators later. One of them is same with thecollection::Values
iterator bellow except the visibility ofcollection::Values::new
.use oracle::sql_type::{Collection, OracleType}; use oracle::{Connection, Result}; fn main() -> Result<()> { let conn = Connection::connect("odpic", "welcome", "")?; // See https://github.com/oracle/odpi/blob/v4.4.1/test/sql/SetupTest.sql#L489-L492 let objtype = conn.object_type("PKG_TESTSTRINGARRAYS.UDT_STRINGLIST")?; // See https://github.com/oracle/odpi/blob/v4.4.1/test/sql/SetupTest.sql#L553-L561 let mut stmt = conn .statement("begin pkg_TestStringArrays.TestIndexBy(:1); end;") .build()?; stmt.execute(&[&OracleType::Object(objtype)])?; let coll: Collection = stmt.bind_value(1)?; let vec: Vec<String> = collection::Values::new(&coll).collect::<Result<Vec<_>>>()?; assert_eq!(vec[0], "First element".to_string()); assert_eq!(vec[1], "Second element".to_string()); assert_eq!(vec[2], "Third element".to_string()); assert_eq!(vec[3], "Fourth element".to_string()); Ok(()) } mod collection { use oracle::sql_type::{Collection, FromSql}; use oracle::{Error, Result}; use std::marker::PhantomData; fn next_item<T>(coll: &Collection, index: Option<i32>) -> Result<Option<(i32, T)>> where T: FromSql, { let new_idx_result = if let Some(idx) = index { coll.next_index(idx) } else { coll.first_index() }; match new_idx_result { Ok(new_idx) => { let obj = coll.get(new_idx)?; Ok(Some((new_idx, obj))) } Err(Error::NoDataFound) => Ok(None), Err(err) => Err(err), } } pub struct Values<'a, T> { coll: &'a Collection, index: Option<i32>, phantom: PhantomData<T>, } impl<'a, T> Values<'a, T> { pub fn new(coll: &Collection) -> Values<T> { Values { coll, index: None, phantom: PhantomData, } } } impl<'a, T> Iterator for Values<'a, T> where T: FromSql, { type Item = Result<T>; fn next(&mut self) -> Option<Result<T>> { match next_item(self.coll, self.index) { Ok(Some((idx, value))) => { self.index = Some(idx); Some(Ok(value)) } Ok(None) => None, Err(err) => Some(Err(err)), } } } }
that's work! Thanks. I have noticed the Collection and couldn't figure out how to use it 😅
Hi, How can I query varray type data to a struct and then convert it to vector of string? Thanks!