reifydb_core/value/column/
frame.rs1use reifydb_value::{
5 fragment::Fragment,
6 value::{
7 constraint::{bytes::MaxBytes, precision::Precision, scale::Scale},
8 frame::{column::FrameColumn, data::FrameColumnData, frame::Frame},
9 },
10};
11
12use crate::value::column::{ColumnBuffer, ColumnWithName, columns::Columns};
13
14impl From<ColumnBuffer> for FrameColumnData {
15 fn from(value: ColumnBuffer) -> Self {
16 match value {
17 ColumnBuffer::Bool(container) => FrameColumnData::Bool(container),
18 ColumnBuffer::Float4(container) => FrameColumnData::Float4(container),
19 ColumnBuffer::Float8(container) => FrameColumnData::Float8(container),
20 ColumnBuffer::Int1(container) => FrameColumnData::Int1(container),
21 ColumnBuffer::Int2(container) => FrameColumnData::Int2(container),
22 ColumnBuffer::Int4(container) => FrameColumnData::Int4(container),
23 ColumnBuffer::Int8(container) => FrameColumnData::Int8(container),
24 ColumnBuffer::Int16(container) => FrameColumnData::Int16(container),
25 ColumnBuffer::Uint1(container) => FrameColumnData::Uint1(container),
26 ColumnBuffer::Uint2(container) => FrameColumnData::Uint2(container),
27 ColumnBuffer::Uint4(container) => FrameColumnData::Uint4(container),
28 ColumnBuffer::Uint8(container) => FrameColumnData::Uint8(container),
29 ColumnBuffer::Uint16(container) => FrameColumnData::Uint16(container),
30 ColumnBuffer::Utf8 {
31 container,
32 ..
33 } => FrameColumnData::Utf8(container),
34 ColumnBuffer::Date(container) => FrameColumnData::Date(container),
35 ColumnBuffer::DateTime(container) => FrameColumnData::DateTime(container),
36 ColumnBuffer::Time(container) => FrameColumnData::Time(container),
37 ColumnBuffer::Duration(container) => FrameColumnData::Duration(container),
38 ColumnBuffer::IdentityId(container) => FrameColumnData::IdentityId(container),
39 ColumnBuffer::Uuid4(container) => FrameColumnData::Uuid4(container),
40 ColumnBuffer::Uuid7(container) => FrameColumnData::Uuid7(container),
41 ColumnBuffer::Blob {
42 container,
43 ..
44 } => FrameColumnData::Blob(container),
45 ColumnBuffer::Int {
46 container,
47 ..
48 } => FrameColumnData::Int(container),
49 ColumnBuffer::Uint {
50 container,
51 ..
52 } => FrameColumnData::Uint(container),
53 ColumnBuffer::Decimal {
54 container,
55 ..
56 } => FrameColumnData::Decimal(container),
57 ColumnBuffer::Any(container) => FrameColumnData::Any(container),
58 ColumnBuffer::DictionaryId(container) => FrameColumnData::DictionaryId(container),
59 ColumnBuffer::Option {
60 inner,
61 bitvec,
62 } => FrameColumnData::Option {
63 inner: Box::new(FrameColumnData::from(*inner)),
64 bitvec,
65 },
66 }
67 }
68}
69
70impl From<ColumnWithName> for FrameColumn {
71 fn from(value: ColumnWithName) -> Self {
72 FrameColumn {
73 name: value.name.to_string(),
74 data: value.data.into(),
75 }
76 }
77}
78
79impl From<Columns> for Frame {
80 fn from(columns: Columns) -> Self {
81 let frame_columns: Vec<FrameColumn> = columns
82 .names
83 .iter()
84 .zip(columns.columns.iter())
85 .map(|(name, data)| FrameColumn {
86 name: name.to_string(),
87 data: data.clone().into(),
88 })
89 .collect();
90 Frame {
91 system: columns.system,
92 columns: frame_columns,
93 }
94 }
95}
96
97impl From<FrameColumnData> for ColumnBuffer {
98 fn from(value: FrameColumnData) -> Self {
99 match value {
100 FrameColumnData::Bool(container) => ColumnBuffer::Bool(container),
101 FrameColumnData::Float4(container) => ColumnBuffer::Float4(container),
102 FrameColumnData::Float8(container) => ColumnBuffer::Float8(container),
103 FrameColumnData::Int1(container) => ColumnBuffer::Int1(container),
104 FrameColumnData::Int2(container) => ColumnBuffer::Int2(container),
105 FrameColumnData::Int4(container) => ColumnBuffer::Int4(container),
106 FrameColumnData::Int8(container) => ColumnBuffer::Int8(container),
107 FrameColumnData::Int16(container) => ColumnBuffer::Int16(container),
108 FrameColumnData::Uint1(container) => ColumnBuffer::Uint1(container),
109 FrameColumnData::Uint2(container) => ColumnBuffer::Uint2(container),
110 FrameColumnData::Uint4(container) => ColumnBuffer::Uint4(container),
111 FrameColumnData::Uint8(container) => ColumnBuffer::Uint8(container),
112 FrameColumnData::Uint16(container) => ColumnBuffer::Uint16(container),
113 FrameColumnData::Utf8(container) => ColumnBuffer::Utf8 {
114 container,
115 max_bytes: MaxBytes::MAX,
116 },
117 FrameColumnData::Date(container) => ColumnBuffer::Date(container),
118 FrameColumnData::DateTime(container) => ColumnBuffer::DateTime(container),
119 FrameColumnData::Time(container) => ColumnBuffer::Time(container),
120 FrameColumnData::Duration(container) => ColumnBuffer::Duration(container),
121 FrameColumnData::IdentityId(container) => ColumnBuffer::IdentityId(container),
122 FrameColumnData::Uuid4(container) => ColumnBuffer::Uuid4(container),
123 FrameColumnData::Uuid7(container) => ColumnBuffer::Uuid7(container),
124 FrameColumnData::Blob(container) => ColumnBuffer::Blob {
125 container,
126 max_bytes: MaxBytes::MAX,
127 },
128 FrameColumnData::Int(container) => ColumnBuffer::Int {
129 container,
130 max_bytes: MaxBytes::MAX,
131 },
132 FrameColumnData::Uint(container) => ColumnBuffer::Uint {
133 container,
134 max_bytes: MaxBytes::MAX,
135 },
136 FrameColumnData::Decimal(container) => ColumnBuffer::Decimal {
137 container,
138 precision: Precision::MAX,
139 scale: Scale::new(0),
140 },
141 FrameColumnData::Any(container) => ColumnBuffer::Any(container),
142 FrameColumnData::DictionaryId(container) => ColumnBuffer::DictionaryId(container),
143 FrameColumnData::Option {
144 inner,
145 bitvec,
146 } => ColumnBuffer::Option {
147 inner: Box::new(ColumnBuffer::from(*inner)),
148 bitvec,
149 },
150 }
151 }
152}
153
154impl From<FrameColumn> for ColumnWithName {
155 fn from(value: FrameColumn) -> Self {
156 ColumnWithName::new(Fragment::internal(value.name), value.data.into())
157 }
158}
159
160impl From<Frame> for Columns {
161 fn from(frame: Frame) -> Self {
162 let columns: Vec<ColumnWithName> = frame.columns.into_iter().map(|col| col.into()).collect();
163 let mut names = Vec::with_capacity(columns.len());
164 let mut buffers = Vec::with_capacity(columns.len());
165 for c in columns {
166 names.push(c.name);
167 buffers.push(c.data);
168 }
169 Columns {
170 system: frame.system,
171 columns: buffers,
172 names,
173 }
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use reifydb_value::value::{datetime::DateTime, row_number::RowNumber, system_columns::SystemColumns};
180
181 use super::*;
182 use crate::value::column::{ColumnWithName, buffer::ColumnBuffer};
183
184 fn columns(time_nanos: [u64; 2]) -> Columns {
185 Columns::with_system(
186 vec![ColumnWithName::new(Fragment::internal("v"), ColumnBuffer::int4(vec![10, 20]))],
187 SystemColumns::new(
188 vec![RowNumber(1), RowNumber(2)],
189 Vec::new(),
190 vec![DateTime::from_nanos(900), DateTime::from_nanos(901)],
191 vec![DateTime::from_nanos(950), DateTime::from_nanos(951)],
192 time_nanos.map(DateTime::from_nanos).to_vec(),
193 ),
194 )
195 }
196
197 #[test]
198 fn a_frame_round_trips_the_time_vector() {
199 let before = columns([1_700_000_000, 1_700_000_001]);
203
204 let after: Columns = Frame::from(before.clone()).into();
205
206 assert_eq!(
207 after.time().to_vec(),
208 before.time().to_vec(),
209 "#time must survive Columns -> Frame -> Columns"
210 );
211 }
212
213 #[test]
214 fn a_round_tripped_frame_keeps_every_system_vector_the_same_length() {
215 let after: Columns = Frame::from(columns([5, 6])).into();
218
219 let rows = after.row_count();
220 assert_eq!(after.row_numbers().len(), rows, "row_numbers");
221 assert_eq!(after.created_at().len(), rows, "created_at");
222 assert_eq!(after.updated_at().len(), rows, "updated_at");
223 assert_eq!(after.time().len(), rows, "time");
224 }
225}