rust-oracle
rust-oracle copied to clipboard
VARRAY
Hi, How can I query varray type data to a struct and then convert it to vector of string? Thanks!
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 😅