Skip to main content

reifydb_core/encoded/
value.rs

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