clickhouse_arrow/native/
convert.rs1use std::borrow::Cow;
2
3use crate::{Error, Result, Type, Value};
4
5pub mod raw_row;
6pub mod std_deserialize;
7pub mod std_serialize;
8pub use raw_row::*;
9pub mod unit_value;
10
11pub type ColumnDefinition<T = Value> = (String, Type, Option<T>);
13
14pub trait ToSql {
16 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value>;
18}
19
20impl ToSql for Value {
21 fn to_sql(self, _type_hint_: Option<&Type>) -> Result<Value> { Ok(self) }
22}
23
24pub fn unexpected_type(type_: &Type) -> Error {
25 Error::DeserializeError(format!("unexpected type: {type_}"))
26}
27
28pub trait FromSql: Sized {
30 fn from_sql(type_: &Type, value: Value) -> Result<Self>;
32}
33
34impl FromSql for Value {
35 fn from_sql(_type_: &Type, value: Value) -> Result<Self> { Ok(value) }
36}
37
38pub trait Row: Sized {
53 const COLUMN_COUNT: Option<usize>;
55
56 fn column_names() -> Option<Vec<Cow<'static, str>>>;
58
59 fn to_schema() -> Option<Vec<ColumnDefinition<Value>>>;
61
62 fn deserialize_row(map: Vec<(&str, &Type, Value)>) -> Result<Self>;
64
65 fn serialize_row(
67 self,
68 type_hints: &[(String, Type)],
69 ) -> Result<Vec<(Cow<'static, str>, Value)>>;
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_column_definition_alias() {
78 let col_def: ColumnDefinition = ("test".to_string(), Type::Int32, Some(Value::Int32(42)));
79 assert_eq!(col_def.0, "test");
80 assert_eq!(col_def.1, Type::Int32);
81 assert_eq!(col_def.2, Some(Value::Int32(42)));
82 }
83
84 #[test]
85 fn test_column_definition_generic() {
86 let col_def: ColumnDefinition<i32> = ("test".to_string(), Type::Int32, Some(42));
87 assert_eq!(col_def.0, "test");
88 assert_eq!(col_def.1, Type::Int32);
89 assert_eq!(col_def.2, Some(42));
90 }
91
92 #[test]
93 fn test_value_to_sql() {
94 let value = Value::Int32(42);
95 let result = value.to_sql(None).unwrap();
96 assert_eq!(result, Value::Int32(42));
97 }
98
99 #[test]
100 fn test_value_to_sql_with_hint() {
101 let value = Value::String("test".to_string().into_bytes());
102 let result = value.to_sql(Some(&Type::String)).unwrap();
103 assert_eq!(result, Value::String("test".to_string().into_bytes()));
104 }
105
106 #[test]
107 fn test_value_from_sql() {
108 let type_ = Type::Int32;
109 let value = Value::Int32(123);
110 let result = Value::from_sql(&type_, value).unwrap();
111 assert_eq!(result, Value::Int32(123));
112 }
113
114 #[test]
115 fn test_unexpected_type() {
116 let type_ = Type::Int32;
117 let error = unexpected_type(&type_);
118
119 match error {
120 Error::DeserializeError(msg) => {
121 assert!(msg.contains("unexpected type"));
122 assert!(msg.contains("Int32"));
123 }
124 _ => panic!("Expected DeserializeError"),
125 }
126 }
127
128 #[test]
129 fn test_unexpected_type_different_types() {
130 let types =
131 vec![Type::String, Type::Int64, Type::Float32, Type::Array(Box::new(Type::Int32))];
132
133 for type_ in types {
134 let error = unexpected_type(&type_);
135 assert!(matches!(error, Error::DeserializeError(_)));
136 }
137 }
138
139 #[test]
141 fn test_module_exports() {
142 let _raw_row = RawRow::default();
144
145 let _col_def: ColumnDefinition = ("test".to_string(), Type::Int32, None);
147 }
148}