1use std::sync::Arc;
43
44use rudb_common::{Error, LogicalType, Result, Value};
45
46use crate::string::StringView;
47use crate::validity::Validity;
48use crate::vector::{Data, Form, NOWHERE, Vector, copy_of, data_for, empty_data_for, layout_of};
49
50#[derive(Debug)]
55pub struct Assembly {
56 ty: LogicalType,
57 rows: usize,
58 data: Data,
60 at: Vec<usize>,
62 live: Vec<bool>,
64 values: Option<Vec<Value>>,
72}
73
74impl Assembly {
75 pub fn new(ty: LogicalType, rows: usize) -> Result<Self> {
81 let nested =
82 matches!(ty, LogicalType::List(_) | LogicalType::Struct(_) | LogicalType::Map(_, _));
83 let values = if nested { Some(vec![Value::Null; rows]) } else { None };
84 let data = if nested { Data::Empty } else { empty_data_for(&ty)? };
85 Ok(Self { ty, rows, data, at: vec![NOWHERE; rows], live: vec![false; rows], values })
86 }
87
88 #[must_use]
90 pub fn rows(&self) -> usize {
91 self.rows
92 }
93
94 pub fn place(&mut self, positions: &[u32], piece: &Vector) -> Result<()> {
107 if positions.len() != piece.len() {
108 return Err(Error::internal(format!(
109 "a piece of {} rows placed at {} positions",
110 piece.len(),
111 positions.len()
112 )));
113 }
114 for &row in positions {
115 if row as usize >= self.rows {
116 return Err(Error::internal(format!(
117 "row {row} placed in an assembly of {} rows",
118 self.rows
119 )));
120 }
121 }
122 if let Some(values) = &mut self.values {
123 for (slot, &row) in positions.iter().enumerate() {
127 values[row as usize] = piece.value_at(slot);
128 }
129 return Ok(());
130 }
131 let flat = piece.flatten()?;
136 let Some(from) = flat.data() else {
137 return Err(Error::internal("a flattened vector with no run of data in it"));
138 };
139 let start = self.data.len();
140 let appended = extend(&mut self.data, from)?;
141 for (slot, &row) in positions.iter().enumerate() {
142 let row = row as usize;
143 if slot < appended {
146 self.at[row] = start + slot;
147 self.live[row] = !piece.is_null_at(slot);
148 } else {
149 self.at[row] = NOWHERE;
150 self.live[row] = false;
151 }
152 }
153 Ok(())
154 }
155
156 pub fn finish(self) -> Result<Vector> {
162 if let Some(values) = self.values {
163 return Vector::from_values(self.ty, &values);
164 }
165 if matches!(self.data, Data::Empty) {
168 return Ok(Vector::constant(self.ty, Value::Null, self.rows));
169 }
170 let validity = Validity::from_run(&self.live);
171 if let Data::Varlen(column) = self.data {
177 let (laid, arena) = column.into_parts();
178 let arena = Arc::new(arena);
179 if straight(&self.at) {
180 return Ok(Vector::string_views(self.ty, laid, arena)?.with_validity(validity));
181 }
182 let views = self
183 .at
184 .iter()
185 .map(|&index| laid.get(index).copied().unwrap_or_else(StringView::empty))
186 .collect();
187 return Ok(Vector::string_views(self.ty, views, arena)?.with_validity(validity));
188 }
189 if straight(&self.at) {
193 return Ok(Vector::flat(self.ty, self.data)?.with_validity(validity));
194 }
195 let gathered = copy_of(&self.data, &self.at);
196 Ok(Vector::flat(self.ty, gathered)?.with_validity(validity))
197 }
198}
199
200pub fn concat(ty: &LogicalType, pieces: &[Vector]) -> Result<Option<Vector>> {
233 if pieces.is_empty() {
234 return Ok(None);
235 }
236 let laid = pieces
239 .iter()
240 .all(|piece| piece.form() == Form::Flat && piece.logical_type() == ty && !piece.is_empty());
241 if !laid {
242 return Ok(None);
243 }
244 let rows = pieces.iter().map(Vector::len).sum();
245 let mut data = data_for(ty, rows)?;
249 for piece in pieces {
250 let from = piece
251 .data()
252 .ok_or_else(|| Error::internal("a flat vector with no run of data in it"))?;
253 let appended = extend(&mut data, from)?;
254 if appended != piece.len() {
255 return Err(Error::internal(format!(
256 "a piece of {} rows laid {appended} values end to end",
257 piece.len()
258 )));
259 }
260 }
261 let validity = run_of(pieces, rows);
262 if let Data::Varlen(column) = data {
263 let (views, arena) = column.into_parts();
264 let page = Vector::string_views(ty.clone(), views, Arc::new(arena))?;
265 return Ok(Some(page.with_validity(validity)));
266 }
267 Ok(Some(Vector::flat(ty.clone(), data)?.with_validity(validity).into_pages()))
268}
269
270fn run_of(pieces: &[Vector], rows: usize) -> Validity {
276 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllValid)) {
277 return Validity::AllValid;
278 }
279 if pieces.iter().all(|piece| matches!(piece.validity(), Validity::AllInvalid)) {
280 return Validity::AllInvalid;
281 }
282 let mut live = Vec::with_capacity(rows);
283 for piece in pieces {
284 for row in 0..piece.len() {
287 live.push(!piece.is_null_at(row));
288 }
289 }
290 Validity::from_run(&live)
291}
292
293fn straight(at: &[usize]) -> bool {
295 at.iter().enumerate().all(|(row, &index)| row == index)
296}
297
298fn extend(into: &mut Data, from: &Data) -> Result<usize> {
304 macro_rules! extended {
305 ($(($variant:ident, $native:ty, $zero:expr)),+ $(,)?) => {
306 match (&mut *into, from) {
307 (_, Data::Empty) => Ok(0),
310 $((Data::$variant(out), Data::$variant(values)) => {
311 out.extend_from_slice(values.as_slice());
312 Ok(values.len())
313 })+
314 (Data::Varlen(out), Data::Varlen(values)) => {
318 out.reserve_views(values.len());
319 out.reserve_bytes(
320 values
321 .views()
322 .iter()
323 .filter(|view| !view.is_inline())
324 .map(StringView::len)
325 .sum(),
326 );
327 for index in 0..values.len() {
328 out.push_from(values, index);
329 }
330 Ok(values.len())
331 }
332 (out, from) => Err(Error::internal(format!(
333 "a run of {:?} values cannot be laid after a run of {:?} ones",
334 layout_of(from),
335 layout_of(out)
336 ))),
337 }
338 };
339 }
340 crate::for_each_layout!(fixed, extended)
341}
342
343#[cfg(test)]
351mod tests {
352 use super::*;
353 use crate::{Chunk, Form};
354
355 fn values(vector: &Vector) -> Vec<Value> {
357 (0..vector.len()).map(|row| vector.value_at(row)).collect()
358 }
359
360 fn scattered(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
365 let mut answers = vec![Value::Null; rows];
366 for (positions, piece) in pieces {
367 for (slot, &row) in positions.iter().enumerate() {
368 answers[row as usize] = piece.value_at(slot);
369 }
370 }
371 Vector::from_values(ty.clone(), &answers).expect("the reference builds")
372 }
373
374 fn agrees(ty: &LogicalType, rows: usize, pieces: &[(Vec<u32>, Vector)]) -> Vector {
376 let mut assembly = Assembly::new(ty.clone(), rows).expect("an assembly of this type");
377 for (positions, piece) in pieces {
378 assembly.place(positions, piece).expect("the piece is placed");
379 }
380 let built = assembly.finish().expect("the assembly finishes");
381 assert_eq!(built.len(), rows, "an assembly of {rows} rows");
382 assert_eq!(values(&built), values(&scattered(ty, rows, pieces)), "against the slow way");
383 built
384 }
385
386 #[test]
387 fn two_pieces_interleave_back_into_the_order_the_rows_came_in() {
388 let evens = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(0), Value::BigInt(2)])
389 .expect("a vector");
390 let odds = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(3)])
391 .expect("a vector");
392 let built = agrees(&LogicalType::BigInt, 4, &[(vec![0, 2], evens), (vec![1, 3], odds)]);
393 assert_eq!(
394 values(&built),
395 vec![Value::BigInt(0), Value::BigInt(1), Value::BigInt(2), Value::BigInt(3)]
396 );
397 }
398
399 #[test]
400 fn a_row_no_piece_claims_is_null() {
401 let piece =
404 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(7)]).expect("a vector");
405 let built = agrees(&LogicalType::BigInt, 3, &[(vec![1], piece)]);
406 assert_eq!(values(&built), vec![Value::Null, Value::BigInt(7), Value::Null]);
407 }
408
409 #[test]
410 fn no_pieces_at_all_is_a_column_of_nulls_of_the_right_length() {
411 let built = agrees(&LogicalType::Integer, 5, &[]);
412 assert!(built.is_null_at(4), "every row of it is null");
413 }
414
415 #[test]
416 fn a_null_inside_a_piece_stays_null_where_the_piece_put_it() {
417 let piece = Vector::from_values(
420 LogicalType::BigInt,
421 &[Value::BigInt(1), Value::Null, Value::BigInt(3)],
422 )
423 .expect("a vector");
424 let built = agrees(&LogicalType::BigInt, 3, &[(vec![2, 0, 1], piece)]);
425 assert!(built.is_null_at(0), "the null landed where the piece put it");
426 assert_eq!(built.value_at(2), Value::BigInt(1));
427 }
428
429 #[test]
430 fn strings_are_assembled_without_going_through_a_value_each() {
431 let left = Vector::from_values(
432 LogicalType::Varchar,
433 &[Value::Varchar("a short one".into()), Value::Varchar("another".into())],
434 )
435 .expect("a vector");
436 let right = Vector::from_values(
437 LogicalType::Varchar,
438 &[Value::Varchar("a string that is far too long to live inline in a view".into())],
439 )
440 .expect("a vector");
441 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 2], left), (vec![1], right)]);
442 assert_eq!(built.value_at(0), Value::Varchar("a short one".into()));
443 assert_eq!(
444 built.value_at(1),
445 Value::Varchar("a string that is far too long to live inline in a view".into())
446 );
447 assert_eq!(built.value_at(2), Value::Varchar("another".into()));
448 }
449
450 #[test]
451 fn strings_laid_end_to_end_in_order_come_back_as_views_over_the_arena_they_went_into() {
452 let first = Vector::from_values(
455 LogicalType::Varchar,
456 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
457 )
458 .expect("a vector");
459 let second = Vector::from_values(
460 LogicalType::Varchar,
461 &[Value::Varchar("a third one long enough to be out of line".into())],
462 )
463 .expect("a vector");
464 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1], first), (vec![2], second)]);
465 assert_eq!(built.form(), Form::StringView, "the bytes stay where they were appended");
466 assert_eq!(
467 built.value_at(2),
468 Value::Varchar("a third one long enough to be out of line".into())
469 );
470 }
471
472 #[test]
473 fn a_string_row_no_piece_claims_is_null_rather_than_empty() {
474 let piece = Vector::from_values(
477 LogicalType::Varchar,
478 &[Value::Varchar("a value long enough to be out of line".into())],
479 )
480 .expect("a vector");
481 let built = agrees(&LogicalType::Varchar, 3, &[(vec![2], piece)]);
482 assert_eq!(built.value_at(0), Value::Null);
483 assert_eq!(built.value_at(1), Value::Null);
484 assert_eq!(
485 built.value_at(2),
486 Value::Varchar("a value long enough to be out of line".into())
487 );
488 }
489
490 #[test]
491 fn a_constant_piece_is_written_out_rather_than_read_a_row_at_a_time() {
492 let arm = Vector::from_values(LogicalType::Varchar, &[Value::Varchar("kept".into())])
495 .expect("a vector");
496 let otherwise = Vector::constant(LogicalType::Varchar, Value::Varchar("".into()), 3);
497 let built = agrees(&LogicalType::Varchar, 4, &[(vec![2], arm), (vec![0, 1, 3], otherwise)]);
498 assert_eq!(built.value_at(0), Value::Varchar("".into()));
499 assert_eq!(built.value_at(2), Value::Varchar("kept".into()));
500 }
501
502 #[test]
503 fn a_dictionary_piece_is_walked_to_its_values() {
504 let dictionary = Vector::from_values(
507 LogicalType::Varchar,
508 &[Value::Varchar("one".into()), Value::Varchar("two".into())],
509 )
510 .expect("a dictionary");
511 let piece = Vector::dictionary(vec![1, 0, 1], dictionary).expect("a dictionary vector");
512 let built = agrees(&LogicalType::Varchar, 3, &[(vec![0, 1, 2], piece)]);
513 assert_eq!(
514 values(&built),
515 vec![
516 Value::Varchar("two".into()),
517 Value::Varchar("one".into()),
518 Value::Varchar("two".into())
519 ]
520 );
521 }
522
523 #[test]
524 fn a_piece_placed_at_the_wrong_number_of_positions_is_an_error() {
525 let piece =
526 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
527 let mut assembly = Assembly::new(LogicalType::BigInt, 4).expect("an assembly");
528 assert!(assembly.place(&[0, 1], &piece).is_err(), "two positions for one row");
529 }
530
531 #[test]
532 fn a_position_past_the_end_is_an_error_rather_than_a_lost_row() {
533 let piece =
534 Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1)]).expect("a vector");
535 let mut assembly = Assembly::new(LogicalType::BigInt, 2).expect("an assembly");
536 assert!(assembly.place(&[9], &piece).is_err(), "a row past the end of the assembly");
537 }
538
539 #[test]
540 fn a_piece_of_the_wrong_layout_is_an_error_rather_than_a_wrong_answer() {
541 let piece =
544 Vector::from_values(LogicalType::Varchar, &[Value::Varchar("x".into())]).expect("text");
545 let mut assembly = Assembly::new(LogicalType::BigInt, 1).expect("an assembly");
546 assert!(assembly.place(&[0], &piece).is_err(), "text laid after integers");
547 }
548
549 #[test]
550 fn every_layout_assembles_the_way_it_scatters() {
551 let cases: Vec<(LogicalType, Vec<Value>)> = vec![
554 (LogicalType::Boolean, vec![Value::Boolean(true), Value::Boolean(false)]),
555 (LogicalType::TinyInt, vec![Value::TinyInt(1), Value::TinyInt(-2)]),
556 (LogicalType::SmallInt, vec![Value::SmallInt(3), Value::SmallInt(-4)]),
557 (LogicalType::Integer, vec![Value::Integer(5), Value::Integer(-6)]),
558 (LogicalType::BigInt, vec![Value::BigInt(7), Value::BigInt(-8)]),
559 (LogicalType::HugeInt, vec![Value::HugeInt(9), Value::HugeInt(-10)]),
560 (LogicalType::UTinyInt, vec![Value::UTinyInt(11), Value::UTinyInt(12)]),
561 (LogicalType::USmallInt, vec![Value::USmallInt(13), Value::USmallInt(14)]),
562 (LogicalType::UInteger, vec![Value::UInteger(15), Value::UInteger(16)]),
563 (LogicalType::UBigInt, vec![Value::UBigInt(17), Value::UBigInt(18)]),
564 (LogicalType::Float, vec![Value::Float(1.5), Value::Float(-2.5)]),
565 (LogicalType::Double, vec![Value::Double(3.5), Value::Double(-4.5)]),
566 (
567 LogicalType::Varchar,
568 vec![Value::Varchar("first".into()), Value::Varchar("second".into())],
569 ),
570 (LogicalType::Date, vec![Value::Date(19), Value::Date(20)]),
571 ];
572 for (ty, pair) in cases {
573 let left = Vector::from_values(ty.clone(), &pair[..1]).expect("a vector");
574 let right = Vector::from_values(ty.clone(), &pair[1..]).expect("a vector");
575 let built = agrees(&ty, 2, &[(vec![1], left), (vec![0], right)]);
576 assert_eq!(built.value_at(0), pair[1], "{ty:?} at row 0");
577 assert_eq!(built.value_at(1), pair[0], "{ty:?} at row 1");
578 }
579 }
580
581 #[test]
582 fn an_assembly_is_a_chunk_column_like_any_other() {
583 let piece = Vector::from_values(LogicalType::BigInt, &[Value::BigInt(1), Value::BigInt(2)])
586 .expect("a vector");
587 let built = agrees(&LogicalType::BigInt, 2, &[(vec![1, 0], piece)]);
588 let chunk = Chunk::new(vec![built]).expect("a chunk of one column");
589 assert_eq!(chunk.len(), 2, "two rows");
590 }
591
592 fn all_of(pieces: &[Vector]) -> Vec<Value> {
594 pieces.iter().flat_map(values).collect()
595 }
596
597 fn laid(ty: &LogicalType, pieces: &[Vector]) -> Vector {
599 let built = concat(ty, pieces).expect("the pieces lay").expect("this run lays");
600 assert_eq!(built.len(), pieces.iter().map(Vector::len).sum::<usize>(), "the row count");
601 assert_eq!(values(&built), all_of(pieces), "the values laid end to end");
602 built
603 }
604
605 #[test]
606 fn pieces_laid_end_to_end_read_back_in_the_order_they_were_given() {
607 let piece = |from: i64, to: i64| {
608 let held: Vec<Value> = (from..to).map(Value::BigInt).collect();
609 Vector::from_values(LogicalType::BigInt, &held).expect("a run of bigints")
610 };
611 let pieces = [piece(0, 4), piece(4, 9), piece(9, 10)];
612 let built = laid(&LogicalType::BigInt, &pieces);
613 assert_eq!(built.form(), Form::Flat, "a run of flat pieces lays flat");
614 let window = built.slice(4, 5).expect("a window into the page");
617 assert_eq!(values(&window), all_of(&pieces[1..2]), "the second piece, cut back out");
618 }
619
620 #[test]
621 fn a_null_in_a_piece_is_a_null_in_the_same_row_of_the_page() {
622 let ty = LogicalType::Integer;
623 let whole = Vector::from_values(ty.clone(), &[Value::Integer(1), Value::Integer(2)])
624 .expect("no nulls");
625 let holed =
626 Vector::from_values(ty.clone(), &[Value::Null, Value::Integer(4)]).expect("one null");
627 let built = laid(&ty, &[whole.clone(), holed.clone()]);
628 assert!(!built.is_null_at(1), "a row that was not null became one");
629 assert!(built.is_null_at(2), "the null did not come through");
630 let clean = laid(&ty, &[whole.clone(), whole]);
632 assert_eq!(clean.validity(), &Validity::AllValid, "a mask nothing needed");
633 let empty = laid(&ty, &[holed.clone(), holed]);
634 assert!(empty.is_null_at(0) && empty.is_null_at(2), "both nulls came through");
635 }
636
637 #[test]
639 fn strings_lay_into_one_arena_and_come_back_as_views() {
640 let ty = LogicalType::Varchar;
641 let word = |text: &str| {
642 Vector::from_values(ty.clone(), &[Value::Varchar(text.to_string())]).expect("a string")
643 };
644 let pieces = [word("a string too long to sit inside a view"), word("short")];
645 let built = laid(&ty, &pieces);
646 assert_eq!(
647 built.form(),
648 Form::StringView,
649 "a varchar page that is not views cuts by copying"
650 );
651 let window = built.slice(0, 1).expect("a window into the page");
652 assert_eq!(values(&window), all_of(&pieces[..1]), "the long string, cut back out");
653 }
654
655 #[test]
657 fn an_encoded_piece_is_left_alone_rather_than_flattened() {
658 let ty = LogicalType::BigInt;
659 let flat = Vector::from_values(ty.clone(), &[Value::BigInt(1)]).expect("a flat piece");
660 let values = Vector::from_values(ty.clone(), &[Value::BigInt(7), Value::BigInt(8)])
661 .expect("two distinct values");
662 let coded = Vector::dictionary(vec![0, 1, 0], values).expect("a dictionary piece");
663 let one = std::slice::from_ref(&coded);
664 assert!(concat(&ty, one).expect("no error").is_none(), "a dictionary laid");
665 assert!(
666 concat(&ty, &[flat.clone(), coded]).expect("no error").is_none(),
667 "a mixed run laid"
668 );
669 assert!(concat(&ty, &[]).expect("no error").is_none(), "nothing laid into something");
670 let other =
673 Vector::from_values(LogicalType::Integer, &[Value::Integer(1)]).expect("an int");
674 assert!(concat(&ty, &[flat, other]).expect("no error").is_none(), "two types laid");
675 }
676}