use crate::datatypes::values::Value;
use crate::graph::schema::InternedKey;
use petgraph::graph::{EdgeIndex, NodeIndex};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct Pattern {
pub elements: Vec<PatternElement>,
}
#[derive(Debug, Clone)]
pub enum PatternElement {
Node(NodePattern),
Edge(EdgePattern),
}
#[derive(Debug, Clone)]
pub struct NodePattern {
pub variable: Option<String>,
pub node_type: Option<String>,
pub extra_labels: Vec<String>,
pub properties: Option<HashMap<String, PropertyMatcher>>,
}
#[derive(Debug, Clone)]
pub struct EdgePattern {
pub variable: Option<String>,
pub connection_type: Option<String>,
pub connection_types: Option<Vec<String>>,
pub direction: EdgeDirection,
pub properties: Option<HashMap<String, PropertyMatcher>>,
pub var_length: Option<(usize, usize)>,
pub needs_path_info: bool,
pub skip_target_type_check: bool,
pub edge_filter: Option<RelEdgeFilter>,
}
#[derive(Debug, Clone)]
pub struct RelEdgeFilter {
pub predicate: RelEdgePredicate,
pub anchor: AnchorSide,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AnchorSide {
Source,
Target,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum RelEdgePredicate {
True,
False,
TypeIn(Vec<InternedKey>),
Property {
prop: String,
op: PropOp,
value: Value,
},
StartNodeIsPeer,
EndNodeIsPeer,
StartNodeIs(NodeIndex),
EndNodeIs(NodeIndex),
And(Vec<RelEdgePredicate>),
Or(Vec<RelEdgePredicate>),
Not(Box<RelEdgePredicate>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PropOp {
Eq,
Ne,
Gt,
Ge,
Lt,
Le,
}
impl RelEdgePredicate {
#[inline]
pub fn eval(
&self,
connection_type: InternedKey,
peer_is_start: bool,
edge_source: NodeIndex,
edge_target: NodeIndex,
get_prop: &impl Fn(&str) -> Option<Value>,
) -> bool {
match self {
RelEdgePredicate::True => true,
RelEdgePredicate::False => false,
RelEdgePredicate::TypeIn(types) => types.contains(&connection_type),
RelEdgePredicate::Property { prop, op, value } => {
match get_prop(prop) {
Some(v) => match op {
PropOp::Eq => crate::graph::core::filtering::values_equal(&v, value),
PropOp::Ne => !crate::graph::core::filtering::values_equal(&v, value),
PropOp::Gt => matches!(
crate::graph::core::filtering::compare_values(&v, value),
Some(std::cmp::Ordering::Greater)
),
PropOp::Ge => matches!(
crate::graph::core::filtering::compare_values(&v, value),
Some(std::cmp::Ordering::Greater | std::cmp::Ordering::Equal)
),
PropOp::Lt => matches!(
crate::graph::core::filtering::compare_values(&v, value),
Some(std::cmp::Ordering::Less)
),
PropOp::Le => matches!(
crate::graph::core::filtering::compare_values(&v, value),
Some(std::cmp::Ordering::Less | std::cmp::Ordering::Equal)
),
},
None => false,
}
}
RelEdgePredicate::StartNodeIsPeer => peer_is_start,
RelEdgePredicate::EndNodeIsPeer => !peer_is_start,
RelEdgePredicate::StartNodeIs(idx) => edge_source == *idx,
RelEdgePredicate::EndNodeIs(idx) => edge_target == *idx,
RelEdgePredicate::And(items) => items.iter().all(|p| {
p.eval(
connection_type,
peer_is_start,
edge_source,
edge_target,
get_prop,
)
}),
RelEdgePredicate::Or(items) => items.iter().any(|p| {
p.eval(
connection_type,
peer_is_start,
edge_source,
edge_target,
get_prop,
)
}),
RelEdgePredicate::Not(inner) => !inner.eval(
connection_type,
peer_is_start,
edge_source,
edge_target,
get_prop,
),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EdgeDirection {
Outgoing, Incoming, Both, }
#[derive(Debug, Clone)]
pub enum PropertyMatcher {
Equals(Value),
EqualsParam(String),
EqualsVar(String),
EqualsNodeProp {
var: String,
prop: String,
},
In(Vec<Value>),
GreaterThan(Value),
GreaterOrEqual(Value),
LessThan(Value),
LessOrEqual(Value),
Range {
lower: Value,
lower_inclusive: bool,
upper: Value,
upper_inclusive: bool,
},
StartsWith(String),
}
#[derive(Debug, Clone)]
pub struct PatternMatch {
pub bindings: Vec<(String, MatchBinding)>,
}
#[derive(Debug, Clone)]
pub enum MatchBinding {
Node {
index: NodeIndex,
node_type: String,
title: String,
id: Value,
properties: HashMap<String, Value>,
},
NodeRef(NodeIndex),
Edge {
source: NodeIndex,
target: NodeIndex,
edge_index: EdgeIndex,
connection_type: InternedKey,
properties: HashMap<String, Value>,
},
VariableLengthPath {
source: NodeIndex,
target: NodeIndex,
hops: usize,
path: Vec<(NodeIndex, InternedKey)>,
},
}