1use std::fmt;
29use std::ops::Index;
30
31use crate::{CompactArc, CompactVec, DataType, Error, LogicalTypeRef, Result, Value};
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub struct RowColumnRef<'a> {
36 pub name: &'a str,
37 pub data_type: DataType,
38 pub logical_type: LogicalTypeRef,
39 pub nullable: bool,
40}
41
42impl<'a> RowColumnRef<'a> {
43 pub const fn new(name: &'a str, data_type: DataType, nullable: bool) -> Self {
44 Self {
45 name,
46 data_type,
47 logical_type: LogicalTypeRef::Builtin(data_type),
48 nullable,
49 }
50 }
51
52 pub const fn with_logical_type(mut self, logical_type: LogicalTypeRef) -> Self {
53 self.logical_type = logical_type;
54 self
55 }
56}
57
58pub trait RowSchema {
62 fn row_column_count(&self) -> usize;
63 fn row_column(&self, index: usize) -> Option<RowColumnRef<'_>>;
64}
65
66#[derive(Debug, Clone)]
73enum RowStorage {
74 Shared(CompactArc<[Value]>),
76 Owned(CompactVec<Value>),
78}
79
80impl Default for RowStorage {
81 fn default() -> Self {
82 RowStorage::Owned(CompactVec::new())
83 }
84}
85
86impl PartialEq for RowStorage {
87 #[inline]
88 fn eq(&self, other: &Self) -> bool {
89 match (self, other) {
90 (RowStorage::Shared(a), RowStorage::Shared(b)) => {
91 CompactArc::ptr_eq(a, b) || a.as_ref() == b.as_ref()
93 }
94 (RowStorage::Owned(a), RowStorage::Owned(b)) => a.as_slice() == b.as_slice(),
95 (RowStorage::Shared(a), RowStorage::Owned(b)) => a.as_ref() == b.as_slice(),
97 (RowStorage::Owned(a), RowStorage::Shared(b)) => a.as_slice() == b.as_ref(),
98 }
99 }
100}
101
102impl RowStorage {
103 #[inline(always)]
105 fn get(&self, index: usize) -> Option<&Value> {
106 match self {
107 RowStorage::Shared(arc) => arc.get(index),
108 RowStorage::Owned(vec) => vec.get(index),
109 }
110 }
111
112 #[inline(always)]
113 fn len(&self) -> usize {
114 match self {
115 RowStorage::Shared(arc) => arc.len(),
116 RowStorage::Owned(vec) => vec.len(),
117 }
118 }
119
120 #[inline]
121 fn is_empty(&self) -> bool {
122 self.len() == 0
123 }
124
125 #[inline]
127 fn make_mut(&mut self) -> &mut CompactVec<Value> {
128 match self {
129 RowStorage::Owned(vec) => vec,
130 RowStorage::Shared(arc) => {
131 let len = arc.len();
135 let mut vec = CompactVec::with_capacity(len);
136 vec.extend_clone(arc);
137 *self = RowStorage::Owned(vec);
138 match self {
139 RowStorage::Owned(vec) => vec,
140 _ => unreachable!(),
141 }
142 }
143 }
144 }
145
146 #[inline]
148 fn into_vec(self) -> Vec<Value> {
149 match self {
150 RowStorage::Owned(vec) => vec.into_vec(),
151 RowStorage::Shared(arc) => arc.iter().cloned().collect(),
152 }
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, Default)]
167pub struct Row {
168 storage: RowStorage,
169}
170
171pub struct RowIter<'a> {
173 inner: std::slice::Iter<'a, Value>,
174}
175
176impl<'a> Iterator for RowIter<'a> {
177 type Item = &'a Value;
178
179 #[inline]
180 fn next(&mut self) -> Option<Self::Item> {
181 self.inner.next()
182 }
183
184 #[inline]
185 fn size_hint(&self) -> (usize, Option<usize>) {
186 self.inner.size_hint()
187 }
188}
189
190impl<'a> ExactSizeIterator for RowIter<'a> {
191 fn len(&self) -> usize {
192 self.inner.len()
193 }
194}
195
196impl<'a> DoubleEndedIterator for RowIter<'a> {
197 fn next_back(&mut self) -> Option<Self::Item> {
198 self.inner.next_back()
199 }
200}
201
202pub struct RowIterMut<'a> {
204 inner: std::slice::IterMut<'a, Value>,
205}
206
207impl<'a> Iterator for RowIterMut<'a> {
208 type Item = &'a mut Value;
209
210 #[inline]
211 fn next(&mut self) -> Option<Self::Item> {
212 self.inner.next()
213 }
214
215 #[inline]
216 fn size_hint(&self) -> (usize, Option<usize>) {
217 self.inner.size_hint()
218 }
219}
220
221impl<'a> ExactSizeIterator for RowIterMut<'a> {
222 fn len(&self) -> usize {
223 self.inner.len()
224 }
225}
226
227impl Row {
228 #[inline]
230 pub fn new() -> Self {
231 Self {
232 storage: RowStorage::Owned(CompactVec::new()),
233 }
234 }
235
236 #[inline]
238 pub fn with_capacity(capacity: usize) -> Self {
239 Self {
240 storage: RowStorage::Owned(CompactVec::with_capacity(capacity)),
241 }
242 }
243
244 #[inline]
246 pub fn from_values(values: Vec<Value>) -> Self {
247 Self {
248 storage: RowStorage::Owned(CompactVec::from_vec(values)),
249 }
250 }
251
252 #[inline]
254 pub fn from_compact_vec(values: CompactVec<Value>) -> Self {
255 Self {
256 storage: RowStorage::Owned(values),
257 }
258 }
259
260 #[inline]
262 pub fn from_arc(values: CompactArc<[Value]>) -> Self {
263 Self {
264 storage: RowStorage::Shared(values),
265 }
266 }
267
268 #[inline]
271 pub fn from_combined(left: &Row, right: &Row) -> Self {
272 let total_len = left.len() + right.len();
273 let mut values = CompactVec::with_capacity(total_len);
274 values.extend_clone(left.as_slice());
276 values.extend_clone(right.as_slice());
277 Self {
278 storage: RowStorage::Owned(values),
279 }
280 }
281
282 #[inline]
284 pub fn combine_into_owned(&mut self, left: Row, right: Row) {
285 let total_len = left.len() + right.len();
286 let vec = self.storage.make_mut();
287 vec.clear();
288 vec.reserve(total_len);
289 match left.storage {
291 RowStorage::Owned(left_vec) => vec.extend(left_vec),
292 RowStorage::Shared(arc) => vec.extend_clone(&arc),
293 }
294 match right.storage {
296 RowStorage::Owned(right_vec) => vec.extend(right_vec),
297 RowStorage::Shared(arc) => vec.extend_clone(&arc),
298 }
299 }
300
301 #[inline]
303 pub fn from_combined_clone_move(left: &Row, right: Row) -> Self {
304 let total_len = left.len() + right.len();
305 let mut values = CompactVec::with_capacity(total_len);
306 values.extend_clone(left.as_slice());
308 match right.storage {
309 RowStorage::Owned(right_vec) => values.extend(right_vec),
310 RowStorage::Shared(arc) => values.extend_clone(&arc),
311 }
312 Self {
313 storage: RowStorage::Owned(values),
314 }
315 }
316
317 #[inline]
319 pub fn from_combined_owned(left: Row, right: Row) -> Self {
320 match (left.storage, right.storage) {
322 (RowStorage::Owned(mut left_vec), RowStorage::Owned(right_vec)) => {
323 left_vec.reserve(right_vec.len());
324 left_vec.extend(right_vec);
325 Self {
326 storage: RowStorage::Owned(left_vec),
327 }
328 }
329 (left_storage, right_storage) => {
330 let left_len = left_storage.len();
331 let right_len = right_storage.len();
332 let mut values = CompactVec::with_capacity(left_len + right_len);
333 match left_storage {
335 RowStorage::Owned(v) => values.extend(v),
336 RowStorage::Shared(a) => values.extend_clone(&a),
337 }
338 match right_storage {
339 RowStorage::Owned(v) => values.extend(v),
340 RowStorage::Shared(a) => values.extend_clone(&a),
341 }
342 Self {
343 storage: RowStorage::Owned(values),
344 }
345 }
346 }
347 }
348
349 #[inline]
351 pub fn null_row<S: RowSchema + ?Sized>(schema: &S) -> Self {
352 let values: CompactVec<Value> = (0..schema.row_column_count())
353 .map(|index| {
354 let column = schema
355 .row_column(index)
356 .expect("RowSchema must resolve every declared column index");
357 Value::null(column.data_type)
358 })
359 .collect();
360 Self {
361 storage: RowStorage::Owned(values),
362 }
363 }
364
365 #[inline(always)]
367 pub fn len(&self) -> usize {
368 self.storage.len()
369 }
370
371 #[inline]
373 pub fn is_empty(&self) -> bool {
374 self.storage.is_empty()
375 }
376
377 #[inline(always)]
379 pub fn get(&self, index: usize) -> Option<&Value> {
380 self.storage.get(index)
381 }
382
383 #[inline]
385 pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
386 self.storage.make_mut().get_mut(index)
387 }
388
389 pub fn set(&mut self, index: usize, value: Value) -> Result<()> {
391 let vec = self.storage.make_mut();
392 if index >= vec.len() {
393 return Err(Error::Internal {
394 message: format!("row index {} out of bounds (len={})", index, vec.len()),
395 });
396 }
397 vec[index] = value;
398 Ok(())
399 }
400
401 #[inline]
403 pub fn push(&mut self, value: Value) {
404 self.storage.make_mut().push(value);
405 }
406
407 #[inline]
409 pub fn pop(&mut self) -> Option<Value> {
410 self.storage.make_mut().pop()
411 }
412
413 #[inline]
419 #[doc(hidden)]
420 pub fn remove_column(&mut self, index: usize) -> Option<Value> {
421 (index < self.len()).then(|| self.storage.make_mut().remove(index))
422 }
423
424 #[inline]
426 pub fn truncate(&mut self, len: usize) {
427 self.storage.make_mut().truncate(len);
428 }
429
430 #[inline]
432 pub fn clear(&mut self) {
433 self.storage.make_mut().clear();
434 }
435
436 #[inline]
439 pub fn take_and_clear(&mut self) -> Row {
440 match &mut self.storage {
441 RowStorage::Owned(vec) => {
442 let cap = vec.capacity();
443 let values = std::mem::replace(vec, CompactVec::with_capacity(cap));
444 Row {
445 storage: RowStorage::Owned(values),
446 }
447 }
448 RowStorage::Shared(arc) => {
449 let result = Row {
450 storage: RowStorage::Shared(arc.clone()),
451 };
452 *self = Row::new();
453 result
454 }
455 }
456 }
457
458 #[inline]
460 pub fn reserve(&mut self, additional: usize) {
461 self.storage.make_mut().reserve(additional);
462 }
463
464 #[inline]
466 pub fn extend_from_slice(&mut self, other: &[Value]) {
467 self.storage.make_mut().extend_clone(other);
468 }
469
470 #[inline]
477 pub fn extend_into_compact_vec(self, target: &mut CompactVec<Value>) {
478 match self.storage {
479 RowStorage::Owned(vec) => target.extend(vec),
480 RowStorage::Shared(arc) => target.extend_clone(&arc),
481 }
482 }
483
484 #[inline(always)]
486 pub fn iter(&self) -> RowIter<'_> {
487 RowIter {
488 inner: match &self.storage {
489 RowStorage::Shared(arc) => arc.iter(),
490 RowStorage::Owned(vec) => vec.iter(),
491 },
492 }
493 }
494
495 #[inline]
497 pub fn iter_mut(&mut self) -> RowIterMut<'_> {
498 RowIterMut {
499 inner: self.storage.make_mut().iter_mut(),
500 }
501 }
502
503 #[inline]
505 pub fn into_values(self) -> Vec<Value> {
506 self.storage.into_vec()
507 }
508
509 #[inline]
511 pub fn take_first_value(self) -> Option<Value> {
512 match self.storage {
513 RowStorage::Owned(mut vec) => {
514 if vec.is_empty() {
515 None
516 } else {
517 Some(vec.swap_remove(0))
518 }
519 }
520 RowStorage::Shared(arc) => arc.first().cloned(),
521 }
522 }
523
524 #[inline]
526 pub fn is_shared(&self) -> bool {
527 matches!(self.storage, RowStorage::Shared(_))
528 }
529
530 #[inline]
532 pub fn is_owned(&self) -> bool {
533 matches!(self.storage, RowStorage::Owned(_))
534 }
535
536 #[inline]
540 pub fn into_arc(self) -> CompactArc<[Value]> {
541 match self.storage {
542 RowStorage::Shared(arc) => arc,
543 RowStorage::Owned(vec) => CompactArc::from_compact_vec(vec),
545 }
546 }
547
548 #[inline]
550 pub fn as_arc(&self) -> Option<&CompactArc<[Value]>> {
551 match &self.storage {
552 RowStorage::Shared(arc) => Some(arc),
553 RowStorage::Owned(_) => None,
554 }
555 }
556
557 #[inline]
559 pub fn as_slice(&self) -> &[Value] {
560 match &self.storage {
561 RowStorage::Shared(arc) => arc,
562 RowStorage::Owned(vec) => vec.as_slice(),
563 }
564 }
565
566 #[inline]
568 pub fn select_columns(&self, indices: &[usize]) -> Result<Row> {
569 self.validate_projection_indices(indices)?;
570 let mut values = CompactVec::with_capacity(indices.len());
571 for &idx in indices {
572 values.push(
573 self.storage
574 .get(idx)
575 .expect("projection index validated")
576 .clone(),
577 );
578 }
579 Ok(Row::from_compact_vec(values))
580 }
581
582 #[inline]
583 fn validate_projection_indices(&self, indices: &[usize]) -> Result<()> {
584 let len = self.len();
585 if let Some(&idx) = indices.iter().find(|&&idx| idx >= len) {
586 return Err(Error::Internal {
587 message: format!("column index {} out of bounds (len={})", idx, len),
588 });
589 }
590 Ok(())
591 }
592
593 #[inline]
596 pub fn take_columns(self, indices: &[usize]) -> Result<Row> {
597 self.validate_projection_indices(indices)?;
598 let is_prefix = !indices.is_empty() && indices.iter().enumerate().all(|(i, &idx)| i == idx);
600
601 if is_prefix {
602 match self.storage {
603 RowStorage::Owned(mut vec) => {
604 vec.truncate(indices.len());
605 return Ok(Row {
606 storage: RowStorage::Owned(vec),
607 });
608 }
609 RowStorage::Shared(ref arc) if indices.len() == arc.len() => {
610 return Ok(self);
611 }
612 RowStorage::Shared(arc) => {
613 let values: CompactVec<Value> = arc[..indices.len()].iter().cloned().collect();
615 return Ok(Row {
616 storage: RowStorage::Owned(values),
617 });
618 }
619 }
620 }
621
622 let mut values = CompactVec::with_capacity(indices.len());
624 let slice = self.as_slice();
625 for &idx in indices {
626 values.push(slice[idx].clone());
627 }
628 Ok(Row {
629 storage: RowStorage::Owned(values),
630 })
631 }
632
633 pub fn validate<S: RowSchema + ?Sized>(&self, schema: &S) -> Result<()> {
635 let len = self.len();
636 let column_count = schema.row_column_count();
637
638 if len != column_count {
640 return Err(Error::table_columns_not_match(column_count, len));
641 }
642
643 for (i, value) in self.iter().enumerate() {
645 let col = schema
646 .row_column(i)
647 .expect("RowSchema must resolve every declared column index");
648 if value.is_null() && !col.nullable {
650 return Err(Error::not_null_constraint(col.name));
651 }
652
653 if !value.is_null() {
655 let value_type = value.logical_type();
656 if value_type != col.logical_type {
657 let compatible = matches!(
659 (value_type, col.logical_type),
660 (
661 LogicalTypeRef::Builtin(DataType::Integer),
662 LogicalTypeRef::Builtin(DataType::Float)
663 ) | (
664 LogicalTypeRef::Builtin(DataType::Float),
665 LogicalTypeRef::Builtin(DataType::Integer)
666 )
667 );
668 if !compatible {
669 return Err(Error::type_conversion(
670 format!("column {} at index {}: {:?}", col.name, i, value_type),
671 format!("{:?}", col.logical_type),
672 ));
673 }
674 }
675 }
676 }
677
678 Ok(())
679 }
680
681 #[inline]
683 pub fn clone_subset(&self, indices: &[usize]) -> Result<Row> {
684 self.select_columns(indices)
685 }
686
687 pub fn concat(&self, other: &Row) -> Row {
689 let total_len = self.len() + other.len();
690 let mut values = CompactVec::with_capacity(total_len);
691 values.extend(self.iter().cloned());
692 values.extend(other.iter().cloned());
693 Row::from_compact_vec(values)
694 }
695
696 pub fn repeat(value: Value, count: usize) -> Row {
698 let mut values = CompactVec::with_capacity(count);
699 for _ in 0..count {
700 values.push(value.clone());
701 }
702 Row::from_compact_vec(values)
703 }
704
705 #[inline]
710 pub fn is_inline(&self) -> bool {
711 self.is_owned()
712 }
713
714 #[inline]
716 pub fn clear_inline(&mut self) {
717 self.clear();
718 }
719
720 #[inline]
722 pub fn push_inline(&mut self, value: Value) {
723 self.push(value);
724 }
725
726 #[inline]
728 pub fn reserve_inline(&mut self, capacity: usize) {
729 let vec = self.storage.make_mut();
730 if vec.capacity() < capacity {
731 vec.reserve(capacity - vec.len());
732 }
733 }
734}
735
736impl Index<usize> for Row {
738 type Output = Value;
739
740 #[inline]
741 fn index(&self, index: usize) -> &Self::Output {
742 self.storage.get(index).expect("row index out of bounds")
743 }
744}
745
746impl FromIterator<Value> for Row {
748 fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
749 Row::from_compact_vec(iter.into_iter().collect())
750 }
751}
752
753impl IntoIterator for Row {
755 type Item = Value;
756 type IntoIter = std::vec::IntoIter<Value>;
757
758 fn into_iter(self) -> Self::IntoIter {
759 self.storage.into_vec().into_iter()
760 }
761}
762
763impl<'a> IntoIterator for &'a Row {
764 type Item = &'a Value;
765 type IntoIter = RowIter<'a>;
766
767 fn into_iter(self) -> Self::IntoIter {
768 self.iter()
769 }
770}
771
772impl From<Vec<Value>> for Row {
773 fn from(values: Vec<Value>) -> Self {
774 Row::from_values(values)
775 }
776}
777
778impl From<CompactArc<[Value]>> for Row {
779 fn from(values: CompactArc<[Value]>) -> Self {
780 Row::from_arc(values)
781 }
782}
783
784impl fmt::Display for Row {
785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786 write!(f, "(")?;
787 for (i, value) in self.iter().enumerate() {
788 if i > 0 {
789 write!(f, ", ")?;
790 }
791 write!(f, "{}", value)?;
792 }
793 write!(f, ")")
794 }
795}
796
797#[macro_export]
799macro_rules! row {
800 () => {
801 $crate::Row::new()
802 };
803 ($($value:expr),+ $(,)?) => {
804 $crate::Row::from_values(vec![$($crate::Value::from($value)),+])
805 };
806}
807
808#[cfg(test)]
809mod tests {
810 use super::*;
811 use crate::CompactArc;
812
813 struct TestSchema(Vec<(&'static str, DataType, bool)>);
814
815 impl RowSchema for TestSchema {
816 fn row_column_count(&self) -> usize {
817 self.0.len()
818 }
819
820 fn row_column(&self, index: usize) -> Option<RowColumnRef<'_>> {
821 self.0
822 .get(index)
823 .map(|(name, data_type, nullable)| RowColumnRef::new(name, *data_type, *nullable))
824 }
825 }
826
827 fn create_test_schema() -> TestSchema {
828 TestSchema(vec![
829 ("id", DataType::Integer, false),
830 ("name", DataType::Text, false),
831 ("email", DataType::Text, true),
832 ])
833 }
834
835 #[test]
836 fn test_row_creation() {
837 let row = Row::new();
838 assert!(row.is_empty());
839 assert_eq!(row.len(), 0);
840
841 let row = Row::with_capacity(10);
842 assert!(row.is_empty());
843 }
844
845 #[test]
846 fn test_row_from_values() {
847 let values = vec![
848 Value::integer(1),
849 Value::text("hello"),
850 Value::null(DataType::Text),
851 ];
852 let row = Row::from_values(values);
853 assert_eq!(row.len(), 3);
854 assert!(row.is_owned());
855 }
856
857 #[test]
858 fn test_row_from_arc() {
859 let values: CompactArc<[Value]> =
860 CompactArc::from(vec![Value::integer(1), Value::text("hello")]);
861 let row = Row::from_arc(values);
862 assert_eq!(row.len(), 2);
863 assert!(row.is_shared());
864
865 let row2 = row.clone();
867 assert_eq!(row2.len(), 2);
868 assert_eq!(row, row2);
869 assert!(row2.is_shared());
870 }
871
872 #[test]
873 fn test_row_push_pop() {
874 let mut row = Row::new();
875 row.push(Value::integer(1));
876 row.push(Value::text("hello"));
877
878 assert_eq!(row.len(), 2);
879
880 let popped = row.pop();
881 assert_eq!(popped, Some(Value::text("hello")));
882 assert_eq!(row.len(), 1);
883 }
884
885 #[test]
886 fn test_row_copy_on_write() {
887 let values: CompactArc<[Value]> =
889 CompactArc::from(vec![Value::integer(1), Value::text("hello")]);
890 let mut row = Row::from_arc(values);
891 assert!(row.is_shared());
892
893 row.push(Value::integer(2));
895 assert_eq!(row.len(), 3);
896 assert!(row.is_owned()); }
898
899 #[test]
900 fn test_row_get_set() {
901 let mut row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
902
903 assert_eq!(row.get(0), Some(&Value::integer(1)));
904 assert_eq!(row.get(1), Some(&Value::text("hello")));
905 assert_eq!(row.get(2), None);
906
907 row.set(1, Value::text("world")).unwrap();
908 assert_eq!(row.get(1), Some(&Value::text("world")));
909
910 assert!(row.set(10, Value::integer(0)).is_err());
911 }
912
913 #[test]
914 fn test_row_index() {
915 let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
916
917 assert_eq!(row[0], Value::integer(1));
918 assert_eq!(row[1], Value::text("hello"));
919 }
920
921 #[test]
922 fn test_row_iteration() {
923 let row = Row::from_values(vec![
924 Value::integer(1),
925 Value::integer(2),
926 Value::integer(3),
927 ]);
928
929 let sum: i64 = row.iter().filter_map(|v| v.as_int64()).sum();
930 assert_eq!(sum, 6);
931 }
932
933 #[test]
934 fn test_row_select_columns() {
935 let row = Row::from_values(vec![
936 Value::integer(1),
937 Value::text("hello"),
938 Value::float(3.5),
939 Value::boolean(true),
940 ]);
941
942 let selected = row.select_columns(&[0, 2]).unwrap();
943 assert_eq!(selected.len(), 2);
944 assert_eq!(selected[0], Value::integer(1));
945 assert_eq!(selected[1], Value::float(3.5));
946
947 assert!(row.select_columns(&[0, 10]).is_err());
948 }
949
950 #[test]
951 fn test_row_validate() {
952 let schema = create_test_schema();
953
954 let row = Row::from_values(vec![
956 Value::integer(1),
957 Value::text("Alice"),
958 Value::null(DataType::Text),
959 ]);
960 assert!(row.validate(&schema).is_ok());
961
962 let row = Row::from_values(vec![Value::integer(1)]);
964 assert!(row.validate(&schema).is_err());
965
966 let row = Row::from_values(vec![
968 Value::integer(1),
969 Value::null(DataType::Text), Value::null(DataType::Text),
971 ]);
972 let err = row.validate(&schema).unwrap_err();
973 assert!(matches!(err, Error::NotNullConstraint { .. }));
974 }
975
976 #[test]
977 fn test_row_null_row() {
978 let schema = create_test_schema();
979 let row = Row::null_row(&schema);
980
981 assert_eq!(row.len(), 3);
982 assert!(row[0].is_null());
983 assert!(row[1].is_null());
984 assert!(row[2].is_null());
985 }
986
987 #[test]
988 fn test_row_concat() {
989 let row1 = Row::from_values(vec![Value::integer(1), Value::integer(2)]);
990 let row2 = Row::from_values(vec![Value::integer(3), Value::integer(4)]);
991
992 let combined = row1.concat(&row2);
993 assert_eq!(combined.len(), 4);
994 assert_eq!(combined[0], Value::integer(1));
995 assert_eq!(combined[3], Value::integer(4));
996 }
997
998 #[test]
999 fn test_row_repeat() {
1000 let row = Row::repeat(Value::integer(0), 5);
1001 assert_eq!(row.len(), 5);
1002 for v in row.iter() {
1003 assert_eq!(*v, Value::integer(0));
1004 }
1005 }
1006
1007 #[test]
1008 fn test_row_from_iterator() {
1009 let row: Row = vec![Value::integer(1), Value::integer(2), Value::integer(3)]
1010 .into_iter()
1011 .collect();
1012 assert_eq!(row.len(), 3);
1013 }
1014
1015 #[test]
1016 fn test_row_display() {
1017 let row = Row::from_values(vec![
1018 Value::integer(1),
1019 Value::text("hello"),
1020 Value::null(DataType::Text),
1021 ]);
1022 assert_eq!(row.to_string(), "(1, hello, NULL)");
1023
1024 let empty = Row::new();
1025 assert_eq!(empty.to_string(), "()");
1026 }
1027
1028 #[test]
1029 fn test_row_clone_subset() {
1030 let row = Row::from_values(vec![
1031 Value::integer(1),
1032 Value::text("hello"),
1033 Value::float(3.5),
1034 ]);
1035
1036 let subset = row.clone_subset(&[2, 0]).unwrap();
1037 assert_eq!(subset.len(), 2);
1038 assert_eq!(subset[0], Value::float(3.5));
1039 assert_eq!(subset[1], Value::integer(1));
1040 }
1041
1042 #[test]
1043 fn test_row_projection_helpers_reject_invalid_indices_consistently() {
1044 let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1045 let invalid = [0, 2];
1046
1047 assert!(row.select_columns(&invalid).is_err());
1048 assert!(row.clone().take_columns(&invalid).is_err());
1049 assert!(row.clone_subset(&invalid).is_err());
1050 }
1051
1052 #[test]
1053 fn test_row_equality() {
1054 let row1 = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1055 let row2 = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1056 let row3 = Row::from_values(vec![Value::integer(1), Value::text("world")]);
1057
1058 assert_eq!(row1, row2);
1059 assert_ne!(row1, row3);
1060 }
1061
1062 #[test]
1063 fn test_row_into_values() {
1064 let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1065 let values = row.into_values();
1066
1067 assert_eq!(values.len(), 2);
1068 assert_eq!(values[0], Value::integer(1));
1069 }
1070
1071 #[test]
1072 fn test_row_into_arc() {
1073 let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1074 let arc = row.into_arc();
1075 assert_eq!(arc.len(), 2);
1076
1077 let row2 = Row::from_arc(CompactArc::clone(&arc));
1079 let arc2 = row2.into_arc();
1080 assert!(CompactArc::ptr_eq(&arc, &arc2));
1081 }
1082
1083 #[test]
1084 fn test_row_combined() {
1085 let left = Row::from_values(vec![Value::integer(1), Value::integer(2)]);
1086 let right = Row::from_values(vec![Value::integer(3), Value::integer(4)]);
1087
1088 let combined = Row::from_combined(&left, &right);
1089 assert_eq!(combined.len(), 4);
1090 assert_eq!(combined[0], Value::integer(1));
1091 assert_eq!(combined[3], Value::integer(4));
1092 }
1093
1094 #[test]
1095 fn test_shared_owned_equality() {
1096 let owned = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1097 let shared = Row::from_arc(CompactArc::from(vec![
1098 Value::integer(1),
1099 Value::text("hello"),
1100 ]));
1101
1102 assert_eq!(owned, shared);
1103 }
1104}