1use crate::chkerr;
17use crate::connection::Conn;
18use crate::sql_type::vector::VecFmt;
19use crate::sql_type::vector::VecRef;
20use crate::sql_type::vector::Vector;
21use crate::sql_type::Bfile;
22use crate::sql_type::Blob;
23use crate::sql_type::Clob;
24use crate::sql_type::Collection;
25use crate::sql_type::FromSql;
26use crate::sql_type::InnerValue;
27use crate::sql_type::IntervalDS;
28use crate::sql_type::IntervalYM;
29use crate::sql_type::NativeType;
30use crate::sql_type::Nclob;
31use crate::sql_type::Object;
32use crate::sql_type::ObjectType;
33use crate::sql_type::OracleType;
34use crate::sql_type::RefCursor;
35use crate::sql_type::Timestamp;
36use crate::sql_type::ToSql;
37use crate::statement::LobBindType;
38use crate::statement::QueryParams;
39use crate::to_rust_slice;
40use crate::to_rust_str;
41use crate::util::check_number_format;
42use crate::util::parse_str_into_raw;
43use crate::util::set_hex_string;
44use crate::AssertSend;
45use crate::Context;
46use crate::DpiObject;
47use crate::DpiStmt;
48use crate::DpiVar;
49use crate::Error;
50use crate::ErrorKind;
51use crate::Result;
52use odpic_sys::dpi_impl::DPI_MAX_BASIC_BUFFER_SIZE;
53use odpic_sys::*;
54use std::borrow::Cow;
55use std::convert::TryInto;
56use std::fmt;
57use std::mem::MaybeUninit;
58use std::os::raw::c_char;
59use std::ptr;
60use std::rc::Rc;
61use std::slice;
62use std::str;
63use std::sync::atomic::{AtomicU32, Ordering};
64use std::sync::Arc;
65
66macro_rules! flt_to_int {
67 ($expr:expr, $src_type:ident, $dest_type:ident) => {{
68 let src_val = $expr;
69 if $dest_type::MIN as $src_type <= src_val && src_val <= $dest_type::MAX as $src_type {
70 Ok(src_val as $dest_type)
71 } else {
72 Err(Error::out_of_range(format!(
73 "{} overflow: {}",
74 stringify!($dest_type),
75 src_val.to_string(),
76 )))
77 }
78 }};
79}
80
81macro_rules! define_fn_to_int {
82 ($(#[$attr:meta])* : $func_name:ident, $type:ident) => {
83 $(#[$attr])*
84 pub (crate)fn $func_name(&self) -> Result<$type> {
85 match self.native_type {
86 NativeType::Int64 =>
87 Ok(self.get_i64_unchecked()?.try_into()?),
88 NativeType::UInt64 =>
89 Ok(self.get_u64_unchecked()?.try_into()?),
90 NativeType::Float =>
91 flt_to_int!(self.get_f32_unchecked()?, f32, $type),
92 NativeType::Double =>
93 flt_to_int!(self.get_f64_unchecked()?, f64, $type),
94 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
95 NativeType::Number => Ok(self.get_str_unchecked()?.parse()?),
96 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
97 _ =>
98 self.invalid_conversion_to_rust_type(stringify!($type))
99 }
100 }
101 }
102}
103
104macro_rules! define_fn_set_int {
105 ($(#[$attr:meta])* : $func_name:ident, $type:ident) => {
106 $(#[$attr])*
107 pub(crate) fn $func_name(&mut self, val: &$type) -> Result<()> {
108 match self.native_type {
109 NativeType::Int64 =>
110 self.set_i64_unchecked(*val as i64),
111 NativeType::UInt64 =>
112 self.set_u64_unchecked(*val as u64),
113 NativeType::Float =>
114 self.set_f32_unchecked(*val as f32),
115 NativeType::Double =>
116 self.set_f64_unchecked(*val as f64),
117 NativeType::Char |
118 NativeType::Number => {
119 let s = val.to_string();
120 self.set_string_unchecked(&s)
121 },
122 _ =>
123 self.invalid_conversion_from_rust_type(stringify!($type))
124 }
125 }
126 }
127}
128
129pub enum BufferRowIndex {
130 Shared(Arc<AtomicU32>),
131 Owned(u32),
132}
133
134enum DpiData<'a> {
135 Data(&'a mut dpiData),
136 Var(Rc<DpiVar>), Null,
138}
139
140unsafe impl Send for DpiData<'_> {}
141
142pub struct SqlValue<'a> {
150 conn: Conn,
151 data: DpiData<'a>,
152 native_type: NativeType,
153 oratype: Option<OracleType>,
154 pub(crate) array_size: u32,
155 pub(crate) buffer_row_index: BufferRowIndex,
156 keep_bytes: Vec<u8>,
157 keep_dpiobj: DpiObject,
158 pub(crate) lob_bind_type: LobBindType,
159 pub(crate) query_params: QueryParams,
160 vector_format: VecFmt,
161}
162
163impl SqlValue<'_> {
164 fn new(
165 conn: Conn,
166 lob_bind_type: LobBindType,
167 query_params: QueryParams,
168 array_size: u32,
169 ) -> SqlValue<'static> {
170 SqlValue {
171 conn,
172 data: DpiData::Null,
173 native_type: NativeType::Int64,
174 oratype: None,
175 array_size,
176 buffer_row_index: BufferRowIndex::Owned(0),
177 keep_bytes: Vec::new(),
178 keep_dpiobj: DpiObject::null(),
179 lob_bind_type,
180 query_params,
181 vector_format: VecFmt::Flexible,
182 }
183 }
184
185 pub(crate) fn for_bind(
186 conn: Conn,
187 query_params: QueryParams,
188 array_size: u32,
189 ) -> SqlValue<'static> {
190 SqlValue::new(conn, LobBindType::Locator, query_params, array_size)
191 }
192
193 pub(crate) fn for_column(
194 conn: Conn,
195 query_params: QueryParams,
196 shared_buffer_row_index: Arc<AtomicU32>,
197 oratype: &OracleType,
198 stmt_handle: *mut dpiStmt,
199 pos: u32,
200 ) -> Result<SqlValue<'static>> {
201 let array_size = query_params.fetch_array_size;
202 let mut val = SqlValue::new(conn, query_params.lob_bind_type, query_params, array_size);
203 let oratype_i64 = OracleType::Int64;
204 let oratype = match oratype {
205 OracleType::Number(prec, 0) if 0 < *prec && *prec < DPI_MAX_INT64_PRECISION as u8 => {
208 &oratype_i64
209 }
210 _ => oratype,
211 };
212 val.buffer_row_index = BufferRowIndex::Shared(shared_buffer_row_index);
213 val.init_handle(oratype)?;
214 chkerr!(val.ctxt(), dpiStmt_define(stmt_handle, pos, val.handle()?));
215 Ok(val)
216 }
217
218 pub(crate) fn from_oratype<'a>(
220 conn: Conn,
221 oratype: &OracleType,
222 data: &'a mut dpiData,
223 ) -> Result<SqlValue<'a>> {
224 let param = oratype.var_create_param()?;
225 Ok(SqlValue {
226 conn,
227 data: DpiData::Data(data),
228 native_type: param.native_type,
229 oratype: Some(oratype.clone()),
230 array_size: 0,
231 buffer_row_index: BufferRowIndex::Owned(0),
232 keep_bytes: Vec::new(),
233 keep_dpiobj: DpiObject::null(),
234 lob_bind_type: LobBindType::Locator,
235 query_params: QueryParams::new(),
236 vector_format: param.vector_format,
237 })
238 }
239
240 pub(crate) fn ctxt(&self) -> &Context {
241 self.conn.ctxt()
242 }
243
244 fn handle_is_reusable(&self, oratype: &OracleType) -> Result<bool> {
245 match self.data {
246 DpiData::Var(_) => (),
247 _ => return Ok(false),
248 };
249 let current_oratype = match self.oratype {
250 Some(ref oratype) => oratype,
251 None => return Ok(false),
252 };
253 let current = current_oratype.var_create_param()?;
254 let new = oratype.var_create_param()?;
255 if current.oracle_type_num != new.oracle_type_num {
256 return Ok(false);
257 }
258 match current.oracle_type_num {
259 DPI_ORACLE_TYPE_VARCHAR
260 | DPI_ORACLE_TYPE_NVARCHAR
261 | DPI_ORACLE_TYPE_CHAR
262 | DPI_ORACLE_TYPE_NCHAR
263 | DPI_ORACLE_TYPE_RAW => Ok(current.size >= new.size),
264 DPI_ORACLE_TYPE_OBJECT => Ok(current.native_type == new.native_type),
265 _ => Ok(true),
266 }
267 }
268
269 pub(crate) fn init_handle(&mut self, oratype: &OracleType) -> Result<bool> {
270 if self.handle_is_reusable(oratype)? {
271 return Ok(false);
272 }
273 self.data = DpiData::Null;
274 let param = match self.lob_bind_type {
275 LobBindType::Bytes => match oratype {
276 OracleType::CLOB => &OracleType::Long,
277 OracleType::NCLOB => {
278 &OracleType::NVarchar2(DPI_MAX_BASIC_BUFFER_SIZE + 1)
281 }
282 OracleType::BLOB => &OracleType::LongRaw,
283 OracleType::BFILE => &OracleType::LongRaw,
284 _ => oratype,
285 },
286 LobBindType::Locator => oratype,
287 }
288 .var_create_param()?;
289 let mut handle = ptr::null_mut();
290 let mut data = ptr::null_mut();
291 let native_type_num = param.native_type.to_native_type_num();
292 let object_type_handle = param.native_type.to_object_type_handle();
293 chkerr!(
294 self.ctxt(),
295 dpiConn_newVar(
296 self.conn.handle.raw(),
297 param.oracle_type_num,
298 native_type_num,
299 self.array_size,
300 param.size,
301 param.size_is_byte,
302 0,
303 object_type_handle,
304 &mut handle,
305 &mut data,
306 )
307 );
308 self.data = DpiData::Var(Rc::new(DpiVar::new(handle, data)));
309 self.native_type = param.native_type;
310 self.oratype = Some(oratype.clone());
311 if native_type_num == DPI_NATIVE_TYPE_STMT {
312 for i in 0..self.array_size {
313 let handle = unsafe { dpiData_getStmt(data.offset(i as isize)) };
314 if let Some(prefetch_rows) = self.query_params.prefetch_rows {
315 chkerr!(self.ctxt(), dpiStmt_setPrefetchRows(handle, prefetch_rows));
316 }
317 }
318 }
319 Ok(true)
320 }
321
322 pub(crate) fn fix_internal_data(&mut self) -> Result<()> {
323 let handle = self.handle()?;
324 let mut num = 0;
325 let mut data = ptr::null_mut();
326 chkerr!(
327 self.ctxt(),
328 dpiVar_getReturnedData(handle, 0, &mut num, &mut data)
329 );
330 if num != 0 {
331 self.array_size = num;
332 self.data = DpiData::Var(Rc::new(DpiVar::with_add_ref(handle, data)));
333 }
334 Ok(())
335 }
336
337 fn buffer_row_index(&self) -> u32 {
338 match self.buffer_row_index {
339 BufferRowIndex::Shared(ref idx) => idx.load(Ordering::Relaxed),
340 BufferRowIndex::Owned(idx) => idx,
341 }
342 }
343
344 pub(crate) fn handle(&self) -> Result<*mut dpiVar> {
345 if let DpiData::Var(var) = &self.data {
346 Ok(var.raw)
347 } else {
348 Err(Error::internal_error("dpVar handle isn't initialized"))
349 }
350 }
351
352 pub(crate) fn data(&self) -> Result<&mut dpiData> {
353 unsafe {
354 Ok(&mut *match self.data {
355 DpiData::Data(ref data) => *data as *const dpiData as *mut dpiData,
356 DpiData::Var(ref var) => var.data,
357 DpiData::Null => {
358 return Err(Error::internal_error("dpData isn't initialized"));
359 }
360 }
361 .offset(self.buffer_row_index() as isize))
362 }
363 }
364
365 pub(crate) fn native_type_num(&self) -> dpiNativeTypeNum {
366 self.native_type.to_native_type_num()
367 }
368
369 pub fn get<T>(&self) -> Result<T>
382 where
383 T: FromSql,
384 {
385 <T>::from_sql(self)
386 }
387
388 pub fn set(&mut self, val: &dyn ToSql) -> Result<()> {
400 val.to_sql(self)
401 }
402
403 fn invalid_conversion_to_rust_type<T>(&self, to_type: &str) -> Result<T> {
404 Err(match self.oratype {
405 Some(ref oratype) => Error::invalid_type_conversion(oratype.to_string(), to_type),
406 None => Error::uninitialized_bind_value(),
407 })
408 }
409
410 fn invalid_conversion_from_rust_type<T>(&self, from_type: &str) -> Result<T> {
411 Err(match self.oratype {
412 Some(ref oratype) => Error::invalid_type_conversion(from_type, oratype.to_string()),
413 None => Error::uninitialized_bind_value(),
414 })
415 }
416
417 fn lob_locator_is_not_set<T>(&self, to_type: &str) -> Result<T> {
418 match self.oratype {
419 Some(_) => Err(Error::invalid_operation(format!(
420 "use StatementBuilder.lob_locator() instead to fetch LOB data as {}",
421 to_type
422 ))),
423 None => Err(Error::uninitialized_bind_value()),
424 }
425 }
426
427 fn check_not_null(&self) -> Result<()> {
428 if self.is_null()? {
429 Err(Error::null_value())
430 } else {
431 Ok(())
432 }
433 }
434
435 pub fn is_null(&self) -> Result<bool> {
437 Ok(self.data()?.isNull != 0)
438 }
439
440 pub fn set_null(&mut self) -> Result<()> {
442 self.data()?.isNull = 1;
443 Ok(())
444 }
445
446 pub fn oracle_type(&self) -> Result<&OracleType> {
448 match self.oratype {
449 Some(ref oratype) => Ok(oratype),
450 None => Err(Error::uninitialized_bind_value()),
451 }
452 }
453
454 pub fn as_inner_value(&self) -> Result<InnerValue> {
460 let data = self.data()?;
461 if data.isNull != 0 {
462 return Err(Error::null_value());
463 }
464 Ok(unsafe {
465 match self.native_type {
466 NativeType::Int64 => InnerValue::Int64(data.value.asInt64),
467 NativeType::UInt64 => InnerValue::UInt64(data.value.asUint64),
468 NativeType::Float => InnerValue::Float(data.value.asFloat),
469 NativeType::Double => InnerValue::Double(data.value.asDouble),
470 NativeType::Char => InnerValue::Char(to_rust_slice(
471 data.value.asBytes.ptr,
472 data.value.asBytes.length,
473 )),
474 NativeType::Number => InnerValue::Number(str::from_utf8_unchecked(to_rust_slice(
475 data.value.asBytes.ptr,
476 data.value.asBytes.length,
477 ))),
478 NativeType::Raw => InnerValue::Raw(to_rust_slice(
479 data.value.asBytes.ptr,
480 data.value.asBytes.length,
481 )),
482 NativeType::Timestamp => InnerValue::Timestamp(&data.value.asTimestamp),
483 NativeType::IntervalDS => InnerValue::IntervalDS(&data.value.asIntervalDS),
484 NativeType::IntervalYM => InnerValue::IntervalYM(&data.value.asIntervalYM),
485 NativeType::Clob => InnerValue::Clob(data.value.asLOB),
486 NativeType::Blob => InnerValue::Blob(data.value.asLOB),
487 NativeType::Object(_) => InnerValue::Object(data.value.asObject),
488 NativeType::Boolean => InnerValue::Boolean(data.value.asBoolean != 0),
489 NativeType::Rowid => InnerValue::Rowid(data.value.asRowid),
490 NativeType::Stmt => InnerValue::Stmt(data.value.asStmt),
491 NativeType::Vector => InnerValue::Vector(data.value.asVector),
492 }
493 })
494 }
495
496 fn get_i64_unchecked(&self) -> Result<i64> {
503 self.check_not_null()?;
504 unsafe { Ok(dpiData_getInt64(self.data()?)) }
505 }
506
507 fn get_u64_unchecked(&self) -> Result<u64> {
510 self.check_not_null()?;
511 unsafe { Ok(dpiData_getUint64(self.data()?)) }
512 }
513
514 fn get_f32_unchecked(&self) -> Result<f32> {
517 self.check_not_null()?;
518 unsafe { Ok(dpiData_getFloat(self.data()?)) }
519 }
520
521 fn get_f64_unchecked(&self) -> Result<f64> {
524 self.check_not_null()?;
525 unsafe { Ok(dpiData_getDouble(self.data()?)) }
526 }
527
528 fn get_cow_str_unchecked(&self) -> Result<Cow<str>> {
532 self.check_not_null()?;
533 unsafe {
534 let bytes = dpiData_getBytes(self.data()?);
535 let s = slice::from_raw_parts((*bytes).ptr as *mut u8, (*bytes).length as usize);
536 Ok(String::from_utf8_lossy(s))
537 }
538 }
539
540 fn get_str_unchecked(&self) -> Result<&str> {
546 self.check_not_null()?;
547 unsafe {
548 let bytes = dpiData_getBytes(self.data()?);
549 let s = slice::from_raw_parts((*bytes).ptr as *mut u8, (*bytes).length as usize);
550 Ok(str::from_utf8_unchecked(s))
551 }
552 }
553
554 fn get_raw_unchecked(&self) -> Result<Vec<u8>> {
557 self.check_not_null()?;
558 unsafe {
559 let bytes = dpiData_getBytes(self.data()?);
560 let mut vec = Vec::with_capacity((*bytes).length as usize);
561 vec.extend_from_slice(to_rust_slice((*bytes).ptr, (*bytes).length));
562 Ok(vec)
563 }
564 }
565
566 fn get_raw_as_hex_string_unchecked(&self) -> Result<String> {
569 self.check_not_null()?;
570 unsafe {
571 let bytes = dpiData_getBytes(self.data()?);
572 let mut str = String::with_capacity(((*bytes).length * 2) as usize);
573 set_hex_string(&mut str, to_rust_slice((*bytes).ptr, (*bytes).length));
574 Ok(str)
575 }
576 }
577
578 fn get_timestamp_unchecked(&self) -> Result<Timestamp> {
581 self.check_not_null()?;
582 unsafe {
583 let ts = dpiData_getTimestamp(self.data()?);
584 Ok(Timestamp::from_dpi_timestamp(&*ts, self.oracle_type()?))
585 }
586 }
587
588 fn get_interval_ds_unchecked(&self) -> Result<IntervalDS> {
591 self.check_not_null()?;
592 unsafe {
593 let it = dpiData_getIntervalDS(self.data()?);
594 IntervalDS::from_dpi_interval_ds(&*it, self.oracle_type()?)
595 }
596 }
597
598 fn get_interval_ym_unchecked(&self) -> Result<IntervalYM> {
601 self.check_not_null()?;
602 unsafe {
603 let it = dpiData_getIntervalYM(self.data()?);
604 IntervalYM::from_dpi_interval_ym(&*it, self.oracle_type()?)
605 }
606 }
607
608 fn get_clob_as_string_unchecked(&self) -> Result<String> {
609 self.check_not_null()?;
610 const READ_CHAR_SIZE: u64 = 8192;
611 let lob = unsafe { dpiData_getLOB(self.data()?) };
612 let mut total_char_size = 0;
613 let mut total_byte_size = 0;
614 let mut bufsiz = 0;
615 unsafe {
616 dpiLob_getSize(lob, &mut total_char_size);
617 dpiLob_getBufferSize(lob, total_char_size, &mut total_byte_size);
618 dpiLob_getBufferSize(lob, READ_CHAR_SIZE, &mut bufsiz);
619 }
620 let mut result = String::with_capacity(total_byte_size as usize);
621 let mut buf = vec![0u8; bufsiz as usize];
622 let bufptr = buf.as_mut_ptr() as *mut c_char;
623
624 let mut offset = 1;
625 while offset <= total_char_size {
626 let mut read_len = bufsiz;
627 chkerr!(
628 self.ctxt(),
629 dpiLob_readBytes(lob, offset, READ_CHAR_SIZE, bufptr, &mut read_len)
630 );
631 result.push_str(str::from_utf8(&buf[..(read_len as usize)])?);
632 offset += READ_CHAR_SIZE;
633 }
634 Ok(result)
635 }
636
637 fn get_blob_unchecked(&self) -> Result<Vec<u8>> {
638 self.check_not_null()?;
639 let lob = unsafe { dpiData_getLOB(self.data()?) };
640 let mut total_size = 0;
641 unsafe {
642 dpiLob_getSize(lob, &mut total_size);
643 }
644 let mut result: Vec<u8> = Vec::with_capacity(total_size as usize);
645 let mut read_len = total_size;
646 chkerr!(
647 self.ctxt(),
648 dpiLob_readBytes(
649 lob,
650 1,
651 total_size,
652 result.as_mut_ptr() as *mut c_char,
653 &mut read_len
654 )
655 );
656 unsafe {
657 result.set_len(read_len as usize);
658 }
659 Ok(result)
660 }
661
662 fn get_blob_as_hex_string_unchecked(&self) -> Result<String> {
663 self.check_not_null()?;
664 const READ_SIZE: u64 = 8192;
665 let lob = unsafe { dpiData_getLOB(self.data()?) };
666 let mut total_size = 0;
667 unsafe {
668 dpiLob_getSize(lob, &mut total_size);
669 }
670 let mut result = String::with_capacity((total_size * 2) as usize);
671 let mut buf = vec![0u8; READ_SIZE as usize];
672 let bufptr = buf.as_mut_ptr() as *mut c_char;
673
674 let mut offset = 1;
675 while offset <= total_size {
676 let mut read_len = READ_SIZE;
677 chkerr!(
678 self.ctxt(),
679 dpiLob_readBytes(lob, offset, READ_SIZE, bufptr, &mut read_len)
680 );
681 set_hex_string(&mut result, &buf[..(read_len as usize)]);
682 offset += READ_SIZE;
683 }
684 Ok(result)
685 }
686
687 fn get_collection_unchecked(&self, objtype: &ObjectType) -> Result<Collection> {
688 self.check_not_null()?;
689 let dpiobj = unsafe { dpiData_getObject(self.data()?) };
690 chkerr!(self.ctxt(), dpiObject_addRef(dpiobj));
691 Ok(Collection::new(
692 self.conn.clone(),
693 DpiObject::new(dpiobj),
694 objtype.clone(),
695 ))
696 }
697
698 fn get_object_unchecked(&self, objtype: &ObjectType) -> Result<Object> {
699 self.check_not_null()?;
700 let dpiobj = unsafe { dpiData_getObject(self.data()?) };
701 chkerr!(self.ctxt(), dpiObject_addRef(dpiobj));
702 Ok(Object::new(
703 self.conn.clone(),
704 DpiObject::new(dpiobj),
705 objtype.clone(),
706 ))
707 }
708
709 fn get_bool_unchecked(&self) -> Result<bool> {
712 self.check_not_null()?;
713 unsafe { Ok(dpiData_getBool(self.data()?) != 0) }
714 }
715
716 fn get_rowid_as_string_unchecked(&self) -> Result<String> {
717 self.check_not_null()?;
718 let mut ptr = ptr::null();
719 let mut len = 0;
720 chkerr!(
721 self.ctxt(),
722 dpiRowid_getStringValue(self.data()?.value.asRowid, &mut ptr, &mut len)
723 );
724 Ok(to_rust_str(ptr, len))
725 }
726
727 fn get_lob_unchecked(&self) -> Result<*mut dpiLob> {
728 self.check_not_null()?;
729 unsafe { Ok(dpiData_getLOB(self.data()?)) }
730 }
731
732 fn get_stmt_unchecked(&self) -> Result<*mut dpiStmt> {
733 self.check_not_null()?;
734 unsafe { Ok(dpiData_getStmt(self.data()?)) }
735 }
736
737 unsafe fn get_vec_ref_unchecked(&self) -> Result<VecRef<'static>> {
742 self.check_not_null()?;
743 let mut info = MaybeUninit::uninit();
744 chkerr!(
745 self.ctxt(),
746 dpiVector_getValue(self.data()?.value.asVector, info.as_mut_ptr())
747 );
748 VecRef::from_dpi(info.assume_init())
749 }
750
751 fn set_i64_unchecked(&mut self, val: i64) -> Result<()> {
758 unsafe { dpiData_setInt64(self.data()?, val) }
759 Ok(())
760 }
761
762 fn set_u64_unchecked(&mut self, val: u64) -> Result<()> {
765 unsafe { dpiData_setUint64(self.data()?, val) }
766 Ok(())
767 }
768
769 fn set_f32_unchecked(&mut self, val: f32) -> Result<()> {
772 unsafe { dpiData_setFloat(self.data()?, val) }
773 Ok(())
774 }
775
776 fn set_f64_unchecked(&mut self, val: f64) -> Result<()> {
779 unsafe { dpiData_setDouble(self.data()?, val) }
780 Ok(())
781 }
782
783 fn set_bytes_unchecked(&mut self, val: &[u8]) -> Result<()> {
784 match &self.data {
785 DpiData::Data(_) => {
786 self.keep_bytes = Vec::with_capacity(val.len());
787 self.keep_bytes.extend_from_slice(val);
788 unsafe {
789 dpiData_setBytes(
790 self.data()?,
791 self.keep_bytes.as_mut_ptr() as *mut c_char,
792 val.len() as u32,
793 );
794 }
795 Ok(())
796 }
797 DpiData::Var(var) => {
798 chkerr!(
799 self.ctxt(),
800 dpiVar_setFromBytes(
801 var.raw,
802 self.buffer_row_index(),
803 val.as_ptr() as *const c_char,
804 val.len() as u32
805 )
806 );
807 Ok(())
808 }
809 DpiData::Null => Err(Error::internal_error("dpiData isn't initialized")),
810 }
811 }
812
813 fn set_string_unchecked(&mut self, val: &str) -> Result<()> {
817 self.set_bytes_unchecked(val.as_bytes())
818 }
819
820 fn set_raw_unchecked(&mut self, val: &[u8]) -> Result<()> {
823 self.set_bytes_unchecked(val)
824 }
825
826 fn set_timestamp_unchecked(&mut self, val: &Timestamp) -> Result<()> {
829 let data = self.data()?;
830 data.isNull = 0;
831 data.value.asTimestamp = val.ts;
832 Ok(())
833 }
834
835 fn set_interval_ds_unchecked(&mut self, val: &IntervalDS) -> Result<()> {
838 let data = self.data()?;
839 data.isNull = 0;
840 data.value.asIntervalDS = val.intvl;
841 Ok(())
842 }
843
844 fn set_interval_ym_unchecked(&mut self, val: &IntervalYM) -> Result<()> {
847 let data = self.data()?;
848 data.isNull = 0;
849 data.value.asIntervalYM = val.intvl;
850 Ok(())
851 }
852
853 fn set_string_to_clob_unchecked(&mut self, val: &str) -> Result<()> {
854 let ptr = val.as_ptr() as *const c_char;
855 let len = val.len() as u64;
856 let lob = unsafe { dpiData_getLOB(self.data()?) };
857 chkerr!(self.ctxt(), dpiLob_trim(lob, 0));
858 chkerr!(self.ctxt(), dpiLob_writeBytes(lob, 1, ptr, len));
859 self.data()?.isNull = 0;
860 Ok(())
861 }
862
863 fn set_raw_to_blob_unchecked(&mut self, val: &[u8]) -> Result<()> {
864 let ptr = val.as_ptr() as *const c_char;
865 let len = val.len() as u64;
866 let lob = unsafe { dpiData_getLOB(self.data()?) };
867 chkerr!(self.ctxt(), dpiLob_trim(lob, 0));
868 chkerr!(self.ctxt(), dpiLob_writeBytes(lob, 1, ptr, len));
869 self.data()?.isNull = 0;
870 Ok(())
871 }
872
873 fn set_object_unchecked(&mut self, obj: &DpiObject) -> Result<()> {
874 match self.data {
875 DpiData::Data(_) => {
876 unsafe { dpiData_setObject(self.data()?, obj.raw) }
877 self.keep_dpiobj = obj.clone();
878 Ok(())
879 }
880 DpiData::Var(ref var) => {
881 chkerr!(
882 self.ctxt(),
883 dpiVar_setFromObject(var.raw, self.buffer_row_index(), obj.raw)
884 );
885 Ok(())
886 }
887 DpiData::Null => Err(Error::internal_error("dpiData isn't initialized")),
888 }
889 }
890
891 fn set_bool_unchecked(&mut self, val: bool) -> Result<()> {
894 unsafe { dpiData_setBool(self.data()?, i32::from(val)) }
895 Ok(())
896 }
897
898 fn set_lob_unchecked(&mut self, lob: *mut dpiLob) -> Result<()> {
899 chkerr!(
900 self.ctxt(),
901 dpiVar_setFromLob(self.handle()?, self.buffer_row_index(), lob)
902 );
903 Ok(())
904 }
905
906 fn set_vec_ref_unchecked(&mut self, vec: &VecRef) -> Result<()> {
907 let data = self.data()?;
908 let mut vec = vec.to_dpi()?;
909 chkerr!(
910 self.ctxt(),
911 dpiVector_setValue(data.value.asVector, &mut vec)
912 );
913 data.isNull = 0;
914 Ok(())
915 }
916
917 pub(crate) fn clone_except_fetch_array_buffer(&self) -> Result<SqlValue<'static>> {
918 if let DpiData::Var(ref var) = self.data {
919 Ok(SqlValue {
920 conn: self.conn.clone(),
921 data: DpiData::Var(var.clone()),
922 native_type: self.native_type.clone(),
923 oratype: self.oratype.clone(),
924 array_size: self.array_size,
925 buffer_row_index: BufferRowIndex::Owned(self.buffer_row_index()),
926 keep_bytes: Vec::new(),
927 keep_dpiobj: DpiObject::null(),
928 lob_bind_type: self.lob_bind_type,
929 query_params: self.query_params.clone(),
930 vector_format: self.vector_format,
931 })
932 } else {
933 Err(Error::internal_error("dpVar handle isn't initialized"))
934 }
935 }
936
937 pub(crate) fn fetch_array_buffer_shared_count(&self) -> Result<usize> {
938 if let DpiData::Var(ref var) = self.data {
939 Ok(Rc::strong_count(var))
940 } else {
941 Err(Error::internal_error("dpData isn't initialized"))
942 }
943 }
944
945 define_fn_to_int!(
950 : to_i8, i8);
953 define_fn_to_int!(
954 : to_i16, i16);
957 define_fn_to_int!(
958 : to_i32, i32);
961 define_fn_to_int!(
962 : to_isize, isize);
965
966 pub(crate) fn to_i64(&self) -> Result<i64> {
969 match self.native_type {
970 NativeType::Int64 => self.get_i64_unchecked(),
971 NativeType::UInt64 => Ok(self.get_u64_unchecked()?.try_into()?),
972 NativeType::Float => flt_to_int!(self.get_f32_unchecked()?, f32, i64),
973 NativeType::Double => flt_to_int!(self.get_f64_unchecked()?, f64, i64),
974 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
975 NativeType::Number => Ok(self.get_str_unchecked()?.parse()?),
976 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
977 _ => self.invalid_conversion_to_rust_type("i64"),
978 }
979 }
980
981 define_fn_to_int!(
982 : to_u8, u8);
985 define_fn_to_int!(
986 : to_u16, u16);
989 define_fn_to_int!(
990 : to_u32, u32);
993 define_fn_to_int!(
994 : to_usize, usize);
997
998 pub(crate) fn to_u64(&self) -> Result<u64> {
1001 match self.native_type {
1002 NativeType::Int64 => Ok(self.get_i64_unchecked()?.try_into()?),
1003 NativeType::UInt64 => self.get_u64_unchecked(),
1004 NativeType::Float => flt_to_int!(self.get_f32_unchecked()?, f32, u64),
1005 NativeType::Double => flt_to_int!(self.get_f64_unchecked()?, f64, u64),
1006 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1007 NativeType::Number => Ok(self.get_str_unchecked()?.parse()?),
1008 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1009 _ => self.invalid_conversion_to_rust_type("u64"),
1010 }
1011 }
1012
1013 pub(crate) fn to_f32(&self) -> Result<f32> {
1016 match self.native_type {
1017 NativeType::Int64 => Ok(self.get_i64_unchecked()? as f32),
1018 NativeType::UInt64 => Ok(self.get_u64_unchecked()? as f32),
1019 NativeType::Float => self.get_f32_unchecked(),
1020 NativeType::Double => Ok(self.get_f64_unchecked()? as f32),
1021 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1022 NativeType::Number => Ok(self.get_str_unchecked()?.parse()?),
1023 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1024 _ => self.invalid_conversion_to_rust_type("f32"),
1025 }
1026 }
1027
1028 pub(crate) fn to_f64(&self) -> Result<f64> {
1031 match self.native_type {
1032 NativeType::Int64 => Ok(self.get_i64_unchecked()? as f64),
1033 NativeType::UInt64 => Ok(self.get_u64_unchecked()? as f64),
1034 NativeType::Float => Ok(self.get_f32_unchecked()? as f64),
1035 NativeType::Double => self.get_f64_unchecked(),
1036 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1037 NativeType::Number => Ok(self.get_str_unchecked()?.parse()?),
1038 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1039 _ => self.invalid_conversion_to_rust_type("f64"),
1040 }
1041 }
1042
1043 pub(crate) fn to_string(&self) -> Result<String> {
1045 match self.native_type {
1046 NativeType::Int64 => Ok(self.get_i64_unchecked()?.to_string()),
1047 NativeType::UInt64 => Ok(self.get_u64_unchecked()?.to_string()),
1048 NativeType::Float => Ok(self.get_f32_unchecked()?.to_string()),
1049 NativeType::Double => Ok(self.get_f64_unchecked()?.to_string()),
1050 NativeType::Char => Ok(self.get_cow_str_unchecked()?.into()),
1051 NativeType::Number => Ok(self.get_str_unchecked()?.into()),
1052 NativeType::Raw => self.get_raw_as_hex_string_unchecked(),
1053 NativeType::Timestamp => Ok(self.get_timestamp_unchecked()?.to_string()),
1054 NativeType::IntervalDS => Ok(self.get_interval_ds_unchecked()?.to_string()),
1055 NativeType::IntervalYM => Ok(self.get_interval_ym_unchecked()?.to_string()),
1056 NativeType::Clob => self.get_clob_as_string_unchecked(),
1057 NativeType::Blob => self.get_blob_as_hex_string_unchecked(),
1058 NativeType::Object(ref objtype) => {
1059 if objtype.is_collection() {
1060 Ok(self.get_collection_unchecked(objtype)?.to_string())
1061 } else {
1062 Ok(self.get_object_unchecked(objtype)?.to_string())
1063 }
1064 }
1065 NativeType::Boolean => Ok(if self.get_bool_unchecked()? {
1066 "TRUE".into()
1067 } else {
1068 "FALSE".into()
1069 }),
1070 NativeType::Rowid => self.get_rowid_as_string_unchecked(),
1071 NativeType::Stmt => self.invalid_conversion_to_rust_type("string"),
1072 NativeType::Vector => Ok(match unsafe { self.get_vec_ref_unchecked()? } {
1073 VecRef::Float32(slice) => format!("{:?}", slice),
1074 VecRef::Float64(slice) => format!("{:?}", slice),
1075 VecRef::Int8(slice) => format!("{:?}", slice),
1076 VecRef::Binary(slice) => format!("{:?}", slice),
1077 }),
1078 }
1079 }
1080
1081 pub(crate) fn to_bytes(&self) -> Result<Vec<u8>> {
1083 match self.native_type {
1084 NativeType::Raw => self.get_raw_unchecked(),
1085 NativeType::Blob => self.get_blob_unchecked(),
1086 NativeType::Char => Ok(parse_str_into_raw(&self.get_cow_str_unchecked()?)?),
1087 NativeType::Clob => Ok(parse_str_into_raw(&self.get_clob_as_string_unchecked()?)?),
1088 NativeType::Vector
1089 if self.vector_format == VecFmt::Binary
1090 || self.vector_format == VecFmt::Flexible =>
1091 unsafe {
1092 let vec_ref = self.get_vec_ref_unchecked()?;
1093 match vec_ref {
1094 VecRef::Binary(slice) => Ok(slice.to_vec()),
1095 _ => Err(Error::invalid_type_conversion(
1096 vec_ref.oracle_type().to_string(),
1097 "Vec<u8>",
1098 )),
1099 }
1100 },
1101 _ => self.invalid_conversion_to_rust_type("raw"),
1102 }
1103 }
1104
1105 pub(crate) fn to_f32_vec(&self) -> Result<Vec<f32>> {
1106 match self.native_type {
1107 NativeType::Vector
1108 if self.vector_format == VecFmt::Float32
1109 || self.vector_format == VecFmt::Flexible =>
1110 unsafe {
1111 let vec_ref = self.get_vec_ref_unchecked()?;
1112 match vec_ref {
1113 VecRef::Float32(slice) => Ok(slice.to_vec()),
1114 _ => Err(Error::invalid_type_conversion(
1115 vec_ref.oracle_type().to_string(),
1116 "Vec<f32>",
1117 )),
1118 }
1119 },
1120 _ => self.invalid_conversion_to_rust_type("Vec<f32>"),
1121 }
1122 }
1123
1124 pub(crate) fn to_f64_vec(&self) -> Result<Vec<f64>> {
1125 match self.native_type {
1126 NativeType::Vector
1127 if self.vector_format == VecFmt::Float64
1128 || self.vector_format == VecFmt::Flexible =>
1129 unsafe {
1130 let vec_ref = self.get_vec_ref_unchecked()?;
1131 match vec_ref {
1132 VecRef::Float64(slice) => Ok(slice.to_vec()),
1133 _ => Err(Error::invalid_type_conversion(
1134 vec_ref.oracle_type().to_string(),
1135 "Vec<f64>",
1136 )),
1137 }
1138 },
1139 _ => self.invalid_conversion_to_rust_type("Vec<f64>"),
1140 }
1141 }
1142
1143 pub(crate) fn to_i8_vec(&self) -> Result<Vec<i8>> {
1144 match self.native_type {
1145 NativeType::Vector
1146 if self.vector_format == VecFmt::Int8 || self.vector_format == VecFmt::Flexible =>
1147 unsafe {
1148 let vec_ref = self.get_vec_ref_unchecked()?;
1149 match vec_ref {
1150 VecRef::Int8(slice) => Ok(slice.to_vec()),
1151 _ => Err(Error::invalid_type_conversion(
1152 vec_ref.oracle_type().to_string(),
1153 "Vec<i8>",
1154 )),
1155 }
1156 },
1157 _ => self.invalid_conversion_to_rust_type("Vec<i8>"),
1158 }
1159 }
1160
1161 pub(crate) fn to_timestamp(&self) -> Result<Timestamp> {
1164 match self.native_type {
1165 NativeType::Timestamp => self.get_timestamp_unchecked(),
1166 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1167 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1168 _ => self.invalid_conversion_to_rust_type("Timestamp"),
1169 }
1170 }
1171
1172 pub(crate) fn to_interval_ds(&self) -> Result<IntervalDS> {
1175 match self.native_type {
1176 NativeType::IntervalDS => self.get_interval_ds_unchecked(),
1177 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1178 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1179 _ => self.invalid_conversion_to_rust_type("IntervalDS"),
1180 }
1181 }
1182
1183 pub(crate) fn to_interval_ym(&self) -> Result<IntervalYM> {
1186 match self.native_type {
1187 NativeType::IntervalYM => self.get_interval_ym_unchecked(),
1188 NativeType::Char => Ok(self.get_cow_str_unchecked()?.parse()?),
1189 NativeType::Clob => Ok(self.get_clob_as_string_unchecked()?.parse()?),
1190 _ => self.invalid_conversion_to_rust_type("IntervalYM"),
1191 }
1192 }
1193
1194 pub(crate) fn to_collection(&self) -> Result<Collection> {
1195 match self.native_type {
1196 NativeType::Object(ref objtype) => {
1197 if objtype.is_collection() {
1198 self.get_collection_unchecked(objtype)
1199 } else {
1200 self.invalid_conversion_to_rust_type("Collection")
1201 }
1202 }
1203 _ => self.invalid_conversion_to_rust_type("Collection"),
1204 }
1205 }
1206
1207 pub(crate) fn to_object(&self) -> Result<Object> {
1208 match self.native_type {
1209 NativeType::Object(ref objtype) => {
1210 if !objtype.is_collection() {
1211 self.get_object_unchecked(objtype)
1212 } else {
1213 self.invalid_conversion_to_rust_type("Object")
1214 }
1215 }
1216 _ => self.invalid_conversion_to_rust_type("Object"),
1217 }
1218 }
1219
1220 pub(crate) fn to_bool(&self) -> Result<bool> {
1223 match self.native_type {
1224 NativeType::Boolean => self.get_bool_unchecked(),
1225 _ => self.invalid_conversion_to_rust_type("bool"),
1226 }
1227 }
1228
1229 pub(crate) fn to_bfile(&self) -> Result<Bfile> {
1230 if self.oratype == Some(OracleType::BFILE) {
1231 match self.native_type {
1232 NativeType::Blob => return Bfile::from_raw(self.ctxt(), self.get_lob_unchecked()?),
1233 NativeType::Raw => return self.lob_locator_is_not_set("Bfile"),
1234 _ => (),
1235 }
1236 }
1237 self.invalid_conversion_to_rust_type("Bfile")
1238 }
1239
1240 pub(crate) fn to_blob(&self) -> Result<Blob> {
1241 if self.oratype == Some(OracleType::BLOB) {
1242 match self.native_type {
1243 NativeType::Blob => return Blob::from_raw(self.ctxt(), self.get_lob_unchecked()?),
1244 NativeType::Raw => return self.lob_locator_is_not_set("Blob"),
1245 _ => (),
1246 }
1247 }
1248 self.invalid_conversion_to_rust_type("Blob")
1249 }
1250
1251 pub(crate) fn to_clob(&self) -> Result<Clob> {
1252 if self.oratype == Some(OracleType::CLOB) {
1253 match self.native_type {
1254 NativeType::Clob => return Clob::from_raw(self.ctxt(), self.get_lob_unchecked()?),
1255 NativeType::Raw => return self.lob_locator_is_not_set("Clob"),
1256 _ => (),
1257 }
1258 }
1259 self.invalid_conversion_to_rust_type("Clob")
1260 }
1261
1262 pub(crate) fn to_nclob(&self) -> Result<Nclob> {
1263 if self.oratype == Some(OracleType::NCLOB) {
1264 match self.native_type {
1265 NativeType::Clob => return Nclob::from_raw(self.ctxt(), self.get_lob_unchecked()?),
1266 NativeType::Raw => return self.lob_locator_is_not_set("Nclob"),
1267 _ => (),
1268 }
1269 }
1270 self.invalid_conversion_to_rust_type("Nclob")
1271 }
1272
1273 pub(crate) fn to_ref_cursor(&self) -> Result<RefCursor> {
1274 match self.native_type {
1275 NativeType::Stmt => Ok(RefCursor::from_handle(
1276 self.conn.clone(),
1277 DpiStmt::with_add_ref(self.get_stmt_unchecked()?),
1278 self.query_params.clone(),
1279 )?),
1280 _ => self.invalid_conversion_to_rust_type("RefCursor"),
1281 }
1282 }
1283
1284 pub(crate) fn to_vector(&self) -> Result<Vector> {
1285 let var = if let DpiData::Var(var) = &self.data {
1286 var.clone()
1287 } else {
1288 return Err(Error::internal_error("dpVar handle isn't initialized"));
1289 };
1290 match self.native_type {
1291 NativeType::Vector => unsafe {
1292 let vec_ref = self.get_vec_ref_unchecked()?;
1293 Vector::new(vec_ref, var)
1294 },
1295 _ => self.invalid_conversion_to_rust_type("Vector"),
1296 }
1297 }
1298
1299 define_fn_set_int!(
1304 : set_i8, i8);
1307 define_fn_set_int!(
1308 : set_i16, i16);
1311 define_fn_set_int!(
1312 : set_i32, i32);
1315 define_fn_set_int!(
1316 : set_i64, i64);
1319 define_fn_set_int!(
1320 : set_isize, isize);
1323 define_fn_set_int!(
1324 : set_u8, u8);
1327 define_fn_set_int!(
1328 : set_u16, u16);
1331 define_fn_set_int!(
1332 : set_u32, u32);
1335 define_fn_set_int!(
1336 : set_u64, u64);
1339 define_fn_set_int!(
1340 : set_usize, usize);
1343 define_fn_set_int!(
1344 : set_f32, f32);
1347 define_fn_set_int!(
1348 : set_f64, f64);
1351
1352 pub(crate) fn set_string(&mut self, val: &str) -> Result<()> {
1354 match self.native_type {
1355 NativeType::Int64 => self.set_i64_unchecked(val.parse()?),
1356 NativeType::UInt64 => self.set_u64_unchecked(val.parse()?),
1357 NativeType::Float => self.set_f32_unchecked(val.parse()?),
1358 NativeType::Double => self.set_f64_unchecked(val.parse()?),
1359 NativeType::Char => self.set_string_unchecked(val),
1360 NativeType::Number => {
1361 check_number_format(val)?;
1362 self.set_string_unchecked(val)
1363 }
1364 NativeType::Raw => self.set_raw_unchecked(&parse_str_into_raw(val)?),
1365 NativeType::Timestamp => self.set_timestamp_unchecked(&val.parse()?),
1366 NativeType::IntervalDS => self.set_interval_ds_unchecked(&val.parse()?),
1367 NativeType::IntervalYM => self.set_interval_ym_unchecked(&val.parse()?),
1368 NativeType::Clob => self.set_string_to_clob_unchecked(val),
1369 NativeType::Blob => self.set_raw_to_blob_unchecked(&parse_str_into_raw(val)?),
1370 _ => self.invalid_conversion_from_rust_type("&str"),
1371 }
1372 }
1373
1374 pub(crate) fn set_bytes(&mut self, val: &[u8]) -> Result<()> {
1376 match self.native_type {
1377 NativeType::Raw => self.set_raw_unchecked(val),
1378 NativeType::Blob => self.set_raw_to_blob_unchecked(val),
1379 _ => self.invalid_conversion_from_rust_type("&[u8]"),
1380 }
1381 }
1382
1383 pub(crate) fn set_timestamp(&mut self, val: &Timestamp) -> Result<()> {
1386 match self.native_type {
1387 NativeType::Timestamp => self.set_timestamp_unchecked(val),
1388 _ => self.invalid_conversion_from_rust_type("Timestamp"),
1389 }
1390 }
1391
1392 pub(crate) fn set_interval_ds(&mut self, val: &IntervalDS) -> Result<()> {
1395 match self.native_type {
1396 NativeType::IntervalDS => self.set_interval_ds_unchecked(val),
1397 _ => self.invalid_conversion_from_rust_type("IntervalDS"),
1398 }
1399 }
1400
1401 pub(crate) fn set_interval_ym(&mut self, val: &IntervalYM) -> Result<()> {
1404 match self.native_type {
1405 NativeType::IntervalYM => self.set_interval_ym_unchecked(val),
1406 _ => self.invalid_conversion_from_rust_type("IntervalYM"),
1407 }
1408 }
1409
1410 pub(crate) fn set_object(&mut self, val: &Object) -> Result<()> {
1412 match self.native_type {
1413 NativeType::Object(_) => self.set_object_unchecked(&val.handle),
1414 _ => self.invalid_conversion_from_rust_type("Object"),
1415 }
1416 }
1417
1418 pub(crate) fn set_collection(&mut self, val: &Collection) -> Result<()> {
1420 match self.native_type {
1421 NativeType::Object(_) => self.set_object_unchecked(&val.handle),
1422 _ => self.invalid_conversion_from_rust_type("Collection"),
1423 }
1424 }
1425
1426 pub(crate) fn set_bool(&mut self, val: &bool) -> Result<()> {
1429 match self.native_type {
1430 NativeType::Boolean => self.set_bool_unchecked(*val),
1431 _ => self.invalid_conversion_from_rust_type("bool"),
1432 }
1433 }
1434
1435 pub(crate) fn set_bfile(&mut self, val: &Bfile) -> Result<()> {
1436 if self.oratype == Some(OracleType::BFILE) {
1437 match self.native_type {
1438 NativeType::Blob => return self.set_lob_unchecked(val.lob.handle),
1439 NativeType::Raw => return self.lob_locator_is_not_set("Bfile"),
1440 _ => (),
1441 }
1442 }
1443 self.invalid_conversion_from_rust_type("Bfile")
1444 }
1445
1446 pub(crate) fn set_blob(&mut self, val: &Blob) -> Result<()> {
1447 if self.oratype == Some(OracleType::BLOB) {
1448 match self.native_type {
1449 NativeType::Blob => return self.set_lob_unchecked(val.lob.handle),
1450 NativeType::Raw => return self.lob_locator_is_not_set("Blob"),
1451 _ => (),
1452 }
1453 }
1454 self.invalid_conversion_from_rust_type("Blob")
1455 }
1456
1457 pub(crate) fn set_clob(&mut self, val: &Clob) -> Result<()> {
1458 if self.oratype == Some(OracleType::CLOB) {
1459 match self.native_type {
1460 NativeType::Clob => return self.set_lob_unchecked(val.lob.handle),
1461 NativeType::Raw => return self.lob_locator_is_not_set("Clob"),
1462 _ => (),
1463 }
1464 }
1465 self.invalid_conversion_from_rust_type("Clob")
1466 }
1467
1468 pub(crate) fn set_nclob(&mut self, val: &Nclob) -> Result<()> {
1469 if self.oratype == Some(OracleType::NCLOB) {
1470 match self.native_type {
1471 NativeType::Clob => return self.set_lob_unchecked(val.lob.handle),
1472 NativeType::Raw => return self.lob_locator_is_not_set("Nclob"),
1473 _ => (),
1474 }
1475 }
1476 self.invalid_conversion_from_rust_type("Nclob")
1477 }
1478
1479 pub(crate) fn set_vec_ref(&mut self, val: &VecRef, typename: &str) -> Result<()> {
1480 match self.native_type {
1481 NativeType::Vector => self.set_vec_ref_unchecked(val),
1482 _ => self.invalid_conversion_from_rust_type(typename),
1483 }
1484 }
1485
1486 pub(crate) fn clone_with_narrow_lifetime(&self) -> Result<SqlValue> {
1487 Ok(SqlValue {
1488 conn: self.conn.clone(),
1489 data: DpiData::Data(self.data()?),
1490 native_type: self.native_type.clone(),
1491 oratype: self.oratype.clone(),
1492 array_size: self.array_size,
1493 buffer_row_index: BufferRowIndex::Owned(0),
1494 keep_bytes: Vec::new(),
1495 keep_dpiobj: DpiObject::null(),
1496 lob_bind_type: self.lob_bind_type,
1497 query_params: self.query_params.clone(),
1498 vector_format: self.vector_format,
1499 })
1500 }
1501}
1502
1503impl AssertSend for SqlValue<'_> {}
1504
1505impl fmt::Display for SqlValue<'_> {
1506 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1510 if self.oratype.is_some() {
1511 match self.to_string() {
1512 Ok(s) => write!(f, "{}", s),
1513 Err(err) if err.kind() == ErrorKind::NullValue => write!(f, "NULL"),
1514 Err(err) => write!(f, "{}", err),
1515 }
1516 } else {
1517 write!(f, "uninitialized SQL value")
1518 }
1519 }
1520}
1521
1522impl fmt::Debug for SqlValue<'_> {
1523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1524 if let Some(ref oratype) = self.oratype {
1525 write!(f, "SqlValue {{ val: ")?;
1526 match self.to_string() {
1527 Ok(s) => match self.native_type {
1528 NativeType::Char | NativeType::Raw | NativeType::Clob | NativeType::Blob => {
1529 write!(f, "{:?}", s)
1530 }
1531 _ => write!(f, "{}", s),
1532 },
1533 Err(err) if err.kind() == ErrorKind::NullValue => write!(f, "NULL"),
1534 Err(err) => write!(f, "{}", err),
1535 }?;
1536 write!(
1537 f,
1538 ", type: {}, idx/size: {}/{})",
1539 oratype,
1540 self.buffer_row_index(),
1541 self.array_size
1542 )
1543 } else {
1544 write!(f, "SqlValue {{ uninitialized }}")
1545 }
1546 }
1547}