Skip to main content

partiql_logical/graph/
mod.rs

1use crate::graph::bind_name::BindNameExt;
2use crate::ValueExpr;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::fmt::Debug;
6
7pub mod bind_name;
8
9/// A plan specification for an edge's direction filtering.
10#[allow(clippy::upper_case_acronyms)]
11#[derive(Debug, Clone, Eq, PartialEq)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub enum DirectionFilter {
14    L,   // <-
15    U,   //  ~
16    R,   //  ->
17    LU,  // <~
18    UR,  //  ~>
19    LR,  // <->
20    LUR, //  -
21}
22
23/// A plan specification for a path's matching mode.
24#[derive(Debug, Copy, Clone, Eq, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub enum PathMode {
27    /// No filtering of edges/nodes.
28    Walk,
29    /// No repeated edges.
30    Trail,
31    /// No repeated nodes.
32    Acyclic,
33    /// No repeated nodes, except that the first and last nodes may be the same.
34    Simple,
35}
36
37/// A plan specification for bind names.
38#[derive(Debug, Clone, Eq, PartialEq)]
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40pub struct BindSpec(pub String);
41
42impl BindSpec {
43    /// `true` if a bind name is 'anonymous'. Anonymous bind names are stand-ins in places
44    /// where the graph match expression doesn't explicitly include a bind name variable.
45    pub fn is_anon(&self) -> bool {
46        self.0.is_anon()
47    }
48}
49
50/// A plan specification for label filtering.
51#[derive(Default, Debug, Clone, Eq, PartialEq)]
52#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53pub enum LabelFilter {
54    #[default]
55    Always,
56    Named(String),
57    Negated(Box<LabelFilter>),
58    Conjunction(Vec<LabelFilter>),
59    Disjunction(Vec<LabelFilter>),
60    Never,
61}
62
63/// A plan specification for value filtering.
64#[derive(Default, Debug, Clone, Eq, PartialEq)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66pub enum ValueFilter {
67    #[default]
68    Always,
69    Filter(Vec<ValueExpr>),
70}
71
72impl ValueFilter {
73    pub fn and(mut self, other: ValueFilter) -> ValueFilter {
74        self.extend(other);
75        self
76    }
77
78    pub fn extend(&mut self, other: ValueFilter) {
79        match other {
80            ValueFilter::Always => {}
81            ValueFilter::Filter(rhs) => match self {
82                ValueFilter::Always => {
83                    *self = ValueFilter::Filter(rhs);
84                }
85                ValueFilter::Filter(lhs) => {
86                    lhs.extend(rhs);
87                }
88            },
89        }
90    }
91}
92
93/// A plan specification for node label & value filtering.
94#[derive(Debug, Clone, Eq, PartialEq)]
95#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96pub struct NodeFilter {
97    pub label: LabelFilter,
98    pub filter: ValueFilter,
99}
100
101/// A plan specification for edge label & value filtering.
102#[derive(Debug, Clone, Eq, PartialEq)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104pub struct EdgeFilter {
105    pub label: LabelFilter,
106    pub filter: ValueFilter,
107}
108
109/// A plan specification for triple (node, edge, node) matching.
110#[derive(Debug, Clone, Eq, PartialEq)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112pub struct TripleFilter {
113    pub lhs: NodeFilter,
114    pub e: EdgeFilter,
115    pub rhs: NodeFilter,
116}
117
118/// A plan specification for 'step' (triple + edge direction) matching.
119#[derive(Debug, Clone, Eq, PartialEq)]
120#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
121pub struct StepFilter {
122    pub dir: DirectionFilter,
123    pub triple: TripleFilter,
124}
125
126/// A plan specification for 'path patterns' (i.e., sequences of 'node edge node's) matching.
127#[derive(Debug, Clone, Eq, PartialEq)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129pub struct PathPattern {
130    pub head: NodeMatch,
131    pub tail: Vec<(DirectionFilter, EdgeMatch, NodeMatch)>,
132    pub filter: ValueFilter,
133    pub mode: PathMode,
134}
135
136/// A plan specification for node matching.
137#[derive(Debug, Clone, Eq, PartialEq)]
138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
139pub struct NodeMatch {
140    pub binder: BindSpec,
141    pub spec: NodeFilter,
142}
143
144/// A plan specification for edge matching.
145#[derive(Debug, Clone, Eq, PartialEq)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147pub struct EdgeMatch {
148    pub binder: BindSpec,
149    pub spec: EdgeFilter,
150}
151
152/// A plan specification for path (i.e., node, edge, node) matching.
153#[derive(Debug, Clone, Eq, PartialEq)]
154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
155pub struct TripleMatch {
156    pub binders: (BindSpec, BindSpec, BindSpec),
157    pub spec: StepFilter,
158    pub filter: ValueFilter,
159    pub path_mode: PathMode,
160}
161
162/// A plan specification for path (i.e., node, edge, node) matching.
163#[derive(Debug, Clone, Eq, PartialEq)]
164#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
165pub struct TripleSeriesMatch {
166    pub triples: Vec<TripleMatch>,
167    pub filter: ValueFilter,
168    pub path_mode: PathMode,
169}
170
171/// A plan specification for path patterns (i.e., sequences of [`TripleMatch`]s) matching.
172#[derive(Debug, Clone, Eq, PartialEq)]
173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
174pub enum PathPatternMatch {
175    Node(NodeMatch),
176    Match(TripleMatch),
177    Concat(Vec<TripleSeriesMatch>, PathMode),
178}