pub(crate) use gnitz_wire::ReduceOutKey;
pub(crate) use gnitz_wire::TypeCode;
#[cfg(test)]
pub(crate) use gnitz_wire::MAX_COLUMNS;
pub(crate) use gnitz_wire::{MAX_PK_BYTES, MAX_PK_COLUMNS};
pub(crate) use gnitz_expr::ColumnLocator;
pub use gnitz_expr::{decode_schema_block, encode_schema_block, SchemaColumn, SchemaDescriptor};
pub mod key;
pub(crate) mod payload_order;
pub use key::KeySpec;
pub(crate) struct DerivedSchema {
cols: Vec<SchemaColumn>,
pk_len: usize,
}
impl DerivedSchema {
pub(crate) fn new() -> Self {
DerivedSchema { cols: Vec::new(), pk_len: 0 }
}
pub(crate) fn push(&mut self, col: SchemaColumn) {
self.cols.push(col);
}
pub(crate) fn push_pk(&mut self, col: SchemaColumn) {
assert_eq!(
self.pk_len,
self.cols.len(),
"DerivedSchema: key column pushed behind a payload column"
);
self.cols.push(col);
self.pk_len += 1;
}
pub(crate) fn push_pk_of(&mut self, schema: &SchemaDescriptor) {
schema.pk_columns().for_each(|(_, c)| self.push_pk(*c));
}
pub(crate) fn push_payload_of(&mut self, schema: &SchemaDescriptor) {
schema.payload_columns().for_each(|(_, c)| self.push(*c));
}
pub(crate) fn finish(&self) -> Result<SchemaDescriptor, String> {
let pk: Vec<u32> = (0..self.pk_len as u32).collect();
Ok(SchemaDescriptor::try_new(&self.cols, &pk)?)
}
}
pub fn project_schema(schema: &SchemaDescriptor, project: &[u32]) -> Result<SchemaDescriptor, String> {
let mut b = DerivedSchema::new();
b.push_pk_of(schema);
for &p in project {
if schema.payload_slot(p as usize).is_none() {
return Err(format!(
"column {p} is not a payload column of a {}-column schema",
schema.num_columns()
));
}
b.push(schema.columns()[p as usize]);
}
b.finish()
}
#[cfg(test)]
#[path = "tests/schema.rs"]
mod tests;