1use std::ops::{Range, RangeInclusive};
15mod bitmap;
19mod encoded_array;
20mod index;
21pub mod segment;
22mod serde;
23pub mod version;
24
25use lance_core::deepsize::DeepSizeOf;
26pub use index::FragmentRowIdIndex;
28pub use index::RowIdIndex;
29use lance_core::{Error, Result};
30use lance_io::ReadBatchParams;
31use lance_select::{RowAddrMask, RowAddrTreeMap, RowSetOps};
32pub use serde::{read_row_ids, write_row_ids};
33
34use crate::utils::LanceIteratorExtension;
35use segment::U64Segment;
36use tracing::instrument;
37
38#[derive(Debug, Clone, DeepSizeOf, PartialEq, Eq, Default)]
51pub struct RowIdSequence(Vec<U64Segment>);
52
53impl std::fmt::Display for RowIdSequence {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 let mut iter = self.iter();
56 let mut first_10 = Vec::new();
57 let mut last_10 = Vec::new();
58 for row_id in iter.by_ref() {
59 first_10.push(row_id);
60 if first_10.len() > 10 {
61 break;
62 }
63 }
64
65 while let Some(row_id) = iter.next_back() {
66 last_10.push(row_id);
67 if last_10.len() > 10 {
68 break;
69 }
70 }
71 last_10.reverse();
72
73 let theres_more = iter.next().is_some();
74
75 write!(f, "[")?;
76 for row_id in first_10 {
77 write!(f, "{}", row_id)?;
78 }
79 if theres_more {
80 write!(f, ", ...")?;
81 }
82 for row_id in last_10 {
83 write!(f, ", {}", row_id)?;
84 }
85 write!(f, "]")
86 }
87}
88
89impl From<Range<u64>> for RowIdSequence {
90 fn from(range: Range<u64>) -> Self {
91 Self(vec![U64Segment::Range(range)])
92 }
93}
94
95impl From<&[u64]> for RowIdSequence {
96 fn from(row_ids: &[u64]) -> Self {
97 Self(vec![U64Segment::from_slice(row_ids)])
98 }
99}
100
101fn find_duplicate(row_ids: &[u64]) -> Option<u64> {
106 if row_ids.windows(2).all(|pair| pair[0] < pair[1]) {
107 return None;
108 }
109 let mut sorted = row_ids.to_vec();
110 sorted.sort_unstable();
111 sorted
112 .windows(2)
113 .find(|pair| pair[0] == pair[1])
114 .map(|pair| pair[0])
115}
116
117impl RowIdSequence {
118 pub fn new() -> Self {
119 Self::default()
120 }
121
122 pub fn try_from_iter(row_ids: impl IntoIterator<Item = u64>) -> Result<Self> {
133 let row_ids: Vec<u64> = row_ids.into_iter().collect();
134 if row_ids.is_empty() {
135 return Ok(Self::new());
136 }
137 if let Some(duplicate) = find_duplicate(&row_ids) {
138 return Err(Error::invalid_input(format!(
139 "Row ids must be unique, but row id {} appears more than once in the sequence of {} row ids",
140 duplicate,
141 row_ids.len()
142 )));
143 }
144 Ok(Self(vec![U64Segment::from_iter(row_ids)]))
145 }
146
147 pub fn iter(&self) -> impl DoubleEndedIterator<Item = u64> + '_ {
148 self.0.iter().flat_map(|segment| segment.iter())
149 }
150
151 pub fn len(&self) -> u64 {
152 self.0.iter().map(|segment| segment.len() as u64).sum()
153 }
154
155 pub fn is_empty(&self) -> bool {
156 self.0.is_empty()
157 }
158
159 pub fn row_id_range(&self) -> Option<RangeInclusive<u64>> {
167 let min = self
168 .0
169 .iter()
170 .filter_map(|s| s.range())
171 .map(|r| *r.start())
172 .min()?;
173 let max = self
174 .0
175 .iter()
176 .filter_map(|s| s.range())
177 .map(|r| *r.end())
178 .max()?;
179 Some(min..=max)
180 }
181
182 pub fn extend(&mut self, other: Self) {
184 if let (Some(U64Segment::Range(range1)), Some(U64Segment::Range(range2))) =
188 (self.0.last(), other.0.first())
189 && range1.end == range2.start
190 {
191 let new_range = U64Segment::Range(range1.start..range2.end);
192 self.0.pop();
193 self.0.push(new_range);
194 self.0.extend(other.0.into_iter().skip(1));
195 return;
196 }
197 self.0.extend(other.0);
199 }
200
201 pub fn delete(&mut self, row_ids: impl IntoIterator<Item = u64>) {
203 let (row_ids, offsets) = self.find_ids(row_ids);
205
206 let capacity = self.0.capacity();
207 let old_segments = std::mem::replace(&mut self.0, Vec::with_capacity(capacity));
208 let mut remaining_segments = old_segments.as_slice();
209
210 for (segment_idx, range) in offsets {
211 let segments_handled = old_segments.len() - remaining_segments.len();
212 let segments_to_add = segment_idx - segments_handled;
213 self.0
214 .extend_from_slice(&remaining_segments[..segments_to_add]);
215 remaining_segments = &remaining_segments[segments_to_add..];
216
217 let segment;
218 (segment, remaining_segments) = remaining_segments.split_first().unwrap();
219
220 let segment_ids = &row_ids[range];
221 self.0.push(segment.delete(segment_ids));
222 }
223
224 self.0.extend_from_slice(remaining_segments);
226 }
227
228 pub fn mask(&mut self, positions: impl IntoIterator<Item = u32>) -> Result<()> {
230 let mut local_positions = Vec::new();
231 let mut positions_iter = positions.into_iter();
232 let mut curr_position = positions_iter.next();
233 let mut offset = 0;
234 let mut cutoff = 0;
235
236 for segment in &mut self.0 {
237 cutoff += segment.len() as u32;
239 while let Some(position) = curr_position {
240 if position >= cutoff {
241 break;
242 }
243 local_positions.push(position - offset);
244 curr_position = positions_iter.next();
245 }
246
247 if !local_positions.is_empty() {
248 segment.mask(&local_positions);
249 local_positions.clear();
250 }
251 offset = cutoff;
252 }
253
254 self.0.retain(|segment| !segment.is_empty());
255
256 Ok(())
257 }
258
259 fn find_ids(
265 &self,
266 row_ids: impl IntoIterator<Item = u64>,
267 ) -> (Vec<u64>, Vec<(usize, Range<usize>)>) {
268 let mut segment_iter = self.0.iter().enumerate().cycle();
272
273 let mut segment_matches = vec![Vec::new(); self.0.len()];
274
275 row_ids.into_iter().for_each(|row_id| {
276 let mut i = 0;
277 while i < self.0.len() {
279 let (segment_idx, segment) = segment_iter.next().unwrap();
280 if segment.range().is_some_and(|range| range.contains(&row_id))
281 && let Some(offset) = segment.position(row_id)
282 {
283 segment_matches.get_mut(segment_idx).unwrap().push(offset);
284 }
286 i += 1;
287 }
288 });
289 for matches in &mut segment_matches {
290 matches.sort_unstable();
291 }
292
293 let mut offset = 0;
294 let segment_ranges = segment_matches
295 .iter()
296 .enumerate()
297 .filter(|(_, matches)| !matches.is_empty())
298 .map(|(segment_idx, matches)| {
299 let range = offset..offset + matches.len();
300 offset += matches.len();
301 (segment_idx, range)
302 })
303 .collect();
304 let row_ids = segment_matches
305 .into_iter()
306 .enumerate()
307 .flat_map(|(segment_idx, offset)| {
308 offset
309 .into_iter()
310 .map(move |offset| self.0[segment_idx].get(offset).unwrap())
311 })
312 .collect();
313
314 (row_ids, segment_ranges)
315 }
316
317 pub fn slice(&self, offset: usize, len: usize) -> RowIdSeqSlice<'_> {
318 if len == 0 {
319 return RowIdSeqSlice {
320 segments: &[],
321 offset_start: 0,
322 offset_last: 0,
323 };
324 }
325
326 let mut offset_start = offset;
328 let mut segment_offset = 0;
329 for segment in &self.0 {
330 let segment_len = segment.len();
331 if offset_start < segment_len {
332 break;
333 }
334 offset_start -= segment_len;
335 segment_offset += 1;
336 }
337
338 let mut offset_last = offset_start + len;
340 let mut segment_offset_last = segment_offset;
341 for segment in &self.0[segment_offset..] {
342 let segment_len = segment.len();
343 if offset_last <= segment_len {
344 break;
345 }
346 offset_last -= segment_len;
347 segment_offset_last += 1;
348 }
349
350 RowIdSeqSlice {
351 segments: &self.0[segment_offset..=segment_offset_last],
352 offset_start,
353 offset_last,
354 }
355 }
356
357 pub fn segments(&self) -> &[U64Segment] {
362 &self.0
363 }
364
365 pub fn get(&self, index: usize) -> Option<u64> {
366 let mut offset = 0;
367 for segment in &self.0 {
368 let segment_len = segment.len();
369 if index < offset + segment_len {
370 return segment.get(index - offset);
371 }
372 offset += segment_len;
373 }
374 None
375 }
376
377 pub fn select<'a>(
385 &'a self,
386 selection: impl Iterator<Item = usize> + 'a,
387 ) -> impl Iterator<Item = u64> + 'a {
388 let mut seg_iter = self.0.iter();
389 let mut cur_seg = seg_iter.next();
390 let mut rows_passed = 0;
391 let mut cur_seg_len = cur_seg.map(|seg| seg.len()).unwrap_or(0);
392 let mut cursor = cur_seg.map(|seg| seg.cursor());
393 let mut last_index = 0;
394 selection.filter_map(move |index| {
395 if index < last_index {
396 panic!("Selection is not sorted");
397 }
398 last_index = index;
399
400 cur_seg?;
401
402 while (index - rows_passed) >= cur_seg_len {
403 rows_passed += cur_seg_len;
404 cur_seg = seg_iter.next();
405 cur_seg_len = cur_seg?.len();
406 cursor = cur_seg.map(|seg| seg.cursor());
407 }
408
409 let value = cursor.as_mut().unwrap().get(index - rows_passed);
410 debug_assert!(
411 value.is_some(),
412 "segment reported {cur_seg_len} rows but has no value at {}",
413 index - rows_passed
414 );
415 value
416 })
417 }
418
419 #[instrument(level = "debug", skip_all)]
434 pub fn mask_to_offset_ranges(&self, mask: &RowAddrMask) -> Vec<Range<u64>> {
435 let mut offset = 0;
436 let mut ranges = Vec::new();
437 for segment in &self.0 {
438 match segment {
439 U64Segment::Range(range) => {
440 let mut ids = RowAddrTreeMap::from(range.clone());
441 ids.mask(mask);
442 let mut cur: Option<Range<u64>> = None;
445 for (fragment, run) in ids.iter_runs() {
446 let frag = u64::from(fragment);
447 let run_start = (frag << 32) | u64::from(*run.start());
448 let run_end_excl = (frag << 32) | (u64::from(*run.end()) + 1);
449 let start = run_start - range.start + offset;
450 let end = run_end_excl - range.start + offset;
451 match cur.as_mut() {
452 Some(c) if c.end == start => c.end = end,
453 Some(c) => {
454 ranges.push(std::mem::replace(c, start..end));
455 }
456 None => cur = Some(start..end),
457 }
458 }
459 if let Some(c) = cur {
460 ranges.push(c);
461 }
462 offset += range.end - range.start;
463 }
464 U64Segment::RangeWithHoles { range, holes } => {
465 let offset_start = offset;
466 let mut ids = RowAddrTreeMap::from(range.clone());
467 offset += range.end - range.start;
468 for hole in holes.iter() {
469 if ids.remove(hole) {
470 offset -= 1;
471 }
472 }
473 ids.mask(mask);
474
475 let mut sorted_holes = holes.clone().into_iter().collect::<Vec<_>>();
477 sorted_holes.sort_unstable();
478 let mut next_holes_iter = sorted_holes.into_iter().peekable();
479 let mut holes_passed = 0;
480 ranges.extend(GroupingIterator::new(ids.into_addr_iter().map(|addr| {
481 while let Some(next_hole) = next_holes_iter.peek() {
482 if *next_hole < addr {
483 next_holes_iter.next();
484 holes_passed += 1;
485 } else {
486 break;
487 }
488 }
489 addr - range.start + offset_start - holes_passed
490 })));
491 }
492 U64Segment::RangeWithBitmap { range, bitmap } => {
493 let mut ids = RowAddrTreeMap::from(range.clone());
494 let offset_start = offset;
495 offset += range.end - range.start;
496 for (i, val) in range.clone().enumerate() {
497 if !bitmap.get(i) && ids.remove(val) {
498 offset -= 1;
499 }
500 }
501 ids.mask(mask);
502 let mut bitmap_iter = bitmap.iter();
503 let mut bitmap_iter_pos = 0;
504 let mut holes_passed = 0;
505 ranges.extend(GroupingIterator::new(ids.into_addr_iter().map(|addr| {
506 let position_in_range = addr - range.start;
507 while bitmap_iter_pos < position_in_range {
508 if !bitmap_iter.next().unwrap() {
509 holes_passed += 1;
510 }
511 bitmap_iter_pos += 1;
512 }
513 offset_start + position_in_range - holes_passed
514 })));
515 }
516 U64Segment::SortedArray(array) | U64Segment::Array(array) => {
517 ranges.extend(GroupingIterator::new(array.iter().enumerate().filter_map(
519 |(off, id)| {
520 if mask.selected(id) {
521 Some(off as u64 + offset)
522 } else {
523 None
524 }
525 },
526 )));
527 offset += array.len() as u64;
528 }
529 }
530 }
531 ranges
532 }
533}
534
535struct GroupingIterator<I: Iterator<Item = u64>> {
540 iter: I,
541 cur_range: Option<Range<u64>>,
542}
543
544impl<I: Iterator<Item = u64>> GroupingIterator<I> {
545 fn new(iter: I) -> Self {
546 Self {
547 iter,
548 cur_range: None,
549 }
550 }
551}
552
553impl<I: Iterator<Item = u64>> Iterator for GroupingIterator<I> {
554 type Item = Range<u64>;
555
556 fn next(&mut self) -> Option<Self::Item> {
557 for id in self.iter.by_ref() {
558 if let Some(range) = self.cur_range.as_mut() {
559 if range.end == id {
560 range.end = id + 1;
561 } else {
562 let ret = Some(range.clone());
563 self.cur_range = Some(id..id + 1);
564 return ret;
565 }
566 } else {
567 self.cur_range = Some(id..id + 1);
568 }
569 }
570 self.cur_range.take()
571 }
572}
573
574impl From<&RowIdSequence> for RowAddrTreeMap {
575 fn from(row_ids: &RowIdSequence) -> Self {
576 let mut tree_map = Self::new();
577 for segment in &row_ids.0 {
578 let mut seg = Self::new();
579 match segment {
580 U64Segment::Range(range) => {
581 seg.insert_range(range.clone());
582 }
583 U64Segment::RangeWithBitmap { range, bitmap } => {
584 seg.insert_range(range.clone());
585 for (i, val) in range.clone().enumerate() {
586 if !bitmap.get(i) {
587 seg.remove(val);
588 }
589 }
590 }
591 U64Segment::RangeWithHoles { range, holes } => {
592 seg.insert_range(range.clone());
593 for hole in holes.iter() {
594 seg.remove(hole);
595 }
596 }
597 U64Segment::SortedArray(array) | U64Segment::Array(array) => {
598 for val in array.iter() {
599 seg.insert(val);
600 }
601 }
602 }
603 tree_map |= seg;
604 }
605 tree_map
606 }
607}
608
609#[derive(Debug)]
610pub struct RowIdSeqSlice<'a> {
611 segments: &'a [U64Segment],
613 offset_start: usize,
615 offset_last: usize,
617}
618
619impl RowIdSeqSlice<'_> {
620 pub fn iter(&self) -> impl Iterator<Item = u64> + '_ {
621 let mut known_size = self.segments.iter().map(|segment| segment.len()).sum();
622 known_size -= self.offset_start;
623 known_size -= self.segments.last().map(|s| s.len()).unwrap_or_default() - self.offset_last;
624
625 let end = self.segments.len().saturating_sub(1);
626 self.segments
627 .iter()
628 .enumerate()
629 .flat_map(move |(i, segment)| {
630 match i {
631 0 if self.segments.len() == 1 => {
632 let len = self.offset_last - self.offset_start;
633 Box::new(segment.iter().skip(self.offset_start).take(len))
636 as Box<dyn Iterator<Item = u64>>
637 }
638 0 => Box::new(segment.iter().skip(self.offset_start)),
639 i if i == end => Box::new(segment.iter().take(self.offset_last)),
640 _ => Box::new(segment.iter()),
641 }
642 })
643 .exact_size(known_size)
644 }
645}
646
647pub fn rechunk_sequences(
661 sequences: impl IntoIterator<Item = RowIdSequence>,
662 chunk_sizes: impl IntoIterator<Item = u64>,
663 allow_incomplete: bool,
664) -> Result<Vec<RowIdSequence>> {
665 let chunk_sizes_vec: Vec<u64> = chunk_sizes.into_iter().collect();
667 let total_chunks = chunk_sizes_vec.len();
668 let mut chunked_sequences = Vec::with_capacity(total_chunks);
669 let mut segment_iter = sequences
670 .into_iter()
671 .flat_map(|sequence| sequence.0.into_iter())
672 .peekable();
673
674 let too_few_segments_error = |chunk_index: usize, expected_chunk_size: u64, remaining: u64| {
675 Error::invalid_input(format!(
676 "Got too few segments for chunk {}. Expected chunk size: {}, remaining needed: {}",
677 chunk_index, expected_chunk_size, remaining
678 ))
679 };
680
681 let too_many_segments_error = |processed_chunks: usize, total_chunk_sizes: usize| {
682 Error::invalid_input(format!(
683 "Got too many segments for the provided chunk lengths. Processed {} chunks out of {} expected",
684 processed_chunks, total_chunk_sizes
685 ))
686 };
687
688 let mut segment_offset = 0_u64;
689
690 for (chunk_index, chunk_size) in chunk_sizes_vec.iter().enumerate() {
691 let chunk_size = *chunk_size;
692 let mut sequence = RowIdSequence(Vec::new());
693 let mut remaining = chunk_size;
694
695 while remaining > 0 {
696 let remaining_in_segment = segment_iter
697 .peek()
698 .map_or(0, |segment| segment.len() as u64 - segment_offset);
699
700 if remaining_in_segment == 0 {
702 if segment_iter.next().is_some() {
703 segment_offset = 0;
704 continue;
705 } else {
706 if allow_incomplete {
708 break;
709 } else {
710 return Err(too_few_segments_error(chunk_index, chunk_size, remaining));
711 }
712 }
713 }
714
715 match remaining_in_segment.cmp(&remaining) {
717 std::cmp::Ordering::Greater => {
718 let segment = segment_iter
720 .peek()
721 .ok_or_else(|| too_few_segments_error(chunk_index, chunk_size, remaining))?
722 .slice(segment_offset as usize, remaining as usize);
723 sequence.extend(RowIdSequence(vec![segment]));
724 segment_offset += remaining;
725 remaining = 0;
726 }
727 std::cmp::Ordering::Equal | std::cmp::Ordering::Less => {
728 let segment = segment_iter
732 .next()
733 .ok_or_else(|| too_few_segments_error(chunk_index, chunk_size, remaining))?
734 .slice(segment_offset as usize, remaining_in_segment as usize);
735 sequence.extend(RowIdSequence(vec![segment]));
736 segment_offset = 0;
737 remaining -= remaining_in_segment;
738 }
739 }
740 }
741
742 chunked_sequences.push(sequence);
743 }
744
745 if segment_iter.peek().is_some() {
746 return Err(too_many_segments_error(
747 chunked_sequences.len(),
748 total_chunks,
749 ));
750 }
751
752 Ok(chunked_sequences)
753}
754
755pub fn select_row_ids<'a>(
757 sequence: &'a RowIdSequence,
758 offsets: &'a ReadBatchParams,
759) -> Result<Vec<u64>> {
760 let out_of_bounds_err = |offset: u32| {
761 Error::invalid_input(format!(
762 "Index out of bounds: {} for sequence of length {}",
763 offset,
764 sequence.len()
765 ))
766 };
767
768 match offsets {
769 ReadBatchParams::Indices(indices) => {
770 let indices = indices.values();
771 if indices.windows(2).all(|pair| pair[0] <= pair[1]) {
772 if let Some(&last) = indices.last()
774 && last as u64 >= sequence.len()
775 {
776 return Err(out_of_bounds_err(last));
777 }
778 return Ok(sequence
779 .select(indices.iter().map(|&index| index as usize))
780 .collect());
781 }
782 indices
783 .iter()
784 .map(|index| {
785 sequence
786 .get(*index as usize)
787 .ok_or_else(|| out_of_bounds_err(*index))
788 })
789 .collect()
790 }
791 ReadBatchParams::Range(range) => {
792 if range.end > sequence.len() as usize {
793 return Err(out_of_bounds_err(range.end as u32));
794 }
795 let sequence = sequence.slice(range.start, range.end - range.start);
796 Ok(sequence.iter().collect())
797 }
798 ReadBatchParams::Ranges(ranges) => {
799 let num_rows = ranges
800 .iter()
801 .map(|r| (r.end - r.start) as usize)
802 .sum::<usize>();
803 let mut result = Vec::with_capacity(num_rows);
804 for range in ranges.as_ref() {
805 if range.end > sequence.len() {
806 return Err(out_of_bounds_err(range.end as u32));
807 }
808 let sequence =
809 sequence.slice(range.start as usize, (range.end - range.start) as usize);
810 result.extend(sequence.iter());
811 }
812 Ok(result)
813 }
814
815 ReadBatchParams::RangeFull => Ok(sequence.iter().collect()),
816 ReadBatchParams::RangeTo(to) => {
817 if to.end > sequence.len() as usize {
818 return Err(out_of_bounds_err(to.end as u32));
819 }
820 let len = to.end;
821 let sequence = sequence.slice(0, len);
822 Ok(sequence.iter().collect())
823 }
824 ReadBatchParams::RangeFrom(from) => {
825 let sequence = sequence.slice(from.start, sequence.len() as usize - from.start);
826 Ok(sequence.iter().collect())
827 }
828 }
829}
830
831#[cfg(test)]
832mod test {
833 use super::*;
834
835 use pretty_assertions::assert_eq;
836 use test::bitmap::Bitmap;
837
838 #[test]
839 fn test_row_id_sequence_from_range() {
840 let sequence = RowIdSequence::from(0..10);
841 assert_eq!(sequence.len(), 10);
842 assert_eq!(sequence.is_empty(), false);
843
844 let iter = sequence.iter();
845 assert_eq!(iter.collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
846 }
847
848 #[rstest::rstest]
849 #[case::sorted_contiguous(vec![0, 1, 2, 3])]
850 #[case::sorted_with_gaps(vec![0, 2, 4])]
851 #[case::sparse(vec![0, 1_000_000])]
852 #[case::unsorted(vec![12, 11, 10])]
853 fn test_row_id_sequence_try_from_iter(#[case] row_ids: Vec<u64>) {
854 let sequence = RowIdSequence::try_from_iter(row_ids.clone()).unwrap();
855 assert_eq!(sequence.len(), row_ids.len() as u64);
856 assert_eq!(sequence.iter().collect::<Vec<_>>(), row_ids);
857 }
858
859 #[test]
860 fn test_row_id_sequence_try_from_iter_contiguous_is_a_range() {
861 let sequence = RowIdSequence::try_from_iter(0..10).unwrap();
862 assert_eq!(sequence.0, vec![U64Segment::Range(0..10)]);
863 }
864
865 #[test]
866 fn test_row_id_sequence_try_from_iter_empty() {
867 let sequence = RowIdSequence::try_from_iter(std::iter::empty()).unwrap();
868 assert_eq!(sequence.len(), 0);
869 assert!(sequence.is_empty());
870 }
871
872 #[rstest::rstest]
873 #[case::adjacent(vec![1, 1, 2])]
874 #[case::separated(vec![1, 2, 3, 1])]
875 #[case::unsorted(vec![5, 3, 5])]
876 fn test_row_id_sequence_try_from_iter_rejects_duplicates(#[case] row_ids: Vec<u64>) {
877 let error = RowIdSequence::try_from_iter(row_ids).unwrap_err();
880 assert!(
881 matches!(error, Error::InvalidInput { .. }),
882 "expected InvalidInput, got {:?}",
883 error
884 );
885 assert!(
886 error.to_string().contains("must be unique"),
887 "unexpected message: {}",
888 error
889 );
890 }
891
892 #[test]
893 fn test_row_id_sequence_extend() {
894 let mut sequence = RowIdSequence::from(0..10);
895 sequence.extend(RowIdSequence::from(10..20));
896 assert_eq!(sequence.0, vec![U64Segment::Range(0..20)]);
897
898 let mut sequence = RowIdSequence::from(0..10);
899 sequence.extend(RowIdSequence::from(20..30));
900 assert_eq!(
901 sequence.0,
902 vec![U64Segment::Range(0..10), U64Segment::Range(20..30)]
903 );
904 }
905
906 #[test]
907 fn test_row_id_sequence_delete() {
908 let mut sequence = RowIdSequence::from(0..10);
909 sequence.delete(vec![1, 3, 5, 7, 9]);
910 let mut expected_bitmap = Bitmap::new_empty(9);
911 for i in [0, 2, 4, 6, 8] {
912 expected_bitmap.set(i as usize);
913 }
914 assert_eq!(
915 sequence.0,
916 vec![U64Segment::RangeWithBitmap {
917 range: 0..9,
918 bitmap: expected_bitmap
919 },]
920 );
921
922 let mut sequence = RowIdSequence::from(0..10);
923 sequence.extend(RowIdSequence::from(12..20));
924 sequence.delete(vec![0, 9, 10, 11, 12, 13]);
925 assert_eq!(
926 sequence.0,
927 vec![U64Segment::Range(1..9), U64Segment::Range(14..20),]
928 );
929
930 let mut sequence = RowIdSequence::from(0..10);
931 sequence.delete(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
932 assert_eq!(sequence.0, vec![U64Segment::Range(0..0)]);
933 }
934
935 #[test]
936 fn test_row_id_slice() {
937 let sequence = RowIdSequence(vec![
940 U64Segment::Range(30..35), U64Segment::RangeWithHoles {
942 range: 50..60,
944 holes: vec![53, 54].into(),
945 },
946 U64Segment::SortedArray(vec![7, 9].into()), U64Segment::RangeWithBitmap {
948 range: 0..5,
949 bitmap: [true, false, true, false, true].as_slice().into(),
950 },
951 U64Segment::Array(vec![35, 39].into()),
952 U64Segment::Range(40..50),
953 ]);
954
955 for offset in 0..sequence.len() as usize {
957 for len in 0..sequence.len() as usize {
958 if offset + len > sequence.len() as usize {
959 continue;
960 }
961 let slice = sequence.slice(offset, len);
962
963 let actual = slice.iter().collect::<Vec<_>>();
964 let expected = sequence.iter().skip(offset).take(len).collect::<Vec<_>>();
965 assert_eq!(
966 actual, expected,
967 "Failed for offset {} and len {}",
968 offset, len
969 );
970
971 let (claimed_size, claimed_max) = slice.iter().size_hint();
972 assert_eq!(claimed_max, Some(claimed_size)); assert_eq!(claimed_size, actual.len()); }
975 }
976 }
977
978 #[test]
979 fn test_row_id_slice_empty() {
980 let sequence = RowIdSequence::from(0..10);
981 let slice = sequence.slice(10, 0);
982 assert_eq!(slice.iter().collect::<Vec<_>>(), Vec::<u64>::new());
983 }
984
985 #[test]
986 fn test_row_id_sequence_rechunk() {
987 fn assert_rechunked(
988 input: Vec<RowIdSequence>,
989 chunk_sizes: Vec<u64>,
990 expected: Vec<RowIdSequence>,
991 ) {
992 let chunked = rechunk_sequences(input, chunk_sizes, false).unwrap();
993 assert_eq!(chunked, expected);
994 }
995
996 let many_segments = vec![
998 RowIdSequence(vec![U64Segment::Range(0..5), U64Segment::Range(35..40)]),
999 RowIdSequence::from(10..18),
1000 RowIdSequence::from(18..28),
1001 RowIdSequence::from(28..30),
1002 ];
1003 let fewer_segments = vec![
1004 RowIdSequence(vec![U64Segment::Range(0..5), U64Segment::Range(35..40)]),
1005 RowIdSequence::from(10..30),
1006 ];
1007 assert_rechunked(
1008 many_segments.clone(),
1009 fewer_segments.iter().map(|seq| seq.len()).collect(),
1010 fewer_segments.clone(),
1011 );
1012
1013 assert_rechunked(
1015 fewer_segments,
1016 many_segments.iter().map(|seq| seq.len()).collect(),
1017 many_segments.clone(),
1018 );
1019
1020 assert_rechunked(
1022 many_segments.clone(),
1023 many_segments.iter().map(|seq| seq.len()).collect(),
1024 many_segments.clone(),
1025 );
1026
1027 let result = rechunk_sequences(many_segments.clone(), vec![100], false);
1029 assert!(result.is_err());
1030
1031 let result = rechunk_sequences(many_segments, vec![5], false);
1033 assert!(result.is_err());
1034 }
1035
1036 #[test]
1037 fn test_select_row_ids() {
1038 let offsets = [
1040 ReadBatchParams::Indices(vec![1, 3, 9, 5, 7, 6].into()),
1041 ReadBatchParams::Indices(vec![1, 3, 5, 6, 7, 9].into()),
1042 ReadBatchParams::Range(2..8),
1043 ReadBatchParams::RangeFull,
1044 ReadBatchParams::RangeTo(..5),
1045 ReadBatchParams::RangeFrom(5..),
1046 ReadBatchParams::Ranges(vec![2..3, 5..10].into()),
1047 ];
1048
1049 let sequences = [
1052 RowIdSequence(vec![
1053 U64Segment::Range(0..5),
1054 U64Segment::RangeWithHoles {
1055 range: 50..60,
1056 holes: vec![53, 54].into(),
1057 },
1058 U64Segment::SortedArray(vec![7, 9].into()),
1059 ]),
1060 RowIdSequence(vec![
1061 U64Segment::RangeWithBitmap {
1062 range: 0..5,
1063 bitmap: [true, false, true, false, true].as_slice().into(),
1064 },
1065 U64Segment::Array(vec![30, 20, 10].into()),
1066 U64Segment::Range(40..50),
1067 ]),
1068 ];
1069
1070 for params in offsets {
1071 for sequence in &sequences {
1072 let row_ids = select_row_ids(sequence, ¶ms).unwrap();
1073 let flat_sequence = sequence.iter().collect::<Vec<_>>();
1074
1075 let selection: Vec<usize> = match ¶ms {
1077 ReadBatchParams::RangeFull => (0..flat_sequence.len()).collect(),
1078 ReadBatchParams::RangeTo(to) => (0..to.end).collect(),
1079 ReadBatchParams::RangeFrom(from) => (from.start..flat_sequence.len()).collect(),
1080 ReadBatchParams::Range(range) => range.clone().collect(),
1081 ReadBatchParams::Ranges(ranges) => ranges
1082 .iter()
1083 .flat_map(|r| r.start as usize..r.end as usize)
1084 .collect(),
1085 ReadBatchParams::Indices(indices) => {
1086 indices.values().iter().map(|i| *i as usize).collect()
1087 }
1088 };
1089
1090 let expected = selection
1091 .into_iter()
1092 .map(|i| flat_sequence[i])
1093 .collect::<Vec<_>>();
1094 assert_eq!(
1095 row_ids, expected,
1096 "Failed for params {:?} on the sequence {:?}",
1097 ¶ms, sequence
1098 );
1099 }
1100 }
1101 }
1102
1103 #[test]
1104 fn test_select_row_ids_out_of_bounds() {
1105 let offsets = [
1106 ReadBatchParams::Indices(vec![1, 1000, 4].into()),
1107 ReadBatchParams::Indices(vec![1, 4, 1000].into()),
1108 ReadBatchParams::Range(2..1000),
1109 ReadBatchParams::RangeTo(..1000),
1110 ];
1111
1112 let sequence = RowIdSequence::from(0..10);
1113
1114 for params in offsets {
1115 let result = select_row_ids(&sequence, ¶ms);
1116 assert!(result.is_err());
1117 assert!(matches!(result.unwrap_err(), Error::InvalidInput { .. }));
1118 }
1119 }
1120
1121 #[test]
1122 fn test_row_id_sequence_to_treemap() {
1123 let sequence = RowIdSequence(vec![
1124 U64Segment::Range(0..5),
1125 U64Segment::RangeWithHoles {
1126 range: 50..60,
1127 holes: vec![53, 54].into(),
1128 },
1129 U64Segment::SortedArray(vec![7, 9].into()),
1130 U64Segment::RangeWithBitmap {
1131 range: 10..15,
1132 bitmap: [true, false, true, false, true].as_slice().into(),
1133 },
1134 U64Segment::Array(vec![35, 39].into()),
1135 U64Segment::Range(40..50),
1136 ]);
1137
1138 let tree_map = RowAddrTreeMap::from(&sequence);
1139 let expected = vec![
1140 0, 1, 2, 3, 4, 7, 9, 10, 12, 14, 35, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
1141 51, 52, 55, 56, 57, 58, 59,
1142 ]
1143 .into_iter()
1144 .collect::<RowAddrTreeMap>();
1145 assert_eq!(tree_map, expected);
1146 }
1147
1148 #[test]
1149 fn test_row_id_sequence_to_treemap_overlapping_segments() {
1150 let sequence = RowIdSequence(vec![
1154 U64Segment::RangeWithBitmap {
1155 range: 0..6,
1156 bitmap: [true, false, true, false, true, false].as_slice().into(),
1157 },
1158 U64Segment::RangeWithBitmap {
1159 range: 0..6,
1160 bitmap: [false, true, false, true, false, true].as_slice().into(),
1161 },
1162 ]);
1163
1164 let expected = sequence.iter().collect::<RowAddrTreeMap>();
1165 assert_eq!(expected, (0..6).collect::<RowAddrTreeMap>());
1166 assert_eq!(RowAddrTreeMap::from(&sequence), expected);
1167 }
1168
1169 #[test]
1170 fn test_row_addr_mask() {
1171 let sequence = RowIdSequence(vec![
1177 U64Segment::Range(0..5),
1178 U64Segment::RangeWithHoles {
1179 range: 50..60,
1180 holes: vec![53, 54].into(),
1181 },
1182 U64Segment::SortedArray(vec![7, 9].into()),
1183 U64Segment::RangeWithBitmap {
1184 range: 10..15,
1185 bitmap: [true, false, true, false, true].as_slice().into(),
1186 },
1187 U64Segment::Array(vec![35, 39].into()),
1188 ]);
1189
1190 let values_to_remove = [4, 55, 7, 12, 39];
1192 let positions_to_remove = sequence
1193 .iter()
1194 .enumerate()
1195 .filter_map(|(i, val)| {
1196 if values_to_remove.contains(&val) {
1197 Some(i as u32)
1198 } else {
1199 None
1200 }
1201 })
1202 .collect::<Vec<_>>();
1203 let mut sequence = sequence;
1204 sequence.mask(positions_to_remove).unwrap();
1205 let expected = RowIdSequence(vec![
1206 U64Segment::Range(0..4),
1207 U64Segment::RangeWithBitmap {
1208 range: 50..60,
1209 bitmap: [
1210 true, true, true, false, false, false, true, true, true, true,
1211 ]
1212 .as_slice()
1213 .into(),
1214 },
1215 U64Segment::Range(9..10),
1216 U64Segment::RangeWithBitmap {
1217 range: 10..15,
1218 bitmap: [true, false, false, false, true].as_slice().into(),
1219 },
1220 U64Segment::Array(vec![35].into()),
1221 ]);
1222 assert_eq!(sequence, expected);
1223 }
1224
1225 #[test]
1226 fn test_row_addr_mask_everything() {
1227 let mut sequence = RowIdSequence(vec![
1228 U64Segment::Range(0..5),
1229 U64Segment::SortedArray(vec![7, 9].into()),
1230 ]);
1231 sequence.mask(0..sequence.len() as u32).unwrap();
1232 let expected = RowIdSequence(vec![]);
1233 assert_eq!(sequence, expected);
1234 }
1235
1236 #[test]
1237 fn test_selection() {
1238 let sequence = RowIdSequence(vec![
1239 U64Segment::Range(0..5),
1240 U64Segment::Range(10..15),
1241 U64Segment::Range(20..25),
1242 ]);
1243 let selection = sequence.select(vec![2, 4, 13, 14, 57].into_iter());
1244 assert_eq!(selection.collect::<Vec<_>>(), vec![2, 4, 23, 24]);
1245 }
1246
1247 #[test]
1248 fn test_selection_over_bitmap_segments() {
1249 let mut bitmap = Bitmap::new_full(40);
1250 for hole in [3, 4, 17, 39] {
1251 bitmap.clear(hole);
1252 }
1253 let sequence = RowIdSequence(vec![
1254 U64Segment::RangeWithBitmap {
1255 range: 100..140,
1256 bitmap,
1257 },
1258 U64Segment::Range(200..205),
1259 ]);
1260 let live: Vec<u64> = sequence.iter().collect();
1261 assert_eq!(live.len(), 41);
1262
1263 let all = sequence.select(0..live.len()).collect::<Vec<_>>();
1265 assert_eq!(all, live);
1266 let picks = vec![0, 2, 3, 3, 15, 16, 35, 36, 40, 99];
1268 let got = sequence.select(picks.iter().copied()).collect::<Vec<_>>();
1269 let want: Vec<u64> = picks.iter().filter_map(|&i| live.get(i).copied()).collect();
1270 assert_eq!(got, want);
1271 }
1272
1273 #[test]
1274 fn test_selection_over_a_large_bitmap_segment() {
1275 const ROWS: usize = 1_000_000;
1278 let mut bitmap = Bitmap::new_full(ROWS);
1279 for hole in (0..ROWS).step_by(17) {
1280 bitmap.clear(hole);
1281 }
1282 let sequence = RowIdSequence(vec![
1283 U64Segment::Range(0..8),
1284 U64Segment::RangeWithBitmap {
1285 range: 1_000..(1_000 + ROWS as u64),
1286 bitmap,
1287 },
1288 ]);
1289 let live: Vec<u64> = sequence.iter().collect();
1290
1291 let all = sequence.select(0..live.len()).collect::<Vec<_>>();
1292 assert_eq!(all, live);
1293
1294 let mut picks: Vec<usize> = [0, 7, 8, 9, 15, 16, 63, 64, 65]
1296 .into_iter()
1297 .chain((0..live.len()).step_by(9973))
1298 .chain([live.len() - 1, live.len()])
1299 .collect();
1300 picks.sort_unstable();
1301 let got = sequence.select(picks.iter().copied()).collect::<Vec<_>>();
1302 let want: Vec<u64> = picks.iter().filter_map(|&i| live.get(i).copied()).collect();
1303 assert_eq!(got, want);
1304 }
1305
1306 #[test]
1307 #[should_panic(expected = "Selection is not sorted")]
1308 fn test_selection_unsorted() {
1309 let sequence = RowIdSequence(vec![
1310 U64Segment::Range(0..5),
1311 U64Segment::Range(10..15),
1312 U64Segment::Range(20..25),
1313 ]);
1314 let _ = sequence
1315 .select(vec![2, 4, 3].into_iter())
1316 .collect::<Vec<_>>();
1317 }
1318
1319 #[test]
1320 fn test_mask_to_offset_ranges() {
1321 let sequence = RowIdSequence(vec![U64Segment::Range(0..10)]);
1323 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 2, 4, 6, 8]));
1324 let ranges = sequence.mask_to_offset_ranges(&mask);
1325 assert_eq!(ranges, vec![0..1, 2..3, 4..5, 6..7, 8..9]);
1326
1327 let sequence = RowIdSequence(vec![U64Segment::Range(40..60)]);
1328 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[54]));
1329 let ranges = sequence.mask_to_offset_ranges(&mask);
1330 assert_eq!(ranges, vec![14..15]);
1331
1332 let sequence = RowIdSequence(vec![U64Segment::Range(40..60)]);
1333 let mask = RowAddrMask::from_block(RowAddrTreeMap::from_iter(&[54]));
1334 let ranges = sequence.mask_to_offset_ranges(&mask);
1335 assert_eq!(ranges, vec![0..14, 15..20]);
1336
1337 let sequence = RowIdSequence(vec![U64Segment::RangeWithHoles {
1340 range: 0..10,
1341 holes: vec![2, 6].into(),
1342 }]);
1343 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 2, 4, 6, 8]));
1344 let ranges = sequence.mask_to_offset_ranges(&mask);
1345 assert_eq!(ranges, vec![0..1, 3..4, 6..7]);
1346
1347 let sequence = RowIdSequence(vec![U64Segment::RangeWithHoles {
1348 range: 40..60,
1349 holes: vec![47, 43].into(),
1350 }]);
1351 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[44]));
1352 let ranges = sequence.mask_to_offset_ranges(&mask);
1353 assert_eq!(ranges, vec![3..4]);
1354
1355 let sequence = RowIdSequence(vec![U64Segment::RangeWithHoles {
1356 range: 40..60,
1357 holes: vec![47, 43].into(),
1358 }]);
1359 let mask = RowAddrMask::from_block(RowAddrTreeMap::from_iter(&[44]));
1360 let ranges = sequence.mask_to_offset_ranges(&mask);
1361 assert_eq!(ranges, vec![0..3, 4..18]);
1362
1363 let sequence = RowIdSequence(vec![U64Segment::RangeWithBitmap {
1366 range: 0..10,
1367 bitmap: [
1368 true, true, false, false, true, true, true, true, false, false,
1369 ]
1370 .as_slice()
1371 .into(),
1372 }]);
1373 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 2, 4, 6, 8]));
1374 let ranges = sequence.mask_to_offset_ranges(&mask);
1375 assert_eq!(ranges, vec![0..1, 2..3, 4..5]);
1376
1377 let sequence = RowIdSequence(vec![U64Segment::RangeWithBitmap {
1378 range: 40..45,
1379 bitmap: [true, true, false, false, true].as_slice().into(),
1380 }]);
1381 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[44]));
1382 let ranges = sequence.mask_to_offset_ranges(&mask);
1383 assert_eq!(ranges, vec![2..3]);
1384
1385 let sequence = RowIdSequence(vec![U64Segment::RangeWithBitmap {
1386 range: 40..45,
1387 bitmap: [true, true, false, false, true].as_slice().into(),
1388 }]);
1389 let mask = RowAddrMask::from_block(RowAddrTreeMap::from_iter(&[44]));
1390 let ranges = sequence.mask_to_offset_ranges(&mask);
1391 assert_eq!(ranges, vec![0..2]);
1392
1393 let sequence = RowIdSequence(vec![U64Segment::SortedArray(vec![0, 2, 4, 6, 8].into())]);
1395 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 6, 8]));
1396 let ranges = sequence.mask_to_offset_ranges(&mask);
1397 assert_eq!(ranges, vec![0..1, 3..5]);
1398
1399 let sequence = RowIdSequence(vec![U64Segment::Array(vec![8, 2, 6, 0, 4].into())]);
1400 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 6, 8]));
1401 let ranges = sequence.mask_to_offset_ranges(&mask);
1402 assert_eq!(ranges, vec![0..1, 2..4]);
1403
1404 let sequence = RowIdSequence(vec![
1409 U64Segment::Range(0..5),
1410 U64Segment::RangeWithHoles {
1411 range: 100..105,
1412 holes: vec![103].into(),
1413 },
1414 U64Segment::SortedArray(vec![44, 46, 78].into()),
1415 ]);
1416 let mask = RowAddrMask::from_allowed(RowAddrTreeMap::from_iter(&[0, 2, 46, 100, 104]));
1417 let ranges = sequence.mask_to_offset_ranges(&mask);
1418 assert_eq!(ranges, vec![0..1, 2..3, 5..6, 8..9, 10..11]);
1419
1420 let sequence = RowIdSequence(vec![U64Segment::Range(0..10)]);
1422 let mask = RowAddrMask::default();
1423 let ranges = sequence.mask_to_offset_ranges(&mask);
1424 assert_eq!(ranges, vec![0..10]);
1425
1426 let sequence = RowIdSequence(vec![U64Segment::Range(0..10)]);
1428 let mask = RowAddrMask::allow_nothing();
1429 let ranges = sequence.mask_to_offset_ranges(&mask);
1430 assert_eq!(ranges, vec![]);
1431 }
1432
1433 #[test]
1434 fn test_row_id_sequence_rechunk_with_empty_segments() {
1435 let input_sequences = vec![
1437 RowIdSequence::from(0..2), RowIdSequence::from(20..23), ];
1440 let chunk_sizes = vec![2, 3]; let result = rechunk_sequences(input_sequences, chunk_sizes, false).unwrap();
1443 assert_eq!(result.len(), 2);
1444 assert_eq!(result[0].len(), 2);
1445 assert_eq!(result[1].len(), 3);
1446
1447 let first_chunk: Vec<u64> = result[0].iter().collect();
1448 let second_chunk: Vec<u64> = result[1].iter().collect();
1449 assert_eq!(first_chunk, vec![0, 1]);
1450 assert_eq!(second_chunk, vec![20, 21, 22]);
1451
1452 let input_sequences = vec![
1454 RowIdSequence::from(0..2), RowIdSequence::from(20..21), RowIdSequence::from(30..32), ];
1458 let chunk_sizes = vec![5]; let result = rechunk_sequences(input_sequences, chunk_sizes, false).unwrap();
1461 assert_eq!(result.len(), 1);
1462 assert_eq!(result[0].len(), 5);
1463
1464 let elements: Vec<u64> = result[0].iter().collect();
1465 assert_eq!(elements, vec![0, 1, 20, 30, 31]);
1466
1467 let input_sequences = vec![
1469 RowIdSequence::from(0..2), RowIdSequence::from(10..10), RowIdSequence::from(20..22), ];
1473 let chunk_sizes = vec![3, 1];
1474 let result = rechunk_sequences(input_sequences, chunk_sizes, false).unwrap();
1475
1476 assert_eq!(result.len(), 2);
1477 assert_eq!(result[0].len(), 3);
1478 assert_eq!(result[1].len(), 1);
1479
1480 let first_chunk_elements: Vec<u64> = result[0].iter().collect();
1481 let second_chunk_elements: Vec<u64> = result[1].iter().collect();
1482 assert_eq!(first_chunk_elements, vec![0, 1, 20]);
1483 assert_eq!(second_chunk_elements, vec![21]);
1484
1485 let input_sequences = vec![
1487 RowIdSequence::from(0..1), RowIdSequence::from(10..10), RowIdSequence::from(20..20), RowIdSequence::from(30..32), ];
1492 let chunk_sizes = vec![3];
1493 let result = rechunk_sequences(input_sequences, chunk_sizes, false).unwrap();
1494
1495 assert_eq!(result.len(), 1);
1496 assert_eq!(result[0].len(), 3);
1497
1498 let elements: Vec<u64> = result[0].iter().collect();
1499 assert_eq!(elements, vec![0, 30, 31]);
1500
1501 let input_sequences = vec![
1503 RowIdSequence::from(0..3), RowIdSequence::from(10..10), RowIdSequence::from(20..22), ];
1507 let chunk_sizes = vec![3, 2];
1508 let result = rechunk_sequences(input_sequences, chunk_sizes, false).unwrap();
1509
1510 assert_eq!(result.len(), 2);
1511 assert_eq!(result[0].len(), 3);
1512 assert_eq!(result[1].len(), 2);
1513
1514 let first_chunk_elements: Vec<u64> = result[0].iter().collect();
1515 let second_chunk_elements: Vec<u64> = result[1].iter().collect();
1516 assert_eq!(first_chunk_elements, vec![0, 1, 2]);
1517 assert_eq!(second_chunk_elements, vec![20, 21]);
1518
1519 let input_sequences = vec![
1521 RowIdSequence::from(0..2), RowIdSequence::from(10..10), ];
1524 let chunk_sizes = vec![5]; let result = rechunk_sequences(input_sequences, chunk_sizes, true).unwrap();
1526
1527 assert_eq!(result.len(), 1);
1528 assert_eq!(result[0].len(), 2);
1529
1530 let elements: Vec<u64> = result[0].iter().collect();
1531 assert_eq!(elements, vec![0, 1]);
1532 }
1533
1534 #[test]
1535 fn test_row_id_range_empty() {
1536 let seq = RowIdSequence::from(0u64..0);
1537 assert_eq!(seq.row_id_range(), None);
1538 }
1539
1540 #[test]
1541 fn test_row_id_range_single_contiguous() {
1542 let seq = RowIdSequence::from(10u64..20);
1543 assert_eq!(seq.row_id_range(), Some(10..=19));
1544 }
1545
1546 #[test]
1547 fn test_row_id_range_unsorted_array() {
1548 let seq = RowIdSequence::from([50u64, 10, 30].as_slice());
1550 let r = seq.row_id_range().unwrap();
1551 assert!(*r.start() <= 10);
1552 assert!(*r.end() >= 50);
1553 }
1554
1555 #[test]
1556 fn test_row_id_range_multi_segment() {
1557 let mut seq = RowIdSequence::from(0u64..5);
1559 seq.extend(RowIdSequence::from(100u64..105));
1560 let r = seq.row_id_range().unwrap();
1561 assert_eq!(*r.start(), 0);
1562 assert_eq!(*r.end(), 104);
1563 }
1564}