Skip to main content

reifydb_core/encoded/schema/
from.rs

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