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