use super::{CqlType, TableSchema};
use crate::error::{Error, Result};
use crate::types::ComparatorType;
use std::collections::HashMap;
impl TableSchema {
pub fn get_column_comparator(&self, column_name: &str) -> Result<ComparatorType> {
let column = self
.get_column(column_name)
.ok_or_else(|| Error::Schema(format!("Column '{}' not found", column_name)))?;
let cql_type = CqlType::parse(&column.data_type)?;
ComparatorType::from_cql_type(&cql_type)
}
pub fn get_all_comparators(&self) -> Result<HashMap<String, ComparatorType>> {
let mut comparators = HashMap::new();
for column in &self.columns {
let cql_type = CqlType::parse(&column.data_type)?;
let comparator = ComparatorType::from_cql_type(&cql_type)?;
comparators.insert(column.name.clone(), comparator);
}
Ok(comparators)
}
pub fn get_partition_key_comparators(&self) -> Result<Vec<ComparatorType>> {
let mut comparators = Vec::new();
let ordered_keys = self.ordered_partition_keys();
for key_column in ordered_keys {
let cql_type = CqlType::parse(&key_column.data_type)?;
let comparator = ComparatorType::from_cql_type(&cql_type)?;
comparators.push(comparator);
}
Ok(comparators)
}
pub fn get_clustering_key_comparators(&self) -> Result<Vec<ComparatorType>> {
let mut comparators = Vec::new();
let ordered_keys = self.ordered_clustering_keys();
for key_column in ordered_keys {
let cql_type = CqlType::parse(&key_column.data_type)?;
let comparator = ComparatorType::from_cql_type(&cql_type)?;
comparators.push(comparator);
}
Ok(comparators)
}
pub fn is_column_type_compatible(
&self,
column_name: &str,
expected_type: &str,
) -> Result<bool> {
let column_comparator = self.get_column_comparator(column_name)?;
let expected_cql_type = CqlType::parse(expected_type)?;
let expected_comparator = ComparatorType::from_cql_type(&expected_cql_type)?;
Ok(self.comparators_are_compatible(&column_comparator, &expected_comparator))
}
#[allow(clippy::only_used_in_recursion)]
fn comparators_are_compatible(&self, left: &ComparatorType, right: &ComparatorType) -> bool {
match (left, right) {
(ComparatorType::Boolean, ComparatorType::Boolean) => true,
(ComparatorType::TinyInt, ComparatorType::TinyInt) => true,
(ComparatorType::SmallInt, ComparatorType::SmallInt) => true,
(ComparatorType::Int, ComparatorType::Int) => true,
(ComparatorType::BigInt, ComparatorType::BigInt) => true,
(ComparatorType::Float32, ComparatorType::Float32) => true,
(ComparatorType::Float, ComparatorType::Float) => true,
(ComparatorType::Text, ComparatorType::Text) => true,
(ComparatorType::Blob, ComparatorType::Blob) => true,
(ComparatorType::Timestamp, ComparatorType::Timestamp) => true,
(ComparatorType::Uuid, ComparatorType::Uuid) => true,
(ComparatorType::Json, ComparatorType::Json) => true,
(ComparatorType::List(l_elem), ComparatorType::List(r_elem)) => {
self.comparators_are_compatible(l_elem, r_elem)
}
(ComparatorType::Set(l_elem), ComparatorType::Set(r_elem)) => {
self.comparators_are_compatible(l_elem, r_elem)
}
(ComparatorType::Map(l_key, l_val), ComparatorType::Map(r_key, r_val)) => {
self.comparators_are_compatible(l_key, r_key)
&& self.comparators_are_compatible(l_val, r_val)
}
(ComparatorType::Tuple(l_fields), ComparatorType::Tuple(r_fields)) => {
l_fields.len() == r_fields.len()
&& l_fields
.iter()
.zip(r_fields.iter())
.all(|(l, r)| self.comparators_are_compatible(l, r))
}
(
ComparatorType::Udt {
type_name: l_name,
keyspace: l_ks,
..
},
ComparatorType::Udt {
type_name: r_name,
keyspace: r_ks,
..
},
) => l_name == r_name && l_ks == r_ks,
(ComparatorType::Frozen(l_inner), ComparatorType::Frozen(r_inner)) => {
self.comparators_are_compatible(l_inner, r_inner)
}
(ComparatorType::Custom(l_name), ComparatorType::Custom(r_name)) => l_name == r_name,
_ => false,
}
}
}