Skip to main content

stoolap/core/
row.rs

1// Copyright 2025 Stoolap Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Row type for Stoolap - a collection of column values
16//!
17//! # Storage Design
18//!
19//! Row uses a simple 2-variant storage model:
20//! - `Shared(CompactArc<[Value]>)`: O(1) clone, for storage reads and sharing
21//! - `Owned(CompactVec<Value>)`: Mutable, for intermediate results
22//!
23//! This design avoids per-value Arc overhead while enabling:
24//! - Row-level sharing between arena, version store, transaction store
25//! - String-level sharing via SmartString::Shared(Arc<str>)
26//! - Zero-copy JOINs via RowRef::Composite/DirectBuildComposite (see operator.rs)
27
28use std::fmt;
29use std::ops::Index;
30
31use super::error::{Error, Result};
32use super::schema::Schema;
33use super::types::DataType;
34use super::value::Value;
35use crate::common::{CompactArc, CompactVec};
36
37/// Internal storage for Row - simple 2-variant design
38///
39/// - `Shared`: Arc-wrapped for O(1) clone (storage reads, sharing)
40/// - `Owned`: Direct values for mutations and intermediate results
41///
42/// Both variants are 16 bytes for optimal move performance.
43#[derive(Debug, Clone)]
44enum RowStorage {
45    /// Shared storage - O(1) clone, immutable (checked first for read-heavy workloads)
46    Shared(CompactArc<[Value]>),
47    /// Owned storage - mutable, for intermediate results
48    Owned(CompactVec<Value>),
49}
50
51impl Default for RowStorage {
52    fn default() -> Self {
53        RowStorage::Owned(CompactVec::new())
54    }
55}
56
57impl PartialEq for RowStorage {
58    #[inline]
59    fn eq(&self, other: &Self) -> bool {
60        match (self, other) {
61            (RowStorage::Shared(a), RowStorage::Shared(b)) => {
62                // Fast path: same Arc pointer
63                CompactArc::ptr_eq(a, b) || a.as_ref() == b.as_ref()
64            }
65            (RowStorage::Owned(a), RowStorage::Owned(b)) => a.as_slice() == b.as_slice(),
66            // Mixed storage types - compare by value
67            (RowStorage::Shared(a), RowStorage::Owned(b)) => a.as_ref() == b.as_slice(),
68            (RowStorage::Owned(a), RowStorage::Shared(b)) => a.as_slice() == b.as_ref(),
69        }
70    }
71}
72
73impl RowStorage {
74    /// Get a value by index
75    #[inline(always)]
76    fn get(&self, index: usize) -> Option<&Value> {
77        match self {
78            RowStorage::Shared(arc) => arc.get(index),
79            RowStorage::Owned(vec) => vec.get(index),
80        }
81    }
82
83    #[inline(always)]
84    fn len(&self) -> usize {
85        match self {
86            RowStorage::Shared(arc) => arc.len(),
87            RowStorage::Owned(vec) => vec.len(),
88        }
89    }
90
91    #[inline]
92    fn is_empty(&self) -> bool {
93        self.len() == 0
94    }
95
96    /// Get mutable access to owned storage, converting if necessary (copy-on-write)
97    #[inline]
98    fn make_mut(&mut self) -> &mut CompactVec<Value> {
99        match self {
100            RowStorage::Owned(vec) => vec,
101            RowStorage::Shared(arc) => {
102                // Copy-on-write: convert shared to owned
103                // Use extend_clone directly instead of .cloned().collect() to avoid
104                // the Cloned iterator adapter overhead
105                let len = arc.len();
106                let mut vec = CompactVec::with_capacity(len);
107                vec.extend_clone(arc);
108                *self = RowStorage::Owned(vec);
109                match self {
110                    RowStorage::Owned(vec) => vec,
111                    _ => unreachable!(),
112                }
113            }
114        }
115    }
116
117    /// Convert to owned Vec<Value>, consuming self
118    #[inline]
119    fn into_vec(self) -> Vec<Value> {
120        match self {
121            RowStorage::Owned(vec) => vec.into_vec(),
122            RowStorage::Shared(arc) => arc.iter().cloned().collect(),
123        }
124    }
125}
126
127/// A database row containing column values
128///
129/// Row provides methods for accessing and manipulating column values
130/// while maintaining type safety and consistency with the schema.
131///
132/// # Performance
133///
134/// - `Shared` storage: O(1) clone (just Arc increment)
135/// - `Owned` storage: O(n) clone (copies values)
136/// - String values use SmartString with internal Arc<str> for efficient sharing
137#[derive(Debug, Clone, PartialEq, Default)]
138pub struct Row {
139    storage: RowStorage,
140}
141
142/// Iterator over row values
143pub struct RowIter<'a> {
144    inner: std::slice::Iter<'a, Value>,
145}
146
147impl<'a> Iterator for RowIter<'a> {
148    type Item = &'a Value;
149
150    #[inline]
151    fn next(&mut self) -> Option<Self::Item> {
152        self.inner.next()
153    }
154
155    #[inline]
156    fn size_hint(&self) -> (usize, Option<usize>) {
157        self.inner.size_hint()
158    }
159}
160
161impl<'a> ExactSizeIterator for RowIter<'a> {
162    fn len(&self) -> usize {
163        self.inner.len()
164    }
165}
166
167impl<'a> DoubleEndedIterator for RowIter<'a> {
168    fn next_back(&mut self) -> Option<Self::Item> {
169        self.inner.next_back()
170    }
171}
172
173/// Mutable iterator over row values
174pub struct RowIterMut<'a> {
175    inner: std::slice::IterMut<'a, Value>,
176}
177
178impl<'a> Iterator for RowIterMut<'a> {
179    type Item = &'a mut Value;
180
181    #[inline]
182    fn next(&mut self) -> Option<Self::Item> {
183        self.inner.next()
184    }
185
186    #[inline]
187    fn size_hint(&self) -> (usize, Option<usize>) {
188        self.inner.size_hint()
189    }
190}
191
192impl<'a> ExactSizeIterator for RowIterMut<'a> {
193    fn len(&self) -> usize {
194        self.inner.len()
195    }
196}
197
198impl Row {
199    /// Create a new empty row
200    #[inline]
201    pub fn new() -> Self {
202        Self {
203            storage: RowStorage::Owned(CompactVec::new()),
204        }
205    }
206
207    /// Create a row with pre-allocated capacity
208    #[inline]
209    pub fn with_capacity(capacity: usize) -> Self {
210        Self {
211            storage: RowStorage::Owned(CompactVec::with_capacity(capacity)),
212        }
213    }
214
215    /// Create a row from a vector of values
216    #[inline]
217    pub fn from_values(values: Vec<Value>) -> Self {
218        Self {
219            storage: RowStorage::Owned(CompactVec::from_vec(values)),
220        }
221    }
222
223    /// Create a row from CompactVec<Value>
224    #[inline]
225    pub fn from_compact_vec(values: CompactVec<Value>) -> Self {
226        Self {
227            storage: RowStorage::Owned(values),
228        }
229    }
230
231    /// Create a row from an Arc slice - O(1), no copying
232    #[inline]
233    pub fn from_arc(values: CompactArc<[Value]>) -> Self {
234        Self {
235            storage: RowStorage::Shared(values),
236        }
237    }
238
239    /// Create a row by combining two rows (for JOINs)
240    /// Result uses Owned storage (optimal for intermediate results)
241    #[inline]
242    pub fn from_combined(left: &Row, right: &Row) -> Self {
243        let total_len = left.len() + right.len();
244        let mut values = CompactVec::with_capacity(total_len);
245        // Use extend_clone to avoid Cloned iterator adapter overhead
246        values.extend_clone(left.as_slice());
247        values.extend_clone(right.as_slice());
248        Self {
249            storage: RowStorage::Owned(values),
250        }
251    }
252
253    /// Combine two rows into this row buffer (for JOINs) - reuses allocation
254    #[inline]
255    pub fn combine_into(&mut self, left: &Row, right: &Row) {
256        let total_len = left.len() + right.len();
257        let vec = self.storage.make_mut();
258        vec.clear();
259        vec.reserve(total_len);
260        // Use extend_clone to avoid Cloned iterator adapter overhead
261        vec.extend_clone(left.as_slice());
262        vec.extend_clone(right.as_slice());
263    }
264
265    /// Combine rows: clone left, move right (for JOINs) - reuses allocation
266    #[inline]
267    pub fn combine_into_clone_move(&mut self, left: &Row, right: Row) {
268        let total_len = left.len() + right.len();
269        let vec = self.storage.make_mut();
270        vec.clear();
271        vec.reserve(total_len);
272        // Use extend_clone to avoid Cloned iterator adapter overhead
273        vec.extend_clone(left.as_slice());
274        // Move right values
275        match right.storage {
276            RowStorage::Owned(right_vec) => vec.extend(right_vec),
277            RowStorage::Shared(arc) => vec.extend_clone(&arc),
278        }
279    }
280
281    /// Combine rows: move both (for JOINs) - reuses allocation
282    #[inline]
283    pub fn combine_into_owned(&mut self, left: Row, right: Row) {
284        let total_len = left.len() + right.len();
285        let vec = self.storage.make_mut();
286        vec.clear();
287        vec.reserve(total_len);
288        // Move left values - use extend_clone to avoid Cloned iterator overhead
289        match left.storage {
290            RowStorage::Owned(left_vec) => vec.extend(left_vec),
291            RowStorage::Shared(arc) => vec.extend_clone(&arc),
292        }
293        // Move right values
294        match right.storage {
295            RowStorage::Owned(right_vec) => vec.extend(right_vec),
296            RowStorage::Shared(arc) => vec.extend_clone(&arc),
297        }
298    }
299
300    /// Combine rows: clone left, move right (for JOINs)
301    #[inline]
302    pub fn from_combined_clone_move(left: &Row, right: Row) -> Self {
303        let total_len = left.len() + right.len();
304        let mut values = CompactVec::with_capacity(total_len);
305        // Use extend_clone to avoid Cloned iterator adapter overhead
306        values.extend_clone(left.as_slice());
307        match right.storage {
308            RowStorage::Owned(right_vec) => values.extend(right_vec),
309            RowStorage::Shared(arc) => values.extend_clone(&arc),
310        }
311        Self {
312            storage: RowStorage::Owned(values),
313        }
314    }
315
316    /// Combine two owned rows (for JOINs) - moves values without cloning
317    #[inline]
318    pub fn from_combined_owned(left: Row, right: Row) -> Self {
319        // Fast path: both Owned
320        match (left.storage, right.storage) {
321            (RowStorage::Owned(mut left_vec), RowStorage::Owned(right_vec)) => {
322                left_vec.reserve(right_vec.len());
323                left_vec.extend(right_vec);
324                Self {
325                    storage: RowStorage::Owned(left_vec),
326                }
327            }
328            (left_storage, right_storage) => {
329                let left_len = left_storage.len();
330                let right_len = right_storage.len();
331                let mut values = CompactVec::with_capacity(left_len + right_len);
332                // Use extend_clone to avoid Cloned iterator adapter overhead
333                match left_storage {
334                    RowStorage::Owned(v) => values.extend(v),
335                    RowStorage::Shared(a) => values.extend_clone(&a),
336                }
337                match right_storage {
338                    RowStorage::Owned(v) => values.extend(v),
339                    RowStorage::Shared(a) => values.extend_clone(&a),
340                }
341                Self {
342                    storage: RowStorage::Owned(values),
343                }
344            }
345        }
346    }
347
348    /// Create a row with null values for a given schema
349    #[inline]
350    pub fn null_row(schema: &Schema) -> Self {
351        let values: CompactVec<Value> = schema
352            .columns
353            .iter()
354            .map(|col| Value::null(col.data_type))
355            .collect();
356        Self {
357            storage: RowStorage::Owned(values),
358        }
359    }
360
361    /// Get the number of values in the row
362    #[inline(always)]
363    pub fn len(&self) -> usize {
364        self.storage.len()
365    }
366
367    /// Check if the row is empty
368    #[inline]
369    pub fn is_empty(&self) -> bool {
370        self.storage.is_empty()
371    }
372
373    /// Get a value by index
374    #[inline(always)]
375    pub fn get(&self, index: usize) -> Option<&Value> {
376        self.storage.get(index)
377    }
378
379    /// Get a mutable value by index (triggers copy-on-write if shared)
380    #[inline]
381    pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
382        self.storage.make_mut().get_mut(index)
383    }
384
385    /// Set a value at the given index (triggers copy-on-write if shared)
386    pub fn set(&mut self, index: usize, value: Value) -> Result<()> {
387        let vec = self.storage.make_mut();
388        if index >= vec.len() {
389            return Err(Error::Internal {
390                message: format!("row index {} out of bounds (len={})", index, vec.len()),
391            });
392        }
393        vec[index] = value;
394        Ok(())
395    }
396
397    /// Push a value to the end of the row
398    #[inline]
399    pub fn push(&mut self, value: Value) {
400        self.storage.make_mut().push(value);
401    }
402
403    /// Pop a value from the end of the row
404    #[inline]
405    pub fn pop(&mut self) -> Option<Value> {
406        self.storage.make_mut().pop()
407    }
408
409    /// Truncate the row to a specific length
410    #[inline]
411    pub fn truncate(&mut self, len: usize) {
412        self.storage.make_mut().truncate(len);
413    }
414
415    /// Clear the row values while keeping allocated capacity
416    #[inline]
417    pub fn clear(&mut self) {
418        self.storage.make_mut().clear();
419    }
420
421    /// Take the values from this row, returning them in a new Row.
422    /// The original row is cleared but keeps its allocated capacity.
423    #[inline]
424    pub fn take_and_clear(&mut self) -> Row {
425        match &mut self.storage {
426            RowStorage::Owned(vec) => {
427                let cap = vec.capacity();
428                let values = std::mem::replace(vec, CompactVec::with_capacity(cap));
429                Row {
430                    storage: RowStorage::Owned(values),
431                }
432            }
433            RowStorage::Shared(arc) => {
434                let result = Row {
435                    storage: RowStorage::Shared(arc.clone()),
436                };
437                *self = Row::new();
438                result
439            }
440        }
441    }
442
443    /// Reserve capacity for at least `additional` more values
444    #[inline]
445    pub fn reserve(&mut self, additional: usize) {
446        self.storage.make_mut().reserve(additional);
447    }
448
449    /// Extend the row with values from a slice
450    #[inline]
451    pub fn extend_from_slice(&mut self, other: &[Value]) {
452        self.storage.make_mut().extend_clone(other);
453    }
454
455    /// Extend a CompactVec with this row's values, consuming self.
456    ///
457    /// OPTIMIZATION: This avoids the intermediate Vec allocation that would occur
458    /// with `target.extend(row)` which goes through `Row::into_iter()`.
459    /// - Owned storage: directly extends from CompactVec (moves values)
460    /// - Shared storage: clones values from Arc slice
461    #[inline]
462    pub fn extend_into_compact_vec(self, target: &mut CompactVec<Value>) {
463        match self.storage {
464            RowStorage::Owned(vec) => target.extend(vec),
465            RowStorage::Shared(arc) => target.extend_clone(&arc),
466        }
467    }
468
469    /// Get an iterator over the values
470    #[inline(always)]
471    pub fn iter(&self) -> RowIter<'_> {
472        RowIter {
473            inner: match &self.storage {
474                RowStorage::Shared(arc) => arc.iter(),
475                RowStorage::Owned(vec) => vec.iter(),
476            },
477        }
478    }
479
480    /// Get a mutable iterator over the values (triggers copy-on-write if shared)
481    #[inline]
482    pub fn iter_mut(&mut self) -> RowIterMut<'_> {
483        RowIterMut {
484            inner: self.storage.make_mut().iter_mut(),
485        }
486    }
487
488    /// Get the underlying vector of values, consuming the row
489    #[inline]
490    pub fn into_values(self) -> Vec<Value> {
491        self.storage.into_vec()
492    }
493
494    /// Extract the first value, consuming the row
495    #[inline]
496    pub fn take_first_value(self) -> Option<Value> {
497        match self.storage {
498            RowStorage::Owned(mut vec) => {
499                if vec.is_empty() {
500                    None
501                } else {
502                    Some(vec.swap_remove(0))
503                }
504            }
505            RowStorage::Shared(arc) => arc.first().cloned(),
506        }
507    }
508
509    /// Check if storage is shared (Arc-wrapped)
510    #[inline]
511    pub fn is_shared(&self) -> bool {
512        matches!(self.storage, RowStorage::Shared(_))
513    }
514
515    /// Check if storage is owned
516    #[inline]
517    pub fn is_owned(&self) -> bool {
518        matches!(self.storage, RowStorage::Owned(_))
519    }
520
521    /// Convert Row to CompactArc<[Value]>, consuming self
522    /// - Shared: returns the CompactArc directly (O(1))
523    /// - Owned: creates new Arc (O(n))
524    #[inline]
525    pub fn into_arc(self) -> CompactArc<[Value]> {
526        match self.storage {
527            RowStorage::Shared(arc) => arc,
528            // Use from_compact_vec directly - avoids intermediate Vec conversion
529            RowStorage::Owned(vec) => CompactArc::from_compact_vec(vec),
530        }
531    }
532
533    /// Convert to Shared storage for O(1) clone.
534    ///
535    /// Use this when the row will be cloned multiple times (e.g., hash join build side).
536    /// After conversion, `row.clone()` is just an Arc increment.
537    #[inline]
538    pub fn into_shared(self) -> Self {
539        match self.storage {
540            RowStorage::Shared(_) => self, // Already shared
541            RowStorage::Owned(vec) => Self {
542                // Use from_compact_vec directly - avoids intermediate Vec conversion
543                storage: RowStorage::Shared(CompactArc::from_compact_vec(vec)),
544            },
545        }
546    }
547
548    /// Get CompactArc<[Value]> reference if shared, None if owned
549    #[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    /// Get slice of values
558    #[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    /// Extract specific columns by their indices
567    #[inline]
568    pub fn select_columns(&self, indices: &[usize]) -> Result<Row> {
569        let len = self.len();
570        let mut values = CompactVec::with_capacity(indices.len());
571        for &idx in indices {
572            match self.storage.get(idx) {
573                Some(val) => values.push(val.clone()),
574                None => {
575                    return Err(Error::Internal {
576                        message: format!("column index {} out of bounds (len={})", idx, len),
577                    })
578                }
579            }
580        }
581        Ok(Row::from_compact_vec(values))
582    }
583
584    /// Take specific columns by their indices, consuming the row
585    /// Detects prefix projections (0, 1, 2, ..., n-1) and truncates in-place.
586    #[inline]
587    pub fn take_columns(self, indices: &[usize]) -> Row {
588        // Fast path: check if indices form a prefix (0, 1, 2, ..., n-1)
589        let is_prefix = !indices.is_empty()
590            && indices.len() <= self.len()
591            && indices.iter().enumerate().all(|(i, &idx)| i == idx);
592
593        if is_prefix {
594            match self.storage {
595                RowStorage::Owned(mut vec) => {
596                    vec.truncate(indices.len());
597                    return Row {
598                        storage: RowStorage::Owned(vec),
599                    };
600                }
601                RowStorage::Shared(ref arc) if indices.len() == arc.len() => {
602                    return self;
603                }
604                RowStorage::Shared(arc) => {
605                    // Prefix selection from Shared
606                    let values: CompactVec<Value> = arc[..indices.len()].iter().cloned().collect();
607                    return Row {
608                        storage: RowStorage::Owned(values),
609                    };
610                }
611            }
612        }
613
614        // General case: select specific columns
615        let mut values = CompactVec::with_capacity(indices.len());
616        let slice = self.as_slice();
617        for &idx in indices {
618            if idx < slice.len() {
619                values.push(slice[idx].clone());
620            } else {
621                values.push(Value::null_unknown());
622            }
623        }
624        Row {
625            storage: RowStorage::Owned(values),
626        }
627    }
628
629    /// Validate the row against a schema
630    pub fn validate(&self, schema: &Schema) -> Result<()> {
631        let len = self.len();
632
633        // Check column count
634        if len != schema.columns.len() {
635            return Err(Error::table_columns_not_match(schema.columns.len(), len));
636        }
637
638        // Check each value
639        for (i, (value, col)) in self.iter().zip(schema.columns.iter()).enumerate() {
640            // Check nullability
641            if value.is_null() && !col.nullable && !col.primary_key {
642                return Err(Error::not_null_constraint(&col.name));
643            }
644
645            // Check type compatibility (skip for null values)
646            if !value.is_null() {
647                let value_type = value.data_type();
648                if value_type != col.data_type {
649                    // Allow some implicit conversions
650                    let compatible = matches!(
651                        (value_type, col.data_type),
652                        (DataType::Integer, DataType::Float) | (DataType::Float, DataType::Integer)
653                    );
654                    if !compatible {
655                        return Err(Error::type_conversion(
656                            format!("column {} at index {}: {:?}", col.name, i, value_type),
657                            format!("{:?}", col.data_type),
658                        ));
659                    }
660                }
661            }
662        }
663
664        Ok(())
665    }
666
667    /// Clone the row, selecting only the specified column indices
668    #[inline]
669    pub fn clone_subset(&self, indices: &[usize]) -> Row {
670        let mut values = CompactVec::with_capacity(indices.len());
671        let slice = self.as_slice();
672        for &i in indices {
673            if let Some(v) = slice.get(i) {
674                values.push(v.clone());
675            }
676        }
677        Row::from_compact_vec(values)
678    }
679
680    /// Concatenate two rows
681    pub fn concat(&self, other: &Row) -> Row {
682        let total_len = self.len() + other.len();
683        let mut values = CompactVec::with_capacity(total_len);
684        values.extend(self.iter().cloned());
685        values.extend(other.iter().cloned());
686        Row::from_compact_vec(values)
687    }
688
689    /// Create a row by repeating a value
690    pub fn repeat(value: Value, count: usize) -> Row {
691        let mut values = CompactVec::with_capacity(count);
692        for _ in 0..count {
693            values.push(value.clone());
694        }
695        Row::from_compact_vec(values)
696    }
697
698    // === Compatibility methods for gradual migration ===
699    // These methods maintain API compatibility with code expecting CompactArc
700
701    /// Alias for is_owned (backwards compatibility)
702    #[inline]
703    pub fn is_inline(&self) -> bool {
704        self.is_owned()
705    }
706
707    /// Clear and use as inline storage (backwards compatibility)
708    #[inline]
709    pub fn clear_inline(&mut self) {
710        self.clear();
711    }
712
713    /// Push to inline storage (backwards compatibility)
714    #[inline]
715    pub fn push_inline(&mut self, value: Value) {
716        self.push(value);
717    }
718
719    /// Reserve inline capacity (backwards compatibility)
720    #[inline]
721    pub fn reserve_inline(&mut self, capacity: usize) {
722        let vec = self.storage.make_mut();
723        if vec.capacity() < capacity {
724            vec.reserve(capacity - vec.len());
725        }
726    }
727
728    /// Refill with values (backwards compatibility)
729    #[inline]
730    pub fn refill_inline<I: Iterator<Item = Value>>(&mut self, values: I) {
731        let vec = self.storage.make_mut();
732        vec.clear();
733        vec.extend(values);
734    }
735}
736
737// Implement Index for convenient access
738impl Index<usize> for Row {
739    type Output = Value;
740
741    #[inline]
742    fn index(&self, index: usize) -> &Self::Output {
743        self.storage.get(index).expect("row index out of bounds")
744    }
745}
746
747// Implement FromIterator for collecting values into a row
748impl FromIterator<Value> for Row {
749    fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
750        Row::from_compact_vec(iter.into_iter().collect())
751    }
752}
753
754// Implement IntoIterator for consuming iteration
755impl IntoIterator for Row {
756    type Item = Value;
757    type IntoIter = std::vec::IntoIter<Value>;
758
759    fn into_iter(self) -> Self::IntoIter {
760        self.storage.into_vec().into_iter()
761    }
762}
763
764impl<'a> IntoIterator for &'a Row {
765    type Item = &'a Value;
766    type IntoIter = RowIter<'a>;
767
768    fn into_iter(self) -> Self::IntoIter {
769        self.iter()
770    }
771}
772
773impl From<Vec<Value>> for Row {
774    fn from(values: Vec<Value>) -> Self {
775        Row::from_values(values)
776    }
777}
778
779impl From<CompactArc<[Value]>> for Row {
780    fn from(values: CompactArc<[Value]>) -> Self {
781        Row::from_arc(values)
782    }
783}
784
785impl fmt::Display for Row {
786    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787        write!(f, "(")?;
788        for (i, value) in self.iter().enumerate() {
789            if i > 0 {
790                write!(f, ", ")?;
791            }
792            write!(f, "{}", value)?;
793        }
794        write!(f, ")")
795    }
796}
797
798/// Macro for creating rows conveniently
799#[macro_export]
800macro_rules! row {
801    () => {
802        $crate::core::Row::new()
803    };
804    ($($value:expr),+ $(,)?) => {
805        $crate::core::Row::from_values(vec![$($crate::core::Value::from($value)),+])
806    };
807}
808
809#[cfg(test)]
810mod tests {
811    use super::*;
812    use crate::common::CompactArc;
813    use crate::core::schema::SchemaBuilder;
814
815    fn create_test_schema() -> Schema {
816        SchemaBuilder::new("test")
817            .add_primary_key("id", DataType::Integer)
818            .add("name", DataType::Text)
819            .add_nullable("email", DataType::Text)
820            .build()
821    }
822
823    #[test]
824    fn test_row_creation() {
825        let row = Row::new();
826        assert!(row.is_empty());
827        assert_eq!(row.len(), 0);
828
829        let row = Row::with_capacity(10);
830        assert!(row.is_empty());
831    }
832
833    #[test]
834    fn test_row_from_values() {
835        let values = vec![
836            Value::integer(1),
837            Value::text("hello"),
838            Value::null(DataType::Text),
839        ];
840        let row = Row::from_values(values);
841        assert_eq!(row.len(), 3);
842        assert!(row.is_owned());
843    }
844
845    #[test]
846    fn test_row_from_arc() {
847        let values: CompactArc<[Value]> =
848            CompactArc::from(vec![Value::integer(1), Value::text("hello")]);
849        let row = Row::from_arc(values);
850        assert_eq!(row.len(), 2);
851        assert!(row.is_shared());
852
853        // Clone should be O(1) - just Arc increment
854        let row2 = row.clone();
855        assert_eq!(row2.len(), 2);
856        assert_eq!(row, row2);
857        assert!(row2.is_shared());
858    }
859
860    #[test]
861    fn test_row_push_pop() {
862        let mut row = Row::new();
863        row.push(Value::integer(1));
864        row.push(Value::text("hello"));
865
866        assert_eq!(row.len(), 2);
867
868        let popped = row.pop();
869        assert_eq!(popped, Some(Value::text("hello")));
870        assert_eq!(row.len(), 1);
871    }
872
873    #[test]
874    fn test_row_copy_on_write() {
875        // Create shared row
876        let values: CompactArc<[Value]> =
877            CompactArc::from(vec![Value::integer(1), Value::text("hello")]);
878        let mut row = Row::from_arc(values);
879        assert!(row.is_shared());
880
881        // Mutation should trigger copy-on-write
882        row.push(Value::integer(2));
883        assert_eq!(row.len(), 3);
884        assert!(row.is_owned()); // Now owned after mutation
885    }
886
887    #[test]
888    fn test_row_get_set() {
889        let mut row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
890
891        assert_eq!(row.get(0), Some(&Value::integer(1)));
892        assert_eq!(row.get(1), Some(&Value::text("hello")));
893        assert_eq!(row.get(2), None);
894
895        row.set(1, Value::text("world")).unwrap();
896        assert_eq!(row.get(1), Some(&Value::text("world")));
897
898        assert!(row.set(10, Value::integer(0)).is_err());
899    }
900
901    #[test]
902    fn test_row_index() {
903        let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
904
905        assert_eq!(row[0], Value::integer(1));
906        assert_eq!(row[1], Value::text("hello"));
907    }
908
909    #[test]
910    fn test_row_iteration() {
911        let row = Row::from_values(vec![
912            Value::integer(1),
913            Value::integer(2),
914            Value::integer(3),
915        ]);
916
917        let sum: i64 = row.iter().filter_map(|v| v.as_int64()).sum();
918        assert_eq!(sum, 6);
919    }
920
921    #[test]
922    fn test_row_select_columns() {
923        let row = Row::from_values(vec![
924            Value::integer(1),
925            Value::text("hello"),
926            Value::float(3.5),
927            Value::boolean(true),
928        ]);
929
930        let selected = row.select_columns(&[0, 2]).unwrap();
931        assert_eq!(selected.len(), 2);
932        assert_eq!(selected[0], Value::integer(1));
933        assert_eq!(selected[1], Value::float(3.5));
934
935        assert!(row.select_columns(&[0, 10]).is_err());
936    }
937
938    #[test]
939    fn test_row_validate() {
940        let schema = create_test_schema();
941
942        // Valid row
943        let row = Row::from_values(vec![
944            Value::integer(1),
945            Value::text("Alice"),
946            Value::null(DataType::Text),
947        ]);
948        assert!(row.validate(&schema).is_ok());
949
950        // Wrong column count
951        let row = Row::from_values(vec![Value::integer(1)]);
952        assert!(row.validate(&schema).is_err());
953
954        // Not null constraint violation
955        let row = Row::from_values(vec![
956            Value::integer(1),
957            Value::null(DataType::Text), // name is not nullable
958            Value::null(DataType::Text),
959        ]);
960        let err = row.validate(&schema).unwrap_err();
961        assert!(matches!(err, Error::NotNullConstraint { .. }));
962    }
963
964    #[test]
965    fn test_row_null_row() {
966        let schema = create_test_schema();
967        let row = Row::null_row(&schema);
968
969        assert_eq!(row.len(), 3);
970        assert!(row[0].is_null());
971        assert!(row[1].is_null());
972        assert!(row[2].is_null());
973    }
974
975    #[test]
976    fn test_row_concat() {
977        let row1 = Row::from_values(vec![Value::integer(1), Value::integer(2)]);
978        let row2 = Row::from_values(vec![Value::integer(3), Value::integer(4)]);
979
980        let combined = row1.concat(&row2);
981        assert_eq!(combined.len(), 4);
982        assert_eq!(combined[0], Value::integer(1));
983        assert_eq!(combined[3], Value::integer(4));
984    }
985
986    #[test]
987    fn test_row_repeat() {
988        let row = Row::repeat(Value::integer(0), 5);
989        assert_eq!(row.len(), 5);
990        for v in row.iter() {
991            assert_eq!(*v, Value::integer(0));
992        }
993    }
994
995    #[test]
996    fn test_row_from_iterator() {
997        let row: Row = vec![Value::integer(1), Value::integer(2), Value::integer(3)]
998            .into_iter()
999            .collect();
1000        assert_eq!(row.len(), 3);
1001    }
1002
1003    #[test]
1004    fn test_row_display() {
1005        let row = Row::from_values(vec![
1006            Value::integer(1),
1007            Value::text("hello"),
1008            Value::null(DataType::Text),
1009        ]);
1010        assert_eq!(row.to_string(), "(1, hello, NULL)");
1011
1012        let empty = Row::new();
1013        assert_eq!(empty.to_string(), "()");
1014    }
1015
1016    #[test]
1017    fn test_row_clone_subset() {
1018        let row = Row::from_values(vec![
1019            Value::integer(1),
1020            Value::text("hello"),
1021            Value::float(3.5),
1022        ]);
1023
1024        let subset = row.clone_subset(&[2, 0]);
1025        assert_eq!(subset.len(), 2);
1026        assert_eq!(subset[0], Value::float(3.5));
1027        assert_eq!(subset[1], Value::integer(1));
1028    }
1029
1030    #[test]
1031    fn test_row_equality() {
1032        let row1 = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1033        let row2 = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1034        let row3 = Row::from_values(vec![Value::integer(1), Value::text("world")]);
1035
1036        assert_eq!(row1, row2);
1037        assert_ne!(row1, row3);
1038    }
1039
1040    #[test]
1041    fn test_row_into_values() {
1042        let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1043        let values = row.into_values();
1044
1045        assert_eq!(values.len(), 2);
1046        assert_eq!(values[0], Value::integer(1));
1047    }
1048
1049    #[test]
1050    fn test_row_into_arc() {
1051        let row = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1052        let arc = row.into_arc();
1053        assert_eq!(arc.len(), 2);
1054
1055        // From shared - should be O(1)
1056        let row2 = Row::from_arc(CompactArc::clone(&arc));
1057        let arc2 = row2.into_arc();
1058        assert!(CompactArc::ptr_eq(&arc, &arc2));
1059    }
1060
1061    #[test]
1062    fn test_row_combined() {
1063        let left = Row::from_values(vec![Value::integer(1), Value::integer(2)]);
1064        let right = Row::from_values(vec![Value::integer(3), Value::integer(4)]);
1065
1066        let combined = Row::from_combined(&left, &right);
1067        assert_eq!(combined.len(), 4);
1068        assert_eq!(combined[0], Value::integer(1));
1069        assert_eq!(combined[3], Value::integer(4));
1070    }
1071
1072    #[test]
1073    fn test_shared_owned_equality() {
1074        let owned = Row::from_values(vec![Value::integer(1), Value::text("hello")]);
1075        let shared = Row::from_arc(CompactArc::from(vec![
1076            Value::integer(1),
1077            Value::text("hello"),
1078        ]));
1079
1080        assert_eq!(owned, shared);
1081    }
1082}