1use std::{os::raw::c_int, str::FromStr};
20
21use crate::constants::{ADBC_OPTION_VALUE_DISABLED, ADBC_OPTION_VALUE_ENABLED};
22use crate::{
23 constants,
24 error::{Error, Status},
25};
26
27#[derive(Debug, Clone)]
38#[non_exhaustive]
39pub enum OptionValue {
40 String(String),
41 Bytes(Vec<u8>),
42 Int(i64),
43 Double(f64),
44}
45
46impl From<String> for OptionValue {
47 fn from(value: String) -> Self {
48 Self::String(value)
49 }
50}
51
52impl From<&str> for OptionValue {
53 fn from(value: &str) -> Self {
54 Self::String(value.into())
55 }
56}
57
58impl From<i64> for OptionValue {
59 fn from(value: i64) -> Self {
60 Self::Int(value)
61 }
62}
63
64impl From<f64> for OptionValue {
65 fn from(value: f64) -> Self {
66 Self::Double(value)
67 }
68}
69
70impl From<Vec<u8>> for OptionValue {
71 fn from(value: Vec<u8>) -> Self {
72 Self::Bytes(value)
73 }
74}
75
76impl From<&[u8]> for OptionValue {
77 fn from(value: &[u8]) -> Self {
78 Self::Bytes(value.into())
79 }
80}
81
82impl<const N: usize> From<[u8; N]> for OptionValue {
83 fn from(value: [u8; N]) -> Self {
84 Self::Bytes(value.into())
85 }
86}
87
88impl<const N: usize> From<&[u8; N]> for OptionValue {
89 fn from(value: &[u8; N]) -> Self {
90 Self::Bytes(value.into())
91 }
92}
93
94impl From<bool> for OptionValue {
95 fn from(value: bool) -> Self {
100 if value {
101 ADBC_OPTION_VALUE_ENABLED.into()
102 } else {
103 ADBC_OPTION_VALUE_DISABLED.into()
104 }
105 }
106}
107
108impl TryFrom<OptionValue> for bool {
109 type Error = Error;
110
111 fn try_from(value: OptionValue) -> Result<Self, Self::Error> {
116 <bool as TryFrom<&OptionValue>>::try_from(&value)
118 }
119}
120
121impl TryFrom<&OptionValue> for bool {
122 type Error = Error;
123
124 fn try_from(value: &OptionValue) -> Result<Self, Self::Error> {
129 match value {
130 OptionValue::String(value) if value == ADBC_OPTION_VALUE_ENABLED => Ok(true),
131 OptionValue::String(value) if value == ADBC_OPTION_VALUE_DISABLED => Ok(false),
132 _ => Err(Error::with_message_and_status(
133 format!(
134 "expected {ADBC_OPTION_VALUE_ENABLED:?} or {ADBC_OPTION_VALUE_DISABLED:?}, \
135 got {value:?}"
136 ),
137 Status::InvalidArguments,
138 )),
139 }
140 }
141}
142
143#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
147#[non_exhaustive]
148pub enum AdbcVersion {
149 V100,
151 #[default]
155 V110,
156}
157
158impl From<AdbcVersion> for c_int {
159 fn from(value: AdbcVersion) -> Self {
160 match value {
161 AdbcVersion::V100 => constants::ADBC_VERSION_1_0_0,
162 AdbcVersion::V110 => constants::ADBC_VERSION_1_1_0,
163 }
164 }
165}
166
167impl TryFrom<c_int> for AdbcVersion {
168 type Error = Error;
169 fn try_from(value: c_int) -> Result<Self, Self::Error> {
170 match value {
171 constants::ADBC_VERSION_1_0_0 => Ok(AdbcVersion::V100),
172 constants::ADBC_VERSION_1_1_0 => Ok(AdbcVersion::V110),
173 value => Err(Error::with_message_and_status(
174 format!("Unknown ADBC version: {value}"),
175 Status::InvalidArguments,
176 )),
177 }
178 }
179}
180
181impl FromStr for AdbcVersion {
182 type Err = Error;
183
184 fn from_str(s: &str) -> Result<Self, Self::Err> {
185 match s {
186 "1.0.0" | "1_0_0" | "100" => Ok(AdbcVersion::V100),
187 "1.1.0" | "1_1_0" | "110" => Ok(AdbcVersion::V110),
188 value => Err(Error::with_message_and_status(
189 format!("Unknown ADBC version: {value}"),
190 Status::InvalidArguments,
191 )),
192 }
193 }
194}
195
196#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
198#[non_exhaustive]
199pub enum InfoCode {
200 VendorName,
202 VendorVersion,
204 VendorArrowVersion,
206 VendorSql,
208 VendorSubstrait,
210 VendorSubstraitMinVersion,
212 VendorSubstraitMaxVersion,
214 DriverName,
216 DriverVersion,
218 DriverArrowVersion,
220 DriverAdbcVersion,
226 Other(u32),
239}
240
241impl From<&InfoCode> for u32 {
242 fn from(value: &InfoCode) -> Self {
243 match value {
244 InfoCode::VendorName => constants::ADBC_INFO_VENDOR_NAME,
245 InfoCode::VendorVersion => constants::ADBC_INFO_VENDOR_VERSION,
246 InfoCode::VendorArrowVersion => constants::ADBC_INFO_VENDOR_ARROW_VERSION,
247 InfoCode::VendorSql => constants::ADBC_INFO_VENDOR_SQL,
248 InfoCode::VendorSubstrait => constants::ADBC_INFO_VENDOR_SUBSTRAIT,
249 InfoCode::VendorSubstraitMinVersion => {
250 constants::ADBC_INFO_VENDOR_SUBSTRAIT_MIN_VERSION
251 }
252 InfoCode::VendorSubstraitMaxVersion => {
253 constants::ADBC_INFO_VENDOR_SUBSTRAIT_MAX_VERSION
254 }
255 InfoCode::DriverName => constants::ADBC_INFO_DRIVER_NAME,
256 InfoCode::DriverVersion => constants::ADBC_INFO_DRIVER_VERSION,
257 InfoCode::DriverArrowVersion => constants::ADBC_INFO_DRIVER_ARROW_VERSION,
258 InfoCode::DriverAdbcVersion => constants::ADBC_INFO_DRIVER_ADBC_VERSION,
259 InfoCode::Other(v) => *v,
260 }
261 }
262}
263
264impl From<u32> for InfoCode {
265 fn from(value: u32) -> Self {
266 match value {
267 constants::ADBC_INFO_VENDOR_NAME => InfoCode::VendorName,
268 constants::ADBC_INFO_VENDOR_VERSION => InfoCode::VendorVersion,
269 constants::ADBC_INFO_VENDOR_ARROW_VERSION => InfoCode::VendorArrowVersion,
270 constants::ADBC_INFO_VENDOR_SQL => InfoCode::VendorSql,
271 constants::ADBC_INFO_VENDOR_SUBSTRAIT => InfoCode::VendorSubstrait,
272 constants::ADBC_INFO_VENDOR_SUBSTRAIT_MIN_VERSION => {
273 InfoCode::VendorSubstraitMinVersion
274 }
275 constants::ADBC_INFO_VENDOR_SUBSTRAIT_MAX_VERSION => {
276 InfoCode::VendorSubstraitMaxVersion
277 }
278 constants::ADBC_INFO_DRIVER_NAME => InfoCode::DriverName,
279 constants::ADBC_INFO_DRIVER_VERSION => InfoCode::DriverVersion,
280 constants::ADBC_INFO_DRIVER_ARROW_VERSION => InfoCode::DriverArrowVersion,
281 constants::ADBC_INFO_DRIVER_ADBC_VERSION => InfoCode::DriverAdbcVersion,
282 v => InfoCode::Other(v),
283 }
284 }
285}
286
287#[derive(Debug, Clone, Copy, Eq, PartialEq)]
289pub enum ObjectDepth {
290 All,
292 Catalogs,
294 Schemas,
296 Tables,
298 Columns,
300}
301
302impl From<ObjectDepth> for c_int {
303 fn from(value: ObjectDepth) -> Self {
304 match value {
305 ObjectDepth::All => constants::ADBC_OBJECT_DEPTH_ALL,
306 ObjectDepth::Catalogs => constants::ADBC_OBJECT_DEPTH_CATALOGS,
307 ObjectDepth::Schemas => constants::ADBC_OBJECT_DEPTH_DB_SCHEMAS,
308 ObjectDepth::Tables => constants::ADBC_OBJECT_DEPTH_TABLES,
309 ObjectDepth::Columns => constants::ADBC_OBJECT_DEPTH_COLUMNS,
310 }
311 }
312}
313
314impl TryFrom<c_int> for ObjectDepth {
315 type Error = Error;
316
317 fn try_from(value: c_int) -> Result<Self, Error> {
318 match value {
319 constants::ADBC_OBJECT_DEPTH_ALL => Ok(ObjectDepth::All),
320 constants::ADBC_OBJECT_DEPTH_CATALOGS => Ok(ObjectDepth::Catalogs),
321 constants::ADBC_OBJECT_DEPTH_DB_SCHEMAS => Ok(ObjectDepth::Schemas),
322 constants::ADBC_OBJECT_DEPTH_TABLES => Ok(ObjectDepth::Tables),
323 v => Err(Error::with_message_and_status(
324 format!("Unknown object depth: {v}"),
325 Status::InvalidData,
326 )),
327 }
328 }
329}
330
331#[derive(PartialEq, Eq, Hash, Debug, Clone)]
333#[non_exhaustive]
334pub enum OptionDatabase {
335 Uri,
341 Username,
347 Password,
353 Other(String),
355}
356
357impl AsRef<str> for OptionDatabase {
358 fn as_ref(&self) -> &str {
359 match self {
360 Self::Uri => constants::ADBC_OPTION_URI,
361 Self::Username => constants::ADBC_OPTION_USERNAME,
362 Self::Password => constants::ADBC_OPTION_PASSWORD,
363 Self::Other(key) => key,
364 }
365 }
366}
367
368impl From<&str> for OptionDatabase {
369 fn from(value: &str) -> Self {
370 match value {
371 constants::ADBC_OPTION_URI => Self::Uri,
372 constants::ADBC_OPTION_USERNAME => Self::Username,
373 constants::ADBC_OPTION_PASSWORD => Self::Password,
374 key => Self::Other(key.into()),
375 }
376 }
377}
378
379#[derive(PartialEq, Eq, Hash, Debug, Clone)]
381#[non_exhaustive]
382pub enum OptionConnection {
383 AutoCommit,
385 ReadOnly,
387 CurrentCatalog,
391 CurrentSchema,
395 IsolationLevel,
397 Other(String),
399}
400
401impl AsRef<str> for OptionConnection {
402 fn as_ref(&self) -> &str {
403 match self {
404 Self::AutoCommit => constants::ADBC_CONNECTION_OPTION_AUTOCOMMIT,
405 Self::ReadOnly => constants::ADBC_CONNECTION_OPTION_READ_ONLY,
406 Self::CurrentCatalog => constants::ADBC_CONNECTION_OPTION_CURRENT_CATALOG,
407 Self::CurrentSchema => constants::ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA,
408 Self::IsolationLevel => constants::ADBC_CONNECTION_OPTION_ISOLATION_LEVEL,
409 Self::Other(key) => key,
410 }
411 }
412}
413
414impl From<&str> for OptionConnection {
415 fn from(value: &str) -> Self {
416 match value {
417 constants::ADBC_CONNECTION_OPTION_AUTOCOMMIT => Self::AutoCommit,
418 constants::ADBC_CONNECTION_OPTION_READ_ONLY => Self::ReadOnly,
419 constants::ADBC_CONNECTION_OPTION_CURRENT_CATALOG => Self::CurrentCatalog,
420 constants::ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA => Self::CurrentSchema,
421 constants::ADBC_CONNECTION_OPTION_ISOLATION_LEVEL => Self::IsolationLevel,
422 key => Self::Other(key.into()),
423 }
424 }
425}
426
427#[derive(PartialEq, Eq, Hash, Debug, Clone)]
429#[non_exhaustive]
430pub enum OptionStatement {
431 IngestMode,
433 TargetTable,
435 TargetCatalog,
437 TargetDbSchema,
439 Temporary,
441 Incremental,
454 Progress,
468 MaxProgress,
480 Other(String),
482}
483
484impl AsRef<str> for OptionStatement {
485 fn as_ref(&self) -> &str {
486 match self {
487 Self::IngestMode => constants::ADBC_INGEST_OPTION_MODE,
488 Self::TargetTable => constants::ADBC_INGEST_OPTION_TARGET_TABLE,
489 Self::TargetCatalog => constants::ADBC_INGEST_OPTION_TARGET_CATALOG,
490 Self::TargetDbSchema => constants::ADBC_INGEST_OPTION_TARGET_DB_SCHEMA,
491 Self::Temporary => constants::ADBC_INGEST_OPTION_TEMPORARY,
492 Self::Incremental => constants::ADBC_STATEMENT_OPTION_INCREMENTAL,
493 Self::Progress => constants::ADBC_STATEMENT_OPTION_PROGRESS,
494 Self::MaxProgress => constants::ADBC_STATEMENT_OPTION_MAX_PROGRESS,
495 Self::Other(key) => key,
496 }
497 }
498}
499
500impl From<&str> for OptionStatement {
501 fn from(value: &str) -> Self {
502 match value {
503 constants::ADBC_INGEST_OPTION_MODE => Self::IngestMode,
504 constants::ADBC_INGEST_OPTION_TARGET_TABLE => Self::TargetTable,
505 constants::ADBC_INGEST_OPTION_TARGET_CATALOG => Self::TargetCatalog,
506 constants::ADBC_INGEST_OPTION_TARGET_DB_SCHEMA => Self::TargetDbSchema,
507 constants::ADBC_INGEST_OPTION_TEMPORARY => Self::Temporary,
508 constants::ADBC_STATEMENT_OPTION_INCREMENTAL => Self::Incremental,
509 constants::ADBC_STATEMENT_OPTION_PROGRESS => Self::Progress,
510 constants::ADBC_STATEMENT_OPTION_MAX_PROGRESS => Self::MaxProgress,
511 key => Self::Other(key.into()),
512 }
513 }
514}
515
516#[derive(Debug)]
518pub enum IsolationLevel {
519 Default,
521 ReadUncommitted,
524 ReadCommitted,
535 RepeatableRead,
541 Snapshot,
546 Serializable,
550 Linearizable,
559}
560
561impl From<IsolationLevel> for String {
562 fn from(value: IsolationLevel) -> Self {
563 match value {
564 IsolationLevel::Default => constants::ADBC_OPTION_ISOLATION_LEVEL_DEFAULT.into(),
565 IsolationLevel::ReadUncommitted => {
566 constants::ADBC_OPTION_ISOLATION_LEVEL_READ_UNCOMMITTED.into()
567 }
568 IsolationLevel::ReadCommitted => {
569 constants::ADBC_OPTION_ISOLATION_LEVEL_READ_COMMITTED.into()
570 }
571 IsolationLevel::RepeatableRead => {
572 constants::ADBC_OPTION_ISOLATION_LEVEL_REPEATABLE_READ.into()
573 }
574 IsolationLevel::Snapshot => constants::ADBC_OPTION_ISOLATION_LEVEL_SNAPSHOT.into(),
575 IsolationLevel::Serializable => {
576 constants::ADBC_OPTION_ISOLATION_LEVEL_SERIALIZABLE.into()
577 }
578 IsolationLevel::Linearizable => {
579 constants::ADBC_OPTION_ISOLATION_LEVEL_LINEARIZABLE.into()
580 }
581 }
582 }
583}
584
585impl From<IsolationLevel> for OptionValue {
586 fn from(value: IsolationLevel) -> Self {
587 Self::String(value.into())
588 }
589}
590
591#[derive(Debug, Clone, Copy, Eq, PartialEq)]
593pub enum IngestMode {
594 Create,
596 Append,
600 Replace,
607 CreateAppend,
615}
616
617impl From<IngestMode> for String {
618 fn from(value: IngestMode) -> Self {
619 match value {
620 IngestMode::Create => constants::ADBC_INGEST_OPTION_MODE_CREATE.into(),
621 IngestMode::Append => constants::ADBC_INGEST_OPTION_MODE_APPEND.into(),
622 IngestMode::Replace => constants::ADBC_INGEST_OPTION_MODE_REPLACE.into(),
623 IngestMode::CreateAppend => constants::ADBC_INGEST_OPTION_MODE_CREATE_APPEND.into(),
624 }
625 }
626}
627impl From<IngestMode> for OptionValue {
628 fn from(value: IngestMode) -> Self {
629 Self::String(value.into())
630 }
631}
632
633impl FromStr for IngestMode {
634 type Err = Error;
635
636 fn from_str(s: &str) -> Result<Self, Self::Err> {
637 match s {
638 constants::ADBC_INGEST_OPTION_MODE_CREATE => Ok(Self::Create),
639 constants::ADBC_INGEST_OPTION_MODE_APPEND => Ok(Self::Append),
640 constants::ADBC_INGEST_OPTION_MODE_REPLACE => Ok(Self::Replace),
641 constants::ADBC_INGEST_OPTION_MODE_CREATE_APPEND => Ok(Self::CreateAppend),
642 other => Err(Error::with_message_and_status(
643 format!(
644 "invalid value for option {:?}: {other:?}",
645 constants::ADBC_INGEST_OPTION_MODE
646 ),
647 Status::InvalidArguments,
648 )),
649 }
650 }
651}
652
653impl TryFrom<&OptionValue> for IngestMode {
654 type Error = Error;
655
656 fn try_from(value: &OptionValue) -> Result<Self, Self::Error> {
657 match value {
658 OptionValue::String(s) => s.parse(),
659 other => Err(Error::with_message_and_status(
660 format!(
661 "invalid value type for option {:?}: {other:?}",
662 constants::ADBC_INGEST_OPTION_MODE
663 ),
664 Status::InvalidArguments,
665 )),
666 }
667 }
668}
669
670#[derive(Debug, Clone)]
672pub enum Statistics {
673 AverageByteWidth,
677 DistinctCount,
681 MaxByteWidth,
685 MaxValue,
687 MinValue,
689 NullCount,
692 RowCount,
695 Other { key: i16, name: String },
697}
698
699impl TryFrom<i16> for Statistics {
700 type Error = Error;
701 fn try_from(value: i16) -> Result<Self, Self::Error> {
702 match value {
703 constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_KEY => Ok(Self::AverageByteWidth),
704 constants::ADBC_STATISTIC_DISTINCT_COUNT_KEY => Ok(Self::DistinctCount),
705 constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_KEY => Ok(Self::MaxByteWidth),
706 constants::ADBC_STATISTIC_MAX_VALUE_KEY => Ok(Self::MaxValue),
707 constants::ADBC_STATISTIC_MIN_VALUE_KEY => Ok(Self::MinValue),
708 constants::ADBC_STATISTIC_NULL_COUNT_KEY => Ok(Self::NullCount),
709 constants::ADBC_STATISTIC_ROW_COUNT_KEY => Ok(Self::RowCount),
710 _ => Err(Error::with_message_and_status(
711 format!("Unknown standard statistic key: {value}"),
712 Status::InvalidArguments,
713 )),
714 }
715 }
716}
717
718impl From<Statistics> for i16 {
719 fn from(value: Statistics) -> Self {
720 match value {
721 Statistics::AverageByteWidth => constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_KEY,
722 Statistics::DistinctCount => constants::ADBC_STATISTIC_DISTINCT_COUNT_KEY,
723 Statistics::MaxByteWidth => constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_KEY,
724 Statistics::MaxValue => constants::ADBC_STATISTIC_MAX_VALUE_KEY,
725 Statistics::MinValue => constants::ADBC_STATISTIC_MIN_VALUE_KEY,
726 Statistics::NullCount => constants::ADBC_STATISTIC_NULL_COUNT_KEY,
727 Statistics::RowCount => constants::ADBC_STATISTIC_ROW_COUNT_KEY,
728 Statistics::Other { key, name: _ } => key,
729 }
730 }
731}
732
733impl AsRef<str> for Statistics {
734 fn as_ref(&self) -> &str {
735 match self {
736 Statistics::AverageByteWidth => constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_NAME,
737 Statistics::DistinctCount => constants::ADBC_STATISTIC_DISTINCT_COUNT_NAME,
738 Statistics::MaxByteWidth => constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_NAME,
739 Statistics::MaxValue => constants::ADBC_STATISTIC_MAX_VALUE_NAME,
740 Statistics::MinValue => constants::ADBC_STATISTIC_MIN_VALUE_NAME,
741 Statistics::NullCount => constants::ADBC_STATISTIC_NULL_COUNT_NAME,
742 Statistics::RowCount => constants::ADBC_STATISTIC_ROW_COUNT_NAME,
743 Statistics::Other { key: _, name } => name,
744 }
745 }
746}
747
748impl std::fmt::Display for Statistics {
749 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
750 write!(f, "{}", self.as_ref())
751 }
752}
753
754#[cfg(test)]
755mod tests {
756 use super::*;
757
758 #[test]
759 fn info_code_u32_roundtrip() {
760 for code in (0..20_000_u32).chain([u32::MAX]) {
761 assert_eq!(u32::from(&InfoCode::from(code)), code);
762 }
763 assert_eq!(
764 InfoCode::from(constants::ADBC_INFO_VENDOR_NAME),
765 InfoCode::VendorName
766 );
767 assert_eq!(InfoCode::from(10_042), InfoCode::Other(10_042));
768 }
769}