1use reifydb_type::value::constraint::{Constraint, TypeConstraint};
5
6use crate::{
7 encoded::schema::{Schema, SchemaField},
8 interface::catalog::{column::ColumnDef, subscription::SubscriptionColumnDef},
9};
10
11impl From<&Vec<ColumnDef>> for Schema {
12 fn from(value: &Vec<ColumnDef>) -> Self {
13 Schema::from(value.as_slice())
14 }
15}
16impl From<&[ColumnDef]> for Schema {
17 fn from(value: &[ColumnDef]) -> Self {
18 let fields = value
19 .iter()
20 .map(|col| {
21 let constraint = match col.constraint.constraint() {
25 Some(Constraint::Dictionary(dict_id, id_type)) => {
26 TypeConstraint::dictionary(*dict_id, id_type.clone())
27 }
28 _ => col.constraint.clone(),
29 };
30 SchemaField::new(col.name.clone(), constraint)
31 })
32 .collect();
33 Schema::new(fields)
34 }
35}
36
37impl From<&Vec<SubscriptionColumnDef>> for Schema {
38 fn from(value: &Vec<SubscriptionColumnDef>) -> Self {
39 Schema::from(value.as_slice())
40 }
41}
42impl From<&[SubscriptionColumnDef]> for Schema {
43 fn from(value: &[SubscriptionColumnDef]) -> Self {
44 let fields = value
45 .iter()
46 .map(|col| SchemaField::new(col.name.clone(), TypeConstraint::unconstrained(col.ty.clone())))
47 .collect();
48 Schema::new(fields)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 mod from_schema {
55 }
58
59 mod from_column_def {
60 use reifydb_type::value::{constraint::TypeConstraint, r#type::Type};
61
62 use crate::{
63 encoded::schema::{Schema, SchemaField},
64 interface::catalog::{
65 column::{ColumnDef, ColumnIndex},
66 id::ColumnId,
67 },
68 };
69
70 fn make_column_def(id: u64, name: &str, ty: Type, index: u8) -> ColumnDef {
71 ColumnDef {
72 id: ColumnId(id),
73 name: name.to_string(),
74 constraint: TypeConstraint::unconstrained(ty),
75 properties: vec![],
76 index: ColumnIndex(index),
77 auto_increment: false,
78 dictionary_id: None,
79 }
80 }
81
82 #[test]
83 fn test_from_column_def_single_field() {
84 let columns = vec![make_column_def(1, "id", Type::Int8, 0)];
85
86 let schema = Schema::from(columns.as_slice());
87
88 assert_eq!(schema.fields().len(), 1);
89 assert_eq!(schema.fields()[0].name, "id");
90 assert_eq!(schema.fields()[0].constraint.get_type(), Type::Int8);
91 }
92
93 #[test]
94 fn test_from_column_def_multiple_fields() {
95 let columns = vec![
96 make_column_def(1, "a", Type::Int1, 0),
97 make_column_def(2, "b", Type::Int2, 1),
98 make_column_def(3, "c", Type::Int4, 2),
99 ];
100
101 let schema = Schema::from(columns.as_slice());
102
103 assert_eq!(schema.fields().len(), 3);
104 assert_eq!(schema.fields()[0].name, "a");
105 assert_eq!(schema.fields()[0].constraint.get_type(), Type::Int1);
106 assert_eq!(schema.fields()[1].name, "b");
107 assert_eq!(schema.fields()[1].constraint.get_type(), Type::Int2);
108 assert_eq!(schema.fields()[2].name, "c");
109 assert_eq!(schema.fields()[2].constraint.get_type(), Type::Int4);
110 }
111
112 #[test]
113 fn test_from_column_def_preserves_field_order() {
114 let columns = vec![
115 make_column_def(1, "first", Type::Utf8, 0),
116 make_column_def(2, "second", Type::Int4, 1),
117 make_column_def(3, "third", Type::Boolean, 2),
118 ];
119
120 let schema = Schema::from(columns.as_slice());
121
122 assert_eq!(schema.fields()[0].name, "first");
123 assert_eq!(schema.fields()[0].constraint.get_type(), Type::Utf8);
124 assert_eq!(schema.fields()[1].name, "second");
125 assert_eq!(schema.fields()[1].constraint.get_type(), Type::Int4);
126 assert_eq!(schema.fields()[2].name, "third");
127 assert_eq!(schema.fields()[2].constraint.get_type(), Type::Boolean);
128 }
129
130 #[test]
131 fn test_from_column_def_equivalence_with_direct_construction() {
132 let columns = vec![
133 make_column_def(1, "f0", Type::Uint1, 0),
134 make_column_def(2, "f1", Type::Uint2, 1),
135 make_column_def(3, "f2", Type::Uint4, 2),
136 make_column_def(4, "f3", Type::Uint8, 3),
137 make_column_def(5, "f4", Type::Uint16, 4),
138 ];
139
140 let schema_from_columns = Schema::from(columns.as_slice());
141 let schema_direct = Schema::new(vec![
142 SchemaField::unconstrained("f0", Type::Uint1),
143 SchemaField::unconstrained("f1", Type::Uint2),
144 SchemaField::unconstrained("f2", Type::Uint4),
145 SchemaField::unconstrained("f3", Type::Uint8),
146 SchemaField::unconstrained("f4", Type::Uint16),
147 ]);
148
149 assert_eq!(schema_from_columns.fields().len(), schema_direct.fields().len());
151 assert_eq!(schema_from_columns.fingerprint(), schema_direct.fingerprint());
152
153 for (i, (from_columns, direct)) in
154 schema_from_columns.fields().iter().zip(schema_direct.fields().iter()).enumerate()
155 {
156 assert_eq!(from_columns.name, direct.name, "name mismatch at field {}", i);
157 assert_eq!(
158 from_columns.constraint, direct.constraint,
159 "constraint mismatch at field {}",
160 i
161 );
162 assert_eq!(from_columns.offset, direct.offset, "offset mismatch at field {}", i);
163 assert_eq!(from_columns.size, direct.size, "size mismatch at field {}", i);
164 assert_eq!(from_columns.align, direct.align, "align mismatch at field {}", i);
165 }
166 }
167
168 #[test]
169 fn test_from_column_def_empty() {
170 let columns: Vec<ColumnDef> = vec![];
171
172 let schema = Schema::from(columns.as_slice());
173
174 assert_eq!(schema.fields().len(), 0);
175 }
176
177 #[test]
178 fn test_from_column_def_nine_fields() {
179 let columns = vec![
180 make_column_def(1, "f0", Type::Boolean, 0),
181 make_column_def(2, "f1", Type::Int1, 1),
182 make_column_def(3, "f2", Type::Int2, 2),
183 make_column_def(4, "f3", Type::Int4, 3),
184 make_column_def(5, "f4", Type::Int8, 4),
185 make_column_def(6, "f5", Type::Uint1, 5),
186 make_column_def(7, "f6", Type::Uint2, 6),
187 make_column_def(8, "f7", Type::Uint4, 7),
188 make_column_def(9, "f8", Type::Uint8, 8),
189 ];
190
191 let schema = Schema::from(columns.as_slice());
192
193 assert_eq!(schema.fields().len(), 9);
194 for (i, field) in schema.fields().iter().enumerate() {
195 assert_eq!(field.name, format!("f{}", i));
196 }
197 }
198 }
199}