Skip to main content

reifydb_core/encoded/
value.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use 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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(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_undefined(row, index),
210			(
211				Type::Uint,
212				Value::None {
213					..
214				},
215			) => self.set_undefined(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_undefined(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_undefined(row, index),
239
240			(Type::Any, Value::Any(_)) => unreachable!("Any type cannot be stored in database"),
241			(
242				Type::Any,
243				Value::None {
244					..
245				},
246			) => self.set_undefined(row, index),
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 => unreachable!("Any type cannot be stored in database"),
298		}
299	}
300}
301
302#[cfg(test)]
303#[allow(clippy::approx_constant)]
304pub mod tests {
305	use reifydb_type::value::{
306		Value,
307		blob::Blob,
308		constraint::TypeConstraint,
309		date::Date,
310		datetime::DateTime,
311		dictionary::{DictionaryEntryId, DictionaryId},
312		duration::Duration,
313		ordered_f32::OrderedF32,
314		ordered_f64::OrderedF64,
315		time::Time,
316		r#type::Type,
317		uuid::{Uuid4, Uuid7},
318	};
319
320	use crate::encoded::schema::{Schema, SchemaField};
321
322	#[test]
323	fn test_set_utf8_with_dynamic_content() {
324		let schema = Schema::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
325		let mut row = schema.allocate();
326
327		let value1 = Value::Utf8("hello".to_string());
328		let value2 = Value::Int4(42);
329		let value3 = Value::Utf8("world".to_string());
330
331		schema.set_value(&mut row, 0, &value1);
332		schema.set_value(&mut row, 1, &value2);
333		schema.set_value(&mut row, 2, &value3);
334
335		assert_eq!(schema.get_utf8(&row, 0), "hello");
336		assert_eq!(schema.get_i32(&row, 1), 42);
337		assert_eq!(schema.get_utf8(&row, 2), "world");
338	}
339
340	#[test]
341	fn test_set_values_with_mixed_dynamic_content() {
342		let schema = Schema::testing(&[Type::Boolean, Type::Utf8, Type::Float4, Type::Utf8, Type::Int2]);
343		let mut row = schema.allocate();
344
345		let values = vec![
346			Value::Boolean(true),
347			Value::Utf8("first_string".to_string()),
348			Value::Float4(OrderedF32::try_from(3.14f32).unwrap()),
349			Value::Utf8("second_string".to_string()),
350			Value::Int2(-100),
351		];
352
353		schema.set_values(&mut row, &values);
354
355		assert_eq!(schema.get_bool(&row, 0), true);
356		assert_eq!(schema.get_utf8(&row, 1), "first_string");
357		assert_eq!(schema.get_f32(&row, 2), 3.14f32);
358		assert_eq!(schema.get_utf8(&row, 3), "second_string");
359		assert_eq!(schema.get_i16(&row, 4), -100);
360	}
361
362	#[test]
363	fn test_set_with_empty_and_large_utf8() {
364		let schema = Schema::testing(&[Type::Utf8, Type::Utf8, Type::Utf8]);
365		let mut row = schema.allocate();
366
367		let large_string = "X".repeat(2000);
368		let values = vec![
369			Value::Utf8("".to_string()),
370			Value::Utf8(large_string.clone()),
371			Value::Utf8("small".to_string()),
372		];
373
374		schema.set_values(&mut row, &values);
375
376		assert_eq!(schema.get_utf8(&row, 0), "");
377		assert_eq!(schema.get_utf8(&row, 1), large_string);
378		assert_eq!(schema.get_utf8(&row, 2), "small");
379		assert_eq!(schema.dynamic_section_size(&row), 2005); // 0 + 2000 + 5
380	}
381
382	#[test]
383	fn test_get_from_dynamic_content() {
384		let schema = Schema::testing(&[Type::Utf8, Type::Int8, Type::Utf8]);
385		let mut row = schema.allocate();
386
387		schema.set_utf8(&mut row, 0, "test_string");
388		schema.set_i64(&mut row, 1, 9876543210i64);
389		schema.set_utf8(&mut row, 2, "another_string");
390
391		let value0 = schema.get_value(&row, 0);
392		let value1 = schema.get_value(&row, 1);
393		let value2 = schema.get_value(&row, 2);
394
395		match value0 {
396			Value::Utf8(s) => assert_eq!(s, "test_string"),
397			_ => panic!("Expected UTF8 value"),
398		}
399
400		match value1 {
401			Value::Int8(i) => assert_eq!(i, 9876543210),
402			_ => panic!("Expected Int8 value"),
403		}
404
405		match value2 {
406			Value::Utf8(s) => assert_eq!(s, "another_string"),
407			_ => panic!("Expected UTF8 value"),
408		}
409	}
410
411	#[test]
412	fn test_set_undefined_with_utf8_fields() {
413		let schema = Schema::testing(&[Type::Utf8, Type::Boolean, Type::Utf8]);
414		let mut row = schema.allocate();
415
416		// Set some values
417		schema.set_value(&mut row, 0, &Value::Utf8("hello".to_string()));
418		schema.set_value(&mut row, 1, &Value::Boolean(true));
419		schema.set_value(&mut row, 2, &Value::Utf8("world".to_string()));
420
421		assert!(row.is_defined(0));
422		assert!(row.is_defined(1));
423		assert!(row.is_defined(2));
424
425		// Set some as undefined
426		schema.set_value(&mut row, 0, &Value::none());
427		schema.set_value(&mut row, 2, &Value::none());
428
429		assert!(!row.is_defined(0));
430		assert!(row.is_defined(1));
431		assert!(!row.is_defined(2));
432
433		assert_eq!(schema.get_bool(&row, 1), true);
434	}
435
436	#[test]
437	fn test_get_all_types_including_utf8() {
438		let schema = Schema::testing(&[
439			Type::Boolean,
440			Type::Int1,
441			Type::Int2,
442			Type::Int4,
443			Type::Int8,
444			Type::Uint1,
445			Type::Uint2,
446			Type::Uint4,
447			Type::Uint8,
448			Type::Float4,
449			Type::Float8,
450			Type::Utf8,
451		]);
452		let mut row = schema.allocate();
453
454		schema.set_bool(&mut row, 0, true);
455		schema.set_i8(&mut row, 1, -42);
456		schema.set_i16(&mut row, 2, -1000i16);
457		schema.set_i32(&mut row, 3, -50000i32);
458		schema.set_i64(&mut row, 4, -3000000000i64);
459		schema.set_u8(&mut row, 5, 200u8);
460		schema.set_u16(&mut row, 6, 50000u16);
461		schema.set_u32(&mut row, 7, 3000000000u32);
462		schema.set_u64(&mut row, 8, 15000000000000000000u64);
463		schema.set_f32(&mut row, 9, 2.5);
464		schema.set_f64(&mut row, 10, 123.456789);
465		schema.set_utf8(&mut row, 11, "dynamic_string");
466
467		let values: Vec<Value> = (0..12).map(|i| schema.get_value(&row, i)).collect();
468
469		assert_eq!(values[0], Value::Boolean(true));
470		assert_eq!(values[1], Value::Int1(-42));
471		assert_eq!(values[2], Value::Int2(-1000));
472		assert_eq!(values[3], Value::Int4(-50000));
473		assert_eq!(values[4], Value::Int8(-3000000000));
474		assert_eq!(values[5], Value::Uint1(200));
475		assert_eq!(values[6], Value::Uint2(50000));
476		assert_eq!(values[7], Value::Uint4(3000000000));
477		assert_eq!(values[8], Value::Uint8(15000000000000000000));
478		assert_eq!(values[9], Value::Float4(OrderedF32::try_from(2.5f32).unwrap()));
479		assert_eq!(values[10], Value::Float8(OrderedF64::try_from(123.456789f64).unwrap()));
480		assert_eq!(values[11], Value::Utf8("dynamic_string".to_string()));
481	}
482
483	#[test]
484	fn test_set_values_sparse_with_utf8() {
485		let schema = Schema::testing(&[Type::Utf8, Type::Utf8, Type::Utf8, Type::Utf8]);
486		let mut row = schema.allocate();
487
488		// Only set some values
489		let values = vec![
490			Value::Utf8("first".to_string()),
491			Value::none(),
492			Value::Utf8("third".to_string()),
493			Value::none(),
494		];
495
496		schema.set_values(&mut row, &values);
497
498		assert!(row.is_defined(0));
499		assert!(!row.is_defined(1));
500		assert!(row.is_defined(2));
501		assert!(!row.is_defined(3));
502
503		assert_eq!(schema.get_utf8(&row, 0), "first");
504		assert_eq!(schema.get_utf8(&row, 2), "third");
505	}
506
507	#[test]
508	fn test_set_values_unicode_strings() {
509		let schema = Schema::testing(&[Type::Utf8, Type::Int4, Type::Utf8]);
510		let mut row = schema.allocate();
511
512		let values = vec![
513			Value::Utf8("πŸŽ‰πŸš€βœ¨".to_string()),
514			Value::Int4(123),
515			Value::Utf8("Hello δΈ–η•Œ".to_string()),
516		];
517
518		schema.set_values(&mut row, &values);
519
520		assert_eq!(schema.get_utf8(&row, 0), "πŸŽ‰πŸš€βœ¨");
521		assert_eq!(schema.get_i32(&row, 1), 123);
522		assert_eq!(schema.get_utf8(&row, 2), "Hello δΈ–η•Œ");
523	}
524
525	#[test]
526	fn test_static_fields_only_no_dynamic_with_values() {
527		let schema = Schema::testing(&[Type::Boolean, Type::Int4, Type::Float8]);
528		let mut row = schema.allocate();
529
530		let values = vec![
531			Value::Boolean(false),
532			Value::Int4(999),
533			Value::Float8(OrderedF64::try_from(std::f64::consts::E).unwrap()),
534		];
535
536		schema.set_values(&mut row, &values);
537
538		// Verify no dynamic section
539		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), std::f64::consts::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		// Set values
636		schema.set_values(&mut row, &original_values);
637
638		// Get values back
639		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		// Verify blob content directly
660		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		// Verify dynamic content exists (for blob and utf8)
751		assert!(schema.dynamic_section_size(&row) > 0);
752	}
753
754	#[test]
755	fn test_all_types_comprehensive() {
756		// except encoded id
757
758		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		// Verify all fields are defined
817		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}