use std::path::PathBuf;
use tracing::warn;
use super::CompressionMethod;
use crate::native::protocol::ChunkedProtocolMode;
use crate::prelude::Secret;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ClientOptions {
pub username: String,
pub password: Secret,
pub default_database: String,
pub domain: Option<String>,
pub ipv4_only: bool,
pub cafile: Option<PathBuf>,
pub use_tls: bool,
pub compression: CompressionMethod,
#[cfg_attr(feature = "serde", serde(default))]
pub ext: Extension,
}
impl Default for ClientOptions {
fn default() -> Self {
ClientOptions {
username: "default".to_string(),
password: Secret::new(""),
default_database: String::new(),
domain: None,
ipv4_only: false,
cafile: None,
use_tls: false,
compression: CompressionMethod::default(),
ext: Extension::default(),
}
}
}
impl ClientOptions {
#[must_use]
pub fn new() -> Self { Self::default() }
#[must_use]
pub fn with_username(mut self, username: impl Into<String>) -> Self {
self.username = username.into();
self
}
#[must_use]
pub fn with_password(mut self, password: impl Into<Secret>) -> Self {
self.password = password.into();
self
}
#[must_use]
pub fn with_default_database(mut self, default_database: impl Into<String>) -> Self {
self.default_database = default_database.into();
self
}
#[must_use]
pub fn with_domain(mut self, domain: impl Into<String>) -> Self {
self.domain = Some(domain.into());
self
}
#[must_use]
pub fn with_ipv4_only(mut self, ipv4_only: bool) -> Self {
self.ipv4_only = ipv4_only;
self
}
#[must_use]
pub fn with_cafile<P: AsRef<std::path::Path>>(mut self, cafile: P) -> Self {
self.cafile = Some(cafile.as_ref().into());
self
}
#[must_use]
pub fn with_use_tls(mut self, use_tls: bool) -> Self {
self.use_tls = use_tls;
self
}
#[must_use]
pub fn with_compression(mut self, compression: CompressionMethod) -> Self {
self.compression = compression;
self
}
#[must_use]
pub fn with_extension(mut self, ext: Extension) -> Self {
self.ext = ext;
self
}
#[must_use]
pub fn extend(mut self, ext: impl Fn(Extension) -> Extension) -> Self {
self.ext = ext(self.ext);
self
}
}
#[non_exhaustive]
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Extension {
pub arrow: Option<ArrowOptions>,
#[cfg(feature = "cloud")]
pub cloud: CloudOptions,
#[cfg_attr(feature = "serde", serde(default))]
pub chunked_send: ChunkedProtocolMode,
#[cfg_attr(feature = "serde", serde(default))]
pub chunked_recv: ChunkedProtocolMode,
#[cfg(feature = "inner_pool")]
#[cfg_attr(feature = "serde", serde(default))]
pub fast_mode_size: Option<u8>,
}
impl Extension {
#[must_use]
pub fn with_arrow(mut self, options: ArrowOptions) -> Self {
self.arrow = Some(options);
self
}
#[must_use]
pub fn with_set_arrow(mut self, f: impl Fn(ArrowOptions) -> ArrowOptions) -> Self {
self.arrow = Some(f(self.arrow.unwrap_or_default()));
self
}
#[must_use]
pub fn with_chunked_send_mode(mut self, mode: ChunkedProtocolMode) -> Self {
self.chunked_send = mode;
self
}
#[must_use]
pub fn with_chunked_recv_mode(mut self, mode: ChunkedProtocolMode) -> Self {
self.chunked_recv = mode;
self
}
#[cfg(feature = "cloud")]
#[must_use]
pub fn with_cloud(mut self, options: CloudOptions) -> Self {
self.cloud = options;
self
}
#[cfg(feature = "inner_pool")]
#[must_use]
pub fn with_fast_mode_size(mut self, size: u8) -> Self {
self.fast_mode_size = Some(size);
self
}
}
#[expect(clippy::struct_excessive_bools)]
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ArrowOptions {
pub(crate) strings_as_strings: bool,
pub(crate) use_date32_for_date: bool,
pub(crate) strict_schema: bool,
pub(crate) disable_strict_schema_ddl: bool,
pub(crate) nullable_array_default_empty: bool,
}
impl Default for ArrowOptions {
fn default() -> Self { Self::new() }
}
impl ArrowOptions {
pub const fn new() -> Self {
Self {
strings_as_strings: false,
use_date32_for_date: false,
strict_schema: false,
disable_strict_schema_ddl: false,
nullable_array_default_empty: true,
}
}
pub const fn strict() -> Self {
Self {
strings_as_strings: false,
use_date32_for_date: false,
strict_schema: true,
disable_strict_schema_ddl: false,
nullable_array_default_empty: false,
}
}
#[must_use]
pub fn into_strict_ddl(self) -> Self {
if self.disable_strict_schema_ddl {
return self;
}
Self {
strings_as_strings: self.strings_as_strings,
use_date32_for_date: self.use_date32_for_date,
..Self::strict()
}
}
#[must_use]
pub fn with_strings_as_strings(mut self, enabled: bool) -> Self {
self.strings_as_strings = enabled;
self
}
#[must_use]
pub fn with_use_date32_for_date(mut self, enabled: bool) -> Self {
self.use_date32_for_date = enabled;
self
}
#[must_use]
pub fn with_strict_schema(mut self, enabled: bool) -> Self {
self.strict_schema = enabled;
self
}
#[must_use]
pub fn with_disable_strict_schema_ddl(mut self, enabled: bool) -> Self {
self.disable_strict_schema_ddl = enabled;
self
}
#[must_use]
pub fn with_nullable_array_default_empty(mut self, enabled: bool) -> Self {
self.nullable_array_default_empty = enabled;
self
}
#[must_use]
pub fn with_setting(self, name: &str, value: bool) -> Self {
match name {
"strings_as_strings" => self.with_strings_as_strings(value),
"use_date32_for_date" => self.with_use_date32_for_date(value),
"strict_schema" => self.with_strict_schema(value),
"disable_strict_schema_ddl" => self.with_disable_strict_schema_ddl(value),
"nullable_array_default_empty" => self.with_nullable_array_default_empty(value),
k => {
warn!("Unrecognized option for ArrowOptions: {k}");
self
}
}
}
}
impl<'a, S, I> From<I> for ArrowOptions
where
S: AsRef<str> + 'a,
I: Iterator<Item = &'a (S, bool)> + 'a,
{
fn from(value: I) -> Self {
let mut options = ArrowOptions::default();
for (k, v) in value {
options = options.with_setting(k.as_ref(), *v);
}
options
}
}
impl<'a> FromIterator<(&'a str, bool)> for ArrowOptions {
fn from_iter<I: IntoIterator<Item = (&'a str, bool)>>(iter: I) -> Self {
let mut options = ArrowOptions::default();
for (k, v) in iter {
options = options.with_setting(k, v);
}
options
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CloudOptions {
#[cfg_attr(feature = "serde", serde(default))]
pub timeout: Option<u64>,
#[cfg_attr(feature = "serde", serde(default))]
pub wakeup: bool,
}