Skip to content

Commit be4282c

Browse files
authored
feat(rust): Move setters and getters of options to the adbc_ffi crate (#3927)
These are very close to the functionality provided by the `adbc_ffi` create and would be helpful in a custom implementation of the core traits.
1 parent 1411996 commit be4282c

File tree

5 files changed

+262
-255
lines changed

5 files changed

+262
-255
lines changed

rust/driver_manager/src/lib.rs

Lines changed: 6 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub mod error;
104104

105105
use std::collections::HashSet;
106106
use std::env;
107-
use std::ffi::{CStr, CString, OsStr};
107+
use std::ffi::{CString, OsStr};
108108
use std::fs;
109109
use std::ops::DerefMut;
110110
use std::os::raw::{c_char, c_void};
@@ -113,14 +113,17 @@ use std::pin::Pin;
113113
use std::ptr::{null, null_mut};
114114
use std::sync::{Arc, Mutex};
115115

116+
use adbc_ffi::options::{
117+
check_status, get_option_bytes, get_option_string, set_option_connection, set_option_database,
118+
set_option_statement,
119+
};
116120
use arrow_array::ffi::{to_ffi, FFI_ArrowSchema};
117121
use arrow_array::ffi_stream::{ArrowArrayStreamReader, FFI_ArrowArrayStream};
118122
use arrow_array::{Array, RecordBatch, RecordBatchReader, StructArray};
119123
use toml::de::DeTable;
120124

121125
use adbc_core::{
122-
constants,
123-
error::{AdbcStatusCode, Error, Result, Status},
126+
error::{Error, Result, Status},
124127
options::{self, AdbcVersion, InfoCode, OptionDatabase, OptionValue},
125128
Connection, Database, Driver, LoadFlags, Optionable, PartitionedResult, Statement,
126129
LOAD_FLAG_ALLOW_RELATIVE_PATHS, LOAD_FLAG_SEARCH_ENV, LOAD_FLAG_SEARCH_SYSTEM,
@@ -130,22 +133,10 @@ use adbc_ffi::driver_method;
130133

131134
use crate::error::libloading_error_to_adbc_error;
132135

133-
const ERR_ONLY_STRING_OPT: &str = "Only string option value are supported with ADBC 1.0.0";
134136
const ERR_CANCEL_UNSUPPORTED: &str =
135137
"Canceling connection or statement is not supported with ADBC 1.0.0";
136138
const ERR_STATISTICS_UNSUPPORTED: &str = "Statistics are not supported with ADBC 1.0.0";
137139

138-
fn check_status(status: AdbcStatusCode, error: adbc_ffi::FFI_AdbcError) -> Result<()> {
139-
match status {
140-
constants::ADBC_STATUS_OK => Ok(()),
141-
_ => {
142-
let mut error: Error = error.try_into()?;
143-
error.status = status.try_into()?;
144-
Err(error)
145-
}
146-
}
147-
}
148-
149140
#[derive(Debug)]
150141
struct ManagedDriverInner {
151142
driver: adbc_ffi::FFI_AdbcDriver,
@@ -802,122 +793,6 @@ fn get_default_entrypoint(driver_path: impl AsRef<OsStr>) -> String {
802793
entrypoint
803794
}
804795

805-
fn set_option_database(
806-
driver: &adbc_ffi::FFI_AdbcDriver,
807-
database: &mut adbc_ffi::FFI_AdbcDatabase,
808-
version: AdbcVersion,
809-
key: impl AsRef<str>,
810-
value: OptionValue,
811-
) -> Result<()> {
812-
let key = CString::new(key.as_ref())?;
813-
let mut error = adbc_ffi::FFI_AdbcError::with_driver(driver);
814-
#[allow(unknown_lints)]
815-
#[warn(non_exhaustive_omitted_patterns)]
816-
let status = match (version, value) {
817-
(_, OptionValue::String(value)) => {
818-
let value = CString::new(value)?;
819-
let method = driver_method!(driver, DatabaseSetOption);
820-
unsafe { method(database, key.as_ptr(), value.as_ptr(), &mut error) }
821-
}
822-
(AdbcVersion::V110, OptionValue::Bytes(value)) => {
823-
let method = driver_method!(driver, DatabaseSetOptionBytes);
824-
unsafe {
825-
method(
826-
database,
827-
key.as_ptr(),
828-
value.as_ptr(),
829-
value.len(),
830-
&mut error,
831-
)
832-
}
833-
}
834-
(AdbcVersion::V110, OptionValue::Int(value)) => {
835-
let method = driver_method!(driver, DatabaseSetOptionInt);
836-
unsafe { method(database, key.as_ptr(), value, &mut error) }
837-
}
838-
(AdbcVersion::V110, OptionValue::Double(value)) => {
839-
let method = driver_method!(driver, DatabaseSetOptionDouble);
840-
unsafe { method(database, key.as_ptr(), value, &mut error) }
841-
}
842-
(AdbcVersion::V100, _) => Err(Error::with_message_and_status(
843-
ERR_ONLY_STRING_OPT,
844-
Status::NotImplemented,
845-
))?,
846-
(_, _) => unreachable!(),
847-
};
848-
check_status(status, error)
849-
}
850-
851-
// Utility function to implement `*GetOption` and `*GetOptionBytes`. Basically,
852-
// it allocates a fixed-sized buffer to store the option's value, call the driver's
853-
// `*GetOption`/`*GetOptionBytes` method that will fill this buffer and finally
854-
// we return the option's value as a `Vec`. Note that if the fixed-size buffer
855-
// is too small, we retry the same operation with a bigger buffer (the size of
856-
// which is obtained via the out parameter `length` of `*GetOption`/`*GetOptionBytes`).
857-
fn get_option_buffer<F, T>(
858-
key: impl AsRef<str>,
859-
mut populate: F,
860-
driver: &adbc_ffi::FFI_AdbcDriver,
861-
) -> Result<Vec<T>>
862-
where
863-
F: FnMut(*const c_char, *mut T, *mut usize, *mut adbc_ffi::FFI_AdbcError) -> AdbcStatusCode,
864-
T: Default + Clone,
865-
{
866-
const DEFAULT_LENGTH: usize = 128;
867-
let key = CString::new(key.as_ref())?;
868-
let mut run = |length| {
869-
let mut value = vec![T::default(); length];
870-
let mut length: usize = core::mem::size_of::<T>() * value.len();
871-
let mut error = adbc_ffi::FFI_AdbcError::with_driver(driver);
872-
(
873-
populate(key.as_ptr(), value.as_mut_ptr(), &mut length, &mut error),
874-
length,
875-
value,
876-
error,
877-
)
878-
};
879-
880-
let (status, length, value, error) = run(DEFAULT_LENGTH);
881-
check_status(status, error)?;
882-
883-
if length <= DEFAULT_LENGTH {
884-
Ok(value[..length].to_vec())
885-
} else {
886-
let (status, _, value, error) = run(length);
887-
check_status(status, error)?;
888-
Ok(value)
889-
}
890-
}
891-
892-
fn get_option_bytes<F>(
893-
key: impl AsRef<str>,
894-
populate: F,
895-
driver: &adbc_ffi::FFI_AdbcDriver,
896-
) -> Result<Vec<u8>>
897-
where
898-
F: FnMut(*const c_char, *mut u8, *mut usize, *mut adbc_ffi::FFI_AdbcError) -> AdbcStatusCode,
899-
{
900-
get_option_buffer(key, populate, driver)
901-
}
902-
903-
fn get_option_string<F>(
904-
key: impl AsRef<str>,
905-
populate: F,
906-
driver: &adbc_ffi::FFI_AdbcDriver,
907-
) -> Result<String>
908-
where
909-
F: FnMut(
910-
*const c_char,
911-
*mut c_char,
912-
*mut usize,
913-
*mut adbc_ffi::FFI_AdbcError,
914-
) -> AdbcStatusCode,
915-
{
916-
let value = get_option_buffer(key, populate, driver)?;
917-
let value = unsafe { CStr::from_ptr(value.as_ptr()) };
918-
Ok(value.to_string_lossy().to_string())
919-
}
920-
921796
struct ManagedDatabaseInner {
922797
database: Mutex<adbc_ffi::FFI_AdbcDatabase>,
923798
driver: Pin<Arc<ManagedDriverInner>>,
@@ -1130,52 +1005,6 @@ impl Database for ManagedDatabase {
11301005
}
11311006
}
11321007

1133-
fn set_option_connection(
1134-
driver: &adbc_ffi::FFI_AdbcDriver,
1135-
connection: &mut adbc_ffi::FFI_AdbcConnection,
1136-
version: AdbcVersion,
1137-
key: impl AsRef<str>,
1138-
value: OptionValue,
1139-
) -> Result<()> {
1140-
let key = CString::new(key.as_ref())?;
1141-
let mut error = adbc_ffi::FFI_AdbcError::with_driver(driver);
1142-
#[allow(unknown_lints)]
1143-
#[warn(non_exhaustive_omitted_patterns)]
1144-
let status = match (version, value) {
1145-
(_, OptionValue::String(value)) => {
1146-
let value = CString::new(value)?;
1147-
let method = driver_method!(driver, ConnectionSetOption);
1148-
unsafe { method(connection, key.as_ptr(), value.as_ptr(), &mut error) }
1149-
}
1150-
(AdbcVersion::V110, OptionValue::Bytes(value)) => {
1151-
let method = driver_method!(driver, ConnectionSetOptionBytes);
1152-
unsafe {
1153-
method(
1154-
connection,
1155-
key.as_ptr(),
1156-
value.as_ptr(),
1157-
value.len(),
1158-
&mut error,
1159-
)
1160-
}
1161-
}
1162-
(AdbcVersion::V110, OptionValue::Int(value)) => {
1163-
let method = driver_method!(driver, ConnectionSetOptionInt);
1164-
unsafe { method(connection, key.as_ptr(), value, &mut error) }
1165-
}
1166-
(AdbcVersion::V110, OptionValue::Double(value)) => {
1167-
let method = driver_method!(driver, ConnectionSetOptionDouble);
1168-
unsafe { method(connection, key.as_ptr(), value, &mut error) }
1169-
}
1170-
(AdbcVersion::V100, _) => Err(Error::with_message_and_status(
1171-
ERR_ONLY_STRING_OPT,
1172-
Status::NotImplemented,
1173-
))?,
1174-
(_, _) => unreachable!(),
1175-
};
1176-
check_status(status, error)
1177-
}
1178-
11791008
struct ManagedConnectionInner {
11801009
connection: Mutex<adbc_ffi::FFI_AdbcConnection>,
11811010
database: Arc<ManagedDatabaseInner>,
@@ -1546,52 +1375,6 @@ impl Connection for ManagedConnection {
15461375
}
15471376
}
15481377

1549-
fn set_option_statement(
1550-
driver: &adbc_ffi::FFI_AdbcDriver,
1551-
statement: &mut adbc_ffi::FFI_AdbcStatement,
1552-
version: AdbcVersion,
1553-
key: impl AsRef<str>,
1554-
value: OptionValue,
1555-
) -> Result<()> {
1556-
let key = CString::new(key.as_ref())?;
1557-
let mut error = adbc_ffi::FFI_AdbcError::with_driver(driver);
1558-
#[allow(unknown_lints)]
1559-
#[warn(non_exhaustive_omitted_patterns)]
1560-
let status = match (version, value) {
1561-
(_, OptionValue::String(value)) => {
1562-
let value = CString::new(value)?;
1563-
let method = driver_method!(driver, StatementSetOption);
1564-
unsafe { method(statement, key.as_ptr(), value.as_ptr(), &mut error) }
1565-
}
1566-
(AdbcVersion::V110, OptionValue::Bytes(value)) => {
1567-
let method = driver_method!(driver, StatementSetOptionBytes);
1568-
unsafe {
1569-
method(
1570-
statement,
1571-
key.as_ptr(),
1572-
value.as_ptr(),
1573-
value.len(),
1574-
&mut error,
1575-
)
1576-
}
1577-
}
1578-
(AdbcVersion::V110, OptionValue::Int(value)) => {
1579-
let method = driver_method!(driver, StatementSetOptionInt);
1580-
unsafe { method(statement, key.as_ptr(), value, &mut error) }
1581-
}
1582-
(AdbcVersion::V110, OptionValue::Double(value)) => {
1583-
let method = driver_method!(driver, StatementSetOptionDouble);
1584-
unsafe { method(statement, key.as_ptr(), value, &mut error) }
1585-
}
1586-
(AdbcVersion::V100, _) => Err(Error::with_message_and_status(
1587-
ERR_ONLY_STRING_OPT,
1588-
Status::NotImplemented,
1589-
))?,
1590-
(_, _) => unreachable!(),
1591-
};
1592-
check_status(status, error)
1593-
}
1594-
15951378
struct ManagedStatementInner {
15961379
statement: Mutex<adbc_ffi::FFI_AdbcStatement>,
15971380
connection: Arc<ManagedConnectionInner>,

rust/ffi/src/driver_exporter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use arrow_array::StructArray;
2626
use arrow_schema::DataType;
2727

2828
use super::{
29-
types::ErrorPrivateData, utils::get_opt_name, FFI_AdbcConnection, FFI_AdbcDatabase,
29+
options::get_opt_name, types::ErrorPrivateData, FFI_AdbcConnection, FFI_AdbcDatabase,
3030
FFI_AdbcDriver, FFI_AdbcError, FFI_AdbcErrorDetail, FFI_AdbcPartitions, FFI_AdbcStatement,
3131
};
3232
use adbc_core::constants::ADBC_STATUS_OK;

rust/ffi/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
//! [export_driver] macro.
4040
4141
pub mod driver_exporter;
42-
mod utils;
42+
pub mod options;
4343
#[doc(hidden)]
4444
pub use driver_exporter::FFIDriver;
4545
pub mod methods;

0 commit comments

Comments
 (0)