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<V: AsRef<Vector>>(ty: &LogicalType, pieces: &[V]) -> Result<Option<Vector>> {
233 let pieces: Vec<&Vector> = pieces.iter().map(AsRef::as_ref).collect();
234 laid(ty, &pieces)
235}
236
237fn laid(ty: &LogicalType, pieces: &[&Vector]) -> Result<Option<Vector>> {
243 if pieces.is_empty() {
244 return Ok(None);
245 }
246 let rows = pieces.iter().map(|piece| piece.len()).sum();
247 let shared = pieces[0].stable_dictionary_parts().map(|(_, values)| values).filter(|values| {
248 pieces.iter().all(|piece| {
249 piece.logical_type() == ty
250 && !piece.is_empty()
251 && piece
252 .stable_dictionary_parts()
253 .is_some_and(|(_, held)| Arc::ptr_eq(held, values))
254 })
255 });
256 if let Some(values) = shared {
257 let mut codes = Vec::with_capacity(rows);
258 for piece in pieces {
259 if let Some((held, _)) = piece.stable_dictionary_parts() {
260 codes.extend_from_slice(held);
261 }
262 }
263 let validity = run_of(pieces, rows);
264 return Ok(Some(
265 Vector::stable_dictionary(codes, Arc::clone(values))?.with_validity(validity),
266 ));
267 }
268 if let Some(arena) = pieces[0].shared_views().map(|(_, arena)| arena).filter(|arena| {
272 pieces.iter().all(|piece| {
273 piece.logical_type() == ty
274 && piece.shared_views().is_some_and(|(_, held)| Arc::ptr_eq(held, arena))
275 })
276 }) {
277 let mut views = Vec::with_capacity(rows);
278 for piece in pieces {
279 if let Some((held, _)) = piece.shared_views() {
280 views.extend_from_slice(held);
281 }
282 }
283 let validity = run_of(pieces, rows);
284 return Ok(Some(
285 Vector::string_views(ty.clone(), views, Arc::clone(arena))?.with_validity(validity),
286 ));
287 }
288 let laid = pieces
291 .iter()
292 .all(|piece| piece.form() == Form::Flat && piece.logical_type() == ty && !piece.is_empty());
293 if !laid {
294 return Ok(None);
295 }
296 if let Some(data) = adjoined(pieces) {
297 let validity = run_of(pieces, rows);
298 return Ok(Some(Vector::flat(ty.clone(), data)?.with_validity(validity)));
299 }
300 let mut data = data_for(ty, rows)?;
304 let mut arenas = arenas_of(pieces);
305 for piece in pieces {
306 let from = piece
307 .data()
308 .ok_or_else(|| Error::internal("a flat vector with no run of data in it"))?;
309 let appended = extend(&mut data, from, &mut arenas)?;
310 if appended != piece.len() {
311 return Err(Error::internal(format!(
312 "a piece of {} rows laid {appended} values end to end",
313 piece.len()
314 )));
315 }
316 }
317 let validity = run_of(pieces, rows);
318 if let Data::Varlen(column) = data {
319 let (views, arena) = column.into_parts();
320 let page = Vector::string_views(ty.clone(), views, Arc::new(arena))?;
321 return Ok(Some(page.with_validity(validity)));
322 }
323 Ok(Some(Vector::flat(ty.clone(), data)?.with_validity(validity).into_pages()))
324}
325
326pub fn interleave(ty: &LogicalType, pieces: &[Vector], order: &[usize]) -> Result<Vector> {
343 interleave_placed(ty, pieces, order, None)
344}
345
346pub fn interleave_placed(
367 ty: &LogicalType,
368 pieces: &[Vector],
369 order: &[usize],
370 inverse: Option<&[u32]>,
371) -> Result<Vector> {
372 let rows: usize = pieces.iter().map(Vector::len).sum();
373 if let Some(inverse) = inverse.filter(|inverse| inverse.len() != rows || order.len() != rows) {
374 return Err(Error::internal(format!(
375 "{} places and {} positions for a permutation of {rows} rows",
376 inverse.len(),
377 order.len()
378 )));
379 }
380 if let Some(&past) = order.iter().find(|&&index| index >= rows) {
381 return Err(Error::internal(format!("row {past} read out of pieces of {rows} rows")));
382 }
383 if matches!(ty, LogicalType::List(_) | LogicalType::Struct(_) | LogicalType::Map(_, _)) {
384 let laid: Vec<Value> = pieces
387 .iter()
388 .flat_map(|piece| (0..piece.len()).map(|row| piece.value_at(row)))
389 .collect();
390 let values: Vec<Value> =
391 order.iter().map(|&index| laid.get(index).cloned().unwrap_or(Value::Null)).collect();
392 return Vector::from_values(ty.clone(), &values);
393 }
394 if let Some(merged) = merged_dictionary(ty, pieces, order, inverse)? {
395 return Ok(merged);
396 }
397 if let Some(inverse) = inverse {
398 if let Some(placed) = placed_strings(ty, pieces, inverse, 0..rows)? {
399 return Ok(placed);
400 }
401 if let Some(placed) = placed_fixed(ty, pieces, inverse)? {
402 return Ok(placed);
403 }
404 }
405 let mut data = data_for(ty, rows)?;
406 if matches!(data, Data::Empty) {
409 return Ok(Vector::constant(ty.clone(), Value::Null, order.len()));
410 }
411 let mut arenas = arenas_of(pieces);
412 if let Data::Varlen(column) = &mut data {
415 column.reserve_bytes(arenas.bytes());
416 }
417 let mut masks = Vec::with_capacity(pieces.len());
420 for piece in pieces {
421 let flat = piece.flatten()?;
425 let from = flat.data().ok_or_else(|| Error::internal("a flattened vector with no data"))?;
426 let appended = extend(&mut data, from, &mut arenas)?;
427 if appended != piece.len() {
428 return Err(Error::internal(format!(
429 "a piece of {} rows laid {appended} values end to end",
430 piece.len()
431 )));
432 }
433 masks.push((flat.len(), flat.validity().clone()));
434 }
435 let laid = if masks.iter().all(|(_, mask)| matches!(mask, Validity::AllValid)) {
436 Validity::AllValid
437 } else {
438 let mut live = Vec::with_capacity(rows);
439 for (len, mask) in &masks {
440 live.extend((0..*len).map(|row| mask.is_valid(row)));
443 }
444 Validity::from_run(&live)
445 };
446 if laid.count_valid(rows) == 0 {
447 return Ok(Vector::constant(ty.clone(), Value::Null, order.len()));
448 }
449 let validity = match (laid, inverse) {
450 (Validity::AllValid, _) => Validity::AllValid,
451 (laid, Some(inverse)) => {
452 let mut live = vec![false; order.len()];
453 for (row, &to) in inverse.iter().enumerate() {
454 if let Some(slot) = live.get_mut(to as usize) {
455 *slot = laid.is_valid(row);
456 }
457 }
458 Validity::from_run(&live)
459 }
460 (laid, None) => Validity::from_iter(order.len(), |row| {
461 order.get(row).is_some_and(|&index| laid.is_valid(index))
462 }),
463 };
464 if let Data::Varlen(column) = data {
465 let (views, arena) = column.into_parts();
466 let gathered = match inverse {
467 Some(inverse) => {
468 let mut placed = vec![StringView::empty(); order.len()];
469 for (view, &to) in views.iter().zip(inverse) {
470 if let Some(slot) = placed.get_mut(to as usize) {
471 *slot = *view;
472 }
473 }
474 placed
475 }
476 None => order
477 .iter()
478 .map(|&index| views.get(index).copied().unwrap_or_else(StringView::empty))
479 .collect(),
480 };
481 return Ok(
482 Vector::string_views(ty.clone(), gathered, Arc::new(arena))?.with_validity(validity)
483 );
484 }
485 let data = match inverse {
486 Some(inverse) => placed_of(&data, inverse),
487 None => copy_of(&data, order),
488 };
489 Ok(Vector::flat(ty.clone(), data)?.with_validity(validity))
490}
491
492fn placed_fixed(ty: &LogicalType, pieces: &[Vector], inverse: &[u32]) -> Result<Option<Vector>> {
504 let rows = inverse.len();
505 let mut live: Option<Vec<bool>> = None;
506 let mut base = 0;
507 let mut mark = |mask: &Validity, places: &[u32]| {
509 if matches!(mask, Validity::AllValid) {
510 return;
511 }
512 let live = live.get_or_insert_with(|| vec![true; rows]);
513 for (row, &to) in places.iter().enumerate() {
514 if let Some(slot) = live.get_mut(to as usize) {
515 *slot = mask.is_valid(row);
516 }
517 }
518 };
519 macro_rules! placed {
520 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
521 match data_for(ty, 0)? {
522 $(Data::$variant(_) => {
523 let mut out: Vec<$native> = vec![$zero; rows];
524 for piece in pieces {
525 let len = piece.len();
526 let places = inverse.get(base..base + len).ok_or_else(|| {
527 Error::internal("pieces longer than the places they are written to")
528 })?;
529 base += len;
530 let coded = piece.dictionary_parts().and_then(|(codes, values)| {
531 match (values.form(), values.validity(), values.data()) {
532 (Form::Flat, Validity::AllValid, Some(Data::$variant(held))) => {
533 Some((codes, held.as_slice()))
534 }
535 _ => None,
536 }
537 });
538 if let Some((codes, held)) = coded {
539 for (&code, &to) in codes.iter().zip(places) {
540 if let (Some(slot), Some(value)) =
541 (out.get_mut(to as usize), held.get(code as usize))
542 {
543 *slot = *value;
544 }
545 }
546 mark(piece.validity(), places);
547 continue;
548 }
549 let flat;
551 let piece = if piece.form() == Form::Flat {
552 piece
553 } else {
554 flat = piece.flatten()?;
557 &flat
558 };
559 let Some(Data::$variant(values)) = piece.data() else {
560 return Err(Error::internal(format!(
561 "a piece of {} laid into a column of {ty}",
562 piece.logical_type()
563 )));
564 };
565 if values.len() != len {
566 return Err(Error::internal(format!(
567 "a piece of {len} rows holds {} values",
568 values.len()
569 )));
570 }
571 for (value, &to) in values.iter().zip(places) {
572 if let Some(slot) = out.get_mut(to as usize) {
573 *slot = *value;
574 }
575 }
576 mark(piece.validity(), places);
577 }
578 let validity = match live {
579 None => Validity::AllValid,
580 Some(live) if !live.contains(&true) => {
581 return Ok(Some(Vector::constant(ty.clone(), Value::Null, rows)));
582 }
583 Some(live) => Validity::from_run(&live),
584 };
585 let data = Data::$variant(Buffer::from_vec(out));
586 Ok(Some(Vector::flat(ty.clone(), data)?.with_validity(validity)))
587 })+
588 _ => Ok(None),
589 }
590 };
591 }
592 crate::for_each_layout!(fixed, placed)
593}
594
595fn placed_strings(
610 ty: &LogicalType,
611 pieces: &[Vector],
612 inverse: &[u32],
613 range: Range<usize>,
614) -> Result<Option<Vector>> {
615 if !strings_placeable(ty, pieces) {
616 return Ok(None);
617 }
618 let first = range.start;
619 let rows = range.len();
620 let local = |to: u32| (to as usize).checked_sub(first).filter(|&at| at < rows);
622 let mut offsets = vec![0u64; rows + 1];
623 let mut places = inverse.iter();
624 for piece in pieces {
625 let (views, _) = piece.text_parts().unwrap_or_default();
626 for (view, &to) in views.iter().zip(places.by_ref()) {
627 if view.is_inline() {
628 continue;
629 }
630 if let Some(slot) = local(to).and_then(|at| offsets.get_mut(at + 1)) {
631 *slot = view.len() as u64;
632 }
633 }
634 }
635 let mut total = 0;
636 for offset in &mut offsets {
637 total += *offset;
638 *offset = total;
639 }
640 let mut arena =
641 vec![0u8; usize::try_from(total).map_err(|_| Error::internal("an arena too large"))?];
642 let mut placed = vec![StringView::empty(); rows];
643 let mut live = vec![true; rows];
644 let mut places = inverse.iter();
645 for piece in pieces {
646 let (views, from) = piece.text_parts().unwrap_or_default();
647 let validity = piece.validity();
648 for (row, (view, &to)) in views.iter().zip(places.by_ref()).enumerate() {
649 let Some(to) = local(to) else {
650 continue;
651 };
652 if !validity.is_valid(row) {
653 if let Some(slot) = live.get_mut(to) {
654 *slot = false;
655 }
656 continue;
657 }
658 let (Some(bytes), Some(&at), Some(slot)) =
659 (view.bytes_in(from), offsets.get(to), placed.get_mut(to))
660 else {
661 continue;
662 };
663 if view.is_inline() {
664 *slot = *view;
665 continue;
666 }
667 if let Some(into) = arena.get_mut(at as usize..at as usize + bytes.len()) {
668 into.copy_from_slice(bytes);
669 }
670 *slot = StringView::over(bytes, at);
671 }
672 }
673 let validity = if live.iter().all(|&valid| valid) {
674 Validity::AllValid
675 } else {
676 Validity::from_run(&live)
677 };
678 let vector = Vector::string_views(ty.clone(), placed, Arc::new(Buffer::from_vec(arena)))?;
679 Ok(Some(vector.with_validity(validity)))
680}
681
682#[must_use]
685pub fn strings_placeable(ty: &LogicalType, pieces: &[Vector]) -> bool {
686 matches!(ty, LogicalType::Varchar | LogicalType::Blob)
687 && pieces.iter().all(|piece| piece.text_parts().is_some())
688}
689
690pub fn placed_string_rows(
702 ty: &LogicalType,
703 pieces: &[Vector],
704 inverse: &[u32],
705 range: Range<usize>,
706) -> Result<Vector> {
707 let rows: usize = pieces.iter().map(Vector::len).sum();
708 if inverse.len() != rows || range.end > rows || range.start > range.end {
709 return Err(Error::internal(format!(
710 "rows {range:?} of {} places for {rows} rows",
711 inverse.len()
712 )));
713 }
714 placed_strings(ty, pieces, inverse, range)?
715 .ok_or_else(|| Error::internal("a string column placed that is not flat views"))
716}
717
718const ROWS_PER_MERGED_ENTRY: usize = 8;
727
728fn merged_dictionary(
738 ty: &LogicalType,
739 pieces: &[Vector],
740 order: &[usize],
741 inverse: Option<&[u32]>,
742) -> Result<Option<Vector>> {
743 if !matches!(ty, LogicalType::Varchar | LogicalType::Blob) || pieces.is_empty() {
744 return Ok(None);
745 }
746 let rows: usize = pieces.iter().map(Vector::len).sum();
747 let mut dictionaries: Vec<&Arc<Vector>> = Vec::new();
748 let mut which = Vec::with_capacity(pieces.len());
749 let mut entries = 0;
750 for piece in pieces {
751 let Some((_, values)) = piece.shared_dictionary_parts() else {
752 return Ok(None);
753 };
754 if !matches!(piece.validity(), Validity::AllValid) {
755 return Ok(None);
756 }
757 let at = match dictionaries.iter().position(|seen| Arc::ptr_eq(seen, values)) {
758 Some(at) => at,
759 None => {
760 entries += values.len();
761 if entries.saturating_mul(ROWS_PER_MERGED_ENTRY) > rows {
762 return Ok(None);
763 }
764 dictionaries.push(values);
765 dictionaries.len() - 1
766 }
767 };
768 which.push(at);
769 }
770 let mut merged: HashMap<Option<&[u8]>, u32> = HashMap::new();
772 let mut values = Vec::new();
773 let mut remaps = Vec::with_capacity(dictionaries.len());
774 for dictionary in &dictionaries {
775 let mut remap = Vec::with_capacity(dictionary.len());
776 for entry in 0..dictionary.len() {
779 let next = u32::try_from(values.len())
780 .map_err(|_| Error::internal("a merged dictionary past four billion entries"))?;
781 let code = *merged.entry(dictionary.bytes_at(entry)).or_insert_with(|| {
782 values.push(dictionary.value_at(entry));
783 next
784 });
785 remap.push(code);
786 }
787 remaps.push(remap);
788 }
789 let mut laid = Vec::with_capacity(rows);
790 for (piece, &at) in pieces.iter().zip(&which) {
791 let (codes, _) = piece
792 .dictionary_parts()
793 .ok_or_else(|| Error::internal("a dictionary piece lost its dictionary"))?;
794 let remap = &remaps[at];
795 laid.extend(codes.iter().map(|&code| remap[code as usize]));
796 }
797 let codes = match inverse {
800 Some(inverse) => {
801 let mut codes = vec![0u32; order.len()];
802 for (&code, &to) in laid.iter().zip(inverse) {
803 if let Some(slot) = codes.get_mut(to as usize) {
804 *slot = code;
805 }
806 }
807 codes
808 }
809 None => order.iter().map(|&index| laid[index]).collect(),
810 };
811 let values = Vector::from_values(ty.clone(), &values)?;
812 Ok(Some(Vector::stable_dictionary(codes, Arc::new(values))?))
813}
814
815fn run_of(pieces: &[&Vector], rows: usize) -> Validity {
821 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllValid)) {
822 return Validity::AllValid;
823 }
824 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllInvalid)) {
825 return Validity::AllInvalid;
826 }
827 let mut live = Vec::with_capacity(rows);
828 for piece in pieces {
829 for row in 0..piece.len() {
832 live.push(!piece.is_null_at(row));
833 }
834 }
835 Validity::from_run(&live)
836}
837
838fn straight(at: &[usize]) -> bool {
840 at.iter().enumerate().all(|(row, &index)| row == index)
841}
842
843fn arenas_of<V: AsRef<Vector>>(pieces: &[V]) -> Arenas {
845 let mut arenas = Arenas::default();
846 for piece in pieces {
847 if let Some(Data::Varlen(column)) = piece.as_ref().data() {
848 arenas.count(column);
849 }
850 }
851 arenas
852}
853
854fn adjoined(pieces: &[&Vector]) -> Option<Data> {
861 macro_rules! joined {
862 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
863 match pieces.first()?.data()? {
864 $(Data::$variant(first) => {
865 if !first.is_shared() {
866 return None;
867 }
868 let mut run = first.clone();
869 for piece in &pieces[1..] {
870 let Some(Data::$variant(next)) = piece.data() else { return None };
871 run = run.joined(next)?;
872 }
873 Some(Data::$variant(run))
874 })+
875 Data::Varlen(first) => {
876 if !first.is_paged() {
877 return None;
878 }
879 let mut run = first.clone();
880 for piece in &pieces[1..] {
881 let Some(Data::Varlen(next)) = piece.data() else { return None };
882 run = run.joined(next)?;
883 }
884 Some(Data::Varlen(run))
885 }
886 _ => None,
887 }
888 };
889 }
890 crate::for_each_layout!(fixed, joined)
891}
892
893fn extend(into: &mut Data, from: &Data, arenas: &mut Arenas) -> Result<usize> {
899 macro_rules! extended {
900 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
901 match (&mut *into, from) {
902 (_, Data::Empty) => Ok(0),
905 $((Data::$variant(out), Data::$variant(values)) => {
906 out.extend_from_slice(values.as_slice());
907 Ok(values.len())
908 })+
909 (Data::Varlen(out), Data::Varlen(values)) => {
912 out.push_column(values, arenas);
913 Ok(values.len())
914 }
915 (out, from) => Err(Error::internal(format!(
916 "a run of {:?} values cannot be laid after a run of {:?} ones",
917 layout_of(from),
918 layout_of(out)
919 ))),
920 }
921 };
922 }
923 crate::for_each_layout!(fixed, extended)
924}
925
926#[cfg(test)]
934mod tests {
935 use super::*;
936 use crate::{Chunk, Form};
937
938 fn values(vector: &Vector) -> Vec<Value> {
940 (0..vector.len()).map(|row| vector.value_at(row)).collect()
941 }
942
943 fn scattered(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
948 let mut answers = vec![Value::Null; rows];
949 for (positions, piece) in pieces {
950 for (slot, &row) in positions.iter().enumerate() {
951 answers[row as usize] = piece.value_at(slot);
952 }
953 }
954 Vector::from_values(ty.clone(), &answers).expect("the reference builds")
955 }
956
957 fn agrees(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
959 let mut assembly = Assembly::new(ty.clone(), rows).expect("an assembly of this type");
960 for (positions, piece) in pieces {
961 assembly.place(positions, piece).expect("the piece is placed");
962 }
963 let built = assembly.finish().expect("the assembly finishes");
964 assert_eq!(built.len(), rows, "an assembly of {rows} rows");
965 assert_eq!(values(&built), values(&scattered(ty, rows, pieces)), "against the slow way");
966 built
967 }
968
969 #[test]
970 fn two_pieces_interleave_back_into_the_order_the_rows_came_in() {
971 let evens = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(0), Value::BigInt(2)])
972 .expect("a vector");
973 let odds = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(3)])
974 .expect("a vector");
975 let built = agrees(&LogicalType::BigInt, 4, &[(vec![0, 2], evens), (vec![1, 3], odds)]);
976 assert_eq!(
977 values(&built),
978 vec![Value::BigInt(0), Value::BigInt(1), Value::BigInt(2), Value::BigInt(3)]
979 );
980 }
981
982 #[test]
983 fn a_row_no_piece_claims_is_null() {
984 let piece =
987 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(7)]).expect("a vector");
988 let built = agrees(&LogicalType::BigInt, 3, &[(vec![1], piece)]);
989 assert_eq!(values(&built), vec![Value::Null, Value::BigInt(7), Value::Null]);
990 }
991
992 #[test]
993 fn no_pieces_at_all_is_a_column_of_nulls_of_the_right_length() {
994 let built = agrees(&LogicalType::Integer, 5, &[]);
995 assert!(built.is_null_at(4), "every row of it is null");
996 }
997
998 #[test]
999 fn a_null_inside_a_piece_stays_null_where_the_piece_put_it() {
1000 let piece = Vector::from_values(
1003 LogicalType::BigInt,
1004 &[Value::BigInt(1), Value::Null, Value::BigInt(3)],
1005 )
1006 .expect("a vector");
1007 let built = agrees(&LogicalType::BigInt, 3, &[(vec![2, 0, 1], piece)]);
1008 assert!(built.is_null_at(0), "the null landed where the piece put it");
1009 assert_eq!(built.value_at(2), Value::BigInt(1));
1010 }
1011
1012 #[test]
1013 fn strings_are_assembled_without_going_through_a_value_each() {
1014 let left = Vector::from_values(
1015 LogicalType::Varchar,
1016 &[Value::Varchar("a short one".into()), Value::Varchar("another".into())],
1017 )
1018 .expect("a vector");
1019 let right = Vector::from_values(
1020 LogicalType::Varchar,
1021 &[Value::Varchar("a string that is far too long to live inline in a view".into())],
1022 )
1023 .expect("a vector");
1024 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 2], left), (vec![1], right)]);
1025 assert_eq!(built.value_at(0), Value::Varchar("a short one".into()));
1026 assert_eq!(
1027 built.value_at(1),
1028 Value::Varchar("a string that is far too long to live inline in a view".into())
1029 );
1030 assert_eq!(built.value_at(2), Value::Varchar("another".into()));
1031 }
1032
1033 #[test]
1034 fn strings_laid_end_to_end_in_order_come_back_as_views_over_the_arena_they_went_into() {
1035 let first = Vector::from_values(
1038 LogicalType::Varchar,
1039 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
1040 )
1041 .expect("a vector");
1042 let second = Vector::from_values(
1043 LogicalType::Varchar,
1044 &[Value::Varchar("a third one long enough to be out of line".into())],
1045 )
1046 .expect("a vector");
1047 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1], first), (vec![2], second)]);
1048 assert_eq!(built.form(), Form::StringView, "the bytes stay where they were appended");
1049 assert_eq!(
1050 built.value_at(2),
1051 Value::Varchar("a third one long enough to be out of line".into())
1052 );
1053 }
1054
1055 #[test]
1056 fn a_string_row_no_piece_claims_is_null_rather_than_empty() {
1057 let piece = Vector::from_values(
1060 LogicalType::Varchar,
1061 &[Value::Varchar("a value long enough to be out of line".into())],
1062 )
1063 .expect("a vector");
1064 let built = agrees(&LogicalType::Varchar, 3, &[(vec![2], piece)]);
1065 assert_eq!(built.value_at(0), Value::Null);
1066 assert_eq!(built.value_at(1), Value::Null);
1067 assert_eq!(
1068 built.value_at(2),
1069 Value::Varchar("a value long enough to be out of line".into())
1070 );
1071 }
1072
1073 #[test]
1074 fn a_constant_piece_is_written_out_rather_than_read_a_row_at_a_time() {
1075 let arm = Vector::from_values(LogicalType::Varchar, &[Value::Varchar("kept".into())])
1078 .expect("a vector");
1079 let otherwise = Vector::constant(LogicalType::Varchar, Value::Varchar("".into()), 3);
1080 let built = agrees(&LogicalType::Varchar, 4, &[(vec![2], arm), (vec![0, 1, 3], otherwise)]);
1081 assert_eq!(built.value_at(0), Value::Varchar("".into()));
1082 assert_eq!(built.value_at(2), Value::Varchar("kept".into()));
1083 }
1084
1085 #[test]
1086 fn a_dictionary_piece_is_walked_to_its_values() {
1087 let dictionary = Vector::from_values(
1090 LogicalType::Varchar,
1091 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
1092 )
1093 .expect("a dictionary");
1094 let piece = Vector::dictionary(vec![1, 0, 1], dictionary).expect("a dictionary vector");
1095 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1, 2], piece)]);
1096 assert_eq!(
1097 values(&built),
1098 vec![
1099 Value::Varchar("two".into()),
1100 Value::Varchar("one".into()),
1101 Value::Varchar("two".into())
1102 ]
1103 );
1104 }
1105
1106 #[test]
1107 fn a_piece_placed_at_the_wrong_number_of_positions_is_an_error() {
1108 let piece =
1109 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
1110 let mut assembly = Assembly::new(LogicalType::BigInt, 4).expect("an assembly");
1111 assert!(assembly.place(&[0, 1], &piece).is_err(), "two positions for one row");
1112 }
1113
1114 #[test]
1115 fn a_position_past_the_end_is_an_error_rather_than_a_lost_row() {
1116 let piece =
1117 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
1118 let mut assembly = Assembly::new(LogicalType::BigInt, 2).expect("an assembly");
1119 assert!(assembly.place(&[9], &piece).is_err(), "a row past the end of the assembly");
1120 }
1121
1122 #[test]
1123 fn a_piece_of_the_wrong_layout_is_an_error_rather_than_a_wrong_answer() {
1124 let piece =
1127 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("x".into())]).expect("text");
1128 let mut assembly = Assembly::new(LogicalType::BigInt, 1).expect("an assembly");
1129 assert!(assembly.place(&[0], &piece).is_err(), "text laid after integers");
1130 }
1131
1132 #[test]
1133 fn every_layout_assembles_the_way_it_scatters() {
1134 let cases: Vec<(LogicalType, Vec<Value>)> = vec![
1137 (LogicalType::Boolean, vec![Value::Boolean(true), Value::Boolean(false)]),
1138 (LogicalType::TinyInt, vec![Value::TinyInt(1), Value::TinyInt(-2)]),
1139 (LogicalType::SmallInt, vec![Value::SmallInt(3), Value::SmallInt(-4)]),
1140 (LogicalType::Integer, vec![Value::Integer(5), Value::Integer(-6)]),
1141 (LogicalType::BigInt, vec![Value::BigInt(7), Value::BigInt(-8)]),
1142 (LogicalType::HugeInt, vec![Value::HugeInt(9), Value::HugeInt(-10)]),
1143 (LogicalType::UTinyInt, vec![Value::UTinyInt(11), Value::UTinyInt(12)]),
1144 (LogicalType::USmallInt, vec![Value::USmallInt(13), Value::USmallInt(14)]),
1145 (LogicalType::UInteger, vec![Value::UInteger(15), Value::UInteger(16)]),
1146 (LogicalType::UBigInt, vec![Value::UBigInt(17), Value::UBigInt(18)]),
1147 (LogicalType::Float, vec![Value::Float(1.5), Value::Float(-2.5)]),
1148 (LogicalType::Double, vec![Value::Double(3.5), Value::Double(-4.5)]),
1149 (
1150 LogicalType::Varchar,
1151 vec![Value::Varchar("first".into()), Value::Varchar("second".into())],
1152 ),
1153 (LogicalType::Date, vec![Value::Date(19), Value::Date(20)]),
1154 ];
1155 for (ty, pair) in cases {
1156 let left = Vector::from_values(ty.clone(), &pair[..1]).expect("a vector");
1157 let right = Vector::from_values(ty.clone(), &pair[1..]).expect("a vector");
1158 let built = agrees(&ty, 2, &[(vec![1], left), (vec![0], right)]);
1159 assert_eq!(built.value_at(0), pair[1], "{ty:?} at row 0");
1160 assert_eq!(built.value_at(1), pair[0], "{ty:?} at row 1");
1161 }
1162 }
1163
1164 #[test]
1165 fn an_assembly_is_a_chunk_column_like_any_other() {
1166 let piece = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(2)])
1169 .expect("a vector");
1170 let built = agrees(&LogicalType::BigInt, 2, &[(vec![1, 0], piece)]);
1171 let chunk = Chunk::new(vec![built]).expect("a chunk of one column");
1172 assert_eq!(chunk.len(), 2, "two rows");
1173 }
1174
1175 fn all_of(pieces: &[Vector]) -> Vec<Value> {
1177 pieces.iter().flat_map(values).collect()
1178 }
1179
1180 fn laid(ty: &LogicalType, pieces: &[Vector]) -> Vector {
1182 let built = concat(ty, pieces).expect("the pieces lay").expect("this run lays");
1183 assert_eq!(built.len(), pieces.iter().map(Vector::len).sum::<usize>(), "the row count");
1184 assert_eq!(values(&built), all_of(pieces), "the values laid end to end");
1185 built
1186 }
1187
1188 #[test]
1189 fn pieces_laid_end_to_end_read_back_in_the_order_they_were_given() {
1190 let piece = |from: i64, to: i64| {
1191 let held: Vec<Value> = (from..to).map(Value::BigInt).collect();
1192 Vector::from_values(LogicalType::BigInt, &held).expect("a run of bigints")
1193 };
1194 let pieces = [piece(0, 4), piece(4, 9), piece(9, 10)];
1195 let built = laid(&LogicalType::BigInt, &pieces);
1196 assert_eq!(built.form(), Form::Flat, "a run of flat pieces lays flat");
1197 let window = built.slice(4, 5).expect("a window into the page");
1200 assert_eq!(values(&window), all_of(&pieces[1..2]), "the second piece, cut back out");
1201 }
1202
1203 #[test]
1206 fn neighbouring_windows_of_one_page_lay_without_a_copy() {
1207 let held: Vec<Value> =
1208 (0..20).map(|at| if at % 7 == 3 { Value::Null } else { Value::BigInt(at) }).collect();
1209 let page = Vector::from_values(LogicalType::BigInt, &held).expect("a run").into_pages();
1210 let cut = |from: usize, len: usize| page.slice(from, len).expect("a window");
1211 let address = |vector: &Vector| match vector.data() {
1212 Some(Data::Int64(run)) => run.as_slice().as_ptr() as usize,
1213 other => panic!("a bigint run laid as {other:?}"),
1214 };
1215 let built = laid(&LogicalType::BigInt, &[cut(2, 5), cut(7, 8), cut(15, 3)]);
1216 assert_eq!(address(&built), address(&page) + 2 * 8, "the neighbours were copied");
1217 let other = Vector::from_values(LogicalType::BigInt, &held).expect("a run").into_pages();
1219 let other_cut = other.slice(7, 3).expect("a window");
1220 for pieces in [
1221 vec![cut(2, 5), cut(8, 3)],
1222 vec![cut(7, 3), cut(2, 5)],
1223 vec![cut(2, 5), other_cut],
1224 vec![Vector::from_values(LogicalType::BigInt, &held[..4]).expect("owned"), cut(4, 2)],
1225 ] {
1226 let built = laid(&LogicalType::BigInt, &pieces);
1227 assert_ne!(address(&built), address(&page) + 2 * 8, "a copy was expected");
1228 }
1229 }
1230
1231 #[test]
1234 fn neighbouring_cuts_of_a_paged_string_column_lay_without_a_copy() {
1235 let held: Vec<Value> = (0..20)
1236 .map(|at| Value::Varchar(format!("a string long enough for the arena {at}")))
1237 .collect();
1238 let page = Vector::from_values(LogicalType::Varchar, &held).expect("a run").into_pages();
1239 let cut = |from: usize, len: usize| page.slice(from, len).expect("a window");
1240 let views = |vector: &Vector| match vector.data() {
1241 Some(Data::Varlen(column)) => column.views().as_ptr() as usize,
1242 other => panic!("a varchar run laid as {other:?}"),
1243 };
1244 let built = laid(&LogicalType::Varchar, &[cut(2, 5), cut(7, 8), cut(15, 3)]);
1245 assert_eq!(views(&built), views(&page) + 2 * size_of::<StringView>(), "views copied");
1246 let owned = Vector::from_values(LogicalType::Varchar, &held).expect("a run");
1247 let copied = laid(&LogicalType::Varchar, &[owned.slice(0, 4).expect("a cut"), cut(4, 2)]);
1248 assert_eq!(copied.len(), 6);
1249 }
1250
1251 #[test]
1252 fn a_null_in_a_piece_is_a_null_in_the_same_row_of_the_page() {
1253 let ty = LogicalType::Integer;
1254 let whole = Vector::from_values(ty.clone(), &[Value::Integer(1), Value::Integer(2)])
1255 .expect("no nulls");
1256 let holed =
1257 Vector::from_values(ty.clone(), &[Value::Null, Value::Integer(4)]).expect("one null");
1258 let built = laid(&ty, &[whole.clone(), holed.clone()]);
1259 assert!(!built.is_null_at(1), "a row that was not null became one");
1260 assert!(built.is_null_at(2), "the null did not come through");
1261 let clean = laid(&ty, &[whole.clone(), whole]);
1263 assert_eq!(clean.validity(), &Validity::AllValid, "a mask nothing needed");
1264 let empty = laid(&ty, &[holed.clone(), holed]);
1265 assert!(empty.is_null_at(0) && empty.is_null_at(2), "both nulls came through");
1266 }
1267
1268 #[test]
1270 fn strings_lay_into_one_arena_and_come_back_as_views() {
1271 let ty = LogicalType::Varchar;
1272 let word = |text: &str| {
1273 Vector::from_values(ty.clone(), &[Value::Varchar(text.to_string())]).expect("a string")
1274 };
1275 let pieces = [word("a string too long to sit inside a view"), word("short")];
1276 let built = laid(&ty, &pieces);
1277 assert_eq!(
1278 built.form(),
1279 Form::StringView,
1280 "a varchar page that is not views cuts by copying"
1281 );
1282 let window = built.slice(0, 1).expect("a window into the page");
1283 assert_eq!(values(&window), all_of(&pieces[..1]), "the long string, cut back out");
1284 }
1285
1286 #[test]
1287 fn stable_dictionary_pieces_sharing_values_lay_as_codes() {
1288 let ty = LogicalType::Varchar;
1289 let values = Arc::new(
1290 Vector::from_values(
1291 ty.clone(),
1292 &[Value::Varchar("a".to_string()), Value::Varchar("b".to_string())],
1293 )
1294 .expect("dictionary values"),
1295 );
1296 let first = Vector::stable_dictionary(vec![1, 0], Arc::clone(&values)).expect("codes");
1297 let second = Vector::stable_dictionary(vec![1], Arc::clone(&values)).expect("codes");
1298 let built = concat(&ty, &[first, second]).expect("no error").expect("shared codes lay");
1299 let (codes, held) = built.stable_dictionary_parts().expect("the stable form survives");
1300 assert_eq!(codes, &[1, 0, 1]);
1301 assert!(Arc::ptr_eq(held, &values));
1302 }
1303
1304 #[test]
1306 fn an_encoded_piece_is_left_alone_rather_than_flattened() {
1307 let ty = LogicalType::BigInt;
1308 let flat = Vector::from_values(ty.clone(), &[Value::BigInt(1)]).expect("a flat piece");
1309 let values = Vector::from_values(ty.clone(), &[Value::BigInt(7), Value::BigInt(8)])
1310 .expect("two distinct values");
1311 let coded = Vector::dictionary(vec![0, 1, 0], values).expect("a dictionary piece");
1312 let one = std::slice::from_ref(&coded);
1313 assert!(concat(&ty, one).expect("no error").is_none(), "a dictionary laid");
1314 assert!(
1315 concat(&ty, &[flat.clone(), coded]).expect("no error").is_none(),
1316 "a mixed run laid"
1317 );
1318 assert!(
1319 concat::<Vector>(&ty, &[]).expect("no error").is_none(),
1320 "nothing laid into something"
1321 );
1322 let other =
1325 Vector::from_values(LogicalType::Integer, &[Value::Integer(1)]).expect("an int");
1326 assert!(concat(&ty, &[flat, other]).expect("no error").is_none(), "two types laid");
1327 }
1328
1329 #[test]
1332 fn an_interleave_reads_the_pieces_in_the_order_it_is_given() {
1333 let words: Vec<Value> = ["a long enough word to leave the inline view", "b", "c"]
1334 .iter()
1335 .map(|word| Value::Varchar((*word).to_string()))
1336 .collect();
1337 let dictionary = Vector::from_values(LogicalType::Varchar, &words).expect("words");
1338 let strings = [
1339 Vector::dictionary(vec![2, 0, 1], dictionary).expect("a dictionary"),
1340 Vector::from_values(
1341 LogicalType::Varchar,
1342 &[Value::Null, Value::Varchar("another string past twelve bytes".to_string())],
1343 )
1344 .expect("flat"),
1345 ];
1346 let numbers = [
1347 Vector::from_values(
1348 LogicalType::BigInt,
1349 &[Value::BigInt(7), Value::Null, Value::BigInt(9)],
1350 )
1351 .expect("flat"),
1352 Vector::constant(LogicalType::BigInt, Value::BigInt(4), 1),
1353 Vector::constant(LogicalType::BigInt, Value::Null, 1),
1354 ];
1355 let lists = [
1356 Vector::from_values(
1357 LogicalType::List(Box::new(LogicalType::Integer)),
1358 &[
1359 Value::List { element: LogicalType::Integer, values: vec![Value::Integer(1)] },
1360 Value::Null,
1361 Value::List { element: LogicalType::Integer, values: vec![] },
1362 ],
1363 )
1364 .expect("lists"),
1365 Vector::from_values(
1366 LogicalType::List(Box::new(LogicalType::Integer)),
1367 &[
1368 Value::List {
1369 element: LogicalType::Integer,
1370 values: vec![Value::Integer(2), Value::Integer(3)],
1371 },
1372 Value::Null,
1373 ],
1374 )
1375 .expect("lists"),
1376 ];
1377 let order = [4, 0, 3, 1, 2, 3];
1378 for pieces in [&strings[..], &numbers[..], &lists[..]] {
1379 let ty = pieces[0].logical_type().clone();
1380 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1381 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1382 let got = interleave(&ty, pieces, &order).expect("an interleave");
1383 assert_eq!(values(&got), expected, "{ty}");
1384 }
1385 assert!(interleave(&LogicalType::BigInt, &numbers, &[5]).is_err(), "row 5 of 5 rows");
1386 let order = [4, 0, 3, 1, 2];
1389 let mut inverse = [0u32; 5];
1390 for (at, &row) in order.iter().enumerate() {
1391 inverse[row] = at as u32;
1392 }
1393 let texts: Vec<Value> = ["a string past the twelve bytes of a view", "short", "x"]
1394 .iter()
1395 .map(|text| Value::Varchar((*text).to_string()))
1396 .chain([Value::Varchar("another long string for the arena".to_string())])
1397 .collect();
1398 let valid = [
1399 Vector::from_values(LogicalType::Varchar, &texts[..2]).expect("flat"),
1400 Vector::from_values(LogicalType::Varchar, &texts[2..]).expect("flat"),
1401 Vector::constant(LogicalType::Varchar, Value::Varchar("one more".to_string()), 1),
1402 ];
1403 for pieces in [&strings[..], &numbers[..], &lists[..], &valid[..]] {
1404 let ty = pieces[0].logical_type().clone();
1405 let pulled = interleave(&ty, pieces, &order).expect("an interleave");
1406 let pushed =
1407 interleave_placed(&ty, pieces, &order, Some(&inverse)).expect("a placed one");
1408 assert_eq!(values(&pushed), values(&pulled), "{ty}");
1409 }
1410 assert!(
1411 interleave_placed(&LogicalType::BigInt, &numbers, &order, Some(&inverse[..4])).is_err(),
1412 "four places for five rows"
1413 );
1414 let untyped = [Vector::constant(LogicalType::Null, Value::Null, 3)];
1415 let got = interleave(&LogicalType::Null, &untyped, &[2, 0]).expect("an untyped null");
1416 assert_eq!(values(&got), vec![Value::Null, Value::Null]);
1417 }
1418
1419 #[test]
1422 fn a_fixed_width_column_is_written_to_its_places_from_pieces_of_any_form() {
1423 let ty = LogicalType::BigInt;
1424 let int = Value::BigInt;
1425 let flat = Vector::from_values(ty.clone(), &[int(1), Value::Null, int(3)]).expect("flat");
1426 let paged = Vector::from_values(ty.clone(), &[int(4), int(5)]).expect("flat").into_pages();
1427 let words = Vector::from_values(ty.clone(), &[int(70), int(80)]).expect("values");
1428 let coded = Vector::dictionary(vec![1, 0, 1], words).expect("coded");
1429 let nulled = Vector::from_values(ty.clone(), &[int(90), Value::Null]).expect("values");
1430 let chained = Vector::dictionary(vec![1, 0], nulled).expect("coded over nulls");
1431 let constant = Vector::constant(ty.clone(), int(6), 2);
1432 let pieces = [flat, paged, coded, chained, constant];
1433 let rows: usize = pieces.iter().map(Vector::len).sum();
1434 let order: Vec<usize> = (0..rows).map(|at| (at * 5 + 3) % rows).collect();
1435 let mut inverse = vec![0u32; rows];
1436 for (to, &from) in order.iter().enumerate() {
1437 inverse[from] = u32::try_from(to).expect("a small row");
1438 }
1439 let read = interleave_placed(&ty, &pieces, &order, None).expect("read through order");
1440 let written =
1441 interleave_placed(&ty, &pieces, &order, Some(&inverse)).expect("written to places");
1442 assert_eq!(values(&written), values(&read));
1443 assert_eq!(values(&written)[inverse[1] as usize], Value::Null, "the flat piece's null");
1444 assert_eq!(values(&written)[inverse[8] as usize], Value::Null, "the dictionary's null");
1445
1446 let nothing = Vector::from_values(ty.clone(), &[Value::Null, Value::Null]).expect("nulls");
1447 let written = interleave_placed(&ty, &[nothing], &[1, 0], Some(&[1, 0])).expect("nulls");
1448 assert_eq!(values(&written), [Value::Null, Value::Null]);
1449 }
1450
1451 #[test]
1452 fn placed_strings_are_laid_in_the_order_of_the_result() {
1453 let word = |text: &str| Value::Varchar(text.to_string());
1454 let flat = Vector::from_values(
1455 LogicalType::Varchar,
1456 &[word("the first string past twelve bytes"), Value::Null, word("short")],
1457 )
1458 .expect("flat");
1459 let arena = b"xxa second string past twelve bytesyy".to_vec();
1460 let views = vec![StringView::over(&arena[2..35], 2), StringView::inline("tiny")];
1461 let viewed =
1462 Vector::string_views(LogicalType::Varchar, views, Arc::new(Buffer::from_vec(arena)))
1463 .expect("views");
1464 let pieces = [flat, viewed];
1465 let order = [3, 0, 4, 2, 1];
1466 let mut inverse = vec![0u32; order.len()];
1467 for (to, &from) in order.iter().enumerate() {
1468 inverse[from] = u32::try_from(to).expect("a small row");
1469 }
1470 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1471 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1472 let got = interleave_placed(&LogicalType::Varchar, &pieces, &order, Some(&inverse))
1473 .expect("a placed interleave");
1474 assert_eq!(values(&got), expected);
1475 let (_, arena) = got.text_parts().expect("views");
1476 assert_eq!(
1477 arena, b"a second string past twelve bytesthe first string past twelve bytes",
1478 "the long strings in the order they come out, and nothing else"
1479 );
1480 assert!(strings_placeable(&LogicalType::Varchar, &pieces));
1481 for split in 0..=order.len() {
1482 let mut joined = Vec::new();
1483 for range in [0..split, split..order.len()] {
1484 let part = placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, range)
1485 .expect("a range of rows");
1486 joined.extend(values(&part));
1487 }
1488 assert_eq!(joined, expected, "split at {split}");
1489 }
1490 let (_, arena) = placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, 1..3)
1491 .expect("the middle rows")
1492 .text_parts()
1493 .map(|(views, arena)| (views.len(), arena.to_vec()))
1494 .expect("views");
1495 assert_eq!(arena, b"the first string past twelve bytes", "only the range's own strings");
1496 assert!(placed_string_rows(&LogicalType::Varchar, &pieces, &inverse, 4..6).is_err());
1497 }
1498
1499 #[test]
1500 fn an_interleave_of_dictionaries_merges_them_into_one() {
1501 let word = |text: &str| Value::Varchar(text.to_string());
1502 let first = [word("MAIL"), word("a word long enough to leave the inline view")];
1503 let second = [Value::Null, word("MAIL"), word("SHIP")];
1504 let first = Arc::new(Vector::from_values(LogicalType::Varchar, &first).expect("words"));
1505 let second = Arc::new(Vector::from_values(LogicalType::Varchar, &second).expect("words"));
1506 let over = |codes: Vec<u32>, dictionary: &Arc<Vector>| {
1507 Vector::dictionary_over(codes, Arc::clone(dictionary)).expect("a dictionary")
1508 };
1509 let pieces = [
1510 over((0..16).map(|row| row % 2).collect(), &first),
1511 over((0..16).map(|row| row % 3).collect(), &second),
1512 over(vec![1; 8], &first),
1513 ];
1514 let order: Vec<usize> = (0..40).rev().collect();
1515 let laid: Vec<Value> = pieces.iter().flat_map(values).collect();
1516 let expected: Vec<Value> = order.iter().map(|&index| laid[index].clone()).collect();
1517 let got = interleave(&LogicalType::Varchar, &pieces, &order).expect("an interleave");
1518 assert_eq!(values(&got), expected);
1519 let (_, merged) = got.stable_dictionary_parts().expect("one stable dictionary");
1520 assert_eq!(merged.len(), 4, "MAIL once, the long word, the null and SHIP");
1521 let mut inverse = vec![0u32; order.len()];
1522 for (to, &from) in order.iter().enumerate() {
1523 inverse[from] = u32::try_from(to).expect("a small row");
1524 }
1525 let placed = interleave_placed(&LogicalType::Varchar, &pieces, &order, Some(&inverse))
1526 .expect("a placed interleave");
1527 assert_eq!(values(&placed), expected, "placed codes land where pulled ones do");
1528 assert!(placed.stable_dictionary_parts().is_some(), "and stay one dictionary");
1529
1530 let mixed = [pieces[0].clone(), pieces[1].flatten().expect("flat")];
1531 let got = interleave(&LogicalType::Varchar, &mixed, &order[8..]).expect("an interleave");
1532 assert!(got.dictionary_parts().is_none(), "a flat piece gathers flat");
1533 let few = &pieces[..1];
1534 let got = interleave(&LogicalType::Varchar, few, &[3, 2]).expect("an interleave");
1535 assert_eq!(
1536 values(&got),
1537 vec![word("a word long enough to leave the inline view"), word("MAIL")]
1538 );
1539 }
1540}