use crate::error::Result;
use meshdb_core::{Edge, EdgeId, Node, NodeId, Property};
use meshdb_storage::{PropertyConstraintSpec, StorageEngine};
pub trait GraphReader: Send + Sync {
fn get_node(&self, id: NodeId) -> Result<Option<Node>>;
fn get_edge(&self, id: EdgeId) -> Result<Option<Edge>>;
fn all_node_ids(&self) -> Result<Vec<NodeId>>;
fn nodes_by_label(&self, label: &str) -> Result<Vec<NodeId>>;
fn nodes_by_property(
&self,
label: &str,
property: &str,
value: &Property,
) -> Result<Vec<NodeId>>;
fn nodes_by_properties(
&self,
label: &str,
properties: &[String],
values: &[Property],
) -> Result<Vec<NodeId>> {
if properties.len() == 1 && values.len() == 1 {
return self.nodes_by_property(label, &properties[0], &values[0]);
}
Ok(Vec::new())
}
fn edges_by_property(
&self,
_edge_type: &str,
_property: &str,
_value: &Property,
) -> Result<Vec<EdgeId>> {
Ok(Vec::new())
}
fn list_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(Vec::new())
}
fn list_edge_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(Vec::new())
}
fn list_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(Vec::new())
}
fn list_edge_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(Vec::new())
}
fn nodes_in_bbox(
&self,
label: &str,
property: &str,
srid: i32,
xlo: f64,
ylo: f64,
xhi: f64,
yhi: f64,
) -> Result<Vec<NodeId>> {
let (lox, hix) = if xlo <= xhi { (xlo, xhi) } else { (xhi, xlo) };
let (loy, hiy) = if ylo <= yhi { (ylo, yhi) } else { (yhi, ylo) };
let mut result: Vec<NodeId> = Vec::new();
for id in self.nodes_by_label(label)? {
let Some(node) = self.get_node(id)? else {
continue;
};
if let Some(Property::Point(p)) = node.properties.get(property) {
if p.srid == srid && p.x >= lox && p.x <= hix && p.y >= loy && p.y <= hiy {
result.push(id);
}
}
}
Ok(result)
}
fn edges_in_bbox(
&self,
_edge_type: &str,
_property: &str,
_srid: i32,
_xlo: f64,
_ylo: f64,
_xhi: f64,
_yhi: f64,
) -> Result<Vec<EdgeId>> {
Ok(Vec::new())
}
fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
Ok(Vec::new())
}
fn outgoing(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>>;
fn incoming(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>>;
}
impl<T: StorageEngine> GraphReader for T {
fn get_node(&self, id: NodeId) -> Result<Option<Node>> {
Ok(StorageEngine::get_node(self, id)?)
}
fn get_edge(&self, id: EdgeId) -> Result<Option<Edge>> {
Ok(StorageEngine::get_edge(self, id)?)
}
fn all_node_ids(&self) -> Result<Vec<NodeId>> {
Ok(StorageEngine::all_node_ids(self)?)
}
fn nodes_by_label(&self, label: &str) -> Result<Vec<NodeId>> {
Ok(StorageEngine::nodes_by_label(self, label)?)
}
fn nodes_by_property(
&self,
label: &str,
property: &str,
value: &Property,
) -> Result<Vec<NodeId>> {
Ok(StorageEngine::nodes_by_property(
self, label, property, value,
)?)
}
fn nodes_by_properties(
&self,
label: &str,
properties: &[String],
values: &[Property],
) -> Result<Vec<NodeId>> {
Ok(StorageEngine::nodes_by_properties(
self, label, properties, values,
)?)
}
fn edges_by_property(
&self,
edge_type: &str,
property: &str,
value: &Property,
) -> Result<Vec<EdgeId>> {
Ok(StorageEngine::edges_by_property(
self, edge_type, property, value,
)?)
}
fn list_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(StorageEngine::list_property_indexes(self)
.into_iter()
.map(|s| (s.label, s.properties))
.collect())
}
fn list_edge_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(StorageEngine::list_edge_property_indexes(self)
.into_iter()
.map(|s| (s.edge_type, s.properties))
.collect())
}
fn list_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(StorageEngine::list_point_indexes(self)
.into_iter()
.map(|s| (s.label, s.property))
.collect())
}
fn list_edge_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(StorageEngine::list_edge_point_indexes(self)
.into_iter()
.map(|s| (s.edge_type, s.property))
.collect())
}
fn nodes_in_bbox(
&self,
label: &str,
property: &str,
srid: i32,
xlo: f64,
ylo: f64,
xhi: f64,
yhi: f64,
) -> Result<Vec<NodeId>> {
Ok(StorageEngine::nodes_in_bbox(
self, label, property, srid, xlo, ylo, xhi, yhi,
)?)
}
fn edges_in_bbox(
&self,
edge_type: &str,
property: &str,
srid: i32,
xlo: f64,
ylo: f64,
xhi: f64,
yhi: f64,
) -> Result<Vec<EdgeId>> {
Ok(StorageEngine::edges_in_bbox(
self, edge_type, property, srid, xlo, ylo, xhi, yhi,
)?)
}
fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
Ok(StorageEngine::list_property_constraints(self))
}
fn outgoing(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>> {
Ok(StorageEngine::outgoing(self, id)?)
}
fn incoming(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>> {
Ok(StorageEngine::incoming(self, id)?)
}
}
pub struct StorageReaderAdapter<'a>(pub &'a dyn StorageEngine);
impl GraphReader for StorageReaderAdapter<'_> {
fn get_node(&self, id: NodeId) -> Result<Option<Node>> {
Ok(self.0.get_node(id)?)
}
fn get_edge(&self, id: EdgeId) -> Result<Option<Edge>> {
Ok(self.0.get_edge(id)?)
}
fn all_node_ids(&self) -> Result<Vec<NodeId>> {
Ok(self.0.all_node_ids()?)
}
fn nodes_by_label(&self, label: &str) -> Result<Vec<NodeId>> {
Ok(self.0.nodes_by_label(label)?)
}
fn nodes_by_property(
&self,
label: &str,
property: &str,
value: &Property,
) -> Result<Vec<NodeId>> {
Ok(self.0.nodes_by_property(label, property, value)?)
}
fn edges_by_property(
&self,
edge_type: &str,
property: &str,
value: &Property,
) -> Result<Vec<EdgeId>> {
Ok(self.0.edges_by_property(edge_type, property, value)?)
}
fn list_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(self
.0
.list_property_indexes()
.into_iter()
.map(|s| (s.label, s.properties))
.collect())
}
fn list_edge_property_indexes(&self) -> Result<Vec<(String, Vec<String>)>> {
Ok(self
.0
.list_edge_property_indexes()
.into_iter()
.map(|s| (s.edge_type, s.properties))
.collect())
}
fn list_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(self
.0
.list_point_indexes()
.into_iter()
.map(|s| (s.label, s.property))
.collect())
}
fn list_edge_point_indexes(&self) -> Result<Vec<(String, String)>> {
Ok(self
.0
.list_edge_point_indexes()
.into_iter()
.map(|s| (s.edge_type, s.property))
.collect())
}
fn nodes_in_bbox(
&self,
label: &str,
property: &str,
srid: i32,
xlo: f64,
ylo: f64,
xhi: f64,
yhi: f64,
) -> Result<Vec<NodeId>> {
Ok(self
.0
.nodes_in_bbox(label, property, srid, xlo, ylo, xhi, yhi)?)
}
fn edges_in_bbox(
&self,
edge_type: &str,
property: &str,
srid: i32,
xlo: f64,
ylo: f64,
xhi: f64,
yhi: f64,
) -> Result<Vec<EdgeId>> {
Ok(self
.0
.edges_in_bbox(edge_type, property, srid, xlo, ylo, xhi, yhi)?)
}
fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
Ok(self.0.list_property_constraints())
}
fn outgoing(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>> {
Ok(self.0.outgoing(id)?)
}
fn incoming(&self, id: NodeId) -> Result<Vec<(EdgeId, NodeId)>> {
Ok(self.0.incoming(id)?)
}
}