use std::{os::raw::c_int, str::FromStr};
use crate::{
constants,
error::{Error, Status},
};
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum OptionValue {
String(String),
Bytes(Vec<u8>),
Int(i64),
Double(f64),
}
impl From<String> for OptionValue {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<&str> for OptionValue {
fn from(value: &str) -> Self {
Self::String(value.into())
}
}
impl From<i64> for OptionValue {
fn from(value: i64) -> Self {
Self::Int(value)
}
}
impl From<f64> for OptionValue {
fn from(value: f64) -> Self {
Self::Double(value)
}
}
impl From<Vec<u8>> for OptionValue {
fn from(value: Vec<u8>) -> Self {
Self::Bytes(value)
}
}
impl From<&[u8]> for OptionValue {
fn from(value: &[u8]) -> Self {
Self::Bytes(value.into())
}
}
impl<const N: usize> From<[u8; N]> for OptionValue {
fn from(value: [u8; N]) -> Self {
Self::Bytes(value.into())
}
}
impl<const N: usize> From<&[u8; N]> for OptionValue {
fn from(value: &[u8; N]) -> Self {
Self::Bytes(value.into())
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[non_exhaustive]
pub enum AdbcVersion {
V100,
#[default]
V110,
}
impl From<AdbcVersion> for c_int {
fn from(value: AdbcVersion) -> Self {
match value {
AdbcVersion::V100 => constants::ADBC_VERSION_1_0_0,
AdbcVersion::V110 => constants::ADBC_VERSION_1_1_0,
}
}
}
impl TryFrom<c_int> for AdbcVersion {
type Error = Error;
fn try_from(value: c_int) -> Result<Self, Self::Error> {
match value {
constants::ADBC_VERSION_1_0_0 => Ok(AdbcVersion::V100),
constants::ADBC_VERSION_1_1_0 => Ok(AdbcVersion::V110),
value => Err(Error::with_message_and_status(
format!("Unknown ADBC version: {value}"),
Status::InvalidArguments,
)),
}
}
}
impl FromStr for AdbcVersion {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"1.0.0" | "1_0_0" | "100" => Ok(AdbcVersion::V100),
"1.1.0" | "1_1_0" | "110" => Ok(AdbcVersion::V110),
value => Err(Error::with_message_and_status(
format!("Unknown ADBC version: {value}"),
Status::InvalidArguments,
)),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum InfoCode {
VendorName,
VendorVersion,
VendorArrowVersion,
VendorSql,
VendorSubstrait,
VendorSubstraitMinVersion,
VendorSubstraitMaxVersion,
DriverName,
DriverVersion,
DriverArrowVersion,
DriverAdbcVersion,
}
impl From<&InfoCode> for u32 {
fn from(value: &InfoCode) -> Self {
match value {
InfoCode::VendorName => constants::ADBC_INFO_VENDOR_NAME,
InfoCode::VendorVersion => constants::ADBC_INFO_VENDOR_VERSION,
InfoCode::VendorArrowVersion => constants::ADBC_INFO_VENDOR_ARROW_VERSION,
InfoCode::VendorSql => constants::ADBC_INFO_VENDOR_SQL,
InfoCode::VendorSubstrait => constants::ADBC_INFO_VENDOR_SUBSTRAIT,
InfoCode::VendorSubstraitMinVersion => {
constants::ADBC_INFO_VENDOR_SUBSTRAIT_MIN_VERSION
}
InfoCode::VendorSubstraitMaxVersion => {
constants::ADBC_INFO_VENDOR_SUBSTRAIT_MAX_VERSION
}
InfoCode::DriverName => constants::ADBC_INFO_DRIVER_NAME,
InfoCode::DriverVersion => constants::ADBC_INFO_DRIVER_VERSION,
InfoCode::DriverArrowVersion => constants::ADBC_INFO_DRIVER_ARROW_VERSION,
InfoCode::DriverAdbcVersion => constants::ADBC_INFO_DRIVER_ADBC_VERSION,
}
}
}
impl TryFrom<u32> for InfoCode {
type Error = Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
constants::ADBC_INFO_VENDOR_NAME => Ok(InfoCode::VendorName),
constants::ADBC_INFO_VENDOR_VERSION => Ok(InfoCode::VendorVersion),
constants::ADBC_INFO_VENDOR_ARROW_VERSION => Ok(InfoCode::VendorArrowVersion),
constants::ADBC_INFO_VENDOR_SQL => Ok(InfoCode::VendorSql),
constants::ADBC_INFO_VENDOR_SUBSTRAIT => Ok(InfoCode::VendorSubstrait),
constants::ADBC_INFO_VENDOR_SUBSTRAIT_MIN_VERSION => {
Ok(InfoCode::VendorSubstraitMinVersion)
}
constants::ADBC_INFO_VENDOR_SUBSTRAIT_MAX_VERSION => {
Ok(InfoCode::VendorSubstraitMaxVersion)
}
constants::ADBC_INFO_DRIVER_NAME => Ok(InfoCode::DriverName),
constants::ADBC_INFO_DRIVER_VERSION => Ok(InfoCode::DriverVersion),
constants::ADBC_INFO_DRIVER_ARROW_VERSION => Ok(InfoCode::DriverArrowVersion),
constants::ADBC_INFO_DRIVER_ADBC_VERSION => Ok(InfoCode::DriverAdbcVersion),
v => Err(Error::with_message_and_status(
format!("Unknown info code: {v}"),
Status::InvalidData,
)),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ObjectDepth {
All,
Catalogs,
Schemas,
Tables,
Columns,
}
impl From<ObjectDepth> for c_int {
fn from(value: ObjectDepth) -> Self {
match value {
ObjectDepth::All => constants::ADBC_OBJECT_DEPTH_ALL,
ObjectDepth::Catalogs => constants::ADBC_OBJECT_DEPTH_CATALOGS,
ObjectDepth::Schemas => constants::ADBC_OBJECT_DEPTH_DB_SCHEMAS,
ObjectDepth::Tables => constants::ADBC_OBJECT_DEPTH_TABLES,
ObjectDepth::Columns => constants::ADBC_OBJECT_DEPTH_COLUMNS,
}
}
}
impl TryFrom<c_int> for ObjectDepth {
type Error = Error;
fn try_from(value: c_int) -> Result<Self, Error> {
match value {
constants::ADBC_OBJECT_DEPTH_ALL => Ok(ObjectDepth::All),
constants::ADBC_OBJECT_DEPTH_CATALOGS => Ok(ObjectDepth::Catalogs),
constants::ADBC_OBJECT_DEPTH_DB_SCHEMAS => Ok(ObjectDepth::Schemas),
constants::ADBC_OBJECT_DEPTH_TABLES => Ok(ObjectDepth::Tables),
v => Err(Error::with_message_and_status(
format!("Unknown object depth: {v}"),
Status::InvalidData,
)),
}
}
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
#[non_exhaustive]
pub enum OptionDatabase {
Uri,
Username,
Password,
Other(String),
}
impl AsRef<str> for OptionDatabase {
fn as_ref(&self) -> &str {
match self {
Self::Uri => constants::ADBC_OPTION_URI,
Self::Username => constants::ADBC_OPTION_USERNAME,
Self::Password => constants::ADBC_OPTION_PASSWORD,
Self::Other(key) => key,
}
}
}
impl From<&str> for OptionDatabase {
fn from(value: &str) -> Self {
match value {
constants::ADBC_OPTION_URI => Self::Uri,
constants::ADBC_OPTION_USERNAME => Self::Username,
constants::ADBC_OPTION_PASSWORD => Self::Password,
key => Self::Other(key.into()),
}
}
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
#[non_exhaustive]
pub enum OptionConnection {
AutoCommit,
ReadOnly,
CurrentCatalog,
CurrentSchema,
IsolationLevel,
Other(String),
}
impl AsRef<str> for OptionConnection {
fn as_ref(&self) -> &str {
match self {
Self::AutoCommit => constants::ADBC_CONNECTION_OPTION_AUTOCOMMIT,
Self::ReadOnly => constants::ADBC_CONNECTION_OPTION_READ_ONLY,
Self::CurrentCatalog => constants::ADBC_CONNECTION_OPTION_CURRENT_CATALOG,
Self::CurrentSchema => constants::ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA,
Self::IsolationLevel => constants::ADBC_CONNECTION_OPTION_ISOLATION_LEVEL,
Self::Other(key) => key,
}
}
}
impl From<&str> for OptionConnection {
fn from(value: &str) -> Self {
match value {
constants::ADBC_CONNECTION_OPTION_AUTOCOMMIT => Self::AutoCommit,
constants::ADBC_CONNECTION_OPTION_READ_ONLY => Self::ReadOnly,
constants::ADBC_CONNECTION_OPTION_CURRENT_CATALOG => Self::CurrentCatalog,
constants::ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA => Self::CurrentSchema,
constants::ADBC_CONNECTION_OPTION_ISOLATION_LEVEL => Self::IsolationLevel,
key => Self::Other(key.into()),
}
}
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
#[non_exhaustive]
pub enum OptionStatement {
IngestMode,
TargetTable,
TargetCatalog,
TargetDbSchema,
Temporary,
Incremental,
Progress,
MaxProgress,
Other(String),
}
impl AsRef<str> for OptionStatement {
fn as_ref(&self) -> &str {
match self {
Self::IngestMode => constants::ADBC_INGEST_OPTION_MODE,
Self::TargetTable => constants::ADBC_INGEST_OPTION_TARGET_TABLE,
Self::TargetCatalog => constants::ADBC_INGEST_OPTION_TARGET_CATALOG,
Self::TargetDbSchema => constants::ADBC_INGEST_OPTION_TARGET_DB_SCHEMA,
Self::Temporary => constants::ADBC_INGEST_OPTION_TEMPORARY,
Self::Incremental => constants::ADBC_STATEMENT_OPTION_INCREMENTAL,
Self::Progress => constants::ADBC_STATEMENT_OPTION_PROGRESS,
Self::MaxProgress => constants::ADBC_STATEMENT_OPTION_MAX_PROGRESS,
Self::Other(key) => key,
}
}
}
impl From<&str> for OptionStatement {
fn from(value: &str) -> Self {
match value {
constants::ADBC_INGEST_OPTION_MODE => Self::IngestMode,
constants::ADBC_INGEST_OPTION_TARGET_TABLE => Self::TargetTable,
constants::ADBC_INGEST_OPTION_TARGET_CATALOG => Self::TargetCatalog,
constants::ADBC_INGEST_OPTION_TARGET_DB_SCHEMA => Self::TargetDbSchema,
constants::ADBC_INGEST_OPTION_TEMPORARY => Self::Temporary,
constants::ADBC_STATEMENT_OPTION_INCREMENTAL => Self::Incremental,
constants::ADBC_STATEMENT_OPTION_PROGRESS => Self::Progress,
constants::ADBC_STATEMENT_OPTION_MAX_PROGRESS => Self::MaxProgress,
key => Self::Other(key.into()),
}
}
}
#[derive(Debug)]
pub enum IsolationLevel {
Default,
ReadUncommitted,
ReadCommitted,
RepeatableRead,
Snapshot,
Serializable,
Linearizable,
}
impl From<IsolationLevel> for String {
fn from(value: IsolationLevel) -> Self {
match value {
IsolationLevel::Default => constants::ADBC_OPTION_ISOLATION_LEVEL_DEFAULT.into(),
IsolationLevel::ReadUncommitted => {
constants::ADBC_OPTION_ISOLATION_LEVEL_READ_UNCOMMITTED.into()
}
IsolationLevel::ReadCommitted => {
constants::ADBC_OPTION_ISOLATION_LEVEL_READ_COMMITTED.into()
}
IsolationLevel::RepeatableRead => {
constants::ADBC_OPTION_ISOLATION_LEVEL_REPEATABLE_READ.into()
}
IsolationLevel::Snapshot => constants::ADBC_OPTION_ISOLATION_LEVEL_SNAPSHOT.into(),
IsolationLevel::Serializable => {
constants::ADBC_OPTION_ISOLATION_LEVEL_SERIALIZABLE.into()
}
IsolationLevel::Linearizable => {
constants::ADBC_OPTION_ISOLATION_LEVEL_LINEARIZABLE.into()
}
}
}
}
impl From<IsolationLevel> for OptionValue {
fn from(value: IsolationLevel) -> Self {
Self::String(value.into())
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum IngestMode {
Create,
Append,
Replace,
CreateAppend,
}
impl From<IngestMode> for String {
fn from(value: IngestMode) -> Self {
match value {
IngestMode::Create => constants::ADBC_INGEST_OPTION_MODE_CREATE.into(),
IngestMode::Append => constants::ADBC_INGEST_OPTION_MODE_APPEND.into(),
IngestMode::Replace => constants::ADBC_INGEST_OPTION_MODE_REPLACE.into(),
IngestMode::CreateAppend => constants::ADBC_INGEST_OPTION_MODE_CREATE_APPEND.into(),
}
}
}
impl From<IngestMode> for OptionValue {
fn from(value: IngestMode) -> Self {
Self::String(value.into())
}
}
#[derive(Debug, Clone)]
pub enum Statistics {
AverageByteWidth,
DistinctCount,
MaxByteWidth,
MaxValue,
MinValue,
NullCount,
RowCount,
Other { key: i16, name: String },
}
impl TryFrom<i16> for Statistics {
type Error = Error;
fn try_from(value: i16) -> Result<Self, Self::Error> {
match value {
constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_KEY => Ok(Self::AverageByteWidth),
constants::ADBC_STATISTIC_DISTINCT_COUNT_KEY => Ok(Self::DistinctCount),
constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_KEY => Ok(Self::MaxByteWidth),
constants::ADBC_STATISTIC_MAX_VALUE_KEY => Ok(Self::MaxValue),
constants::ADBC_STATISTIC_MIN_VALUE_KEY => Ok(Self::MinValue),
constants::ADBC_STATISTIC_NULL_COUNT_KEY => Ok(Self::NullCount),
constants::ADBC_STATISTIC_ROW_COUNT_KEY => Ok(Self::RowCount),
_ => Err(Error::with_message_and_status(
format!("Unknown standard statistic key: {value}"),
Status::InvalidArguments,
)),
}
}
}
impl From<Statistics> for i16 {
fn from(value: Statistics) -> Self {
match value {
Statistics::AverageByteWidth => constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_KEY,
Statistics::DistinctCount => constants::ADBC_STATISTIC_DISTINCT_COUNT_KEY,
Statistics::MaxByteWidth => constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_KEY,
Statistics::MaxValue => constants::ADBC_STATISTIC_MAX_VALUE_KEY,
Statistics::MinValue => constants::ADBC_STATISTIC_MIN_VALUE_KEY,
Statistics::NullCount => constants::ADBC_STATISTIC_NULL_COUNT_KEY,
Statistics::RowCount => constants::ADBC_STATISTIC_ROW_COUNT_KEY,
Statistics::Other { key, name: _ } => key,
}
}
}
impl AsRef<str> for Statistics {
fn as_ref(&self) -> &str {
match self {
Statistics::AverageByteWidth => constants::ADBC_STATISTIC_AVERAGE_BYTE_WIDTH_NAME,
Statistics::DistinctCount => constants::ADBC_STATISTIC_DISTINCT_COUNT_NAME,
Statistics::MaxByteWidth => constants::ADBC_STATISTIC_MAX_BYTE_WIDTH_NAME,
Statistics::MaxValue => constants::ADBC_STATISTIC_MAX_VALUE_NAME,
Statistics::MinValue => constants::ADBC_STATISTIC_MIN_VALUE_NAME,
Statistics::NullCount => constants::ADBC_STATISTIC_NULL_COUNT_NAME,
Statistics::RowCount => constants::ADBC_STATISTIC_ROW_COUNT_NAME,
Statistics::Other { key: _, name } => name,
}
}
}
impl std::fmt::Display for Statistics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_ref())
}
}