#[cfg(any(feature = "bundled", feature = "linked"))]
use std::ffi::{c_int, c_void};
use std::{fmt, sync::LazyLock};
use adbc_core::{
error::{AdbcStatusCode, Result},
options::{AdbcVersion, OptionDatabase, OptionValue},
};
use adbc_driver_manager::ManagedDriver;
#[cfg(any(feature = "bundled", feature = "linked"))]
use adbc_ffi::{FFI_AdbcDriverInitFunc, FFI_AdbcError};
use crate::Database;
mod builder;
pub use builder::*;
static DRIVER: LazyLock<Result<ManagedDriver>> = LazyLock::new(|| {
ManagedDriver::load_dynamic_from_name(
"adbc_driver_snowflake",
Some(b"AdbcDriverSnowflakeInit"),
Default::default(),
)
});
#[derive(Clone)]
pub struct Driver(ManagedDriver);
impl Default for Driver {
fn default() -> Self {
Self::try_load().expect("driver init")
}
}
impl fmt::Debug for Driver {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SnowflakeDriver")
.field("version", &self.0.version())
.finish_non_exhaustive()
}
}
#[cfg(any(feature = "bundled", feature = "linked"))]
extern "C" {
#[link_name = "AdbcDriverSnowflakeInit"]
fn init(version: c_int, raw_driver: *mut c_void, err: *mut FFI_AdbcError) -> AdbcStatusCode;
}
impl Driver {
pub fn try_load() -> Result<Self> {
Self::try_new(Default::default())
}
fn try_new(version: AdbcVersion) -> Result<Self> {
#[cfg(any(feature = "bundled", feature = "linked"))]
{
let driver_init: FFI_AdbcDriverInitFunc = init;
ManagedDriver::load_static(&driver_init, version).map(Self)
}
#[cfg(not(any(feature = "bundled", feature = "linked")))]
{
let _ = version;
Self::try_new_dynamic()
}
}
fn try_new_dynamic() -> Result<Self> {
DRIVER.clone().map(Self)
}
pub fn try_load_dynamic() -> Result<Self> {
Self::try_new_dynamic()
}
}
impl adbc_core::Driver for Driver {
type DatabaseType = Database;
fn new_database(&mut self) -> Result<Self::DatabaseType> {
self.0.new_database().map(Database)
}
fn new_database_with_opts(
&mut self,
opts: impl IntoIterator<Item = (OptionDatabase, OptionValue)>,
) -> Result<Self::DatabaseType> {
self.0.new_database_with_opts(opts).map(Database)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn try_load(version: AdbcVersion) -> Result<()> {
Builder::default().with_adbc_version(version).try_load()?;
Ok(())
}
#[test]
fn load_v1_0_0() -> Result<()> {
try_load(AdbcVersion::V100)
}
#[test]
fn load_v1_1_0() -> Result<()> {
try_load(AdbcVersion::V110)
}
#[test]
#[cfg_attr(
not(feature = "linked"),
ignore = "because the `linked` feature is not enabled"
)]
fn dynamic() -> Result<()> {
let _a = Driver::try_load_dynamic()?;
let _b = Driver::try_load_dynamic()?;
Ok(())
}
}