use reifydb_type::storage::DataBitVec;
use crate::value::column::{ColumnData, data::with_container};
impl ColumnData {
pub fn reorder(&mut self, indices: &[usize]) {
match self {
ColumnData::Option {
inner,
bitvec,
} => {
inner.reorder(indices);
let mut new_bitvec = DataBitVec::spawn(bitvec, indices.len());
for &idx in indices {
if idx < DataBitVec::len(bitvec) {
DataBitVec::push(&mut new_bitvec, DataBitVec::get(bitvec, idx));
} else {
DataBitVec::push(&mut new_bitvec, false);
}
}
*bitvec = new_bitvec;
}
_ => with_container!(self, |c| c.reorder(indices)),
}
}
}
#[cfg(test)]
pub mod tests {
use reifydb_runtime::context::{
clock::{Clock, MockClock},
rng::Rng,
};
use reifydb_type::value::{Value, dictionary::DictionaryEntryId, identity::IdentityId, r#type::Type};
use crate::value::column::ColumnData;
fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
let mock = MockClock::from_millis(1000);
let clock = Clock::Mock(mock.clone());
let rng = Rng::seeded(42);
(mock, clock, rng)
}
#[test]
fn test_reorder_bool() {
let mut col = ColumnData::bool([true, false, true]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
assert_eq!(col.get_value(0), Value::Boolean(true));
assert_eq!(col.get_value(1), Value::Boolean(true));
assert_eq!(col.get_value(2), Value::Boolean(false));
}
#[test]
fn test_reorder_float4() {
let mut col = ColumnData::float4([1.0, 2.0, 3.0]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
match col.get_value(0) {
Value::Float4(v) => assert_eq!(v.value(), 3.0),
_ => panic!("Expected Float4"),
}
match col.get_value(1) {
Value::Float4(v) => assert_eq!(v.value(), 1.0),
_ => panic!("Expected Float4"),
}
match col.get_value(2) {
Value::Float4(v) => assert_eq!(v.value(), 2.0),
_ => panic!("Expected Float4"),
}
}
#[test]
fn test_reorder_int4() {
let mut col = ColumnData::int4([1, 2, 3]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
assert_eq!(col.get_value(0), Value::Int4(3));
assert_eq!(col.get_value(1), Value::Int4(1));
assert_eq!(col.get_value(2), Value::Int4(2));
}
#[test]
fn test_reorder_string() {
let mut col = ColumnData::utf8(["a".to_string(), "b".to_string(), "c".to_string()]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
assert_eq!(col.get_value(0), Value::Utf8("c".to_string()));
assert_eq!(col.get_value(1), Value::Utf8("a".to_string()));
assert_eq!(col.get_value(2), Value::Utf8("b".to_string()));
}
#[test]
fn test_reorder_none() {
let mut col = ColumnData::none_typed(Type::Boolean, 3);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
col.reorder(&[1, 0]);
assert_eq!(col.len(), 2);
}
#[test]
fn test_reorder_identity_id() {
let (mock, clock, rng) = test_clock_and_rng();
let id1 = IdentityId::generate(&clock, &rng);
mock.advance_millis(1);
let id2 = IdentityId::generate(&clock, &rng);
mock.advance_millis(1);
let id3 = IdentityId::generate(&clock, &rng);
let mut col = ColumnData::identity_id([id1, id2, id3]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
assert_eq!(col.get_value(0), Value::IdentityId(id3));
assert_eq!(col.get_value(1), Value::IdentityId(id1));
assert_eq!(col.get_value(2), Value::IdentityId(id2));
}
#[test]
fn test_reorder_dictionary_id() {
let e1 = DictionaryEntryId::U4(10);
let e2 = DictionaryEntryId::U4(20);
let e3 = DictionaryEntryId::U4(30);
let mut col = ColumnData::dictionary_id([e1, e2, e3]);
col.reorder(&[2, 0, 1]);
assert_eq!(col.len(), 3);
assert_eq!(col.get_value(0), Value::DictionaryId(e3));
assert_eq!(col.get_value(1), Value::DictionaryId(e1));
assert_eq!(col.get_value(2), Value::DictionaryId(e2));
}
}