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