use nodedb_array::types::ArrayId;
use nodedb_types::SurrogateBitmap;
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
serde::Serialize,
serde::Deserialize,
zerompk::ToMessagePack,
zerompk::FromMessagePack,
)]
#[msgpack(c_enum)]
pub enum ArrayReducer {
Sum,
Count,
Min,
Max,
Mean,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
serde::Serialize,
serde::Deserialize,
zerompk::ToMessagePack,
zerompk::FromMessagePack,
)]
#[msgpack(c_enum)]
pub enum ArrayBinaryOp {
Add,
Sub,
Mul,
Div,
}
#[derive(
Debug,
Clone,
PartialEq,
serde::Serialize,
serde::Deserialize,
zerompk::ToMessagePack,
zerompk::FromMessagePack,
)]
pub enum ArrayOp {
OpenArray {
array_id: ArrayId,
schema_msgpack: Vec<u8>,
schema_hash: u64,
prefix_bits: u8,
},
Put {
array_id: ArrayId,
cells_msgpack: Vec<u8>,
wal_lsn: u64,
},
Delete {
array_id: ArrayId,
coords_msgpack: Vec<u8>,
wal_lsn: u64,
},
Slice {
array_id: ArrayId,
slice_msgpack: Vec<u8>,
attr_projection: Vec<u32>,
limit: u32,
cell_filter: Option<SurrogateBitmap>,
hilbert_range: Option<(u64, u64)>,
system_as_of: Option<i64>,
valid_at_ms: Option<i64>,
},
Project {
array_id: ArrayId,
attr_indices: Vec<u32>,
},
Aggregate {
array_id: ArrayId,
attr_idx: u32,
reducer: ArrayReducer,
group_by_dim: i32,
cell_filter: Option<SurrogateBitmap>,
return_partial: bool,
hilbert_range: Option<(u64, u64)>,
system_as_of: Option<i64>,
valid_at_ms: Option<i64>,
},
Elementwise {
left: ArrayId,
right: ArrayId,
op: ArrayBinaryOp,
attr_idx: u32,
cell_filter: Option<SurrogateBitmap>,
},
Flush { array_id: ArrayId, wal_lsn: u64 },
Compact {
array_id: ArrayId,
audit_retain_ms: Option<i64>,
},
SurrogateBitmapScan {
array_id: ArrayId,
slice_msgpack: Vec<u8>,
},
DropArray { array_id: ArrayId },
}
impl ArrayOp {
pub fn primary_array(&self) -> &ArrayId {
match self {
ArrayOp::OpenArray { array_id, .. }
| ArrayOp::Put { array_id, .. }
| ArrayOp::Delete { array_id, .. }
| ArrayOp::Slice { array_id, .. }
| ArrayOp::SurrogateBitmapScan { array_id, .. }
| ArrayOp::Project { array_id, .. }
| ArrayOp::Aggregate { array_id, .. }
| ArrayOp::Flush { array_id, .. }
| ArrayOp::Compact { array_id, .. }
| ArrayOp::DropArray { array_id } => array_id,
ArrayOp::Elementwise { left, .. } => left,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use nodedb_types::TenantId;
fn aid() -> ArrayId {
ArrayId::new(TenantId::new(1), "g")
}
#[test]
fn array_op_roundtrips_through_msgpack() {
let op = ArrayOp::Aggregate {
array_id: aid(),
attr_idx: 0,
reducer: ArrayReducer::Sum,
group_by_dim: -1,
cell_filter: None,
return_partial: false,
hilbert_range: None,
system_as_of: None,
valid_at_ms: None,
};
let bytes = zerompk::to_msgpack_vec(&op).unwrap();
let back: ArrayOp = zerompk::from_msgpack(&bytes).unwrap();
assert_eq!(op, back);
}
#[test]
fn primary_array_picks_left_for_elementwise() {
let op = ArrayOp::Elementwise {
left: ArrayId::new(TenantId::new(1), "L"),
right: ArrayId::new(TenantId::new(1), "R"),
op: ArrayBinaryOp::Add,
attr_idx: 0,
cell_filter: None,
};
assert_eq!(op.primary_array().name, "L");
}
#[test]
fn binary_op_and_reducer_are_c_enum_one_byte() {
for r in [
ArrayReducer::Sum,
ArrayReducer::Count,
ArrayReducer::Min,
ArrayReducer::Max,
ArrayReducer::Mean,
] {
let bytes = zerompk::to_msgpack_vec(&r).unwrap();
let back: ArrayReducer = zerompk::from_msgpack(&bytes).unwrap();
assert_eq!(r, back);
}
for o in [
ArrayBinaryOp::Add,
ArrayBinaryOp::Sub,
ArrayBinaryOp::Mul,
ArrayBinaryOp::Div,
] {
let bytes = zerompk::to_msgpack_vec(&o).unwrap();
let back: ArrayBinaryOp = zerompk::from_msgpack(&bytes).unwrap();
assert_eq!(o, back);
}
}
}