use serde::{Deserialize, Serialize};
use super::MappingType;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FlussoType {
Text,
Identifier,
Keyword,
Enum,
Uuid,
Boolean,
Short,
Integer,
Long,
Float,
Double,
Decimal,
Date,
Timestamp,
Binary,
Json,
Map { values: Box<FlussoType> },
GeoPoint,
Custom {
postgres: Vec<String>,
opensearch: String,
},
}
impl FlussoType {
pub fn opensearch(&self) -> MappingType {
match self {
FlussoType::Text | FlussoType::Identifier => MappingType::Text,
FlussoType::Keyword | FlussoType::Enum | FlussoType::Uuid => MappingType::Keyword,
FlussoType::Boolean => MappingType::Boolean,
FlussoType::Short => MappingType::Short,
FlussoType::Integer => MappingType::Integer,
FlussoType::Long => MappingType::Long,
FlussoType::Float => MappingType::Float,
FlussoType::Double | FlussoType::Decimal => MappingType::Double,
FlussoType::Date | FlussoType::Timestamp => MappingType::Date,
FlussoType::Binary => MappingType::Other("binary".to_owned()),
FlussoType::Json | FlussoType::Map { .. } => MappingType::Object,
FlussoType::GeoPoint => MappingType::Other("geo_point".to_owned()),
FlussoType::Custom { opensearch, .. } => MappingType::from_name(opensearch),
}
}
pub fn accepts_pg(&self, sql_type: &str) -> bool {
let base = normalize_pg_type(sql_type);
match self {
FlussoType::Text | FlussoType::Identifier | FlussoType::Keyword | FlussoType::Enum => {
matches!(
base.as_str(),
"text"
| "character varying"
| "varchar"
| "character"
| "char"
| "bpchar"
| "citext"
| "name"
)
}
FlussoType::Uuid => base == "uuid",
FlussoType::Boolean => matches!(base.as_str(), "boolean" | "bool"),
FlussoType::Short => matches!(base.as_str(), "smallint" | "int2" | "smallserial"),
FlussoType::Integer => matches!(base.as_str(), "integer" | "int" | "int4" | "serial"),
FlussoType::Long => matches!(base.as_str(), "bigint" | "int8" | "bigserial"),
FlussoType::Float => matches!(base.as_str(), "real" | "float4"),
FlussoType::Double => matches!(base.as_str(), "double precision" | "float8"),
FlussoType::Decimal => matches!(base.as_str(), "numeric" | "decimal" | "money"),
FlussoType::Date => base == "date",
FlussoType::Timestamp => matches!(
base.as_str(),
"timestamp with time zone"
| "timestamp without time zone"
| "timestamp"
| "timestamptz"
| "time with time zone"
| "time without time zone"
| "time"
| "timetz"
),
FlussoType::Binary => base == "bytea",
FlussoType::Json | FlussoType::Map { .. } => {
matches!(base.as_str(), "json" | "jsonb")
}
FlussoType::GeoPoint => matches!(
base.as_str(),
"json"
| "jsonb"
| "text"
| "character varying"
| "varchar"
| "character"
| "char"
| "bpchar"
| "citext"
| "name"
),
FlussoType::Custom { postgres, .. } => {
postgres.iter().any(|t| normalize_pg_type(t) == base)
}
}
}
}
fn normalize_pg_type(sql_type: &str) -> String {
let base = sql_type.trim().trim_end_matches("[]").trim();
let base = base.split('(').next().unwrap_or(base).trim();
base.to_ascii_lowercase()
}
#[cfg(test)]
mod tests;