1use reifydb_type::value::{Value, ordered_f32::OrderedF32, ordered_f64::OrderedF64, r#type::Type};
5
6use super::shape::RowShape;
7use crate::encoded::row::EncodedRow;
8
9impl RowShape {
10 pub fn set_values(&self, row: &mut EncodedRow, values: &[Value]) {
11 debug_assert!(values.len() == self.fields().len());
12 for (idx, value) in values.iter().enumerate() {
13 self.set_value(row, idx, value)
14 }
15 }
16
17 pub fn set_value(&self, row: &mut EncodedRow, index: usize, val: &Value) {
18 let field = &self.fields()[index];
19 debug_assert!(row.len() >= self.total_static_size());
20
21 let field_type = match field.constraint.get_type() {
22 Type::Option(inner) => *inner,
23 other => other,
24 };
25
26 match (field_type, val) {
27 (Type::Boolean, Value::Boolean(v)) => self.set_bool(row, index, *v),
28 (
29 Type::Boolean,
30 Value::None {
31 ..
32 },
33 ) => self.set_none(row, index),
34
35 (Type::Float4, Value::Float4(v)) => self.set_f32(row, index, v.value()),
36 (
37 Type::Float4,
38 Value::None {
39 ..
40 },
41 ) => self.set_none(row, index),
42
43 (Type::Float8, Value::Float8(v)) => self.set_f64(row, index, v.value()),
44 (
45 Type::Float8,
46 Value::None {
47 ..
48 },
49 ) => self.set_none(row, index),
50
51 (Type::Int1, Value::Int1(v)) => self.set_i8(row, index, *v),
52 (
53 Type::Int1,
54 Value::None {
55 ..
56 },
57 ) => self.set_none(row, index),
58
59 (Type::Int2, Value::Int2(v)) => self.set_i16(row, index, *v),
60 (
61 Type::Int2,
62 Value::None {
63 ..
64 },
65 ) => self.set_none(row, index),
66
67 (Type::Int4, Value::Int4(v)) => self.set_i32(row, index, *v),
68 (
69 Type::Int4,
70 Value::None {
71 ..
72 },
73 ) => self.set_none(row, index),
74
75 (Type::Int8, Value::Int8(v)) => self.set_i64(row, index, *v),
76 (
77 Type::Int8,
78 Value::None {
79 ..
80 },
81 ) => self.set_none(row, index),
82
83 (Type::Int16, Value::Int16(v)) => self.set_i128(row, index, *v),
84 (
85 Type::Int16,
86 Value::None {
87 ..
88 },
89 ) => self.set_none(row, index),
90
91 (Type::Utf8, Value::Utf8(v)) => self.set_utf8(row, index, v),
92 (
93 Type::Utf8,
94 Value::None {
95 ..
96 },
97 ) => self.set_none(row, index),
98
99 (Type::Uint1, Value::Uint1(v)) => self.set_u8(row, index, *v),
100 (
101 Type::Uint1,
102 Value::None {
103 ..
104 },
105 ) => self.set_none(row, index),
106
107 (Type::Uint2, Value::Uint2(v)) => self.set_u16(row, index, *v),
108 (
109 Type::Uint2,
110 Value::None {
111 ..
112 },
113 ) => self.set_none(row, index),
114
115 (Type::Uint4, Value::Uint4(v)) => self.set_u32(row, index, *v),
116 (
117 Type::Uint4,
118 Value::None {
119 ..
120 },
121 ) => self.set_none(row, index),
122
123 (Type::Uint8, Value::Uint8(v)) => self.set_u64(row, index, *v),
124 (
125 Type::Uint8,
126 Value::None {
127 ..
128 },
129 ) => self.set_none(row, index),
130
131 (Type::Uint16, Value::Uint16(v)) => self.set_u128(row, index, *v),
132 (
133 Type::Uint16,
134 Value::None {
135 ..
136 },
137 ) => self.set_none(row, index),
138
139 (Type::Date, Value::Date(v)) => self.set_date(row, index, *v),
140 (
141 Type::Date,
142 Value::None {
143 ..
144 },
145 ) => self.set_none(row, index),
146
147 (Type::DateTime, Value::DateTime(v)) => self.set_datetime(row, index, *v),
148 (
149 Type::DateTime,
150 Value::None {
151 ..
152 },
153 ) => self.set_none(row, index),
154
155 (Type::Time, Value::Time(v)) => self.set_time(row, index, *v),
156 (
157 Type::Time,
158 Value::None {
159 ..
160 },
161 ) => self.set_none(row, index),
162
163 (Type::Duration, Value::Duration(v)) => self.set_duration(row, index, *v),
164 (
165 Type::Duration,
166 Value::None {
167 ..
168 },
169 ) => self.set_none(row, index),
170
171 (Type::Uuid4, Value::Uuid4(v)) => self.set_uuid4(row, index, *v),
172 (
173 Type::Uuid4,
174 Value::None {
175 ..
176 },
177 ) => self.set_none(row, index),
178
179 (Type::Uuid7, Value::Uuid7(v)) => self.set_uuid7(row, index, *v),
180 (
181 Type::Uuid7,
182 Value::None {
183 ..
184 },
185 ) => self.set_none(row, index),
186
187 (Type::Blob, Value::Blob(v)) => self.set_blob(row, index, v),
188 (
189 Type::Blob,
190 Value::None {
191 ..
192 },
193 ) => self.set_none(row, index),
194
195 (Type::Int, Value::Int(v)) => self.set_int(row, index, v),
196 (Type::Uint, Value::Uint(v)) => self.set_uint(row, index, v),
197 (
198 Type::Int,
199 Value::None {
200 ..
201 },
202 ) => self.set_none(row, index),
203 (
204 Type::Uint,
205 Value::None {
206 ..
207 },
208 ) => self.set_none(row, index),
209
210 (Type::Decimal, Value::Decimal(v)) => self.set_decimal(row, index, v),
211 (
212 Type::Decimal,
213 Value::None {
214 ..
215 },
216 ) => self.set_none(row, index),
217 (Type::DictionaryId, Value::DictionaryId(id)) => self.set_dictionary_id(row, index, id),
218
219 (
220 Type::DictionaryId,
221 Value::None {
222 ..
223 },
224 ) => self.set_none(row, index),
225
226 (Type::IdentityId, Value::IdentityId(id)) => self.set_identity_id(row, index, *id),
227 (
228 Type::IdentityId,
229 Value::None {
230 ..
231 },
232 ) => self.set_none(row, index),
233
234 (
235 Type::Any,
236 Value::None {
237 ..
238 },
239 ) => self.set_none(row, index),
240 (Type::Any, Value::Any(inner)) => self.set_any(row, index, inner),
241 (ty, val) => unreachable!(
242 "set_value type mismatch at index {index}: column name={:?} declared_type={ty:?}, value={val:?}",
243 field.name,
244 ),
245 }
246 }
247
248 pub fn get_value(&self, row: &EncodedRow, index: usize) -> Value {
249 let field = &self.fields()[index];
250 if !row.is_defined(index) {
251 return Value::none();
252 }
253 let field_type = match field.constraint.get_type() {
254 Type::Option(inner) => *inner,
255 other => other,
256 };
257
258 match field_type {
259 Type::Boolean => Value::Boolean(self.get_bool(row, index)),
260 Type::Float4 => OrderedF32::try_from(self.get_f32(row, index))
261 .map(Value::Float4)
262 .unwrap_or(Value::none()),
263 Type::Float8 => OrderedF64::try_from(self.get_f64(row, index))
264 .map(Value::Float8)
265 .unwrap_or(Value::none()),
266 Type::Int1 => Value::Int1(self.get_i8(row, index)),
267 Type::Int2 => Value::Int2(self.get_i16(row, index)),
268 Type::Int4 => Value::Int4(self.get_i32(row, index)),
269 Type::Int8 => Value::Int8(self.get_i64(row, index)),
270 Type::Int16 => Value::Int16(self.get_i128(row, index)),
271 Type::Utf8 => Value::Utf8(self.get_utf8(row, index).to_string()),
272 Type::Uint1 => Value::Uint1(self.get_u8(row, index)),
273 Type::Uint2 => Value::Uint2(self.get_u16(row, index)),
274 Type::Uint4 => Value::Uint4(self.get_u32(row, index)),
275 Type::Uint8 => Value::Uint8(self.get_u64(row, index)),
276 Type::Uint16 => Value::Uint16(self.get_u128(row, index)),
277 Type::Date => Value::Date(self.get_date(row, index)),
278 Type::DateTime => Value::DateTime(self.get_datetime(row, index)),
279 Type::Time => Value::Time(self.get_time(row, index)),
280 Type::Duration => Value::Duration(self.get_duration(row, index)),
281 Type::IdentityId => Value::IdentityId(self.get_identity_id(row, index)),
282 Type::Uuid4 => Value::Uuid4(self.get_uuid4(row, index)),
283 Type::Uuid7 => Value::Uuid7(self.get_uuid7(row, index)),
284 Type::Blob => Value::Blob(self.get_blob(row, index)),
285 Type::Int => Value::Int(self.get_int(row, index)),
286 Type::Uint => Value::Uint(self.get_uint(row, index)),
287 Type::Decimal => Value::Decimal(self.get_decimal(row, index)),
288 Type::DictionaryId => Value::DictionaryId(self.get_dictionary_id(row, index)),
289 Type::Option(_) => unreachable!("Option type already unwrapped"),
290 Type::Any => Value::Any(Box::new(self.get_any(row, index))),
291 Type::List(_) => unreachable!("List type cannot be stored in database"),
292 Type::Record(_) => unreachable!("Record type cannot be stored in database"),
293 Type::Tuple(_) => unreachable!("Tuple type cannot be stored in database"),
294 }
295 }
296}
297
298#[cfg(test)]
299#[allow(clippy::approx_constant)]
300pub mod tests {
301 use std::f64::consts::E;
302
303 use reifydb_runtime::context::{
304 clock::{Clock, MockClock},
305 rng::Rng,
306 };
307 use reifydb_type::value::{
308 Value,
309 blob::Blob,
310 constraint::TypeConstraint,
311 date::Date,
312 datetime::DateTime,
313 dictionary::{DictionaryEntryId, DictionaryId},
314 duration::Duration,
315 ordered_f32::OrderedF32,
316 ordered_f64::OrderedF64,
317 time::Time,
318 r#type::Type,
319 uuid::{Uuid4, Uuid7},
320 };
321
322 use crate::encoded::shape::{RowShape, RowShapeField};
323
324 fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
325 let mock = MockClock::from_millis(1000);
326 let clock = Clock::Mock(mock.clone());
327 let rng = Rng::seeded(42);
328 (mock, clock, rng)
329 }
330
331 #[test]
332 fn test_set_utf8_with_dynamic_content() {
333 let shape = RowShape::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
334 let mut row = shape.allocate();
335
336 let value1 = Value::Utf8("hello".to_string());
337 let value2 = Value::Int4(42);
338 let value3 = Value::Utf8("world".to_string());
339
340 shape.set_value(&mut row, 0, &value1);
341 shape.set_value(&mut row, 1, &value2);
342 shape.set_value(&mut row, 2, &value3);
343
344 assert_eq!(shape.get_utf8(&row, 0), "hello");
345 assert_eq!(shape.get_i32(&row, 1), 42);
346 assert_eq!(shape.get_utf8(&row, 2), "world");
347 }
348
349 #[test]
350 fn test_set_values_with_mixed_dynamic_content() {
351 let shape = RowShape::testing(&[Type::Boolean, Type::Utf8, Type::Float4, Type::Utf8, Type::Int2]);
352 let mut row = shape.allocate();
353
354 let values = vec![
355 Value::Boolean(true),
356 Value::Utf8("first_string".to_string()),
357 Value::Float4(OrderedF32::try_from(3.14f32).unwrap()),
358 Value::Utf8("second_string".to_string()),
359 Value::Int2(-100),
360 ];
361
362 shape.set_values(&mut row, &values);
363
364 assert_eq!(shape.get_bool(&row, 0), true);
365 assert_eq!(shape.get_utf8(&row, 1), "first_string");
366 assert_eq!(shape.get_f32(&row, 2), 3.14f32);
367 assert_eq!(shape.get_utf8(&row, 3), "second_string");
368 assert_eq!(shape.get_i16(&row, 4), -100);
369 }
370
371 #[test]
372 fn test_set_with_empty_and_large_utf8() {
373 let shape = RowShape::testing(&[Type::Utf8, Type::Utf8, Type::Utf8]);
374 let mut row = shape.allocate();
375
376 let large_string = "X".repeat(2000);
377 let values = vec![
378 Value::Utf8("".to_string()),
379 Value::Utf8(large_string.clone()),
380 Value::Utf8("small".to_string()),
381 ];
382
383 shape.set_values(&mut row, &values);
384
385 assert_eq!(shape.get_utf8(&row, 0), "");
386 assert_eq!(shape.get_utf8(&row, 1), large_string);
387 assert_eq!(shape.get_utf8(&row, 2), "small");
388 assert_eq!(shape.dynamic_section_size(&row), 2005); }
390
391 #[test]
392 fn test_get_from_dynamic_content() {
393 let shape = RowShape::testing(&[Type::Utf8, Type::Int8, Type::Utf8]);
394 let mut row = shape.allocate();
395
396 shape.set_utf8(&mut row, 0, "test_string");
397 shape.set_i64(&mut row, 1, 9876543210i64);
398 shape.set_utf8(&mut row, 2, "another_string");
399
400 let value0 = shape.get_value(&row, 0);
401 let value1 = shape.get_value(&row, 1);
402 let value2 = shape.get_value(&row, 2);
403
404 match value0 {
405 Value::Utf8(s) => assert_eq!(s, "test_string"),
406 _ => panic!("Expected UTF8 value"),
407 }
408
409 match value1 {
410 Value::Int8(i) => assert_eq!(i, 9876543210),
411 _ => panic!("Expected Int8 value"),
412 }
413
414 match value2 {
415 Value::Utf8(s) => assert_eq!(s, "another_string"),
416 _ => panic!("Expected UTF8 value"),
417 }
418 }
419
420 #[test]
421 fn test_set_none_with_utf8_fields() {
422 let shape = RowShape::testing(&[Type::Utf8, Type::Boolean, Type::Utf8]);
423 let mut row = shape.allocate();
424
425 shape.set_value(&mut row, 0, &Value::Utf8("hello".to_string()));
427 shape.set_value(&mut row, 1, &Value::Boolean(true));
428 shape.set_value(&mut row, 2, &Value::Utf8("world".to_string()));
429
430 assert!(row.is_defined(0));
431 assert!(row.is_defined(1));
432 assert!(row.is_defined(2));
433
434 shape.set_value(&mut row, 0, &Value::none());
436 shape.set_value(&mut row, 2, &Value::none());
437
438 assert!(!row.is_defined(0));
439 assert!(row.is_defined(1));
440 assert!(!row.is_defined(2));
441
442 assert_eq!(shape.get_bool(&row, 1), true);
443 }
444
445 #[test]
446 fn test_get_all_types_including_utf8() {
447 let shape = RowShape::testing(&[
448 Type::Boolean,
449 Type::Int1,
450 Type::Int2,
451 Type::Int4,
452 Type::Int8,
453 Type::Uint1,
454 Type::Uint2,
455 Type::Uint4,
456 Type::Uint8,
457 Type::Float4,
458 Type::Float8,
459 Type::Utf8,
460 ]);
461 let mut row = shape.allocate();
462
463 shape.set_bool(&mut row, 0, true);
464 shape.set_i8(&mut row, 1, -42);
465 shape.set_i16(&mut row, 2, -1000i16);
466 shape.set_i32(&mut row, 3, -50000i32);
467 shape.set_i64(&mut row, 4, -3000000000i64);
468 shape.set_u8(&mut row, 5, 200u8);
469 shape.set_u16(&mut row, 6, 50000u16);
470 shape.set_u32(&mut row, 7, 3000000000u32);
471 shape.set_u64(&mut row, 8, 15000000000000000000u64);
472 shape.set_f32(&mut row, 9, 2.5);
473 shape.set_f64(&mut row, 10, 123.456789);
474 shape.set_utf8(&mut row, 11, "dynamic_string");
475
476 let values: Vec<Value> = (0..12).map(|i| shape.get_value(&row, i)).collect();
477
478 assert_eq!(values[0], Value::Boolean(true));
479 assert_eq!(values[1], Value::Int1(-42));
480 assert_eq!(values[2], Value::Int2(-1000));
481 assert_eq!(values[3], Value::Int4(-50000));
482 assert_eq!(values[4], Value::Int8(-3000000000));
483 assert_eq!(values[5], Value::Uint1(200));
484 assert_eq!(values[6], Value::Uint2(50000));
485 assert_eq!(values[7], Value::Uint4(3000000000));
486 assert_eq!(values[8], Value::Uint8(15000000000000000000));
487 assert_eq!(values[9], Value::Float4(OrderedF32::try_from(2.5f32).unwrap()));
488 assert_eq!(values[10], Value::Float8(OrderedF64::try_from(123.456789f64).unwrap()));
489 assert_eq!(values[11], Value::Utf8("dynamic_string".to_string()));
490 }
491
492 #[test]
493 fn test_set_values_sparse_with_utf8() {
494 let shape = RowShape::testing(&[Type::Utf8, Type::Utf8, Type::Utf8, Type::Utf8]);
495 let mut row = shape.allocate();
496
497 let values = vec![
499 Value::Utf8("first".to_string()),
500 Value::none(),
501 Value::Utf8("third".to_string()),
502 Value::none(),
503 ];
504
505 shape.set_values(&mut row, &values);
506
507 assert!(row.is_defined(0));
508 assert!(!row.is_defined(1));
509 assert!(row.is_defined(2));
510 assert!(!row.is_defined(3));
511
512 assert_eq!(shape.get_utf8(&row, 0), "first");
513 assert_eq!(shape.get_utf8(&row, 2), "third");
514 }
515
516 #[test]
517 fn test_set_values_unicode_strings() {
518 let shape = RowShape::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
519 let mut row = shape.allocate();
520
521 let values = vec![
522 Value::Utf8("ππβ¨".to_string()),
523 Value::Int4(123),
524 Value::Utf8("Hello δΈη".to_string()),
525 ];
526
527 shape.set_values(&mut row, &values);
528
529 assert_eq!(shape.get_utf8(&row, 0), "ππβ¨");
530 assert_eq!(shape.get_i32(&row, 1), 123);
531 assert_eq!(shape.get_utf8(&row, 2), "Hello δΈη");
532 }
533
534 #[test]
535 fn test_static_fields_only_no_dynamic_with_values() {
536 let shape = RowShape::testing(&[Type::Boolean, Type::Int4, Type::Float8]);
537 let mut row = shape.allocate();
538
539 let values =
540 vec![Value::Boolean(false), Value::Int4(999), Value::Float8(OrderedF64::try_from(E).unwrap())];
541
542 shape.set_values(&mut row, &values);
543
544 assert_eq!(shape.dynamic_section_size(&row), 0);
546 assert_eq!(row.len(), shape.total_static_size());
547
548 assert_eq!(shape.get_bool(&row, 0), false);
549 assert_eq!(shape.get_i32(&row, 1), 999);
550 assert_eq!(shape.get_f64(&row, 2), E);
551 }
552
553 #[test]
554 fn test_temporal_types_roundtrip() {
555 let shape = RowShape::testing(&[Type::Date, Type::DateTime, Type::Time, Type::Duration]);
556 let mut row = shape.allocate();
557
558 let original_values = vec![
559 Value::Date(Date::new(2025, 7, 15).unwrap()),
560 Value::DateTime(DateTime::from_ymd_hms(2025, 7, 15, 14, 30, 45).unwrap()),
561 Value::Time(Time::new(14, 30, 45, 123456789).unwrap()),
562 Value::Duration(Duration::from_seconds(3600).unwrap()),
563 ];
564
565 shape.set_values(&mut row, &original_values);
566
567 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
568
569 assert_eq!(retrieved_values, original_values);
570 }
571
572 #[test]
573 fn test_temporal_types_with_undefined() {
574 let shape = RowShape::testing(&[Type::Date, Type::DateTime, Type::Time, Type::Duration]);
575 let mut row = shape.allocate();
576
577 let values = vec![
578 Value::Date(Date::new(2000, 1, 1).unwrap()),
579 Value::none(),
580 Value::Time(Time::default()),
581 Value::none(),
582 ];
583
584 shape.set_values(&mut row, &values);
585
586 assert!(row.is_defined(0));
587 assert!(!row.is_defined(1));
588 assert!(row.is_defined(2));
589 assert!(!row.is_defined(3));
590
591 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
592
593 assert_eq!(retrieved_values[0], values[0]);
594 assert_eq!(retrieved_values[1], Value::none());
595 assert_eq!(retrieved_values[2], values[2]);
596 assert_eq!(retrieved_values[3], Value::none());
597 }
598
599 #[test]
600 fn test_mixed_temporal_and_regular_types() {
601 let shape = RowShape::testing(&[
602 Type::Boolean,
603 Type::Date,
604 Type::Utf8,
605 Type::DateTime,
606 Type::Int4,
607 Type::Time,
608 Type::Duration,
609 ]);
610 let mut row = shape.allocate();
611
612 let values = vec![
613 Value::Boolean(true),
614 Value::Date(Date::new(1985, 10, 26).unwrap()),
615 Value::Utf8("time travel".to_string()),
616 Value::DateTime(DateTime::new(2015, 10, 21, 16, 29, 0, 0).unwrap()),
617 Value::Int4(88),
618 Value::Time(Time::new(12, 0, 0, 0).unwrap()),
619 Value::Duration(Duration::from_minutes(30).unwrap()),
620 ];
621
622 shape.set_values(&mut row, &values);
623
624 let retrieved_values: Vec<Value> = (0..7).map(|i| shape.get_value(&row, i)).collect();
625
626 assert_eq!(retrieved_values, values);
627 }
628
629 #[test]
630 fn test_roundtrip_with_dynamic_content() {
631 let shape = RowShape::testing(&[Type::Utf8, Type::Int2, Type::Utf8, Type::Float4]);
632 let mut row = shape.allocate();
633
634 let original_values = vec![
635 Value::Utf8("roundtrip_test".to_string()),
636 Value::Int2(32000),
637 Value::Utf8("".to_string()),
638 Value::Float4(OrderedF32::try_from(1.5f32).unwrap()),
639 ];
640
641 shape.set_values(&mut row, &original_values);
643
644 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
646
647 assert_eq!(retrieved_values, original_values);
648 }
649
650 #[test]
651 fn test_blob_roundtrip() {
652 let shape = RowShape::testing(&[Type::Blob, Type::Int4, Type::Blob]);
653 let mut row = shape.allocate();
654
655 let blob1 = Blob::new(vec![0xDE, 0xAD, 0xBE, 0xEF]);
656 let blob2 = Blob::new(vec![]);
657 let values = vec![Value::Blob(blob1.clone()), Value::Int4(42), Value::Blob(blob2.clone())];
658
659 shape.set_values(&mut row, &values);
660
661 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
662
663 assert_eq!(retrieved_values, values);
664
665 match &retrieved_values[0] {
667 Value::Blob(b) => assert_eq!(b.as_bytes(), &[0xDE, 0xAD, 0xBE, 0xEF]),
668 _ => panic!("Expected Blob value"),
669 }
670
671 match &retrieved_values[2] {
672 Value::Blob(b) => assert!(b.is_empty()),
673 _ => panic!("Expected Blob value"),
674 }
675 }
676
677 #[test]
678 fn test_blob_with_undefined() {
679 let shape = RowShape::testing(&[Type::Blob, Type::Blob, Type::Blob]);
680 let mut row = shape.allocate();
681
682 let values = vec![
683 Value::Blob(Blob::new(vec![0x00, 0x01, 0x02])),
684 Value::none(),
685 Value::Blob(Blob::new(vec![0xFF, 0xFE])),
686 ];
687
688 shape.set_values(&mut row, &values);
689
690 assert!(row.is_defined(0));
691 assert!(!row.is_defined(1));
692 assert!(row.is_defined(2));
693
694 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
695
696 assert_eq!(retrieved_values[0], values[0]);
697 assert_eq!(retrieved_values[1], Value::none());
698 assert_eq!(retrieved_values[2], values[2]);
699 }
700
701 #[test]
702 fn test_uuid_roundtrip() {
703 let (_, clock, rng) = test_clock_and_rng();
704 let shape = RowShape::testing(&[Type::Uuid4, Type::Uuid7, Type::Int4]);
705 let mut row = shape.allocate();
706
707 let uuid4 = Uuid4::generate();
708 let uuid7 = Uuid7::generate(&clock, &rng);
709 let values = vec![Value::Uuid4(uuid4), Value::Uuid7(uuid7), Value::Int4(123)];
710
711 shape.set_values(&mut row, &values);
712
713 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
714
715 assert_eq!(retrieved_values, values);
716 }
717
718 #[test]
719 fn test_uuid_with_undefined() {
720 let (_, clock, rng) = test_clock_and_rng();
721 let shape = RowShape::testing(&[Type::Uuid4, Type::Uuid7]);
722 let mut row = shape.allocate();
723
724 let values = vec![Value::none(), Value::Uuid7(Uuid7::generate(&clock, &rng))];
725
726 shape.set_values(&mut row, &values);
727
728 assert!(!row.is_defined(0));
729 assert!(row.is_defined(1));
730
731 let retrieved_values: Vec<Value> = (0..2).map(|i| shape.get_value(&row, i)).collect();
732
733 assert_eq!(retrieved_values[0], Value::none());
734 assert_eq!(retrieved_values[1], values[1]);
735 }
736
737 #[test]
738 fn test_mixed_blob_row_number_uuid_types() {
739 let (_, clock, rng) = test_clock_and_rng();
740 let shape =
741 RowShape::testing(&[Type::Blob, Type::Int16, Type::Uuid4, Type::Utf8, Type::Uuid7, Type::Int4]);
742 let mut row = shape.allocate();
743
744 let values = vec![
745 Value::Blob(Blob::new(vec![0xCA, 0xFE, 0xBA, 0xBE])),
746 Value::Int16(42424242i128),
747 Value::Uuid4(Uuid4::generate()),
748 Value::Utf8("mixed types test".to_string()),
749 Value::Uuid7(Uuid7::generate(&clock, &rng)),
750 Value::Int4(-999),
751 ];
752
753 shape.set_values(&mut row, &values);
754
755 let retrieved_values: Vec<Value> = (0..6).map(|i| shape.get_value(&row, i)).collect();
756
757 assert_eq!(retrieved_values, values);
758
759 assert!(shape.dynamic_section_size(&row) > 0);
761 }
762
763 #[test]
764 fn test_all_types_comprehensive() {
765 let (_, clock, rng) = test_clock_and_rng();
767
768 let shape = RowShape::testing(&[
769 Type::Boolean,
770 Type::Int1,
771 Type::Int2,
772 Type::Int4,
773 Type::Int8,
774 Type::Int16,
775 Type::Uint1,
776 Type::Uint2,
777 Type::Uint4,
778 Type::Uint8,
779 Type::Uint16,
780 Type::Float4,
781 Type::Float8,
782 Type::Utf8,
783 Type::Date,
784 Type::DateTime,
785 Type::Time,
786 Type::Duration,
787 Type::Uuid4,
788 Type::Uuid7,
789 Type::Blob,
790 ]);
791 let mut row = shape.allocate();
792
793 let values = vec![
794 Value::Boolean(true),
795 Value::Int1(-128),
796 Value::Int2(-32768),
797 Value::Int4(-2147483648),
798 Value::Int8(-9223372036854775808),
799 Value::Int16(-170141183460469231731687303715884105728),
800 Value::Uint1(255),
801 Value::Uint2(65535),
802 Value::Uint4(4294967295),
803 Value::Uint8(18446744073709551615),
804 Value::Uint16(340282366920938463463374607431768211455),
805 Value::Float4(OrderedF32::try_from(3.14159f32).unwrap()),
806 Value::Float8(OrderedF64::try_from(2.718281828459045).unwrap()),
807 Value::Utf8("comprehensive test".to_string()),
808 Value::Date(Date::new(2025, 12, 31).unwrap()),
809 Value::DateTime(DateTime::new(2025, 1, 1, 0, 0, 0, 0).unwrap()),
810 Value::Time(Time::new(23, 59, 59, 999999999).unwrap()),
811 Value::Duration(Duration::from_hours(24).unwrap()),
812 Value::Uuid4(Uuid4::generate()),
813 Value::Uuid7(Uuid7::generate(&clock, &rng)),
814 Value::Blob(Blob::new(vec![
815 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
816 0xEE, 0xFF,
817 ])),
818 ];
819
820 shape.set_values(&mut row, &values);
821
822 let retrieved_values: Vec<Value> = (0..21).map(|i| shape.get_value(&row, i)).collect();
823
824 assert_eq!(retrieved_values, values);
825
826 for i in 0..21 {
828 assert!(row.is_defined(i), "Field {} should be defined", i);
829 }
830 }
831
832 #[test]
833 fn test_dictionary_id_roundtrip_u4() {
834 let constraint = TypeConstraint::dictionary(DictionaryId::from(42u64), Type::Uint4);
835 let shape = RowShape::new(vec![RowShapeField::new("status", constraint)]);
836
837 let mut row = shape.allocate();
838 let entry = DictionaryEntryId::U4(7);
839 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
840
841 assert!(row.is_defined(0));
842 let retrieved = shape.get_value(&row, 0);
843 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U4(7)));
844 }
845
846 #[test]
847 fn test_dictionary_id_roundtrip_u2() {
848 let constraint = TypeConstraint::dictionary(DictionaryId::from(10u64), Type::Uint2);
849 let shape = RowShape::new(vec![RowShapeField::new("category", constraint)]);
850
851 let mut row = shape.allocate();
852 let entry = DictionaryEntryId::U2(500);
853 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
854
855 assert!(row.is_defined(0));
856 let retrieved = shape.get_value(&row, 0);
857 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U2(500)));
858 }
859
860 #[test]
861 fn test_dictionary_id_roundtrip_u8() {
862 let constraint = TypeConstraint::dictionary(DictionaryId::from(99u64), Type::Uint8);
863 let shape = RowShape::new(vec![RowShapeField::new("tag", constraint)]);
864
865 let mut row = shape.allocate();
866 let entry = DictionaryEntryId::U8(123456789);
867 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
868
869 assert!(row.is_defined(0));
870 let retrieved = shape.get_value(&row, 0);
871 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U8(123456789)));
872 }
873
874 #[test]
875 fn test_dictionary_id_with_undefined() {
876 let constraint = TypeConstraint::dictionary(DictionaryId::from(1u64), Type::Uint4);
877 let shape = RowShape::new(vec![
878 RowShapeField::new("dict_col", constraint),
879 RowShapeField::unconstrained("int_col", Type::Int4),
880 ]);
881
882 let mut row = shape.allocate();
883 shape.set_value(&mut row, 0, &Value::none());
884 shape.set_value(&mut row, 1, &Value::Int4(42));
885
886 assert!(!row.is_defined(0));
887 assert!(row.is_defined(1));
888
889 assert_eq!(shape.get_value(&row, 0), Value::none());
890 assert_eq!(shape.get_value(&row, 1), Value::Int4(42));
891 }
892
893 #[test]
894 fn test_dictionary_id_mixed_with_other_types() {
895 let dict_constraint = TypeConstraint::dictionary(DictionaryId::from(5u64), Type::Uint4);
896 let shape = RowShape::new(vec![
897 RowShapeField::unconstrained("id", Type::Int4),
898 RowShapeField::new("status", dict_constraint),
899 RowShapeField::unconstrained("name", Type::Utf8),
900 ]);
901
902 let mut row = shape.allocate();
903 let values = vec![
904 Value::Int4(100),
905 Value::DictionaryId(DictionaryEntryId::U4(3)),
906 Value::Utf8("test".to_string()),
907 ];
908 shape.set_values(&mut row, &values);
909
910 let retrieved: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
911 assert_eq!(retrieved, values);
912 }
913}