clickhouse_arrow/native/convert/
unit_value.rs

1use std::borrow::Cow;
2
3use crate::{Error, FromSql, Result, Row, ToSql, Type, Value};
4
5/// A single column row
6#[derive(Clone, Debug, Default)]
7pub struct UnitValue<T: FromSql + ToSql>(pub T);
8
9impl<T: FromSql + ToSql> Row for UnitValue<T> {
10    const COLUMN_COUNT: Option<usize> = Some(1);
11
12    fn column_names() -> Option<Vec<Cow<'static, str>>> { None }
13
14    fn to_schema() -> Option<Vec<(String, Type, Option<Value>)>> { None }
15
16    fn deserialize_row(map: Vec<(&str, &Type, Value)>) -> Result<Self> {
17        if map.is_empty() {
18            return Err(Error::MissingField("<unit>"));
19        }
20        let item = map.into_iter().next().unwrap();
21        T::from_sql(item.1, item.2).map(UnitValue)
22    }
23
24    fn serialize_row(
25        self,
26        type_hints: &[(String, Type)],
27    ) -> Result<Vec<(Cow<'static, str>, Value)>> {
28        Ok(vec![(Cow::Borrowed("_"), self.0.to_sql(type_hints.iter().map(|(_, t)| t).next())?)])
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn test_unit_value_creation() {
38        let unit = UnitValue(42i32);
39        assert_eq!(unit.0, 42);
40    }
41
42    #[test]
43    fn test_unit_value_default() {
44        let unit: UnitValue<i32> = UnitValue::default();
45        assert_eq!(unit.0, 0);
46    }
47
48    #[test]
49    fn test_unit_value_clone_debug() {
50        let unit = UnitValue(123i64);
51        let cloned = unit.clone();
52        assert_eq!(unit.0, cloned.0);
53
54        // Test Debug implementation
55        let debug_str = format!("{unit:?}");
56        assert!(debug_str.contains("UnitValue"));
57        assert!(debug_str.contains("123"));
58    }
59
60    #[test]
61    fn test_unit_value_deserialize_success() {
62        let map = vec![("col", &Type::Int32, Value::Int32(42))];
63        let unit: UnitValue<i32> = UnitValue::deserialize_row(map).unwrap();
64        assert_eq!(unit.0, 42);
65    }
66
67    #[test]
68    fn test_unit_value_deserialize_empty() {
69        let map = vec![];
70        let result: Result<UnitValue<i32>> = UnitValue::deserialize_row(map);
71        assert!(matches!(result, Err(Error::MissingField(_))));
72    }
73
74    #[test]
75    fn test_unit_value_serialize() {
76        let unit = UnitValue(123i32);
77        let type_hints = vec![("col".to_string(), Type::Int32)];
78        let result = unit.serialize_row(&type_hints).unwrap();
79
80        assert_eq!(result.len(), 1);
81        assert_eq!(result[0].0, "_");
82        assert_eq!(result[0].1, Value::Int32(123));
83    }
84
85    #[test]
86    fn test_unit_value_serialize_no_hints() {
87        let unit = UnitValue(456i64);
88        let result = unit.serialize_row(&[]).unwrap();
89
90        assert_eq!(result.len(), 1);
91        assert_eq!(result[0].0, "_");
92        assert_eq!(result[0].1, Value::Int64(456));
93    }
94
95    #[test]
96    fn test_unit_value_static_methods() {
97        // Test Row trait static methods
98        assert_eq!(UnitValue::<i32>::COLUMN_COUNT, Some(1));
99        assert_eq!(UnitValue::<i32>::column_names(), None);
100        assert_eq!(UnitValue::<i32>::to_schema(), None);
101    }
102
103    #[test]
104    fn test_unit_value_string() {
105        let unit = UnitValue("hello".to_string());
106        let type_hints = vec![("col".to_string(), Type::String)];
107        let result = unit.serialize_row(&type_hints).unwrap();
108
109        assert_eq!(result.len(), 1);
110        assert_eq!(result[0].1, Value::String("hello".to_string().into_bytes()));
111    }
112
113    #[test]
114    fn test_unit_value_deserialize_string() {
115        let map = vec![("col", &Type::String, Value::String("test".to_string().into_bytes()))];
116        let unit: UnitValue<String> = UnitValue::deserialize_row(map).unwrap();
117        assert_eq!(unit.0, "test");
118    }
119}