Skip to main content

akar_parser/
ast.rs

1//! Abstract Syntax Tree (AST) types for Cypher queries.
2
3/// EXPLAIN type — what kind of plan to show.
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub enum ExplainType {
6    /// `EXPLAIN` — show the physical plan (default).
7    PhysicalPlan,
8    /// `EXPLAIN LOGICAL` — show the logical plan.
9    LogicalPlan,
10    /// `EXPLAIN PROFILE` — execute and show profile.
11    Profile,
12}
13
14/// EXPORT DATABASE statement.
15#[derive(Debug, Clone, PartialEq)]
16pub struct ExportDatabase {
17    /// Path to the export directory.
18    pub file_path: String,
19    /// Export options (format, schema_only, etc.).
20    pub options: std::collections::HashMap<String, String>,
21}
22
23/// IMPORT DATABASE statement.
24#[derive(Debug, Clone, PartialEq)]
25pub struct ImportDatabase {
26    /// Path to the import directory (previously exported).
27    pub file_path: String,
28    /// Import options (format, etc.) — accepted for Kuzu syntax parity.
29    pub options: std::collections::HashMap<String, String>,
30}
31
32/// ANALYZE statement — collect table statistics.
33#[derive(Debug, Clone, PartialEq)]
34pub struct AnalyzeStatement {
35    /// Table name to analyze, or None for all tables (ANALYZE *).
36    pub table_name: Option<String>,
37}
38
39/// Transaction action type.
40#[derive(Debug, Clone, Copy, PartialEq)]
41pub enum TransactionAction {
42    Begin,
43    Commit,
44    Rollback,
45    Checkpoint,
46}
47
48/// TRANSACTION statement (BEGIN, COMMIT, ROLLBACK, CHECKPOINT).
49#[derive(Debug, Clone, PartialEq)]
50pub struct TransactionStatement {
51    pub action: TransactionAction,
52}
53
54/// Extension management action.
55#[derive(Debug, Clone, Copy, PartialEq)]
56pub enum ExtensionAction {
57    Install,
58    Load,
59    Uninstall,
60}
61
62/// EXTENSION management statement (INSTALL/LOAD/UNINSTALL EXTENSION name).
63#[derive(Debug, Clone, PartialEq)]
64pub struct ExtensionStatement {
65    pub action: ExtensionAction,
66    pub name: String,
67}
68
69/// ATTACH DATABASE statement.
70#[derive(Debug, Clone, PartialEq)]
71pub struct AttachDatabase {
72    pub path: String,
73    pub alias: String,
74    pub options: std::collections::HashMap<String, String>,
75}
76
77/// DETACH DATABASE statement.
78#[derive(Debug, Clone, PartialEq)]
79pub struct DetachDatabase {
80    pub alias: String,
81}
82
83/// USE DATABASE statement.
84#[derive(Debug, Clone, PartialEq)]
85pub struct UseDatabase {
86    pub alias: String,
87}
88
89/// LOAD FROM statement — scan external file without importing.
90#[derive(Debug, Clone, PartialEq)]
91pub struct LoadFrom {
92    pub path: String,
93    pub options: std::collections::HashMap<String, String>,
94}
95
96/// EXPLAIN statement wrapper.
97#[derive(Debug, Clone, PartialEq)]
98pub struct ExplainStatement {
99    /// The statement being explained.
100    pub statement: Box<Statement>,
101    /// The type of explain output.
102    pub explain_type: ExplainType,
103}
104
105/// A Cypher statement (top-level AST node).
106#[derive(Debug, Clone, PartialEq)]
107pub enum Statement {
108    Query(Query),
109    CreateNodeTable(CreateNodeTable),
110    CreateRelTable(CreateRelTable),
111    DropTable(DropTable),
112    CopyFrom(CopyFrom),
113    CopyTo(CopyTo),
114    AlterTable(AlterTable),
115    CreateVectorIndex(CreateVectorIndex),
116    CreateIndex(CreateIndex),
117    DropIndex(DropIndex),
118    Union(UnionStatement),
119    Merge(MergeStatement),
120    StandaloneCall(StandaloneCall),
121    CreateDml(CreateClause),
122    Explain(ExplainStatement),
123    CreateSequence(CreateSequence),
124    DropSequence(DropSequence),
125    CreateMacro(CreateMacro),
126    ExportDatabase(ExportDatabase),
127    ImportDatabase(ImportDatabase),
128    Analyze(AnalyzeStatement),
129    CreateFtsIndex(CreateFtsIndex),
130    Transaction(TransactionStatement),
131    Extension(ExtensionStatement),
132    AttachDatabase(AttachDatabase),
133    DetachDatabase(DetachDatabase),
134    UseDatabase(UseDatabase),
135    LoadFrom(LoadFrom),
136    CreateType(CreateType),
137    CommentOnTable(CommentOnTable),
138    CreateGraph(CreateGraph),
139    UseGraph(UseGraph),
140    DropGraph(DropGraph),
141}
142
143/// A Cypher query (e.g., MATCH ... RETURN ...).
144#[derive(Debug, Clone, PartialEq)]
145pub struct Query {
146    pub clauses: Vec<Clause>,
147}
148
149/// A clause in a query.
150#[derive(Debug, Clone, PartialEq)]
151pub enum Clause {
152    Match(MatchClause),
153    Return(ReturnClause),
154    Where(WhereClause),
155    Create(CreateClause),
156    Delete(DeleteClause),
157    Set(SetClause),
158    OptionalMatch(OptionalMatchClause),
159    With(ReturnClause),
160    Unwind(UnwindClause),
161    Foreach(ForeachClause),
162    Merge(MergeStatement),
163}
164
165#[derive(Debug, Clone, PartialEq)]
166pub struct ForeachClause {
167    pub variable: String,
168    pub expression: Expression,
169    /// Sub-statements inside FOREACH (CREATE, SET, DELETE clauses).
170    pub clauses: Vec<Clause>,
171}
172
173#[derive(Debug, Clone, PartialEq)]
174pub struct UnwindClause {
175    pub expression: Expression,
176    pub variable: String,
177}
178
179#[derive(Debug, Clone, PartialEq)]
180pub struct SetClause {
181    pub items: Vec<SetItem>,
182}
183
184#[derive(Debug, Clone, PartialEq)]
185pub struct SetItem {
186    pub property: Expression,
187    pub value: Expression,
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub struct DeleteClause {
192    pub detach: bool,
193    pub expressions: Vec<Expression>,
194}
195
196#[derive(Debug, Clone, PartialEq)]
197pub struct MatchClause {
198    pub patterns: Vec<Pattern>,
199    /// Optional FTS query attached to this MATCH via `USING FTS INDEX name('query')`.
200    pub fts_query: Option<FtsQuery>,
201}
202
203/// A `USING FTS INDEX index_name('search string')` clause attached to a MATCH.
204#[derive(Debug, Clone, PartialEq)]
205pub struct FtsQuery {
206    pub index_name: String,
207    pub query_string: String,
208}
209
210/// CREATE FTS INDEX statement.
211#[derive(Debug, Clone, PartialEq)]
212pub struct CreateFtsIndex {
213    pub index_name: String,
214    pub table_name: String,
215    pub column_name: String,
216    pub if_not_exists: bool,
217}
218
219#[derive(Debug, Clone, PartialEq)]
220pub struct OptionalMatchClause {
221    pub patterns: Vec<Pattern>,
222}
223
224#[derive(Debug, Clone, PartialEq)]
225pub struct ReturnClause {
226    pub expressions: Vec<ReturnItem>,
227    pub distinct: bool,
228    /// Optional ORDER BY clause: list of sort items.
229    pub order_by: Option<Vec<OrderByItem>>,
230    /// Optional LIMIT — maximum number of rows to return.
231    pub limit: Option<u64>,
232    /// Optional SKIP — number of rows to skip before returning.
233    pub skip: Option<u64>,
234}
235
236#[derive(Debug, Clone, PartialEq)]
237pub struct ReturnItem {
238    pub expression: Expression,
239    pub alias: Option<String>,
240}
241
242/// A single sort item in an ORDER BY clause.
243#[derive(Debug, Clone, PartialEq)]
244pub struct OrderByItem {
245    /// The expression to sort by.
246    pub expression: Expression,
247    /// Sort direction: `true` for ascending (default), `false` for descending.
248    pub ascending: bool,
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub struct WhereClause {
253    pub expression: Expression,
254}
255
256#[derive(Debug, Clone, PartialEq)]
257pub struct CreateClause {
258    pub patterns: Vec<Pattern>,
259}
260
261/// A graph pattern (node or relationship).
262#[derive(Debug, Clone, PartialEq)]
263pub struct Pattern {
264    pub node: Option<NodePattern>,
265    pub edge: Option<EdgePattern>,
266}
267
268#[derive(Debug, Clone, PartialEq)]
269pub struct NodePattern {
270    pub variable: Option<String>,
271    pub labels: Vec<String>,
272    pub properties: Vec<(String, Expression)>,
273}
274
275#[derive(Debug, Clone, PartialEq)]
276pub struct EdgePattern {
277    pub variable: Option<String>,
278    pub labels: Vec<String>,
279    pub direction: EdgeDirection,
280    pub properties: Vec<(String, Expression)>,
281    pub lower_bound: Option<u64>,
282    pub upper_bound: Option<u64>,
283}
284
285#[derive(Debug, Clone, PartialEq)]
286pub enum EdgeDirection {
287    LeftToRight,
288    RightToLeft,
289    Both,
290}
291
292impl ExplainStatement {
293    /// Create a new EXPLAIN statement wrapping the given inner statement.
294    pub fn new(statement: Statement, explain_type: ExplainType) -> Self {
295        Self {
296            statement: Box::new(statement),
297            explain_type,
298        }
299    }
300}
301
302/// An expression in a Cypher query.
303#[derive(Debug, Clone, PartialEq)]
304pub enum Expression {
305    Constant(Constant),
306    Variable(String),
307    /// A query parameter reference like `$name` or `$age`.
308    Parameter(String),
309    PropertyAccess(Box<Expression>, String),
310    FunctionCall(String, Vec<Expression>),
311    BinaryOp(BinaryOp, Box<Expression>, Box<Expression>),
312    UnaryOp(UnaryOp, Box<Expression>),
313    List(Vec<Expression>),
314    Map(Vec<(String, Expression)>),
315    /// EXISTS { MATCH ... WHERE ... } — returns true if the pattern matches.
316    ExistsSubquery(Box<Query>),
317    /// CASE [subject] WHEN ... THEN ... [ELSE ...] END
318    Case(CaseExpr),
319    /// STAR expression — represents `*` in `RETURN *`.
320    /// The binder expands this to all variables in scope.
321    Star,
322    /// ANY/ALL/NONE/SINGLE list predicates.
323    /// Example: ANY(x IN [1,2,3] WHERE x > 5)
324    ListPredicate {
325        quantifier: Quantifier,
326        list: Box<Expression>,
327        var_name: String,
328        predicate: Box<Expression>,
329    },
330    /// Lambda expression for list_transform, list_filter, list_reduce.
331    /// Example: x -> x + 1  or  (x, y) -> x + y
332    Lambda {
333        var_name: String,
334        body: Box<Expression>,
335    },
336}
337
338/// Quantifier for list predicates.
339#[derive(Debug, Clone, Copy, PartialEq)]
340pub enum Quantifier {
341    Any,
342    All,
343    None,
344    Single,
345}
346
347/// A single WHEN ... THEN ... branch inside a CASE expression.
348#[derive(Debug, Clone, PartialEq)]
349pub struct CaseAlternative {
350    /// The WHEN expression (a value for simple CASE, or a condition for searched CASE).
351    pub when: Expression,
352    /// The THEN expression returned when WHEN matches.
353    pub then: Expression,
354}
355
356/// A CASE expression (simple or searched).
357#[derive(Debug, Clone, PartialEq)]
358pub struct CaseExpr {
359    /// Optional subject expression for simple CASE: `CASE x WHEN v THEN ...`
360    pub subject: Option<Box<Expression>>,
361    /// The WHEN/THEN branches.
362    pub alternatives: Vec<CaseAlternative>,
363    /// Optional ELSE expression returned when no branch matches.
364    pub else_expr: Option<Box<Expression>>,
365}
366
367#[derive(Debug, Clone, PartialEq)]
368pub enum Constant {
369    Null,
370    Bool(bool),
371    Integer(i64),
372    Float(f64),
373    String(String),
374}
375
376#[derive(Debug, Clone, Copy, PartialEq)]
377pub enum BinaryOp {
378    Add,
379    Subtract,
380    Multiply,
381    Divide,
382    Modulo,
383    Equal,
384    NotEqual,
385    LessThan,
386    LessThanOrEqual,
387    GreaterThan,
388    GreaterThanOrEqual,
389    And,
390    Or,
391    Xor,
392    Concat,
393    /// x IN [list] — true if x equals any element of the list
394    In,
395    /// x NOT IN [list] — true if x equals no element of the list
396    NotIn,
397    /// x STARTS WITH prefix — true if string x starts with prefix
398    StartsWith,
399    /// x ENDS WITH suffix — true if string x ends with suffix
400    EndsWith,
401    /// x CONTAINS substr — true if string x contains substr
402    Contains,
403    /// x LIKE pattern — true if string x matches the SQL LIKE pattern
404    Like,
405}
406
407#[derive(Debug, Clone, Copy, PartialEq)]
408pub enum UnaryOp {
409    Not,
410    Negate,
411    /// x IS NULL — true if x evaluates to null
412    IsNull,
413    /// x IS NOT NULL — true if x does not evaluate to null
414    IsNotNull,
415}
416
417// DDL statements
418#[derive(Debug, Clone, PartialEq)]
419pub struct CreateNodeTable {
420    pub name: String,
421    pub columns: Vec<ColumnDef>,
422    pub primary_key: String,
423    pub if_not_exists: bool,
424}
425
426#[derive(Debug, Clone, PartialEq)]
427pub struct CreateRelTable {
428    pub name: String,
429    pub from: String,
430    pub to: String,
431    pub columns: Vec<ColumnDef>,
432    pub if_not_exists: bool,
433}
434
435#[derive(Debug, Clone, PartialEq)]
436pub struct DropTable {
437    pub name: String,
438}
439
440/// A `CREATE [ART|HASH] INDEX` statement.
441#[derive(Debug, Clone, PartialEq)]
442pub struct CreateIndex {
443    pub index_type: String,
444    pub index_name: String,
445    pub table_name: String,
446    pub variable: String,
447    pub property: String,
448    pub conflict_action: Option<String>,
449}
450
451/// A `DROP INDEX` statement.
452#[derive(Debug, Clone, PartialEq)]
453pub struct DropIndex {
454    pub index_name: String,
455    pub table_name: String,
456}
457
458/// ALTER TABLE statement.
459#[derive(Debug, Clone, PartialEq)]
460pub struct AlterTable {
461    pub table_name: String,
462    pub action: AlterAction,
463}
464
465#[derive(Debug, Clone, PartialEq)]
466pub enum AlterAction {
467    AddColumn { name: String, type_name: String },
468    DropColumn { name: String },
469    RenameColumn { old_name: String, new_name: String },
470    RenameTable { new_name: String },
471}
472
473/// UNION statement — combines results from two queries.
474#[derive(Debug, Clone, PartialEq)]
475pub struct UnionStatement {
476    pub left: Query,
477    pub right: Query,
478    pub all: bool,
479}
480
481/// COPY FROM statement — load data from a file into a table.
482#[derive(Debug, Clone, PartialEq)]
483pub struct CopyFrom {
484    pub table_name: String,
485    pub file_path: String,
486    pub options: std::collections::HashMap<String, String>,
487}
488
489/// COPY TO statement — export query results to a file.
490///
491/// Syntax: `COPY (query) TO 'path' (FORMAT 'CSV'|'PARQUET', HEADER true|false)`
492#[derive(Debug, Clone, PartialEq)]
493pub struct CopyTo {
494    pub query: Query,
495    pub file_path: String,
496    pub format: CopyToFormat,
497    pub header: bool,
498}
499
500#[derive(Debug, Clone, PartialEq)]
501pub enum CopyToFormat {
502    Csv,
503    Parquet,
504}
505
506/// MERGE statement — match or create a pattern with optional ON CREATE / ON MATCH actions.
507#[derive(Debug, Clone, PartialEq)]
508pub struct MergeStatement {
509    pub patterns: Vec<Pattern>,
510    pub on_create: Vec<SetItem>,
511    pub on_match: Vec<SetItem>,
512}
513
514/// CALL statement — invoke a table function or procedure as a standalone statement.
515#[derive(Debug, Clone, PartialEq)]
516pub struct StandaloneCall {
517    pub function_name: String,
518    pub args: Vec<Expression>,
519}
520
521/// CREATE SEQUENCE statement — creates a sequence for auto-incrementing counters.
522///
523/// Syntax:
524/// ```sql
525/// CREATE [OR REPLACE] SEQUENCE [IF NOT EXISTS] name
526///   [START WITH value]
527///   [INCREMENT [BY] value]
528///   [MINVALUE value | NO MINVALUE]
529///   [MAXVALUE value | NO MAXVALUE]
530///   [CYCLE | NO CYCLE]
531/// ```
532#[derive(Debug, Clone, PartialEq)]
533pub struct CreateSequence {
534    pub name: String,
535    pub if_not_exists: bool,
536    pub or_replace: bool,
537    /// START WITH value. Default: 1 for increment > 0, max_value for increment < 0.
538    pub start_with: Option<i64>,
539    /// INCREMENT BY value. Default: 1.
540    pub increment: Option<i64>,
541    /// MINVALUE. Auto-computed from defaults if None.
542    pub min_value: Option<i64>,
543    /// MAXVALUE. Auto-computed from defaults if None.
544    pub max_value: Option<i64>,
545    /// CYCLE behavior. Default: false (NO CYCLE).
546    pub cycle: Option<bool>,
547}
548
549/// DROP SEQUENCE statement.
550#[derive(Debug, Clone, PartialEq)]
551pub struct DropSequence {
552    pub name: String,
553    pub if_exists: bool,
554}
555
556/// CREATE MACRO statement — defines a Cypher scalar macro.
557///
558/// Syntax: `CREATE MACRO macroName(param1, param2, ...) AS expression`
559///
560/// Macros are expanded at binding time: macro invocations are replaced
561/// with the macro body expression (with parameters substituted).
562///
563/// Ported from C++ `parser/create_macro.h`.
564#[derive(Debug, Clone, PartialEq)]
565pub struct CreateMacro {
566    /// The macro name.
567    pub name: String,
568    /// Positional parameter names (no default value).
569    pub positional_args: Vec<String>,
570    /// Parameters with default values (name, default expression).
571    pub default_args: Vec<(String, Expression)>,
572    /// The macro body expression.
573    pub expression: Box<Expression>,
574}
575
576/// CREATE VECTOR INDEX statement — creates an HNSW index on a vector column.
577#[derive(Debug, Clone, PartialEq)]
578pub struct CreateVectorIndex {
579    pub index_name: String,
580    pub table_name: String,
581    pub column_name: String,
582    pub metric: String,
583    pub dimensions: u64,
584}
585
586#[derive(Debug, Clone, PartialEq)]
587pub struct ColumnDef {
588    pub name: String,
589    pub type_name: String,
590    pub compression: Option<String>,
591}
592
593/// CREATE TYPE name AS type — user-defined type alias.
594#[derive(Debug, Clone, PartialEq)]
595pub struct CreateType {
596    pub name: String,
597    pub type_name: String,
598}
599
600/// COMMENT ON TABLE name IS 'string' — add a comment to a table.
601#[derive(Debug, Clone, PartialEq)]
602pub struct CommentOnTable {
603    pub table_name: String,
604    pub comment: String,
605}
606
607/// CREATE [PROJECTION] GRAPH name [ANY] — create a projected graph.
608#[derive(Debug, Clone, PartialEq)]
609pub struct CreateGraph {
610    pub name: String,
611    pub is_any: bool,
612}
613
614/// USE GRAPH name — set the current graph context.
615#[derive(Debug, Clone, PartialEq)]
616pub struct UseGraph {
617    pub name: String,
618}
619
620/// DROP GRAPH name — remove a projected graph.
621#[derive(Debug, Clone, PartialEq)]
622pub struct DropGraph {
623    pub name: String,
624}