1use std::collections::HashMap;
43use std::ops::Range;
44use std::sync::Arc;
45
46use rudb_common::{Error, LogicalType, Result, Value};
47
48use crate::buffer::Buffer;
49use crate::string::{Arenas, StringView};
50use crate::validity::Validity;
51use crate::vector::{
52 Data, Form, NOWHERE, Vector, copy_of, data_for, empty_data_for, layout_of, placed_of,
53};
54
55#[derive(Debug)]
60pub struct Assembly {
61 ty: LogicalType,
62 rows: usize,
63 data: Data,
65 at: Vec<usize>,
67 live: Vec<bool>,
69 values: Option<Vec<Value>>,
77}
78
79impl Assembly {
80 pub fn new(ty: LogicalType, rows: usize) -> Result<Self> {
86 let nested =
87 matches!(ty, LogicalType::List(_) | LogicalType::Struct(_) | LogicalType::Map(_, _));
88 let values = if nested { Some(vec![Value::Null; rows]) } else { None };
89 let data = if nested { Data::Empty } else { empty_data_for(&ty)? };
90 Ok(Self { ty, rows, data, at: vec![NOWHERE; rows], live: vec![false; rows], values })
91 }
92
93 #[must_use]
95 pub fn rows(&self) -> usize {
96 self.rows
97 }
98
99 pub fn place(&mut self, positions: &[u32], piece: &Vector) -> Result<()> {
112 if positions.len() != piece.len() {
113 return Err(Error::internal(format!(
114 "a piece of {} rows placed at {} positions",
115 piece.len(),
116 positions.len()
117 )));
118 }
119 for &row in positions {
120 if row as usize >= self.rows {
121 return Err(Error::internal(format!(
122 "row {row} placed in an assembly of {} rows",
123 self.rows
124 )));
125 }
126 }
127 if let Some(values) = &mut self.values {
128 for (slot, &row) in positions.iter().enumerate() {
132 values[row as usize] = piece.value_at(slot);
133 }
134 return Ok(());
135 }
136 let flat = piece.flatten()?;
141 let Some(from) = flat.data() else {
142 return Err(Error::internal("a flattened vector with no run of data in it"));
143 };
144 let start = self.data.len();
145 let appended = extend(&mut self.data, from, &mut Arenas::default())?;
146 for (slot, &row) in positions.iter().enumerate() {
147 let row = row as usize;
148 if slot < appended {
151 self.at[row] = start + slot;
152 self.live[row] = !piece.is_null_at(slot);
153 } else {
154 self.at[row] = NOWHERE;
155 self.live[row] = false;
156 }
157 }
158 Ok(())
159 }
160
161 pub fn finish(self) -> Result<Vector> {
167 if let Some(values) = self.values {
168 return Vector::from_values(self.ty, &values);
169 }
170 if matches!(self.data, Data::Empty) {
173 return Ok(Vector::constant(self.ty, Value::Null, self.rows));
174 }
175 let validity = Validity::from_run(&self.live);
176 if let Data::Varlen(column) = self.data {
182 let (laid, arena) = column.into_parts();
183 let arena = Arc::new(arena);
184 if straight(&self.at) {
185 return Ok(Vector::string_views(self.ty, laid, arena)?.with_validity(validity));
186 }
187 let views = self
188 .at
189 .iter()
190 .map(|&index| laid.get(index).copied().unwrap_or_else(StringView::empty))
191 .collect();
192 return Ok(Vector::string_views(self.ty, views, arena)?.with_validity(validity));
193 }
194 if straight(&self.at) {
198 return Ok(Vector::flat(self.ty, self.data)?.with_validity(validity));
199 }
200 let gathered = copy_of(&self.data, &self.at);
201 Ok(Vector::flat(self.ty, gathered)?.with_validity(validity))
202 }
203}
204
205pub fn concat(ty: &LogicalType, pieces: &[Vector]) -> Result<Option<Vector>> {
233 if pieces.is_empty() {
234 return Ok(None);
235 }
236 let rows = pieces.iter().map(Vector::len).sum();
237 let shared = pieces[0].stable_dictionary_parts().map(|(_, values)| values).filter(|values| {
238 pieces.iter().all(|piece| {
239 piece.logical_type() == ty
240 && !piece.is_empty()
241 && piece
242 .stable_dictionary_parts()
243 .is_some_and(|(_, held)| Arc::ptr_eq(held, values))
244 })
245 });
246 if let Some(values) = shared {
247 let mut codes = Vec::with_capacity(rows);
248 for piece in pieces {
249 if let Some((held, _)) = piece.stable_dictionary_parts() {
250 codes.extend_from_slice(held);
251 }
252 }
253 let validity = run_of(pieces, rows);
254 return Ok(Some(
255 Vector::stable_dictionary(codes, Arc::clone(values))?.with_validity(validity),
256 ));
257 }
258 let laid = pieces
261 .iter()
262 .all(|piece| piece.form() == Form::Flat && piece.logical_type() == ty && !piece.is_empty());
263 if !laid {
264 return Ok(None);
265 }
266 let mut data = data_for(ty, rows)?;
270 let mut arenas = arenas_of(pieces);
271 for piece in pieces {
272 let from = piece
273 .data()
274 .ok_or_else(|| Error::internal("a flat vector with no run of data in it"))?;
275 let appended = extend(&mut data, from, &mut arenas)?;
276 if appended != piece.len() {
277 return Err(Error::internal(format!(
278 "a piece of {} rows laid {appended} values end to end",
279 piece.len()
280 )));
281 }
282 }
283 let validity = run_of(pieces, rows);
284 if let Data::Varlen(column) = data {
285 let (views, arena) = column.into_parts();
286 let page = Vector::string_views(ty.clone(), views, Arc::new(arena))?;
287 return Ok(Some(page.with_validity(validity)));
288 }
289 Ok(Some(Vector::flat(ty.clone(), data)?.with_validity(validity).into_pages()))
290}
291
292pub fn interleave(ty: &LogicalType, pieces: &[Vector], order: &[usize]) -> Result<Vector> {
309 interleave_placed(ty, pieces, order, None)
310}
311
312pub fn interleave_placed(
333 ty: &LogicalType,
334 pieces: &[Vector],
335 order: &[usize],
336 inverse: Option<&[u32]>,
337) -> Result<Vector> {
338 let rows: usize = pieces.iter().map(Vector::len).sum();
339 if let Some(inverse) = inverse.filter(|inverse| inverse.len() != rows || order.len() != rows) {
340 return Err(Error::internal(format!(
341 "{} places and {} positions for a permutation of {rows} rows",
342 inverse.len(),
343 order.len()
344 )));
345 }
346 if let Some(&past) = order.iter().find(|&&index| index >= rows) {
347 return Err(Error::internal(format!("row {past} read out of pieces of {rows} rows")));
348 }
349 if matches!(ty, LogicalType::List(_) | LogicalType::Struct(_) | LogicalType::Map(_, _)) {
350 let laid: Vec<Value> = pieces
353 .iter()
354 .flat_map(|piece| (0..piece.len()).map(|row| piece.value_at(row)))
355 .collect();
356 let values: Vec<Value> =
357 order.iter().map(|&index| laid.get(index).cloned().unwrap_or(Value::Null)).collect();
358 return Vector::from_values(ty.clone(), &values);
359 }
360 if let Some(merged) = merged_dictionary(ty, pieces, order, inverse)? {
361 return Ok(merged);
362 }
363 if let Some(inverse) = inverse {
364 if let Some(placed) = placed_strings(ty, pieces, inverse, 0..rows)? {
365 return Ok(placed);
366 }
367 }
368 let mut data = data_for(ty, rows)?;
369 if matches!(data, Data::Empty) {
372 return Ok(Vector::constant(ty.clone(), Value::Null, order.len()));
373 }
374 let mut arenas = arenas_of(pieces);
375 if let Data::Varlen(column) = &mut data {
378 column.reserve_bytes(arenas.bytes());
379 }
380 let mut masks = Vec::with_capacity(pieces.len());
383 for piece in pieces {
384 let flat = piece.flatten()?;
388 let from = flat.data().ok_or_else(|| Error::internal("a flattened vector with no data"))?;
389 let appended = extend(&mut data, from, &mut arenas)?;
390 if appended != piece.len() {
391 return Err(Error::internal(format!(
392 "a piece of {} rows laid {appended} values end to end",
393 piece.len()
394 )));
395 }
396 masks.push((flat.len(), flat.validity().clone()));
397 }
398 let laid = if masks.iter().all(|(_, mask)| matches!(mask, Validity::AllValid)) {
399 Validity::AllValid
400 } else {
401 let mut live = Vec::with_capacity(rows);
402 for (len, mask) in &masks {
403 live.extend((0..*len).map(|row| mask.is_valid(row)));
406 }
407 Validity::from_run(&live)
408 };
409 if laid.count_valid(rows) == 0 {
410 return Ok(Vector::constant(ty.clone(), Value::Null, order.len()));
411 }
412 let validity = match (laid, inverse) {
413 (Validity::AllValid, _) => Validity::AllValid,
414 (laid, Some(inverse)) => {
415 let mut live = vec![false; order.len()];
416 for (row, &to) in inverse.iter().enumerate() {
417 if let Some(slot) = live.get_mut(to as usize) {
418 *slot = laid.is_valid(row);
419 }
420 }
421 Validity::from_run(&live)
422 }
423 (laid, None) => Validity::from_iter(order.len(), |row| {
424 order.get(row).is_some_and(|&index| laid.is_valid(index))
425 }),
426 };
427 if let Data::Varlen(column) = data {
428 let (views, arena) = column.into_parts();
429 let gathered = match inverse {
430 Some(inverse) => {
431 let mut placed = vec![StringView::empty(); order.len()];
432 for (view, &to) in views.iter().zip(inverse) {
433 if let Some(slot) = placed.get_mut(to as usize) {
434 *slot = *view;
435 }
436 }
437 placed
438 }
439 None => order
440 .iter()
441 .map(|&index| views.get(index).copied().unwrap_or_else(StringView::empty))
442 .collect(),
443 };
444 return Ok(
445 Vector::string_views(ty.clone(), gathered, Arc::new(arena))?.with_validity(validity)
446 );
447 }
448 let data = match inverse {
449 Some(inverse) => placed_of(&data, inverse),
450 None => copy_of(&data, order),
451 };
452 Ok(Vector::flat(ty.clone(), data)?.with_validity(validity))
453}
454
455fn placed_strings(
470 ty: &LogicalType,
471 pieces: &[Vector],
472 inverse: &[u32],
473 range: Range<usize>,
474) -> Result<Option<Vector>> {
475 if !strings_placeable(ty, pieces) {
476 return Ok(None);
477 }
478 let first = range.start;
479 let rows = range.len();
480 let local = |to: u32| (to as usize).checked_sub(first).filter(|&at| at < rows);
482 let mut offsets = vec![0u64; rows + 1];
483 let mut places = inverse.iter();
484 for piece in pieces {
485 let (views, _) = piece.text_parts().unwrap_or_default();
486 for (view, &to) in views.iter().zip(places.by_ref()) {
487 if view.is_inline() {
488 continue;
489 }
490 if let Some(slot) = local(to).and_then(|at| offsets.get_mut(at + 1)) {
491 *slot = view.len() as u64;
492 }
493 }
494 }
495 let mut total = 0;
496 for offset in &mut offsets {
497 total += *offset;
498 *offset = total;
499 }
500 let mut arena =
501 vec![0u8; usize::try_from(total).map_err(|_| Error::internal("an arena too large"))?];
502 let mut placed = vec![StringView::empty(); rows];
503 let mut live = vec![true; rows];
504 let mut places = inverse.iter();
505 for piece in pieces {
506 let (views, from) = piece.text_parts().unwrap_or_default();
507 let validity = piece.validity();
508 for (row, (view, &to)) in views.iter().zip(places.by_ref()).enumerate() {
509 let Some(to) = local(to) else {
510 continue;
511 };
512 if !validity.is_valid(row) {
513 if let Some(slot) = live.get_mut(to) {
514 *slot = false;
515 }
516 continue;
517 }
518 let (Some(bytes), Some(&at), Some(slot)) =
519 (view.bytes_in(from), offsets.get(to), placed.get_mut(to))
520 else {
521 continue;
522 };
523 if view.is_inline() {
524 *slot = *view;
525 continue;
526 }
527 if let Some(into) = arena.get_mut(at as usize..at as usize + bytes.len()) {
528 into.copy_from_slice(bytes);
529 }
530 *slot = StringView::over(bytes, at);
531 }
532 }
533 let validity = if live.iter().all(|&valid| valid) {
534 Validity::AllValid
535 } else {
536 Validity::from_run(&live)
537 };
538 let vector = Vector::string_views(ty.clone(), placed, Arc::new(Buffer::from_vec(arena)))?;
539 Ok(Some(vector.with_validity(validity)))
540}
541
542#[must_use]
545pub fn strings_placeable(ty: &LogicalType, pieces: &[Vector]) -> bool {
546 matches!(ty, LogicalType::Varchar | LogicalType::Blob)
547 && pieces.iter().all(|piece| piece.text_parts().is_some())
548}
549
550pub fn placed_string_rows(
562 ty: &LogicalType,
563 pieces: &[Vector],
564 inverse: &[u32],
565 range: Range<usize>,
566) -> Result<Vector> {
567 let rows: usize = pieces.iter().map(Vector::len).sum();
568 if inverse.len() != rows || range.end > rows || range.start > range.end {
569 return Err(Error::internal(format!(
570 "rows {range:?} of {} places for {rows} rows",
571 inverse.len()
572 )));
573 }
574 placed_strings(ty, pieces, inverse, range)?
575 .ok_or_else(|| Error::internal("a string column placed that is not flat views"))
576}
577
578const ROWS_PER_MERGED_ENTRY: usize = 8;
587
588fn merged_dictionary(
598 ty: &LogicalType,
599 pieces: &[Vector],
600 order: &[usize],
601 inverse: Option<&[u32]>,
602) -> Result<Option<Vector>> {
603 if !matches!(ty, LogicalType::Varchar | LogicalType::Blob) || pieces.is_empty() {
604 return Ok(None);
605 }
606 let rows: usize = pieces.iter().map(Vector::len).sum();
607 let mut dictionaries: Vec<&Arc<Vector>> = Vec::new();
608 let mut which = Vec::with_capacity(pieces.len());
609 let mut entries = 0;
610 for piece in pieces {
611 let Some((_, values)) = piece.shared_dictionary_parts() else {
612 return Ok(None);
613 };
614 if !matches!(piece.validity(), Validity::AllValid) {
615 return Ok(None);
616 }
617 let at = match dictionaries.iter().position(|seen| Arc::ptr_eq(seen, values)) {
618 Some(at) => at,
619 None => {
620 entries += values.len();
621 if entries.saturating_mul(ROWS_PER_MERGED_ENTRY) > rows {
622 return Ok(None);
623 }
624 dictionaries.push(values);
625 dictionaries.len() - 1
626 }
627 };
628 which.push(at);
629 }
630 let mut merged: HashMap<Option<&[u8]>, u32> = HashMap::new();
632 let mut values = Vec::new();
633 let mut remaps = Vec::with_capacity(dictionaries.len());
634 for dictionary in &dictionaries {
635 let mut remap = Vec::with_capacity(dictionary.len());
636 for entry in 0..dictionary.len() {
639 let next = u32::try_from(values.len())
640 .map_err(|_| Error::internal("a merged dictionary past four billion entries"))?;
641 let code = *merged.entry(dictionary.bytes_at(entry)).or_insert_with(|| {
642 values.push(dictionary.value_at(entry));
643 next
644 });
645 remap.push(code);
646 }
647 remaps.push(remap);
648 }
649 let mut laid = Vec::with_capacity(rows);
650 for (piece, &at) in pieces.iter().zip(&which) {
651 let (codes, _) = piece
652 .dictionary_parts()
653 .ok_or_else(|| Error::internal("a dictionary piece lost its dictionary"))?;
654 let remap = &remaps[at];
655 laid.extend(codes.iter().map(|&code| remap[code as usize]));
656 }
657 let codes = match inverse {
660 Some(inverse) => {
661 let mut codes = vec![0u32; order.len()];
662 for (&code, &to) in laid.iter().zip(inverse) {
663 if let Some(slot) = codes.get_mut(to as usize) {
664 *slot = code;
665 }
666 }
667 codes
668 }
669 None => order.iter().map(|&index| laid[index]).collect(),
670 };
671 let values = Vector::from_values(ty.clone(), &values)?;
672 Ok(Some(Vector::stable_dictionary(codes, Arc::new(values))?))
673}
674
675fn run_of(pieces: &[Vector], rows: usize) -> Validity {
681 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllValid)) {
682 return Validity::AllValid;
683 }
684 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllInvalid)) {
685 return Validity::AllInvalid;
686 }
687 let mut live = Vec::with_capacity(rows);
688 for piece in pieces {
689 for row in 0..piece.len() {
692 live.push(!piece.is_null_at(row));
693 }
694 }
695 Validity::from_run(&live)
696}
697
698fn straight(at: &[usize]) -> bool {
700 at.iter().enumerate().all(|(row, &index)| row == index)
701}
702
703fn arenas_of(pieces: &[Vector]) -> Arenas {
705 let mut arenas = Arenas::default();
706 for piece in pieces {
707 if let Some(Data::Varlen(column)) = piece.data() {
708 arenas.count(column);
709 }
710 }
711 arenas
712}
713
714fn extend(into: &mut Data, from: &Data, arenas: &mut Arenas) -> Result<usize> {
720 macro_rules! extended {
721 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
722 match (&mut *into, from) {
723 (_, Data::Empty) => Ok(0),
726 $((Data::$variant(out), Data::$variant(values)) => {
727 out.extend_from_slice(values.as_slice());
728 Ok(values.len())
729 })+
730 (Data::Varlen(out), Data::Varlen(values)) => {
733 out.push_column(values, arenas);
734 Ok(values.len())
735 }
736 (out, from) => Err(Error::internal(format!(
737 "a run of {:?} values cannot be laid after a run of {:?} ones",
738 layout_of(from),
739 layout_of(out)
740 ))),
741 }
742 };
743 }
744 crate::for_each_layout!(fixed, extended)
745}
746
747#[cfg(test)]
755mod tests {
756 use super::*;
757 use crate::{Chunk, Form};
758
759 fn values(vector: &Vector) -> Vec<Value> {
761 (0..vector.len()).map(|row| vector.value_at(row)).collect()
762 }
763
764 fn scattered(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
769 let mut answers = vec![Value::Null; rows];
770 for (positions, piece) in pieces {
771 for (slot, &row) in positions.iter().enumerate() {
772 answers[row as usize] = piece.value_at(slot);
773 }
774 }
775 Vector::from_values(ty.clone(), &answers).expect("the reference builds")
776 }
777
778 fn agrees(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
780 let mut assembly = Assembly::new(ty.clone(), rows).expect("an assembly of this type");
781 for (positions, piece) in pieces {
782 assembly.place(positions, piece).expect("the piece is placed");
783 }
784 let built = assembly.finish().expect("the assembly finishes");
785 assert_eq!(built.len(), rows, "an assembly of {rows} rows");
786 assert_eq!(values(&built), values(&scattered(ty, rows, pieces)), "against the slow way");
787 built
788 }
789
790 #[test]
791 fn two_pieces_interleave_back_into_the_order_the_rows_came_in() {
792 let evens = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(0), Value::BigInt(2)])
793 .expect("a vector");
794 let odds = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(3)])
795 .expect("a vector");
796 let built = agrees(&LogicalType::BigInt, 4, &[(vec![0, 2], evens), (vec![1, 3], odds)]);
797 assert_eq!(
798 values(&built),
799 vec![Value::BigInt(0), Value::BigInt(1), Value::BigInt(2), Value::BigInt(3)]
800 );
801 }
802
803 #[test]
804 fn a_row_no_piece_claims_is_null() {
805 let piece =
808 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(7)]).expect("a vector");
809 let built = agrees(&LogicalType::BigInt, 3, &[(vec![1], piece)]);
810 assert_eq!(values(&built), vec![Value::Null, Value::BigInt(7), Value::Null]);
811 }
812
813 #[test]
814 fn no_pieces_at_all_is_a_column_of_nulls_of_the_right_length() {
815 let built = agrees(&LogicalType::Integer, 5, &[]);
816 assert!(built.is_null_at(4), "every row of it is null");
817 }
818
819 #[test]
820 fn a_null_inside_a_piece_stays_null_where_the_piece_put_it() {
821 let piece = Vector::from_values(
824 LogicalType::BigInt,
825 &[Value::BigInt(1), Value::Null, Value::BigInt(3)],
826 )
827 .expect("a vector");
828 let built = agrees(&LogicalType::BigInt, 3, &[(vec![2, 0, 1], piece)]);
829 assert!(built.is_null_at(0), "the null landed where the piece put it");
830 assert_eq!(built.value_at(2), Value::BigInt(1));
831 }
832
833 #[test]
834 fn strings_are_assembled_without_going_through_a_value_each() {
835 let left = Vector::from_values(
836 LogicalType::Varchar,
837 &[Value::Varchar("a short one".into()), Value::Varchar("another".into())],
838 )
839 .expect("a vector");
840 let right = Vector::from_values(
841 LogicalType::Varchar,
842 &[Value::Varchar("a string that is far too long to live inline in a view".into())],
843 )
844 .expect("a vector");
845 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 2], left), (vec![1], right)]);
846 assert_eq!(built.value_at(0), Value::Varchar("a short one".into()));
847 assert_eq!(
848 built.value_at(1),
849 Value::Varchar("a string that is far too long to live inline in a view".into())
850 );
851 assert_eq!(built.value_at(2), Value::Varchar("another".into()));
852 }
853
854 #[test]
855 fn strings_laid_end_to_end_in_order_come_back_as_views_over_the_arena_they_went_into() {
856 let first = Vector::from_values(
859 LogicalType::Varchar,
860 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
861 )
862 .expect("a vector");
863 let second = Vector::from_values(
864 LogicalType::Varchar,
865 &[Value::Varchar("a third one long enough to be out of line".into())],
866 )
867 .expect("a vector");
868 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1], first), (vec![2], second)]);
869 assert_eq!(built.form(), Form::StringView, "the bytes stay where they were appended");
870 assert_eq!(
871 built.value_at(2),
872 Value::Varchar("a third one long enough to be out of line".into())
873 );
874 }
875
876 #[test]
877 fn a_string_row_no_piece_claims_is_null_rather_than_empty() {
878 let piece = Vector::from_values(
881 LogicalType::Varchar,
882 &[Value::Varchar("a value long enough to be out of line".into())],
883 )
884 .expect("a vector");
885 let built = agrees(&LogicalType::Varchar, 3, &[(vec![2], piece)]);
886 assert_eq!(built.value_at(0), Value::Null);
887 assert_eq!(built.value_at(1), Value::Null);
888 assert_eq!(
889 built.value_at(2),
890 Value::Varchar("a value long enough to be out of line".into())
891 );
892 }
893
894 #[test]
895 fn a_constant_piece_is_written_out_rather_than_read_a_row_at_a_time() {
896 let arm = Vector::from_values(LogicalType::Varchar, &[Value::Varchar("kept".into())])
899 .expect("a vector");
900 let otherwise = Vector::constant(LogicalType::Varchar, Value::Varchar("".into()), 3);
901 let built = agrees(&LogicalType::Varchar, 4, &[(vec![2], arm), (vec![0, 1, 3], otherwise)]);
902 assert_eq!(built.value_at(0), Value::Varchar("".into()));
903 assert_eq!(built.value_at(2), Value::Varchar("kept".into()));
904 }
905
906 #[test]
907 fn a_dictionary_piece_is_walked_to_its_values() {
908 let dictionary = Vector::from_values(
911 LogicalType::Varchar,
912 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
913 )
914 .expect("a dictionary");
915 let piece = Vector::dictionary(vec![1, 0, 1], dictionary).expect("a dictionary vector");
916 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1, 2], piece)]);
917 assert_eq!(
918 values(&built),
919 vec![
920 Value::Varchar("two".into()),
921 Value::Varchar("one".into()),
922 Value::Varchar("two".into())
923 ]
924 );
925 }
926
927 #[test]
928 fn a_piece_placed_at_the_wrong_number_of_positions_is_an_error() {
929 let piece =
930 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
931 let mut assembly = Assembly::new(LogicalType::BigInt, 4).expect("an assembly");
932 assert!(assembly.place(&[0, 1], &piece).is_err(), "two positions for one row");
933 }
934
935 #[test]
936 fn a_position_past_the_end_is_an_error_rather_than_a_lost_row() {
937 let piece =
938 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
939 let mut assembly = Assembly::new(LogicalType::BigInt, 2).expect("an assembly");
940 assert!(assembly.place(&[9], &piece).is_err(), "a row past the end of the assembly");
941 }
942
943 #[test]
944 fn a_piece_of_the_wrong_layout_is_an_error_rather_than_a_wrong_answer() {
945 let piece =
948 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("x".into())]).expect("text");
949 let mut assembly = Assembly::new(LogicalType::BigInt, 1).expect("an assembly");
950 assert!(assembly.place(&[0], &piece).is_err(), "text laid after integers");
951 }
952
953 #[test]
954 fn every_layout_assembles_the_way_it_scatters() {
955 let cases: Vec<(LogicalType, Vec<Value>)> = vec![
958 (LogicalType::Boolean, vec![Value::Boolean(true), Value::Boolean(false)]),
959 (LogicalType::TinyInt, vec![Value::TinyInt(1), Value::TinyInt(-2)]),
960 (LogicalType::SmallInt, vec![Value::SmallInt(3), Value::SmallInt(-4)]),
961 (LogicalType::Integer, vec![Value::Integer(5), Value::Integer(-6)]),
962 (LogicalType::BigInt, vec![Value::BigInt(7), Value::BigInt(-8)]),
963 (LogicalType::HugeInt, vec![Value::HugeInt(9), Value::HugeInt(-10)]),
964 (LogicalType::UTinyInt, vec![Value::UTinyInt(11), Value::UTinyInt(12)]),
965 (LogicalType::USmallInt, vec![Value::USmallInt(13), Value::USmallInt(14)]),
966 (LogicalType::UInteger, vec![Value::UInteger(15), Value::UInteger(16)]),
967 (LogicalType::UBigInt, vec![Value::UBigInt(17), Value::UBigInt(18)]),
968 (LogicalType::Float, vec![Value::Float(1.5), Value::Float(-2.5)]),
969 (LogicalType::Double, vec![Value::Double(3.5), Value::Double(-4.5)]),
970 (
971 LogicalType::Varchar,
972 vec![Value::Varchar("first".into()), Value::Varchar("second".into())],
973 ),
974 (LogicalType::Date, vec![Value::Date(19), Value::Date(20)]),
975 ];
976 for (ty, pair) in cases {
977 let left = Vector::from_values(ty.clone(), &pair[..1]).expect("a vector");
978 let right = Vector::from_values(ty.clone(), &pair[1..]).expect("a vector");
979 let built = agrees(&ty, 2, &[(vec![1], left), (vec![0], right)]);
980 assert_eq!(built.value_at(0), pair[1], "{ty:?} at row 0");
981 assert_eq!(built.value_at(1), pair[0], "{ty:?} at row 1");
982 }
983 }
984
985 #[test]
986 fn an_assembly_is_a_chunk_column_like_any_other() {
987 let piece = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(2)])
990 .expect("a vector");
991 let built = agrees(&LogicalType::BigInt, 2, &[(vec![1, 0], piece)]);
992 let chunk = Chunk::new(vec![built]).expect("a chunk of one column");
993 assert_eq!(chunk.len(), 2, "two rows");
994 }
995
996 fn all_of(pieces: &[Vector]) -> Vec<Value> {
998 pieces.iter().flat_map(values).collect()
999 }
1000
1001 fn laid(ty: &LogicalType, pieces: &[Vector]) -> Vector {
1003 let built = concat(ty, pieces).expect("the pieces lay").expect("this run lays");
1004 assert_eq!(built.len(), pieces.iter().map(Vector::len).sum::<usize>(), "the row count");
1005 assert_eq!(values(&built), all_of(pieces), "the values laid end to end");
1006 built
1007 }
1008
1009 #[test]
1010 fn pieces_laid_end_to_end_read_back_in_the_order_they_were_given() {
1011 let piece = |from: i64, to: i64| {
1012 let held: Vec<Value> = (from..to).map(Value::BigInt).collect();
1013 Vector::from_values(LogicalType::BigInt, &held).expect("a run of bigints")
1014 };
1015 let pieces = [piece(0, 4), piece(4, 9), piece(9, 10)];
1016 let built = laid(&LogicalType::BigInt, &pieces);
1017 assert_eq!(built.form(), Form::Flat, "a run of flat pieces lays flat");
1018 let window = built.slice(4, 5).expect("a window into the page");
1021 assert_eq!(values(&window), all_of(&pieces[1..2]), "the second piece, cut back out");
1022 }
1023
1024 #[test]
1025 fn a_null_in_a_piece_is_a_null_in_the_same_row_of_the_page() {
1026 let ty = LogicalType::Integer;
1027 let whole = Vector::from_values(ty.clone(), &[Value::Integer(1), Value::Integer(2)])
1028 .expect("no nulls");
1029 let holed =
1030 Vector::from_values(ty.clone(), &[Value::Null, Value::Integer(4)]).expect("one null");
1031 let built = laid(&ty, &[whole.clone(), holed.clone()]);
1032 assert!(!built.is_null_at(1), "a row that was not null became one");
1033 assert!(built.is_null_at(2), "the null did not come through");
1034 let clean = laid(&ty, &[whole.clone(), whole]);
1036 assert_eq!(clean.validity(), &Validity::AllValid, "a mask nothing needed");
1037 let empty = laid(&ty, &[holed.clone(), holed]);
1038 assert!(empty.is_null_at(0) && empty.is_null_at(2), "both nulls came through");
1039 }
1040
1041 #[test]
1043 fn strings_lay_into_one_arena_and_come_back_as_views() {
1044 let ty = LogicalType::Varchar;
1045 let word = |text: &str| {
1046 Vector::from_values(ty.clone(), &[Value::Varchar(text.to_string())]).expect("a string")
1047 };
1048 let pieces = [word("a string too long to sit inside a view"), word("short")];
1049 let built = laid(&ty, &pieces);
1050 assert_eq!(
1051 built.form(),
1052 Form::StringView,
1053 "a varchar page that is not views cuts by copying"
1054 );
1055 let window = built.slice(0, 1).expect("a window into the page");
1056 assert_eq!(values(&window), all_of(&pieces[..1]), "the long string, cut back out");
1057 }
1058
1059 #[test]
1060 fn stable_dictionary_pieces_sharing_values_lay_as_codes() {
1061 let ty = LogicalType::Varchar;
1062 let values = Arc::new(
1063 Vector::from_values(
1064 ty.clone(),
1065 &[Value::Varchar("a".to_string()), Value::Varchar("b".to_string())],
1066 )
1067 .expect("dictionary values"),
1068 );
1069 let first = Vector::stable_dictionary(vec![1, 0], Arc::clone(&values)).expect("codes");
1070 let second = Vector::stable_dictionary(vec![1], Arc::clone(&values)).expect("codes");
1071 let built = concat(&ty, &[first, second]).expect("no error").expect("shared codes lay");
1072 let (codes, held) = built.stable_dictionary_parts().expect("the stable form survives");
1073 assert_eq!(codes, &[1, 0, 1]);
1074 assert!(Arc::ptr_eq(held, &values));
1075 }
1076
1077 #[test]
1079 fn an_encoded_piece_is_left_alone_rather_than_flattened() {
1080 let ty = LogicalType::BigInt;
1081 let flat = Vector::from_values(ty.clone(), &[Value::BigInt(1)]).expect("a flat piece");
1082 let values = Vector::from_values(ty.clone(), &[Value::BigInt(7), Value::BigInt(8)])
1083 .expect("two distinct values");
1084 let coded = Vector::dictionary(vec![0, 1, 0], values).expect("a dictionary piece");
1085 let one = std::slice::from_ref(&coded);
1086 assert!(concat(&ty, one).expect("no error").is_none(), "a dictionary laid");
1087 assert!(
1088 concat(&ty, &[flat.clone(), coded]).expect("no error").is_none(),
1089 "a mixed run laid"
1090 );
1091 assert!(concat(&ty, &[]).expect("no error").is_none(), "nothing laid into something");
1092 let other =
1095 Vector::from_values(LogicalType::Integer, &[Value::Integer(1)]).expect("an int");
1096 assert!(concat(&ty, &[flat, other]).expect("no error").is_none(), "two types laid");
1097 }
1098
1099 #[test]
1102 fn an_interleave_reads_the_pieces_in_the_order_it_is_given() {
1103 let words: Vec<Value> = ["a long enough word to leave the inline view", "b", "c"]
1104 .iter()
1105 .map(|word| Value::Varchar((*word).to_string()))
1106 .collect();
1107 let dictionary = Vector::from_values(LogicalType::Varchar, &words).expect("words");
1108 let strings = [
1109 Vector::dictionary(vec![2, 0, 1], dictionary).expect("a dictionary"),
1110 Vector::from_values(
1111 LogicalType::Varchar,
1112 &[Value::Null, Value::Varchar("another string past twelve bytes".to_string())],
1113 )
1114 .expect("flat"),
1115 ];
1116 let numbers = [
1117 Vector::from_values(
1118 LogicalType::BigInt,
1119 &[Value::BigInt(7), Value::Null, Value::BigInt(9)],
1120 )
1121 .expect("flat"),
1122 Vector::constant(LogicalType::BigInt, Value::BigInt(4), 1),
1123 Vector::constant(LogicalType::BigInt, Value::Null, 1),
1124 ];
1125 let lists = [
1126 Vector::from_values(
1127 LogicalType::List(Box::new(LogicalType::Integer)),
1128 &[
1129 Value::List { element: LogicalType::Integer, values: vec![Value::Integer(1)] },
1130 Value::Null,
1131 Value::List { element: LogicalType::Integer, values: vec![] },
1132 ],
1133 )
1134 .expect("lists"),
1135 Vector::from_values(
1136 LogicalType::List(Box::new(LogicalType::Integer)),
1137 &[
1138 Value::List {
1139 element: LogicalType::Integer,
1140 values: vec![Value::Integer(2), Value::Integer(3)],
1141 },
1142 Value::Null,
1143 ],
1144 )
1145 .expect("lists"),
1146 ];
1147 let order = [4, 0, 3, 1, 2, 3];
1148 for pieces in [&strings[..], &numbers[..], &lists[..]] {
1149 let ty = pieces[0].logical_type().clone();
1150 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1151 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1152 let got = interleave(&ty, pieces, &order).expect("an interleave");
1153 assert_eq!(values(&got), expected, "{ty}");
1154 }
1155 assert!(interleave(&LogicalType::BigInt, &numbers, &[5]).is_err(), "row 5 of 5 rows");
1156 let order = [4, 0, 3, 1, 2];
1159 let mut inverse = [0u32; 5];
1160 for (at, &row) in order.iter().enumerate() {
1161 inverse[row] = at as u32;
1162 }
1163 let texts: Vec<Value> = ["a string past the twelve bytes of a view", "short", "x"]
1164 .iter()
1165 .map(|text| Value::Varchar((*text).to_string()))
1166 .chain([Value::Varchar("another long string for the arena".to_string())])
1167 .collect();
1168 let valid = [
1169 Vector::from_values(LogicalType::Varchar, &texts[..2]).expect("flat"),
1170 Vector::from_values(LogicalType::Varchar, &texts[2..]).expect("flat"),
1171 Vector::constant(LogicalType::Varchar, Value::Varchar("one more".to_string()), 1),
1172 ];
1173 for pieces in [&strings[..], &numbers[..], &lists[..], &valid[..]] {
1174 let ty = pieces[0].logical_type().clone();
1175 let pulled = interleave(&ty, pieces, &order).expect("an interleave");
1176 let pushed =
1177 interleave_placed(&ty, pieces, &order, Some(&inverse)).expect("a placed one");
1178 assert_eq!(values(&pushed), values(&pulled), "{ty}");
1179 }
1180 assert!(
1181 interleave_placed(&LogicalType::BigInt, &numbers, &order, Some(&inverse[..4])).is_err(),
1182 "four places for five rows"
1183 );
1184 let untyped = [Vector::constant(LogicalType::Null, Value::Null, 3)];
1185 let got = interleave(&LogicalType::Null, &untyped, &[2, 0]).expect("an untyped null");
1186 assert_eq!(values(&got), vec![Value::Null, Value::Null]);
1187 }
1188
1189 #[test]
1190 fn placed_strings_are_laid_in_the_order_of_the_result() {
1191 let word = |text: &str| Value::Varchar(text.to_string());
1192 let flat = Vector::from_values(
1193 LogicalType::Varchar,
1194 &[word("the first string past twelve bytes"), Value::Null, word("short")],
1195 )
1196 .expect("flat");
1197 let arena = b"xxa second string past twelve bytesyy".to_vec();
1198 let views = vec![StringView::over(&arena[2..35], 2), StringView::inline("tiny")];
1199 let viewed =
1200 Vector::string_views(LogicalType::Varchar, views, Arc::new(Buffer::from_vec(arena)))
1201 .expect("views");
1202 let pieces = [flat, viewed];
1203 let order = [3, 0, 4, 2, 1];
1204 let mut inverse = vec![0u32; order.len()];
1205 for (to, &from) in order.iter().enumerate() {
1206 inverse[from] = u32::try_from(to).expect("a small row");
1207 }
1208 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1209 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1210 let got = interleave_placed(&LogicalType::Varchar, &pieces, &order, Some(&inverse))
1211 .expect("a placed interleave");
1212 assert_eq!(values(&got), expected);
1213 let (_, arena) = got.text_parts().expect("views");
1214 assert_eq!(
1215 arena, b"a second string past twelve bytesthe first string past twelve bytes",
1216 "the long strings in the order they come out, and nothing else"
1217 );
1218 assert!(strings_placeable(&LogicalType::Varchar, &pieces));
1219 for split in 0..=order.len() {
1220 let mut joined = Vec::new();
1221 for range in [0..split, split..order.len()] {
1222 let part = placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, range)
1223 .expect("a range of rows");
1224 joined.extend(values(&part));
1225 }
1226 assert_eq!(joined, expected, "split at {split}");
1227 }
1228 let (_, arena) = placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, 1..3)
1229 .expect("the middle rows")
1230 .text_parts()
1231 .map(|(views, arena)| (views.len(), arena.to_vec()))
1232 .expect("views");
1233 assert_eq!(arena, b"the first string past twelve bytes", "only the range's own strings");
1234 assert!(placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, 4..6).is_err());
1235 }
1236
1237 #[test]
1238 fn an_interleave_of_dictionaries_merges_them_into_one() {
1239 let word = |text: &str| Value::Varchar(text.to_string());
1240 let first = [word("MAIL"), word("a word long enough to leave the inline view")];
1241 let second = [Value::Null, word("MAIL"), word("SHIP")];
1242 let first = Arc::new(Vector::from_values(LogicalType::Varchar, &first).expect("words"));
1243 let second = Arc::new(Vector::from_values(LogicalType::Varchar, &second).expect("words"));
1244 let over = |codes: Vec<u32>, dictionary: &Arc<Vector>| {
1245 Vector::dictionary_over(codes, Arc::clone(dictionary)).expect("a dictionary")
1246 };
1247 let pieces = [
1248 over((0..16).map(|row| row % 2).collect(), &first),
1249 over((0..16).map(|row| row % 3).collect(), &second),
1250 over(vec![1; 8], &first),
1251 ];
1252 let order: Vec<usize> = (0..40).rev().collect();
1253 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1254 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1255 let got = interleave(&LogicalType::Varchar, &pieces, &order).expect("an interleave");
1256 assert_eq!(values(&got), expected);
1257 let (_, merged) = got.stable_dictionary_parts().expect("one stable dictionary");
1258 assert_eq!(merged.len(), 4, "MAIL once, the long word, the null and SHIP");
1259 let mut inverse = vec![0u32; order.len()];
1260 for (to, &from) in order.iter().enumerate() {
1261 inverse[from] = u32::try_from(to).expect("a small row");
1262 }
1263 let placed = interleave_placed(&LogicalType::Varchar, &pieces, &order, Some(&inverse))
1264 .expect("a placed interleave");
1265 assert_eq!(values(&placed), expected, "placed codes land where pulled ones do");
1266 assert!(placed.stable_dictionary_parts().is_some(), "and stay one dictionary");
1267
1268 let mixed = [pieces[0].clone(), pieces[1].flatten().expect("flat")];
1269 let got = interleave(&LogicalType::Varchar, &mixed, &order[8..]).expect("an interleave");
1270 assert!(got.dictionary_parts().is_none(), "a flat piece gathers flat");
1271 let few = &pieces[..1];
1272 let got = interleave(&LogicalType::Varchar, few, &[3, 2]).expect("an interleave");
1273 assert_eq!(
1274 values(&got),
1275 vec![word("a word long enough to leave the inline view"), word("MAIL")]
1276 );
1277 }
1278}