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