use arcstr::ArcStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ColumnType {
UInt {
bits: u8,
},
DictString,
Bool,
Int8Vector {
dimensions: u16,
},
}
#[derive(Debug, Clone)]
pub struct ColumnDef {
pub name: ArcStr,
pub column_type: ColumnType,
}
impl ColumnDef {
#[must_use]
pub fn new(name: impl Into<ArcStr>, column_type: ColumnType) -> Self {
Self {
name: name.into(),
column_type,
}
}
}
#[derive(Debug, Clone)]
pub struct TableSchema {
pub label: ArcStr,
pub table_id: u16,
pub columns: Vec<ColumnDef>,
}
impl TableSchema {
#[must_use]
pub fn new(label: impl Into<ArcStr>, table_id: u16, columns: Vec<ColumnDef>) -> Self {
Self {
label: label.into(),
table_id,
columns,
}
}
#[must_use]
pub fn column_by_name(&self, name: &str) -> Option<&ColumnDef> {
self.columns.iter().find(|c| c.name.as_str() == name)
}
#[must_use]
pub fn column_count(&self) -> usize {
self.columns.len()
}
}
#[derive(Debug, Clone)]
pub struct EdgeSchema {
pub edge_type: ArcStr,
pub rel_table_id: u16,
pub src_label: ArcStr,
pub dst_label: ArcStr,
pub property_columns: Vec<ColumnDef>,
}
impl EdgeSchema {
#[must_use]
pub fn new(
edge_type: impl Into<ArcStr>,
rel_table_id: u16,
src_label: impl Into<ArcStr>,
dst_label: impl Into<ArcStr>,
property_columns: Vec<ColumnDef>,
) -> Self {
Self {
edge_type: edge_type.into(),
rel_table_id,
src_label: src_label.into(),
dst_label: dst_label.into(),
property_columns,
}
}
#[must_use]
pub fn property_count(&self) -> usize {
self.property_columns.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_column_def_creation() {
let col = ColumnDef::new("age", ColumnType::UInt { bits: 8 });
assert_eq!(col.name.as_str(), "age");
assert_eq!(col.column_type, ColumnType::UInt { bits: 8 });
}
#[test]
fn test_table_schema() {
let schema = TableSchema::new(
"Person",
0,
vec![
ColumnDef::new("name", ColumnType::DictString),
ColumnDef::new("age", ColumnType::UInt { bits: 8 }),
ColumnDef::new("active", ColumnType::Bool),
],
);
assert_eq!(schema.label.as_str(), "Person");
assert_eq!(schema.table_id, 0);
assert_eq!(schema.column_count(), 3);
assert!(schema.column_by_name("name").is_some());
assert!(schema.column_by_name("age").is_some());
assert!(schema.column_by_name("missing").is_none());
}
#[test]
fn test_edge_schema() {
let schema = EdgeSchema::new(
"KNOWS",
1,
"Person",
"Person",
vec![ColumnDef::new("since", ColumnType::UInt { bits: 16 })],
);
assert_eq!(schema.edge_type.as_str(), "KNOWS");
assert_eq!(schema.rel_table_id, 1);
assert_eq!(schema.src_label.as_str(), "Person");
assert_eq!(schema.dst_label.as_str(), "Person");
assert_eq!(schema.property_count(), 1);
}
#[test]
fn test_column_types() {
let types = [
ColumnType::UInt { bits: 8 },
ColumnType::UInt { bits: 32 },
ColumnType::DictString,
ColumnType::Bool,
ColumnType::Int8Vector { dimensions: 128 },
];
for (i, a) in types.iter().enumerate() {
for (j, b) in types.iter().enumerate() {
if i == j {
assert_eq!(a, b);
} else {
assert_ne!(a, b);
}
}
}
}
#[test]
fn test_edge_schema_no_properties() {
let schema = EdgeSchema::new("FOLLOWS", 2, "User", "User", vec![]);
assert_eq!(schema.property_count(), 0);
}
}