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