Skip to main content

cqlite_core/schema/
schema_comparator.rs

1//! Comparator-type derivation and compatibility checks for [`TableSchema`].
2//!
3//! Houses the `TableSchema` methods that map columns to [`ComparatorType`]s and
4//! decide whether two comparators are compatible. Extracted from
5//! `schema/mod.rs` (issue #1134, source-split doctrine) with no behavior change.
6
7use super::{CqlType, TableSchema};
8use crate::error::{Error, Result};
9use crate::types::ComparatorType;
10use std::collections::HashMap;
11
12impl TableSchema {
13    /// Get ComparatorType for a specific column
14    pub fn get_column_comparator(&self, column_name: &str) -> Result<ComparatorType> {
15        let column = self
16            .get_column(column_name)
17            .ok_or_else(|| Error::Schema(format!("Column '{}' not found", column_name)))?;
18
19        let cql_type = CqlType::parse(&column.data_type)?;
20        ComparatorType::from_cql_type(&cql_type)
21    }
22
23    /// Get ComparatorTypes for all columns
24    pub fn get_all_comparators(&self) -> Result<HashMap<String, ComparatorType>> {
25        let mut comparators = HashMap::new();
26
27        for column in &self.columns {
28            let cql_type = CqlType::parse(&column.data_type)?;
29            let comparator = ComparatorType::from_cql_type(&cql_type)?;
30            comparators.insert(column.name.clone(), comparator);
31        }
32
33        Ok(comparators)
34    }
35
36    /// Get ComparatorTypes for partition key columns in order
37    pub fn get_partition_key_comparators(&self) -> Result<Vec<ComparatorType>> {
38        let mut comparators = Vec::new();
39        let ordered_keys = self.ordered_partition_keys();
40
41        for key_column in ordered_keys {
42            let cql_type = CqlType::parse(&key_column.data_type)?;
43            let comparator = ComparatorType::from_cql_type(&cql_type)?;
44            comparators.push(comparator);
45        }
46
47        Ok(comparators)
48    }
49
50    /// Get ComparatorTypes for clustering key columns in order
51    pub fn get_clustering_key_comparators(&self) -> Result<Vec<ComparatorType>> {
52        let mut comparators = Vec::new();
53        let ordered_keys = self.ordered_clustering_keys();
54
55        for key_column in ordered_keys {
56            let cql_type = CqlType::parse(&key_column.data_type)?;
57            let comparator = ComparatorType::from_cql_type(&cql_type)?;
58            comparators.push(comparator);
59        }
60
61        Ok(comparators)
62    }
63
64    /// Check if a column type is compatible with an expected type
65    pub fn is_column_type_compatible(
66        &self,
67        column_name: &str,
68        expected_type: &str,
69    ) -> Result<bool> {
70        let column_comparator = self.get_column_comparator(column_name)?;
71        let expected_cql_type = CqlType::parse(expected_type)?;
72        let expected_comparator = ComparatorType::from_cql_type(&expected_cql_type)?;
73
74        Ok(self.comparators_are_compatible(&column_comparator, &expected_comparator))
75    }
76
77    /// Check if two ComparatorTypes are compatible (helper method)
78    #[allow(clippy::only_used_in_recursion)]
79    fn comparators_are_compatible(&self, left: &ComparatorType, right: &ComparatorType) -> bool {
80        match (left, right) {
81            // Exact matches
82            (ComparatorType::Boolean, ComparatorType::Boolean) => true,
83            (ComparatorType::TinyInt, ComparatorType::TinyInt) => true,
84            (ComparatorType::SmallInt, ComparatorType::SmallInt) => true,
85            (ComparatorType::Int, ComparatorType::Int) => true,
86            (ComparatorType::BigInt, ComparatorType::BigInt) => true,
87            (ComparatorType::Float32, ComparatorType::Float32) => true,
88            (ComparatorType::Float, ComparatorType::Float) => true,
89            (ComparatorType::Text, ComparatorType::Text) => true,
90            (ComparatorType::Blob, ComparatorType::Blob) => true,
91            (ComparatorType::Timestamp, ComparatorType::Timestamp) => true,
92            (ComparatorType::Uuid, ComparatorType::Uuid) => true,
93            (ComparatorType::Json, ComparatorType::Json) => true,
94
95            // Collection types
96            (ComparatorType::List(l_elem), ComparatorType::List(r_elem)) => {
97                self.comparators_are_compatible(l_elem, r_elem)
98            }
99            (ComparatorType::Set(l_elem), ComparatorType::Set(r_elem)) => {
100                self.comparators_are_compatible(l_elem, r_elem)
101            }
102            (ComparatorType::Map(l_key, l_val), ComparatorType::Map(r_key, r_val)) => {
103                self.comparators_are_compatible(l_key, r_key)
104                    && self.comparators_are_compatible(l_val, r_val)
105            }
106
107            // Tuple types
108            (ComparatorType::Tuple(l_fields), ComparatorType::Tuple(r_fields)) => {
109                l_fields.len() == r_fields.len()
110                    && l_fields
111                        .iter()
112                        .zip(r_fields.iter())
113                        .all(|(l, r)| self.comparators_are_compatible(l, r))
114            }
115
116            // UDT types
117            (
118                ComparatorType::Udt {
119                    type_name: l_name,
120                    keyspace: l_ks,
121                    ..
122                },
123                ComparatorType::Udt {
124                    type_name: r_name,
125                    keyspace: r_ks,
126                    ..
127                },
128            ) => l_name == r_name && l_ks == r_ks,
129
130            // Frozen types
131            (ComparatorType::Frozen(l_inner), ComparatorType::Frozen(r_inner)) => {
132                self.comparators_are_compatible(l_inner, r_inner)
133            }
134
135            // Custom types
136            (ComparatorType::Custom(l_name), ComparatorType::Custom(r_name)) => l_name == r_name,
137
138            // No other combinations are compatible
139            _ => false,
140        }
141    }
142}