Skip to main content

cypherlite_query/parser/
ast.rs

1// AST node type definitions for openCypher subset
2
3/// A complete Cypher query.
4#[derive(Debug, Clone, PartialEq)]
5pub struct Query {
6    /// Ordered list of clauses that make up the query.
7    pub clauses: Vec<Clause>,
8}
9
10/// Top-level clause types.
11#[derive(Debug, Clone, PartialEq)]
12pub enum Clause {
13    /// `MATCH` clause.
14    Match(MatchClause),
15    /// `RETURN` clause.
16    Return(ReturnClause),
17    /// `CREATE` clause.
18    Create(CreateClause),
19    /// `SET` clause.
20    Set(SetClause),
21    /// `REMOVE` clause.
22    Remove(RemoveClause),
23    /// `DELETE` / `DETACH DELETE` clause.
24    Delete(DeleteClause),
25    /// `WITH` clause.
26    With(WithClause),
27    /// `MERGE` clause.
28    Merge(MergeClause),
29    /// `UNWIND` clause.
30    Unwind(UnwindClause),
31    /// `CREATE INDEX` clause.
32    CreateIndex(CreateIndexClause),
33    /// `DROP INDEX` clause.
34    DropIndex(DropIndexClause),
35    /// `CREATE SNAPSHOT` clause (subgraph feature).
36    #[cfg(feature = "subgraph")]
37    CreateSnapshot(CreateSnapshotClause),
38    /// `CREATE HYPEREDGE` clause (hypergraph feature).
39    #[cfg(feature = "hypergraph")]
40    CreateHyperedge(CreateHyperedgeClause),
41    /// `MATCH HYPEREDGE` clause (hypergraph feature).
42    #[cfg(feature = "hypergraph")]
43    MatchHyperedge(MatchHyperedgeClause),
44}
45
46/// Temporal predicate for time-travel queries.
47#[derive(Debug, Clone, PartialEq)]
48pub enum TemporalPredicate {
49    /// `AT TIME expr` -- find the version current at a specific point in time.
50    AsOf(Expression),
51    /// `BETWEEN TIME expr AND expr` -- find all versions within a time range.
52    Between(Expression, Expression),
53}
54
55/// A `MATCH` clause with optional temporal predicate and filter.
56#[derive(Debug, Clone, PartialEq)]
57pub struct MatchClause {
58    /// True when `OPTIONAL MATCH`.
59    pub optional: bool,
60    /// The graph pattern to match.
61    pub pattern: Pattern,
62    /// Optional temporal predicate (`AT TIME` / `BETWEEN TIME`).
63    pub temporal_predicate: Option<TemporalPredicate>,
64    /// Optional `WHERE` filter expression.
65    pub where_clause: Option<Expression>,
66}
67
68/// A `RETURN` clause with optional ordering, skip, and limit.
69#[derive(Debug, Clone, PartialEq)]
70pub struct ReturnClause {
71    /// Whether `DISTINCT` was specified.
72    pub distinct: bool,
73    /// Expressions to return.
74    pub items: Vec<ReturnItem>,
75    /// Optional `ORDER BY` items.
76    pub order_by: Option<Vec<OrderItem>>,
77    /// Optional `SKIP` expression.
78    pub skip: Option<Expression>,
79    /// Optional `LIMIT` expression.
80    pub limit: Option<Expression>,
81}
82
83/// A single item in a `RETURN` or `WITH` clause.
84#[derive(Debug, Clone, PartialEq)]
85pub struct ReturnItem {
86    /// The expression to evaluate.
87    pub expr: Expression,
88    /// Optional `AS` alias.
89    pub alias: Option<String>,
90}
91
92/// A single sort key in an `ORDER BY` clause.
93#[derive(Debug, Clone, PartialEq)]
94pub struct OrderItem {
95    /// The expression to sort by.
96    pub expr: Expression,
97    /// True for `ASC` (default), false for `DESC`.
98    pub ascending: bool,
99}
100
101/// A `CREATE` clause with a pattern to create.
102#[derive(Debug, Clone, PartialEq)]
103pub struct CreateClause {
104    /// The graph pattern to create.
105    pub pattern: Pattern,
106}
107
108/// A `SET` clause with property assignments.
109#[derive(Debug, Clone, PartialEq)]
110pub struct SetClause {
111    /// Property assignment items.
112    pub items: Vec<SetItem>,
113}
114
115/// A single property assignment in a `SET` clause.
116#[derive(Debug, Clone, PartialEq)]
117pub enum SetItem {
118    /// Set a property to a value: `target = value`.
119    Property {
120        /// The property access expression (e.g. `n.name`).
121        target: Expression,
122        /// The value expression.
123        value: Expression,
124    },
125}
126
127/// A `REMOVE` clause.
128#[derive(Debug, Clone, PartialEq)]
129pub struct RemoveClause {
130    /// Items to remove.
131    pub items: Vec<RemoveItem>,
132}
133
134/// A single item in a `REMOVE` clause.
135#[derive(Debug, Clone, PartialEq)]
136pub enum RemoveItem {
137    /// Remove a property (e.g. `n.name`).
138    Property(Expression),
139    /// Remove a label from a node (e.g. `n:Label`).
140    Label {
141        /// Variable name.
142        variable: String,
143        /// Label to remove.
144        label: String,
145    },
146}
147
148/// A `DELETE` or `DETACH DELETE` clause.
149#[derive(Debug, Clone, PartialEq)]
150pub struct DeleteClause {
151    /// True if `DETACH DELETE` (also deletes relationships).
152    pub detach: bool,
153    /// Expressions identifying entities to delete.
154    pub exprs: Vec<Expression>,
155}
156
157/// A `WITH` clause for intermediate result piping.
158#[derive(Debug, Clone, PartialEq)]
159pub struct WithClause {
160    /// Whether `DISTINCT` was specified.
161    pub distinct: bool,
162    /// Projected items.
163    pub items: Vec<ReturnItem>,
164    /// Optional `WHERE` filter.
165    pub where_clause: Option<Expression>,
166}
167
168/// A `MERGE` clause with optional `ON MATCH` / `ON CREATE` actions.
169#[derive(Debug, Clone, PartialEq)]
170pub struct MergeClause {
171    /// The pattern to match or create.
172    pub pattern: Pattern,
173    /// `SET` items to apply when the pattern matches.
174    pub on_match: Vec<SetItem>,
175    /// `SET` items to apply when the pattern is created.
176    pub on_create: Vec<SetItem>,
177}
178
179/// An `UNWIND` clause that expands a list into rows.
180#[derive(Debug, Clone, PartialEq)]
181pub struct UnwindClause {
182    /// The list expression to unwind.
183    pub expr: Expression,
184    /// The variable name bound to each element.
185    pub variable: String,
186}
187
188/// The target kind of a property index.
189#[derive(Debug, Clone, PartialEq)]
190pub enum IndexTarget {
191    /// Index on a node label.
192    NodeLabel(String),
193    /// Index on a relationship type.
194    RelationshipType(String),
195}
196
197/// `CREATE INDEX [name] ON :Label(property)` or `CREATE INDEX [name] ON :REL_TYPE(property)`
198#[derive(Debug, Clone, PartialEq)]
199pub struct CreateIndexClause {
200    /// Optional index name.
201    pub name: Option<String>,
202    /// Label or relationship type the index applies to.
203    pub target: IndexTarget,
204    /// Property key the index covers.
205    pub property: String,
206}
207
208/// DROP INDEX name
209#[derive(Debug, Clone, PartialEq)]
210pub struct DropIndexClause {
211    /// Name of the index to drop.
212    pub name: String,
213}
214
215// -- Patterns --
216
217/// A graph pattern consisting of one or more comma-separated chains.
218#[derive(Debug, Clone, PartialEq)]
219pub struct Pattern {
220    /// Comma-separated pattern chains.
221    pub chains: Vec<PatternChain>,
222}
223
224/// A single chain of alternating nodes and relationships.
225#[derive(Debug, Clone, PartialEq)]
226pub struct PatternChain {
227    /// Alternating node and relationship elements.
228    pub elements: Vec<PatternElement>,
229}
230
231/// An element within a pattern chain.
232#[derive(Debug, Clone, PartialEq)]
233pub enum PatternElement {
234    /// A node pattern (e.g. `(n:Person)`).
235    Node(NodePattern),
236    /// A relationship pattern (e.g. `-[:KNOWS]->`).
237    Relationship(RelationshipPattern),
238}
239
240/// A node pattern: `(variable:Label {properties})`.
241#[derive(Debug, Clone, PartialEq)]
242pub struct NodePattern {
243    /// Optional variable binding.
244    pub variable: Option<String>,
245    /// Zero or more labels.
246    pub labels: Vec<String>,
247    /// Optional inline property map.
248    pub properties: Option<MapLiteral>,
249}
250
251/// A relationship pattern: `-[variable:TYPE {props}]->`.
252#[derive(Debug, Clone, PartialEq)]
253pub struct RelationshipPattern {
254    /// Optional variable binding.
255    pub variable: Option<String>,
256    /// Relationship type filters.
257    pub rel_types: Vec<String>,
258    /// Arrow direction.
259    pub direction: RelDirection,
260    /// Optional inline property map.
261    pub properties: Option<MapLiteral>,
262    /// Minimum hops for variable-length paths. None means regular 1-hop.
263    pub min_hops: Option<u32>,
264    /// Maximum hops for variable-length paths. None means unbounded (capped by planner).
265    pub max_hops: Option<u32>,
266}
267
268/// Relationship arrow direction.
269#[derive(Debug, Clone, Copy, PartialEq, Eq)]
270pub enum RelDirection {
271    /// `-[...]->`
272    Outgoing,
273    /// `<-[...]-`
274    Incoming,
275    /// `-[...]-`
276    Undirected,
277}
278
279/// A map literal is a list of key-value pairs: `{key1: expr1, key2: expr2}`.
280pub type MapLiteral = Vec<(String, Expression)>;
281
282// -- Expressions --
283
284/// An expression node in the AST.
285#[derive(Debug, Clone, PartialEq)]
286pub enum Expression {
287    /// A literal value.
288    Literal(Literal),
289    /// A variable reference.
290    Variable(String),
291    /// Property access: `expr.prop`
292    Property(Box<Expression>, String),
293    /// Parameter reference: `$name`
294    Parameter(String),
295    /// Binary operation: `lhs op rhs`.
296    BinaryOp(BinaryOp, Box<Expression>, Box<Expression>),
297    /// Unary operation: `op expr`.
298    UnaryOp(UnaryOp, Box<Expression>),
299    /// Function call: `name(args)` or `name(DISTINCT args)`.
300    FunctionCall {
301        /// Function name.
302        name: String,
303        /// Whether `DISTINCT` was specified.
304        distinct: bool,
305        /// Function arguments.
306        args: Vec<Expression>,
307    },
308    /// `expr IS [NOT] NULL` -- bool is true when IS NOT NULL
309    IsNull(Box<Expression>, bool),
310    /// `count(*)`
311    CountStar,
312    /// List literal: `[expr, expr, ...]`
313    ListLiteral(Vec<Expression>),
314    /// Temporal reference: `expr AT TIME expr` in hyperedge participant lists.
315    #[cfg(feature = "hypergraph")]
316    TemporalRef {
317        /// The node expression.
318        node: Box<Expression>,
319        /// The timestamp expression.
320        timestamp: Box<Expression>,
321    },
322}
323
324/// A literal value in the AST.
325#[derive(Debug, Clone, PartialEq)]
326pub enum Literal {
327    /// Integer literal (e.g. `42`).
328    Integer(i64),
329    /// Floating-point literal (e.g. `3.14`).
330    Float(f64),
331    /// String literal (e.g. `'hello'`).
332    String(String),
333    /// Boolean literal (`true` / `false`).
334    Bool(bool),
335    /// `NULL` literal.
336    Null,
337}
338
339/// Binary operators.
340#[derive(Debug, Clone, Copy, PartialEq, Eq)]
341pub enum BinaryOp {
342    /// `+` addition.
343    Add,
344    /// `-` subtraction.
345    Sub,
346    /// `*` multiplication.
347    Mul,
348    /// `/` division.
349    Div,
350    /// `%` modulus.
351    Mod,
352    /// `=` equality.
353    Eq,
354    /// `<>` / `!=` inequality.
355    Neq,
356    /// `<` less than.
357    Lt,
358    /// `<=` less than or equal.
359    Lte,
360    /// `>` greater than.
361    Gt,
362    /// `>=` greater than or equal.
363    Gte,
364    /// `AND` logical conjunction.
365    And,
366    /// `OR` logical disjunction.
367    Or,
368}
369
370/// Unary operators.
371#[derive(Debug, Clone, Copy, PartialEq, Eq)]
372pub enum UnaryOp {
373    /// `NOT` logical negation.
374    Not,
375    /// `-` arithmetic negation.
376    Neg,
377}
378
379// -- Subgraph Snapshot --
380
381/// CREATE SNAPSHOT clause for materializing query results into a subgraph.
382///
383/// Syntax: CREATE SNAPSHOT (var:Label {props}) [AT TIME expr] FROM MATCH pattern [WHERE filter] RETURN items
384#[cfg(feature = "subgraph")]
385#[derive(Debug, Clone, PartialEq)]
386pub struct CreateSnapshotClause {
387    /// Optional variable name for the snapshot subgraph.
388    pub variable: Option<String>,
389    /// Labels for the snapshot subgraph.
390    pub labels: Vec<String>,
391    /// Properties to set on the snapshot subgraph.
392    pub properties: Option<MapLiteral>,
393    /// Optional temporal anchor (AT TIME expr).
394    pub temporal_anchor: Option<Expression>,
395    /// The FROM MATCH clause defining the source pattern.
396    pub from_match: MatchClause,
397    /// The FROM RETURN items defining what to capture.
398    pub from_return: Vec<ReturnItem>,
399}
400
401/// CREATE HYPEREDGE clause for creating a hyperedge connecting multiple sources and targets.
402///
403/// Syntax: CREATE HYPEREDGE (var:Label) FROM (expr, expr, ...) TO (expr, expr, ...)
404#[cfg(feature = "hypergraph")]
405#[derive(Debug, Clone, PartialEq)]
406pub struct CreateHyperedgeClause {
407    /// Optional variable name for the hyperedge.
408    pub variable: Option<String>,
409    /// Labels (relationship types) for the hyperedge.
410    pub labels: Vec<String>,
411    /// Source participant expressions (FROM list).
412    pub sources: Vec<Expression>,
413    /// Target participant expressions (TO list).
414    pub targets: Vec<Expression>,
415}
416
417/// MATCH HYPEREDGE clause for querying hyperedges.
418///
419/// Syntax: MATCH HYPEREDGE (var:Label)
420#[cfg(feature = "hypergraph")]
421#[derive(Debug, Clone, PartialEq)]
422pub struct MatchHyperedgeClause {
423    /// Optional variable name for the hyperedge.
424    pub variable: Option<String>,
425    /// Labels to filter by.
426    pub labels: Vec<String>,
427}