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!("{ty:?}, {val:?}"),
242 }
243 }
244
245 pub fn get_value(&self, row: &EncodedRow, index: usize) -> Value {
246 let field = &self.fields()[index];
247 if !row.is_defined(index) {
248 return Value::none();
249 }
250 let field_type = match field.constraint.get_type() {
251 Type::Option(inner) => *inner,
252 other => other,
253 };
254
255 match field_type {
256 Type::Boolean => Value::Boolean(self.get_bool(row, index)),
257 Type::Float4 => OrderedF32::try_from(self.get_f32(row, index))
258 .map(Value::Float4)
259 .unwrap_or(Value::none()),
260 Type::Float8 => OrderedF64::try_from(self.get_f64(row, index))
261 .map(Value::Float8)
262 .unwrap_or(Value::none()),
263 Type::Int1 => Value::Int1(self.get_i8(row, index)),
264 Type::Int2 => Value::Int2(self.get_i16(row, index)),
265 Type::Int4 => Value::Int4(self.get_i32(row, index)),
266 Type::Int8 => Value::Int8(self.get_i64(row, index)),
267 Type::Int16 => Value::Int16(self.get_i128(row, index)),
268 Type::Utf8 => Value::Utf8(self.get_utf8(row, index).to_string()),
269 Type::Uint1 => Value::Uint1(self.get_u8(row, index)),
270 Type::Uint2 => Value::Uint2(self.get_u16(row, index)),
271 Type::Uint4 => Value::Uint4(self.get_u32(row, index)),
272 Type::Uint8 => Value::Uint8(self.get_u64(row, index)),
273 Type::Uint16 => Value::Uint16(self.get_u128(row, index)),
274 Type::Date => Value::Date(self.get_date(row, index)),
275 Type::DateTime => Value::DateTime(self.get_datetime(row, index)),
276 Type::Time => Value::Time(self.get_time(row, index)),
277 Type::Duration => Value::Duration(self.get_duration(row, index)),
278 Type::IdentityId => Value::IdentityId(self.get_identity_id(row, index)),
279 Type::Uuid4 => Value::Uuid4(self.get_uuid4(row, index)),
280 Type::Uuid7 => Value::Uuid7(self.get_uuid7(row, index)),
281 Type::Blob => Value::Blob(self.get_blob(row, index)),
282 Type::Int => Value::Int(self.get_int(row, index)),
283 Type::Uint => Value::Uint(self.get_uint(row, index)),
284 Type::Decimal => Value::Decimal(self.get_decimal(row, index)),
285 Type::DictionaryId => Value::DictionaryId(self.get_dictionary_id(row, index)),
286 Type::Option(_) => unreachable!("Option type already unwrapped"),
287 Type::Any => Value::Any(Box::new(self.get_any(row, index))),
288 Type::List(_) => unreachable!("List type cannot be stored in database"),
289 Type::Record(_) => unreachable!("Record type cannot be stored in database"),
290 Type::Tuple(_) => unreachable!("Tuple type cannot be stored in database"),
291 }
292 }
293}
294
295#[cfg(test)]
296#[allow(clippy::approx_constant)]
297pub mod tests {
298 use std::f64::consts::E;
299
300 use reifydb_runtime::context::{
301 clock::{Clock, MockClock},
302 rng::Rng,
303 };
304 use reifydb_type::value::{
305 Value,
306 blob::Blob,
307 constraint::TypeConstraint,
308 date::Date,
309 datetime::DateTime,
310 dictionary::{DictionaryEntryId, DictionaryId},
311 duration::Duration,
312 ordered_f32::OrderedF32,
313 ordered_f64::OrderedF64,
314 time::Time,
315 r#type::Type,
316 uuid::{Uuid4, Uuid7},
317 };
318
319 use crate::encoded::shape::{RowShape, RowShapeField};
320
321 fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
322 let mock = MockClock::from_millis(1000);
323 let clock = Clock::Mock(mock.clone());
324 let rng = Rng::seeded(42);
325 (mock, clock, rng)
326 }
327
328 #[test]
329 fn test_set_utf8_with_dynamic_content() {
330 let shape = RowShape::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
331 let mut row = shape.allocate();
332
333 let value1 = Value::Utf8("hello".to_string());
334 let value2 = Value::Int4(42);
335 let value3 = Value::Utf8("world".to_string());
336
337 shape.set_value(&mut row, 0, &value1);
338 shape.set_value(&mut row, 1, &value2);
339 shape.set_value(&mut row, 2, &value3);
340
341 assert_eq!(shape.get_utf8(&row, 0), "hello");
342 assert_eq!(shape.get_i32(&row, 1), 42);
343 assert_eq!(shape.get_utf8(&row, 2), "world");
344 }
345
346 #[test]
347 fn test_set_values_with_mixed_dynamic_content() {
348 let shape = RowShape::testing(&[Type::Boolean, Type::Utf8, Type::Float4, Type::Utf8, Type::Int2]);
349 let mut row = shape.allocate();
350
351 let values = vec![
352 Value::Boolean(true),
353 Value::Utf8("first_string".to_string()),
354 Value::Float4(OrderedF32::try_from(3.14f32).unwrap()),
355 Value::Utf8("second_string".to_string()),
356 Value::Int2(-100),
357 ];
358
359 shape.set_values(&mut row, &values);
360
361 assert_eq!(shape.get_bool(&row, 0), true);
362 assert_eq!(shape.get_utf8(&row, 1), "first_string");
363 assert_eq!(shape.get_f32(&row, 2), 3.14f32);
364 assert_eq!(shape.get_utf8(&row, 3), "second_string");
365 assert_eq!(shape.get_i16(&row, 4), -100);
366 }
367
368 #[test]
369 fn test_set_with_empty_and_large_utf8() {
370 let shape = RowShape::testing(&[Type::Utf8, Type::Utf8, Type::Utf8]);
371 let mut row = shape.allocate();
372
373 let large_string = "X".repeat(2000);
374 let values = vec![
375 Value::Utf8("".to_string()),
376 Value::Utf8(large_string.clone()),
377 Value::Utf8("small".to_string()),
378 ];
379
380 shape.set_values(&mut row, &values);
381
382 assert_eq!(shape.get_utf8(&row, 0), "");
383 assert_eq!(shape.get_utf8(&row, 1), large_string);
384 assert_eq!(shape.get_utf8(&row, 2), "small");
385 assert_eq!(shape.dynamic_section_size(&row), 2005); }
387
388 #[test]
389 fn test_get_from_dynamic_content() {
390 let shape = RowShape::testing(&[Type::Utf8, Type::Int8, Type::Utf8]);
391 let mut row = shape.allocate();
392
393 shape.set_utf8(&mut row, 0, "test_string");
394 shape.set_i64(&mut row, 1, 9876543210i64);
395 shape.set_utf8(&mut row, 2, "another_string");
396
397 let value0 = shape.get_value(&row, 0);
398 let value1 = shape.get_value(&row, 1);
399 let value2 = shape.get_value(&row, 2);
400
401 match value0 {
402 Value::Utf8(s) => assert_eq!(s, "test_string"),
403 _ => panic!("Expected UTF8 value"),
404 }
405
406 match value1 {
407 Value::Int8(i) => assert_eq!(i, 9876543210),
408 _ => panic!("Expected Int8 value"),
409 }
410
411 match value2 {
412 Value::Utf8(s) => assert_eq!(s, "another_string"),
413 _ => panic!("Expected UTF8 value"),
414 }
415 }
416
417 #[test]
418 fn test_set_none_with_utf8_fields() {
419 let shape = RowShape::testing(&[Type::Utf8, Type::Boolean, Type::Utf8]);
420 let mut row = shape.allocate();
421
422 shape.set_value(&mut row, 0, &Value::Utf8("hello".to_string()));
424 shape.set_value(&mut row, 1, &Value::Boolean(true));
425 shape.set_value(&mut row, 2, &Value::Utf8("world".to_string()));
426
427 assert!(row.is_defined(0));
428 assert!(row.is_defined(1));
429 assert!(row.is_defined(2));
430
431 shape.set_value(&mut row, 0, &Value::none());
433 shape.set_value(&mut row, 2, &Value::none());
434
435 assert!(!row.is_defined(0));
436 assert!(row.is_defined(1));
437 assert!(!row.is_defined(2));
438
439 assert_eq!(shape.get_bool(&row, 1), true);
440 }
441
442 #[test]
443 fn test_get_all_types_including_utf8() {
444 let shape = RowShape::testing(&[
445 Type::Boolean,
446 Type::Int1,
447 Type::Int2,
448 Type::Int4,
449 Type::Int8,
450 Type::Uint1,
451 Type::Uint2,
452 Type::Uint4,
453 Type::Uint8,
454 Type::Float4,
455 Type::Float8,
456 Type::Utf8,
457 ]);
458 let mut row = shape.allocate();
459
460 shape.set_bool(&mut row, 0, true);
461 shape.set_i8(&mut row, 1, -42);
462 shape.set_i16(&mut row, 2, -1000i16);
463 shape.set_i32(&mut row, 3, -50000i32);
464 shape.set_i64(&mut row, 4, -3000000000i64);
465 shape.set_u8(&mut row, 5, 200u8);
466 shape.set_u16(&mut row, 6, 50000u16);
467 shape.set_u32(&mut row, 7, 3000000000u32);
468 shape.set_u64(&mut row, 8, 15000000000000000000u64);
469 shape.set_f32(&mut row, 9, 2.5);
470 shape.set_f64(&mut row, 10, 123.456789);
471 shape.set_utf8(&mut row, 11, "dynamic_string");
472
473 let values: Vec<Value> = (0..12).map(|i| shape.get_value(&row, i)).collect();
474
475 assert_eq!(values[0], Value::Boolean(true));
476 assert_eq!(values[1], Value::Int1(-42));
477 assert_eq!(values[2], Value::Int2(-1000));
478 assert_eq!(values[3], Value::Int4(-50000));
479 assert_eq!(values[4], Value::Int8(-3000000000));
480 assert_eq!(values[5], Value::Uint1(200));
481 assert_eq!(values[6], Value::Uint2(50000));
482 assert_eq!(values[7], Value::Uint4(3000000000));
483 assert_eq!(values[8], Value::Uint8(15000000000000000000));
484 assert_eq!(values[9], Value::Float4(OrderedF32::try_from(2.5f32).unwrap()));
485 assert_eq!(values[10], Value::Float8(OrderedF64::try_from(123.456789f64).unwrap()));
486 assert_eq!(values[11], Value::Utf8("dynamic_string".to_string()));
487 }
488
489 #[test]
490 fn test_set_values_sparse_with_utf8() {
491 let shape = RowShape::testing(&[Type::Utf8, Type::Utf8, Type::Utf8, Type::Utf8]);
492 let mut row = shape.allocate();
493
494 let values = vec![
496 Value::Utf8("first".to_string()),
497 Value::none(),
498 Value::Utf8("third".to_string()),
499 Value::none(),
500 ];
501
502 shape.set_values(&mut row, &values);
503
504 assert!(row.is_defined(0));
505 assert!(!row.is_defined(1));
506 assert!(row.is_defined(2));
507 assert!(!row.is_defined(3));
508
509 assert_eq!(shape.get_utf8(&row, 0), "first");
510 assert_eq!(shape.get_utf8(&row, 2), "third");
511 }
512
513 #[test]
514 fn test_set_values_unicode_strings() {
515 let shape = RowShape::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
516 let mut row = shape.allocate();
517
518 let values = vec![
519 Value::Utf8("ππβ¨".to_string()),
520 Value::Int4(123),
521 Value::Utf8("Hello δΈη".to_string()),
522 ];
523
524 shape.set_values(&mut row, &values);
525
526 assert_eq!(shape.get_utf8(&row, 0), "ππβ¨");
527 assert_eq!(shape.get_i32(&row, 1), 123);
528 assert_eq!(shape.get_utf8(&row, 2), "Hello δΈη");
529 }
530
531 #[test]
532 fn test_static_fields_only_no_dynamic_with_values() {
533 let shape = RowShape::testing(&[Type::Boolean, Type::Int4, Type::Float8]);
534 let mut row = shape.allocate();
535
536 let values =
537 vec![Value::Boolean(false), Value::Int4(999), Value::Float8(OrderedF64::try_from(E).unwrap())];
538
539 shape.set_values(&mut row, &values);
540
541 assert_eq!(shape.dynamic_section_size(&row), 0);
543 assert_eq!(row.len(), shape.total_static_size());
544
545 assert_eq!(shape.get_bool(&row, 0), false);
546 assert_eq!(shape.get_i32(&row, 1), 999);
547 assert_eq!(shape.get_f64(&row, 2), E);
548 }
549
550 #[test]
551 fn test_temporal_types_roundtrip() {
552 let shape = RowShape::testing(&[Type::Date, Type::DateTime, Type::Time, Type::Duration]);
553 let mut row = shape.allocate();
554
555 let original_values = vec![
556 Value::Date(Date::new(2025, 7, 15).unwrap()),
557 Value::DateTime(DateTime::from_ymd_hms(2025, 7, 15, 14, 30, 45).unwrap()),
558 Value::Time(Time::new(14, 30, 45, 123456789).unwrap()),
559 Value::Duration(Duration::from_seconds(3600).unwrap()),
560 ];
561
562 shape.set_values(&mut row, &original_values);
563
564 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
565
566 assert_eq!(retrieved_values, original_values);
567 }
568
569 #[test]
570 fn test_temporal_types_with_undefined() {
571 let shape = RowShape::testing(&[Type::Date, Type::DateTime, Type::Time, Type::Duration]);
572 let mut row = shape.allocate();
573
574 let values = vec![
575 Value::Date(Date::new(2000, 1, 1).unwrap()),
576 Value::none(),
577 Value::Time(Time::default()),
578 Value::none(),
579 ];
580
581 shape.set_values(&mut row, &values);
582
583 assert!(row.is_defined(0));
584 assert!(!row.is_defined(1));
585 assert!(row.is_defined(2));
586 assert!(!row.is_defined(3));
587
588 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
589
590 assert_eq!(retrieved_values[0], values[0]);
591 assert_eq!(retrieved_values[1], Value::none());
592 assert_eq!(retrieved_values[2], values[2]);
593 assert_eq!(retrieved_values[3], Value::none());
594 }
595
596 #[test]
597 fn test_mixed_temporal_and_regular_types() {
598 let shape = RowShape::testing(&[
599 Type::Boolean,
600 Type::Date,
601 Type::Utf8,
602 Type::DateTime,
603 Type::Int4,
604 Type::Time,
605 Type::Duration,
606 ]);
607 let mut row = shape.allocate();
608
609 let values = vec![
610 Value::Boolean(true),
611 Value::Date(Date::new(1985, 10, 26).unwrap()),
612 Value::Utf8("time travel".to_string()),
613 Value::DateTime(DateTime::new(2015, 10, 21, 16, 29, 0, 0).unwrap()),
614 Value::Int4(88),
615 Value::Time(Time::new(12, 0, 0, 0).unwrap()),
616 Value::Duration(Duration::from_minutes(30).unwrap()),
617 ];
618
619 shape.set_values(&mut row, &values);
620
621 let retrieved_values: Vec<Value> = (0..7).map(|i| shape.get_value(&row, i)).collect();
622
623 assert_eq!(retrieved_values, values);
624 }
625
626 #[test]
627 fn test_roundtrip_with_dynamic_content() {
628 let shape = RowShape::testing(&[Type::Utf8, Type::Int2, Type::Utf8, Type::Float4]);
629 let mut row = shape.allocate();
630
631 let original_values = vec![
632 Value::Utf8("roundtrip_test".to_string()),
633 Value::Int2(32000),
634 Value::Utf8("".to_string()),
635 Value::Float4(OrderedF32::try_from(1.5f32).unwrap()),
636 ];
637
638 shape.set_values(&mut row, &original_values);
640
641 let retrieved_values: Vec<Value> = (0..4).map(|i| shape.get_value(&row, i)).collect();
643
644 assert_eq!(retrieved_values, original_values);
645 }
646
647 #[test]
648 fn test_blob_roundtrip() {
649 let shape = RowShape::testing(&[Type::Blob, Type::Int4, Type::Blob]);
650 let mut row = shape.allocate();
651
652 let blob1 = Blob::new(vec![0xDE, 0xAD, 0xBE, 0xEF]);
653 let blob2 = Blob::new(vec![]);
654 let values = vec![Value::Blob(blob1.clone()), Value::Int4(42), Value::Blob(blob2.clone())];
655
656 shape.set_values(&mut row, &values);
657
658 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
659
660 assert_eq!(retrieved_values, values);
661
662 match &retrieved_values[0] {
664 Value::Blob(b) => assert_eq!(b.as_bytes(), &[0xDE, 0xAD, 0xBE, 0xEF]),
665 _ => panic!("Expected Blob value"),
666 }
667
668 match &retrieved_values[2] {
669 Value::Blob(b) => assert!(b.is_empty()),
670 _ => panic!("Expected Blob value"),
671 }
672 }
673
674 #[test]
675 fn test_blob_with_undefined() {
676 let shape = RowShape::testing(&[Type::Blob, Type::Blob, Type::Blob]);
677 let mut row = shape.allocate();
678
679 let values = vec![
680 Value::Blob(Blob::new(vec![0x00, 0x01, 0x02])),
681 Value::none(),
682 Value::Blob(Blob::new(vec![0xFF, 0xFE])),
683 ];
684
685 shape.set_values(&mut row, &values);
686
687 assert!(row.is_defined(0));
688 assert!(!row.is_defined(1));
689 assert!(row.is_defined(2));
690
691 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
692
693 assert_eq!(retrieved_values[0], values[0]);
694 assert_eq!(retrieved_values[1], Value::none());
695 assert_eq!(retrieved_values[2], values[2]);
696 }
697
698 #[test]
699 fn test_uuid_roundtrip() {
700 let (_, clock, rng) = test_clock_and_rng();
701 let shape = RowShape::testing(&[Type::Uuid4, Type::Uuid7, Type::Int4]);
702 let mut row = shape.allocate();
703
704 let uuid4 = Uuid4::generate();
705 let uuid7 = Uuid7::generate(&clock, &rng);
706 let values = vec![Value::Uuid4(uuid4), Value::Uuid7(uuid7), Value::Int4(123)];
707
708 shape.set_values(&mut row, &values);
709
710 let retrieved_values: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
711
712 assert_eq!(retrieved_values, values);
713 }
714
715 #[test]
716 fn test_uuid_with_undefined() {
717 let (_, clock, rng) = test_clock_and_rng();
718 let shape = RowShape::testing(&[Type::Uuid4, Type::Uuid7]);
719 let mut row = shape.allocate();
720
721 let values = vec![Value::none(), Value::Uuid7(Uuid7::generate(&clock, &rng))];
722
723 shape.set_values(&mut row, &values);
724
725 assert!(!row.is_defined(0));
726 assert!(row.is_defined(1));
727
728 let retrieved_values: Vec<Value> = (0..2).map(|i| shape.get_value(&row, i)).collect();
729
730 assert_eq!(retrieved_values[0], Value::none());
731 assert_eq!(retrieved_values[1], values[1]);
732 }
733
734 #[test]
735 fn test_mixed_blob_row_number_uuid_types() {
736 let (_, clock, rng) = test_clock_and_rng();
737 let shape =
738 RowShape::testing(&[Type::Blob, Type::Int16, Type::Uuid4, Type::Utf8, Type::Uuid7, Type::Int4]);
739 let mut row = shape.allocate();
740
741 let values = vec![
742 Value::Blob(Blob::new(vec![0xCA, 0xFE, 0xBA, 0xBE])),
743 Value::Int16(42424242i128),
744 Value::Uuid4(Uuid4::generate()),
745 Value::Utf8("mixed types test".to_string()),
746 Value::Uuid7(Uuid7::generate(&clock, &rng)),
747 Value::Int4(-999),
748 ];
749
750 shape.set_values(&mut row, &values);
751
752 let retrieved_values: Vec<Value> = (0..6).map(|i| shape.get_value(&row, i)).collect();
753
754 assert_eq!(retrieved_values, values);
755
756 assert!(shape.dynamic_section_size(&row) > 0);
758 }
759
760 #[test]
761 fn test_all_types_comprehensive() {
762 let (_, clock, rng) = test_clock_and_rng();
764
765 let shape = RowShape::testing(&[
766 Type::Boolean,
767 Type::Int1,
768 Type::Int2,
769 Type::Int4,
770 Type::Int8,
771 Type::Int16,
772 Type::Uint1,
773 Type::Uint2,
774 Type::Uint4,
775 Type::Uint8,
776 Type::Uint16,
777 Type::Float4,
778 Type::Float8,
779 Type::Utf8,
780 Type::Date,
781 Type::DateTime,
782 Type::Time,
783 Type::Duration,
784 Type::Uuid4,
785 Type::Uuid7,
786 Type::Blob,
787 ]);
788 let mut row = shape.allocate();
789
790 let values = vec![
791 Value::Boolean(true),
792 Value::Int1(-128),
793 Value::Int2(-32768),
794 Value::Int4(-2147483648),
795 Value::Int8(-9223372036854775808),
796 Value::Int16(-170141183460469231731687303715884105728),
797 Value::Uint1(255),
798 Value::Uint2(65535),
799 Value::Uint4(4294967295),
800 Value::Uint8(18446744073709551615),
801 Value::Uint16(340282366920938463463374607431768211455),
802 Value::Float4(OrderedF32::try_from(3.14159f32).unwrap()),
803 Value::Float8(OrderedF64::try_from(2.718281828459045).unwrap()),
804 Value::Utf8("comprehensive test".to_string()),
805 Value::Date(Date::new(2025, 12, 31).unwrap()),
806 Value::DateTime(DateTime::new(2025, 1, 1, 0, 0, 0, 0).unwrap()),
807 Value::Time(Time::new(23, 59, 59, 999999999).unwrap()),
808 Value::Duration(Duration::from_hours(24).unwrap()),
809 Value::Uuid4(Uuid4::generate()),
810 Value::Uuid7(Uuid7::generate(&clock, &rng)),
811 Value::Blob(Blob::new(vec![
812 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
813 0xEE, 0xFF,
814 ])),
815 ];
816
817 shape.set_values(&mut row, &values);
818
819 let retrieved_values: Vec<Value> = (0..21).map(|i| shape.get_value(&row, i)).collect();
820
821 assert_eq!(retrieved_values, values);
822
823 for i in 0..21 {
825 assert!(row.is_defined(i), "Field {} should be defined", i);
826 }
827 }
828
829 #[test]
830 fn test_dictionary_id_roundtrip_u4() {
831 let constraint = TypeConstraint::dictionary(DictionaryId::from(42u64), Type::Uint4);
832 let shape = RowShape::new(vec![RowShapeField::new("status", constraint)]);
833
834 let mut row = shape.allocate();
835 let entry = DictionaryEntryId::U4(7);
836 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
837
838 assert!(row.is_defined(0));
839 let retrieved = shape.get_value(&row, 0);
840 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U4(7)));
841 }
842
843 #[test]
844 fn test_dictionary_id_roundtrip_u2() {
845 let constraint = TypeConstraint::dictionary(DictionaryId::from(10u64), Type::Uint2);
846 let shape = RowShape::new(vec![RowShapeField::new("category", constraint)]);
847
848 let mut row = shape.allocate();
849 let entry = DictionaryEntryId::U2(500);
850 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
851
852 assert!(row.is_defined(0));
853 let retrieved = shape.get_value(&row, 0);
854 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U2(500)));
855 }
856
857 #[test]
858 fn test_dictionary_id_roundtrip_u8() {
859 let constraint = TypeConstraint::dictionary(DictionaryId::from(99u64), Type::Uint8);
860 let shape = RowShape::new(vec![RowShapeField::new("tag", constraint)]);
861
862 let mut row = shape.allocate();
863 let entry = DictionaryEntryId::U8(123456789);
864 shape.set_value(&mut row, 0, &Value::DictionaryId(entry));
865
866 assert!(row.is_defined(0));
867 let retrieved = shape.get_value(&row, 0);
868 assert_eq!(retrieved, Value::DictionaryId(DictionaryEntryId::U8(123456789)));
869 }
870
871 #[test]
872 fn test_dictionary_id_with_undefined() {
873 let constraint = TypeConstraint::dictionary(DictionaryId::from(1u64), Type::Uint4);
874 let shape = RowShape::new(vec![
875 RowShapeField::new("dict_col", constraint),
876 RowShapeField::unconstrained("int_col", Type::Int4),
877 ]);
878
879 let mut row = shape.allocate();
880 shape.set_value(&mut row, 0, &Value::none());
881 shape.set_value(&mut row, 1, &Value::Int4(42));
882
883 assert!(!row.is_defined(0));
884 assert!(row.is_defined(1));
885
886 assert_eq!(shape.get_value(&row, 0), Value::none());
887 assert_eq!(shape.get_value(&row, 1), Value::Int4(42));
888 }
889
890 #[test]
891 fn test_dictionary_id_mixed_with_other_types() {
892 let dict_constraint = TypeConstraint::dictionary(DictionaryId::from(5u64), Type::Uint4);
893 let shape = RowShape::new(vec![
894 RowShapeField::unconstrained("id", Type::Int4),
895 RowShapeField::new("status", dict_constraint),
896 RowShapeField::unconstrained("name", Type::Utf8),
897 ]);
898
899 let mut row = shape.allocate();
900 let values = vec![
901 Value::Int4(100),
902 Value::DictionaryId(DictionaryEntryId::U4(3)),
903 Value::Utf8("test".to_string()),
904 ];
905 shape.set_values(&mut row, &values);
906
907 let retrieved: Vec<Value> = (0..3).map(|i| shape.get_value(&row, i)).collect();
908 assert_eq!(retrieved, values);
909 }
910}