clickhouse_arrow/client/options.rs
1use std::path::PathBuf;
2
3use tracing::warn;
4
5use super::CompressionMethod;
6use crate::native::protocol::ChunkedProtocolMode;
7use crate::prelude::Secret;
8
9/// Configuration options for a `ClickHouse` client connection and Arrow serialization.
10///
11/// The `ClientOptions` struct defines the settings used to establish a connection
12/// to a `ClickHouse` server and handle data serialization/deserialization with
13/// Apache Arrow. These options are typically set via [`super::builder::ClientBuilder`] methods
14/// (e.g., [`super::builder::ClientBuilder::with_username`],
15/// [`super::builder::ClientBuilder::with_tls`]) or constructed directly for use with
16/// [`crate::Client::connect`].
17///
18/// # Fields
19/// - `username`: The username for authenticating with `ClickHouse` (default: `"default"`).
20/// - `password`: The password for authentication, stored securely as a [`Secret`].
21/// - `default_database`: The default database for queries; if empty, uses `ClickHouse`'s
22/// `"default"` database.
23/// - `domain`: Optional domain for TLS verification; inferred from the destination if unset.
24/// - `ipv4_only`: If `true`, restricts address resolution to IPv4; if `false`, allows IPv6.
25/// - `cafile`: Optional path to a certificate authority file for TLS connections.
26/// - `use_tls`: If `true`, enables TLS for secure connections; if `false`, uses plain TCP.
27/// - `compression`: The compression method for data exchange (default: [`CompressionMethod::LZ4`]).
28/// - `arrow`: Optional Arrow-specific serialization options (see [`ArrowOptions`]).
29/// - `cloud`: Cloud-specific options for `ClickHouse` cloud instances (requires `cloud` feature).
30///
31/// # Examples
32/// ```rust,ignore
33/// use clickhouse_arrow::prelude::*;
34///
35/// let options = ClientOptions {
36/// username: "admin".to_string(),
37/// password: Secret::new("secret"),
38/// default_database: "my_db".to_string(),
39/// use_tls: true,
40/// ..ClientOptions::default()
41/// };
42///
43/// let client = Client::connect("localhost:9000", options, None, None)
44/// .await
45/// .unwrap();
46/// ```
47#[derive(Debug, Clone, PartialEq)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49pub struct ClientOptions {
50 /// Username credential
51 pub username: String,
52 /// Password credential. [`Secret`] is used to minimize likelihood of exposure through logs
53 pub password: Secret,
54 /// Scope this client to a specifc database, otherwise 'default' is used
55 pub default_database: String,
56 /// For tls, provide the domain, otherwise it will be determined from the endpoint.
57 pub domain: Option<String>,
58 /// Whether any non-ipv4 socket addrs should be filtered out.
59 pub ipv4_only: bool,
60 /// Provide a path to a certificate authority to use for tls.
61 pub cafile: Option<PathBuf>,
62 /// Whether a connection should be made securely over tls.
63 pub use_tls: bool,
64 /// The compression to use when sending data to clickhouse.
65 pub compression: CompressionMethod,
66 /// Additional configuration not core to `ClickHouse` connections
67 #[cfg_attr(feature = "serde", serde(default))]
68 pub ext: Extension,
69}
70
71impl Default for ClientOptions {
72 fn default() -> Self {
73 ClientOptions {
74 username: "default".to_string(),
75 password: Secret::new(""),
76 default_database: String::new(),
77 domain: None,
78 ipv4_only: false,
79 cafile: None,
80 use_tls: false,
81 compression: CompressionMethod::default(),
82 ext: Extension::default(),
83 }
84 }
85}
86
87impl ClientOptions {
88 /// Create a new `ClientOptions` with default values.
89 #[must_use]
90 pub fn new() -> Self { Self::default() }
91
92 #[must_use]
93 pub fn with_username(mut self, username: impl Into<String>) -> Self {
94 self.username = username.into();
95 self
96 }
97
98 #[must_use]
99 pub fn with_password(mut self, password: impl Into<Secret>) -> Self {
100 self.password = password.into();
101 self
102 }
103
104 #[must_use]
105 pub fn with_default_database(mut self, default_database: impl Into<String>) -> Self {
106 self.default_database = default_database.into();
107 self
108 }
109
110 #[must_use]
111 pub fn with_domain(mut self, domain: impl Into<String>) -> Self {
112 self.domain = Some(domain.into());
113 self
114 }
115
116 #[must_use]
117 pub fn with_ipv4_only(mut self, ipv4_only: bool) -> Self {
118 self.ipv4_only = ipv4_only;
119 self
120 }
121
122 #[must_use]
123 pub fn with_cafile<P: AsRef<std::path::Path>>(mut self, cafile: P) -> Self {
124 self.cafile = Some(cafile.as_ref().into());
125 self
126 }
127
128 #[must_use]
129 pub fn with_use_tls(mut self, use_tls: bool) -> Self {
130 self.use_tls = use_tls;
131 self
132 }
133
134 #[must_use]
135 pub fn with_compression(mut self, compression: CompressionMethod) -> Self {
136 self.compression = compression;
137 self
138 }
139
140 #[must_use]
141 pub fn with_extension(mut self, ext: Extension) -> Self {
142 self.ext = ext;
143 self
144 }
145
146 #[must_use]
147 pub fn extend(mut self, ext: impl Fn(Extension) -> Extension) -> Self {
148 self.ext = ext(self.ext);
149 self
150 }
151}
152
153/// Extra configuration options for `ClickHouse`.
154///
155/// These options are separated to allow extending the configuration capabilities of a connection
156/// without breaking the core [`ClientOptions`] that are unlikely to ever change. For this reason,
157/// `Extensions` is `non_exhaustive` so the api can change without breaking existing
158/// implementations.
159#[non_exhaustive]
160#[derive(Debug, Default, Clone, PartialEq)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162pub struct Extension {
163 /// Options specific to (de)serializing arrow data.
164 pub arrow: Option<ArrowOptions>,
165 /// Options specific to communicating with `ClickHouse` over their cloud offering.
166 #[cfg(feature = "cloud")]
167 pub cloud: CloudOptions,
168 /// Options related to server/client protocol send chunking.
169 /// This may be removed, as it may be defaulted.
170 #[cfg_attr(feature = "serde", serde(default))]
171 pub chunked_send: ChunkedProtocolMode,
172 /// Options related to server/client protocol recv chunking.
173 /// This may be removed, as it may be defaulted
174 #[cfg_attr(feature = "serde", serde(default))]
175 pub chunked_recv: ChunkedProtocolMode,
176 /// Related to `inner_pool`, how many 'inner clients' to spawn. Currently capped at 4.
177 #[cfg(feature = "inner_pool")]
178 #[cfg_attr(feature = "serde", serde(default))]
179 pub fast_mode_size: Option<u8>,
180}
181
182/// Configuration extensions for specialized `ClickHouse` client behavior.
183///
184/// This type provides additional configuration options beyond the standard
185/// client settings, including Arrow format options and cloud-specific settings.
186impl Extension {
187 #[must_use]
188 pub fn with_arrow(mut self, options: ArrowOptions) -> Self {
189 self.arrow = Some(options);
190 self
191 }
192
193 #[must_use]
194 pub fn with_set_arrow(mut self, f: impl Fn(ArrowOptions) -> ArrowOptions) -> Self {
195 self.arrow = Some(f(self.arrow.unwrap_or_default()));
196 self
197 }
198
199 #[must_use]
200 pub fn with_chunked_send_mode(mut self, mode: ChunkedProtocolMode) -> Self {
201 self.chunked_send = mode;
202 self
203 }
204
205 #[must_use]
206 pub fn with_chunked_recv_mode(mut self, mode: ChunkedProtocolMode) -> Self {
207 self.chunked_recv = mode;
208 self
209 }
210
211 #[cfg(feature = "cloud")]
212 #[must_use]
213 pub fn with_cloud(mut self, options: CloudOptions) -> Self {
214 self.cloud = options;
215 self
216 }
217
218 #[cfg(feature = "inner_pool")]
219 #[must_use]
220 pub fn with_fast_mode_size(mut self, size: u8) -> Self {
221 self.fast_mode_size = Some(size);
222 self
223 }
224}
225
226// TODO: Remove - make the properties public!
227/// Configuration options for Arrow serialization and deserialization with `ClickHouse`.
228///
229/// The `ArrowOptions` struct defines settings that control how Apache Arrow data types
230/// are mapped to `ClickHouse` types during serialization (e.g., inserts), deserialization
231/// (e.g., queries), and schema creation (e.g., DDL operations). These options are used
232/// by [`crate::ArrowClient`] and set via [`super::builder::ClientBuilder::with_arrow_options`] or
233/// directly in [`ClientOptions`].
234///
235/// # Fields
236/// - `strings_as_strings`: If `true`, maps `ClickHouse` `String` to Arrow `Utf8`; if `false`, maps
237/// to `Binary` (default).
238/// - `use_date32_for_date`: If `true`, maps Arrow `Date32` to `ClickHouse` `Date32`; if `false`,
239/// maps to `Date` (default).
240/// - `strict_schema`: If `true`, enforces strict type mappings during serialization (inserts) and
241/// schema creation, causing errors on `ClickHouse` invariant violations (e.g.,
242/// `Nullable(LowCardinality(String))`); if `false`, attempts to correct violations (e.g., mapping
243/// to `LowCardinality(Nullable(String))`) (default).
244/// - `disable_strict_schema_ddl`: If `true`, prevents automatic strict mode during schema creation
245/// (via [`ArrowOptions::into_strict_ddl`]); if `false`, schema creation defaults to strict mode
246/// (default).
247/// - `nullable_array_default_empty`: If `true`, maps `Nullable(Array(...))` to `Array(...)` with
248/// `[]` for nulls during inserts and schema creation (if `disable_strict_schema_ddl = true`); if
249/// `false`, errors on `Nullable(Array(...))` (default).
250///
251/// # Notes
252/// - During schema creation, options are converted to strict mode (via
253/// [`ArrowOptions::into_strict_ddl`]) unless `disable_strict_schema_ddl` is `true`. Strict mode
254/// sets `strict_schema = true` and effectively enforces `nullable_array_default_empty = false`,
255/// ensuring non-nullable arrays.
256/// - When `strict_schema` is `false`, violations like `Nullable(LowCardinality(String))` are
257/// corrected, but arrays are handled per `nullable_array_default_empty` for inserts, while
258/// nullable arrays are ignored during schema creation.
259/// - If `strict_schema = true` and `nullable_array_default_empty = true`, non-array violations
260/// (e.g., `LowCardinality`) error, but arrays map to `[]` for nulls during insert. This is useful
261/// in cases where the arrow `Schema` is used to create the table, but arrays may come from
262/// different `RecordBatch`es.
263/// - This struct is `#[non_exhaustive]`, so future fields may be added (e.g., for new `ClickHouse`
264/// types or serialization options). Use [`ArrowOptions::new`] or [`ArrowOptions::default`] to
265/// construct instances.
266///
267/// # Examples
268/// ```rust,ignore
269/// use clickhouse_arrow::prelude::*;
270///
271/// let arrow_options = ArrowOptions::new()
272/// .with_strings_as_strings(true)
273/// .with_strict_schema(true)
274/// .with_nullable_array_default_empty(false);
275/// let options = ClientOptions {
276/// arrow: Some(arrow_options),
277/// ..ClientOptions::default()
278/// };
279/// ```
280#[expect(clippy::struct_excessive_bools)]
281#[non_exhaustive]
282#[derive(Debug, Clone, Copy, PartialEq, Eq)]
283#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
284pub struct ArrowOptions {
285 pub strings_as_strings: bool,
286 pub use_date32_for_date: bool,
287 pub strict_schema: bool,
288 pub disable_strict_schema_ddl: bool,
289 pub nullable_array_default_empty: bool,
290}
291
292impl Default for ArrowOptions {
293 /// Creates an `ArrowOptions` instance with default values.
294 ///
295 /// The default configuration uses relaxed type mappings suitable for most
296 /// `ClickHouse` and `Arrow` use cases:
297 /// - `ClickHouse` `String` maps to Arrow `Binary`.
298 /// - Arrow `Date32` maps to `ClickHouse` `Date`.
299 /// - Type mappings are relaxed, correcting `ClickHouse` invariant violations (e.g., mapping
300 /// `Nullable(LowCardinality(String))` to `LowCardinality(Nullable(String))`).
301 /// - Schema creation defaults to strict mode (via [`ArrowOptions::into_strict_ddl`]).
302 /// - `Nullable(Array(...))` defaults to `Array(...)` with `[]` for nulls.
303 ///
304 /// Use this as a starting point and customize with methods like
305 /// [`ArrowOptions::with_strings_as_strings`].
306 ///
307 /// # Returns
308 /// An [`ArrowOptions`] instance with default settings.
309 ///
310 /// # Examples
311 /// ```rust,ignore
312 /// use clickhouse_arrow::arrow::ArrowOptions;
313 ///
314 /// let arrow_options = ArrowOptions::default();
315 /// println!("Nullable array default empty: {}", arrow_options.nullable_array_default_empty); // true
316 /// ```
317 fn default() -> Self { Self::new() }
318}
319
320impl ArrowOptions {
321 /// Creates a new `ArrowOptions` instance with default values.
322 ///
323 /// This method is equivalent to [`ArrowOptions::default`], initializing fields for
324 /// relaxed type mappings. Use this to start configuring Arrow
325 /// serialization/deserialization options for `ClickHouse`.
326 ///
327 /// # Returns
328 /// A new [`ArrowOptions`] instance with default settings.
329 ///
330 /// # Examples
331 /// ```rust,ignore
332 /// use clickhouse_arrow::arrow::ArrowOptions;
333 ///
334 /// let arrow_options = ArrowOptions::new();
335 /// println!("Nullable array default empty: {}", arrow_options.nullable_array_default_empty); // true
336 /// ```
337 pub const fn new() -> Self {
338 Self {
339 strings_as_strings: false,
340 use_date32_for_date: false,
341 strict_schema: false,
342 disable_strict_schema_ddl: false,
343 nullable_array_default_empty: true,
344 }
345 }
346
347 /// Creates an `ArrowOptions` instance with strict type mapping settings.
348 ///
349 /// This method configures options for strict type mappings, where `ClickHouse`
350 /// invariant violations (e.g., `Nullable(LowCardinality(String))` or
351 /// `Nullable(Array(...))`) cause errors during serialization (inserts) and schema
352 /// creation. It sets `strict_schema` to `true` and `nullable_array_default_empty` to
353 /// `false`, leaving other fields as `false`. Use this for operations where
354 /// `ClickHouse` invariants must be strictly enforced.
355 ///
356 /// # Returns
357 /// An [`ArrowOptions`] instance with strict settings.
358 ///
359 /// # Examples
360 /// ```rust,ignore
361 /// use clickhouse_arrow::arrow::ArrowOptions;
362 ///
363 /// let arrow_options = ArrowOptions::strict();
364 /// println!("Strict schema: {}", arrow_options.strict_schema); // true
365 /// ```
366 pub const fn strict() -> Self {
367 Self {
368 strings_as_strings: false,
369 use_date32_for_date: false,
370 strict_schema: true,
371 disable_strict_schema_ddl: false,
372 nullable_array_default_empty: false,
373 }
374 }
375
376 /// Converts the options to strict mode for schema creation, unless disabled.
377 ///
378 /// This method returns a new [`ArrowOptions`] with strict settings (equivalent to
379 /// [`ArrowOptions::strict`]) unless `disable_strict_schema_ddl` is `true`. If
380 /// `disable_strict_schema_ddl` is `true`, the original options are returned
381 /// unchanged. This method is called automatically during schema creation to enforce
382 /// `ClickHouse` invariants, including non-nullable arrays, unless explicitly disabled.
383 ///
384 /// # Returns
385 /// A new [`ArrowOptions`] instance with strict settings or the original options.
386 ///
387 /// # Examples
388 /// ```rust,ignore
389 /// use clickhouse_arrow::arrow::ArrowOptions;
390 ///
391 /// let options_strict_off = ArrowOptions::new()
392 /// .with_disable_strict_schema_ddl(true)
393 /// .into_strict_ddl();
394 /// assert!(!options_strict_off.strict_schema);
395 /// assert!(options_strict_off.nullable_array_default_empty);
396 ///
397 /// let options_strict = ArrowOptions::new()
398 /// .with_disable_strict_schema_ddl(false) // Default
399 /// .into_strict_ddl();
400 /// assert!(options_strict.strict_schema);
401 /// assert!(!options_strict.nullable_array_default_empty);
402 /// ```
403 #[must_use]
404 pub fn into_strict_ddl(self) -> Self {
405 if self.disable_strict_schema_ddl {
406 return self;
407 }
408
409 Self {
410 strings_as_strings: self.strings_as_strings,
411 use_date32_for_date: self.use_date32_for_date,
412 ..Self::strict()
413 }
414 }
415
416 /// Sets whether `ClickHouse` `String` types are deserialized as Arrow `Utf8`.
417 ///
418 /// By default, `ClickHouse` `String` types map to Arrow `Binary`. When this option
419 /// is enabled (`true`), they map to Arrow `Utf8`, which is more suitable for text
420 /// data. Use this to control serialization/deserialization behavior for string
421 /// columns.
422 ///
423 /// # Parameters
424 /// - `enabled`: If `true`, maps [`crate::Type::String`] to
425 /// [`arrow::datatypes::DataType::Utf8`]; if `false`, maps to
426 /// [`arrow::datatypes::DataType::Binary`].
427 ///
428 /// # Returns
429 /// A new [`ArrowOptions`] with the updated setting.
430 ///
431 /// # Examples
432 /// ```rust,ignore
433 /// use clickhouse_arrow::prelude::*;
434 ///
435 /// let arrow_options = ArrowOptions::new()
436 /// .with_strings_as_strings(true);
437 /// println!("Strings as strings: {}", arrow_options.strings_as_strings); // true
438 /// ```
439 #[must_use]
440 pub fn with_strings_as_strings(mut self, enabled: bool) -> Self {
441 self.strings_as_strings = enabled;
442 self
443 }
444
445 /// Sets whether Arrow `Date32` is mapped to `ClickHouse` `Date` or `Date32`.
446 ///
447 /// By default, Arrow `Date32` maps to `ClickHouse` `Date` (days since 1970-01-01).
448 /// When this option is enabled (`true`), it maps to `ClickHouse` `Date32` (days
449 /// since 1900-01-01). Use this to control date serialization/deserialization
450 /// behavior.
451 ///
452 /// # Parameters
453 /// - `enabled`: If `true`, maps `Date32` to `ClickHouse` `Date32`; if `false`, maps to `Date`.
454 ///
455 /// # Returns
456 /// A new [`ArrowOptions`] with the updated setting.
457 ///
458 /// # Examples
459 /// ```rust,ignore
460 /// use clickhouse_arrow::prelude::*;
461 ///
462 /// let arrow_options = ArrowOptions::new()
463 /// .with_use_date32_for_date(true);
464 /// println!("Use Date32 for Date: {}", arrow_options.use_date32_for_date); // true
465 /// ```
466 #[must_use]
467 pub fn with_use_date32_for_date(mut self, enabled: bool) -> Self {
468 self.use_date32_for_date = enabled;
469 self
470 }
471
472 /// Sets whether type mappings are strict during serialization and schema creation.
473 ///
474 /// By default, type mappings are relaxed, allowing `ClickHouse` invariant violations
475 /// (e.g., `Nullable(LowCardinality(String))`) to be corrected automatically (e.g.,
476 /// mapping to `LowCardinality(Nullable(String))`). When this option is enabled
477 /// (`true`), non-array violations cause errors during serialization (inserts) and
478 /// schema creation. Array violations are controlled by
479 /// [`ArrowOptions::with_nullable_array_default_empty`]. Schema creation defaults to
480 /// strict mode unless [`ArrowOptions::with_disable_strict_schema_ddl`] is enabled.
481 ///
482 /// # Parameters
483 /// - `enabled`: If `true`, enforces strict type mappings for non-array types; if `false`,
484 /// allows relaxed corrections.
485 ///
486 /// # Returns
487 /// A new [`ArrowOptions`] with the updated setting.
488 ///
489 /// # Examples
490 /// ```rust,ignore
491 /// use clickhouse_arrow::arrow::ArrowOptions;
492 ///
493 /// let arrow_options = ArrowOptions::new()
494 /// .with_strict_schema(true);
495 /// println!("Strict schema: {}", arrow_options.strict_schema); // true
496 /// ```
497 #[must_use]
498 pub fn with_strict_schema(mut self, enabled: bool) -> Self {
499 self.strict_schema = enabled;
500 self
501 }
502
503 /// Sets whether strict mode is disabled during schema creation.
504 ///
505 /// By default, schema creation (e.g., DDL operations) uses strict type mappings (via
506 /// [`ArrowOptions::into_strict_ddl`]), enforcing `ClickHouse` invariants and causing
507 /// errors on violations, including `Nullable(Array(...))`. When this option is
508 /// enabled (`true`), strict mode is disabled for schema creation, using the user’s
509 /// `strict_schema` and `nullable_array_default_empty` settings.
510 ///
511 /// # Parameters
512 /// - `enabled`: If `true`, disables strict mode for schema creation; if `false`, enables strict
513 /// mode.
514 ///
515 /// # Returns
516 /// A new [`ArrowOptions`] with the updated setting.
517 ///
518 /// # Examples
519 /// ```rust,ignore
520 /// use clickhouse_arrow::arrow::ArrowOptions;
521 ///
522 /// let arrow_options = ArrowOptions::new()
523 /// .with_disable_strict_schema_ddl(true);
524 /// assert!(arrow_options.disable_strict_schema_ddl);
525 /// ```
526 #[must_use]
527 pub fn with_disable_strict_schema_ddl(mut self, enabled: bool) -> Self {
528 self.disable_strict_schema_ddl = enabled;
529 self
530 }
531
532 /// Sets whether `Nullable(Array(...))` types default to empty arrays during inserts and are
533 /// coerced to non-nullable during DDL.
534 ///
535 /// By default, `Nullable(Array(...))` types are mapped to `Array(...)` with `[]` for
536 /// nulls during serialization (inserts) and schema creation (if
537 /// `disable_strict_schema_ddl = true`). When this option is disabled (`false`),
538 /// `Nullable(Array(...))` causes errors, enforcing non-nullable arrays. Schema
539 /// creation defaults to non-nullable arrays unless
540 /// [`ArrowOptions::with_disable_strict_schema_ddl`] is enabled.
541 ///
542 /// # Parameters
543 /// - `enabled`: If `true`, maps `Nullable(Array(...))` to `Array(...)` with `[]` for nulls; if
544 /// `false`, errors on `Nullable(Array(...))`.
545 ///
546 /// # Returns
547 /// A new [`ArrowOptions`] with the updated setting.
548 ///
549 /// # Examples
550 /// ```rust,ignore
551 /// use clickhouse_arrow::arrow::ArrowOptions;
552 ///
553 /// let arrow_options = ArrowOptions::new()
554 /// .with_nullable_array_default_empty(false);
555 /// assert!(!arrow_options.nullable_array_default_empty);
556 /// ```
557 #[must_use]
558 pub fn with_nullable_array_default_empty(mut self, enabled: bool) -> Self {
559 self.nullable_array_default_empty = enabled;
560 self
561 }
562
563 /// Sets an Arrow option by name and value.
564 ///
565 /// This method updates a specific option identified by `name` to the given boolean
566 /// `value`. Currently supported names are:
567 /// - `"strings_as_strings"`: Maps `ClickHouse` `String` to Arrow `Utf8`.
568 /// - `"use_date32_for_date"`: Maps Arrow `Date32` to `ClickHouse` `Date32`.
569 /// - `"strict_schema"`: Enforces strict type mappings for non-array types.
570 /// - `"disable_strict_schema_ddl"`: Disables strict mode for schema creation.
571 /// - `"nullable_array_default_empty"`: Maps `Nullable(Array(...))` to `Array(...)` with `[]`
572 /// for nulls.
573 ///
574 /// If an unrecognized name is provided, a warning is logged, and the options are
575 /// returned unchanged. Use this for dynamic configuration or when options are
576 /// specified as key-value pairs.
577 ///
578 /// # Parameters
579 /// - `name`: The name of the option to set.
580 /// - `value`: The boolean value to set for the option.
581 ///
582 /// # Returns
583 /// A new [`ArrowOptions`] with the updated setting.
584 ///
585 /// # Examples
586 /// ```rust,ignore
587 /// use clickhouse_arrow::arrow::ArrowOptions;
588 ///
589 /// let arrow_options = ArrowOptions::new()
590 /// .with_setting("strings_as_strings", true)
591 /// .with_setting("nullable_array_default_empty", false);
592 /// assert!(arrow_options.strings_as_strings);
593 /// assert!(!arrow_options.nullable_array_default_empty);
594 /// ```
595 #[must_use]
596 pub fn with_setting(self, name: &str, value: bool) -> Self {
597 match name {
598 "strings_as_strings" => self.with_strings_as_strings(value),
599 "use_date32_for_date" => self.with_use_date32_for_date(value),
600 "strict_schema" => self.with_strict_schema(value),
601 "disable_strict_schema_ddl" => self.with_disable_strict_schema_ddl(value),
602 "nullable_array_default_empty" => self.with_nullable_array_default_empty(value),
603 k => {
604 warn!("Unrecognized option for ArrowOptions: {k}");
605 self
606 }
607 }
608 }
609}
610
611impl<'a, S, I> From<I> for ArrowOptions
612where
613 S: AsRef<str> + 'a,
614 I: Iterator<Item = &'a (S, bool)> + 'a,
615{
616 /// Creates an `ArrowOptions` instance from an iterator of key-value pairs.
617 ///
618 /// This method constructs an [`ArrowOptions`] by applying settings from an iterator
619 /// of `(key, value)` pairs, where `key` is a string (e.g., `"strict_schema"`) and
620 /// `value` is a boolean. It uses [`ArrowOptions::with_setting`] to apply each
621 /// setting. Unrecognized keys trigger a warning but do not cause an error.
622 ///
623 /// See currently supported keys by inspecting [`ArrowOptions::with_setting`].
624 ///
625 /// # Parameters
626 /// - `value`: An iterator of `(key, value)` pairs, where `key` is a string-like type and
627 /// `value` is a boolean.
628 ///
629 /// # Returns
630 /// An [`ArrowOptions`] instance with the applied settings.
631 ///
632 /// # Examples
633 /// ```rust,ignore
634 /// use clickhouse_arrow::arrow::ArrowOptions;
635 ///
636 /// let settings = vec![("strings_as_strings", true), ("nullable_array_default_empty", false)];
637 /// let arrow_options: ArrowOptions = settings.iter().collect();
638 /// assert!(arrow_options.strings_as_strings);
639 /// assert!(!arrow_options.nullable_array_default_empty);
640 /// ```
641 fn from(value: I) -> Self {
642 let mut options = ArrowOptions::default();
643 for (k, v) in value {
644 options = options.with_setting(k.as_ref(), *v);
645 }
646 options
647 }
648}
649
650impl<'a> FromIterator<(&'a str, bool)> for ArrowOptions {
651 /// Creates an `ArrowOptions` instance from an iterator of string-boolean pairs.
652 ///
653 /// This method constructs an [`ArrowOptions`] by applying settings from an iterator
654 /// of `(key, value)` pairs, where `key` is a string slice (e.g., `"strict_schema"`)
655 /// and `value` is a boolean. It uses [`ArrowOptions::with_setting`] to apply each
656 /// setting. Unrecognized keys trigger a warning but do not cause an error.
657 ///
658 /// See currently supported keys by inspecting [`ArrowOptions::with_setting`].
659 ///
660 /// # Parameters
661 /// - `iter`: An iterator of `(key, value)` pairs, where `key` is a string slice and `value` is
662 /// a boolean.
663 ///
664 /// # Returns
665 /// An [`ArrowOptions`] instance with the applied settings.
666 ///
667 /// # Examples
668 /// ```rust,ignore
669 /// use clickhouse_arrow::arrow::ArrowOptions;
670 ///
671 /// let settings = vec![("strings_as_strings", true), ("nullable_array_default_empty", false)];
672 /// let arrow_options = ArrowOptions::from_iter(settings);
673 /// assert!(arrow_options.strings_as_strings);
674 /// assert!(!arrow_options.nullable_array_default_empty);
675 /// ```
676 fn from_iter<I: IntoIterator<Item = (&'a str, bool)>>(iter: I) -> Self {
677 let mut options = ArrowOptions::default();
678 for (k, v) in iter {
679 options = options.with_setting(k, v);
680 }
681 options
682 }
683}
684
685/// Configuration options for connecting to `ClickHouse` cloud instances.
686///
687/// The `CloudOptions` struct defines settings specific to `ClickHouse` cloud
688/// deployments, used within [`ClientOptions`]. These options control the behavior
689/// of cloud wakeup pings to ensure the instance is active before connecting.
690///
691/// # Fields
692/// - `timeout`: Optional timeout (in seconds) for the cloud wakeup ping; if `None`, uses a default
693/// timeout.
694/// - `wakeup`: If `true`, sends a wakeup ping before connecting; if `false`, skips the ping.
695///
696/// # Feature
697/// Requires the `cloud` feature to be enabled.
698///
699/// # Examples
700/// ```rust,ignore
701/// use clickhouse_arrow::prelude::*;
702///
703/// let cloud_options = CloudOptions {
704/// timeout: Some(10),
705/// wakeup: true,
706/// };
707/// let options = ClientOptions {
708/// cloud: cloud_options,
709/// ..ClientOptions::default()
710/// };
711/// ```
712#[derive(Debug, Clone, Copy, Default, PartialEq)]
713#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
714pub struct CloudOptions {
715 #[cfg_attr(feature = "serde", serde(default))]
716 pub timeout: Option<u64>,
717 #[cfg_attr(feature = "serde", serde(default))]
718 pub wakeup: bool,
719}