use crate::datatypes::values::{RelValue, Value};
use crate::graph::core::iterators::GraphEdgeRef;
use crate::graph::schema::{DirGraph, EdgeData};
use crate::graph::storage::GraphRead;
use petgraph::graph::NodeIndex;
pub struct RelationshipEnvelope<'a> {
pub id: usize,
pub rel_type: &'a str,
pub source: NodeIndex,
pub target: NodeIndex,
}
pub fn relationship_property(
graph: &DirGraph,
stored: Option<Value>,
key: &str,
envelope: RelationshipEnvelope<'_>,
) -> Value {
if let Some(value) = stored {
if !matches!(value, Value::Null) {
return value;
}
}
envelope_property(graph, key, envelope)
}
fn envelope_property(graph: &DirGraph, key: &str, envelope: RelationshipEnvelope<'_>) -> Value {
match key {
"type" | "connection_type" => Value::String(envelope.rel_type.to_string()),
"id" => Value::Int64(envelope.id as i64),
"start" | "start_id" => node_id(graph, envelope.source),
"end" | "end_id" => node_id(graph, envelope.target),
_ => Value::Null,
}
}
pub fn relationship_value_property(graph: &DirGraph, rel: &RelValue, key: &str) -> Value {
relationship_property(
graph,
rel.properties.get(key).cloned(),
key,
RelationshipEnvelope {
id: rel.id as usize,
rel_type: &rel.rel_type,
source: NodeIndex::new(rel.start_id as usize),
target: NodeIndex::new(rel.end_id as usize),
},
)
}
pub fn edge_ref_property(
graph: &DirGraph,
edge: &GraphEdgeRef<'_>,
data: &EdgeData,
key: &str,
) -> Option<Value> {
if let Some(value) = data.get_property(key) {
if !matches!(value, Value::Null) {
return Some(value.clone());
}
}
Some(envelope_property(
graph,
key,
RelationshipEnvelope {
id: edge.id().index(),
rel_type: graph.interner.resolve(edge.connection_type()),
source: edge.source(),
target: edge.target(),
},
))
}
fn node_id(graph: &DirGraph, node: NodeIndex) -> Value {
graph
.graph
.node_view(node)
.map_or(Value::Null, |view| view.id().into_owned())
}