use chrono::NaiveDateTime;
use clap::ValueEnum;
use serde_json::Value as JsonValue;
use crate::error::SqlMiddlewareDbError;
#[derive(Debug, Clone, PartialEq)]
pub enum RowValues {
Int(i64),
Float(f64),
Text(String),
Bool(bool),
Timestamp(NaiveDateTime),
Null,
JSON(JsonValue),
Blob(Vec<u8>),
}
impl RowValues {
#[must_use]
pub fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
#[must_use]
pub fn as_int(&self) -> Option<&i64> {
if let RowValues::Int(value) = self {
Some(value)
} else {
None
}
}
#[must_use]
pub fn as_text(&self) -> Option<&str> {
if let RowValues::Text(value) = self {
Some(value)
} else {
None
}
}
#[must_use]
pub fn as_bool(&self) -> Option<&bool> {
if let RowValues::Bool(value) = self {
return Some(value);
} else if let Some(i) = self.as_int() {
if *i == 1 {
return Some(&true);
} else if *i == 0 {
return Some(&false);
}
}
None
}
#[must_use]
pub fn as_timestamp(&self) -> Option<chrono::NaiveDateTime> {
if let RowValues::Timestamp(value) = self {
return Some(*value);
} else if let Some(s) = self.as_text() {
if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
return Some(dt);
}
if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S.%3f") {
return Some(dt);
}
}
None
}
#[must_use]
pub fn as_float(&self) -> Option<f64> {
if let RowValues::Float(value) = self {
Some(*value)
} else {
None
}
}
#[must_use]
pub fn as_blob(&self) -> Option<&[u8]> {
if let RowValues::Blob(bytes) = self {
Some(bytes)
} else {
None
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, ValueEnum)]
pub enum DatabaseType {
#[cfg(feature = "postgres")]
Postgres,
#[cfg(feature = "sqlite")]
Sqlite,
#[cfg(feature = "mssql")]
Mssql,
#[cfg(feature = "turso")]
Turso,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ConversionMode {
Query,
Execute,
}
pub trait ParamConverter<'a> {
type Converted;
fn convert_sql_params(
params: &'a [RowValues],
mode: ConversionMode,
) -> Result<Self::Converted, SqlMiddlewareDbError>;
#[must_use]
fn supports_mode(_mode: ConversionMode) -> bool {
true }
}