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}
424
425#[derive(Debug, Clone, PartialEq)]
426pub struct CreateRelTable {
427    pub name: String,
428    pub from: String,
429    pub to: String,
430    pub columns: Vec<ColumnDef>,
431}
432
433#[derive(Debug, Clone, PartialEq)]
434pub struct DropTable {
435    pub name: String,
436}
437
438/// A `CREATE [ART|HASH] INDEX` statement.
439#[derive(Debug, Clone, PartialEq)]
440pub struct CreateIndex {
441    pub index_type: String,
442    pub index_name: String,
443    pub table_name: String,
444    pub variable: String,
445    pub property: String,
446    pub conflict_action: Option<String>,
447}
448
449/// A `DROP INDEX` statement.
450#[derive(Debug, Clone, PartialEq)]
451pub struct DropIndex {
452    pub index_name: String,
453    pub table_name: String,
454}
455
456/// ALTER TABLE statement.
457#[derive(Debug, Clone, PartialEq)]
458pub struct AlterTable {
459    pub table_name: String,
460    pub action: AlterAction,
461}
462
463#[derive(Debug, Clone, PartialEq)]
464pub enum AlterAction {
465    AddColumn { name: String, type_name: String },
466    DropColumn { name: String },
467    RenameColumn { old_name: String, new_name: String },
468    RenameTable { new_name: String },
469}
470
471/// UNION statement — combines results from two queries.
472#[derive(Debug, Clone, PartialEq)]
473pub struct UnionStatement {
474    pub left: Query,
475    pub right: Query,
476    pub all: bool,
477}
478
479/// COPY FROM statement — load data from a file into a table.
480#[derive(Debug, Clone, PartialEq)]
481pub struct CopyFrom {
482    pub table_name: String,
483    pub file_path: String,
484    pub options: std::collections::HashMap<String, String>,
485}
486
487/// COPY TO statement — export query results to a file.
488///
489/// Syntax: `COPY (query) TO 'path' (FORMAT 'CSV'|'PARQUET', HEADER true|false)`
490#[derive(Debug, Clone, PartialEq)]
491pub struct CopyTo {
492    pub query: Query,
493    pub file_path: String,
494    pub format: CopyToFormat,
495    pub header: bool,
496}
497
498#[derive(Debug, Clone, PartialEq)]
499pub enum CopyToFormat {
500    Csv,
501    Parquet,
502}
503
504/// MERGE statement — match or create a pattern with optional ON CREATE / ON MATCH actions.
505#[derive(Debug, Clone, PartialEq)]
506pub struct MergeStatement {
507    pub patterns: Vec<Pattern>,
508    pub on_create: Vec<SetItem>,
509    pub on_match: Vec<SetItem>,
510}
511
512/// CALL statement — invoke a table function or procedure as a standalone statement.
513#[derive(Debug, Clone, PartialEq)]
514pub struct StandaloneCall {
515    pub function_name: String,
516    pub args: Vec<Expression>,
517}
518
519/// CREATE SEQUENCE statement — creates a sequence for auto-incrementing counters.
520///
521/// Syntax:
522/// ```sql
523/// CREATE [OR REPLACE] SEQUENCE [IF NOT EXISTS] name
524///   [START WITH value]
525///   [INCREMENT [BY] value]
526///   [MINVALUE value | NO MINVALUE]
527///   [MAXVALUE value | NO MAXVALUE]
528///   [CYCLE | NO CYCLE]
529/// ```
530#[derive(Debug, Clone, PartialEq)]
531pub struct CreateSequence {
532    pub name: String,
533    pub if_not_exists: bool,
534    pub or_replace: bool,
535    /// START WITH value. Default: 1 for increment > 0, max_value for increment < 0.
536    pub start_with: Option<i64>,
537    /// INCREMENT BY value. Default: 1.
538    pub increment: Option<i64>,
539    /// MINVALUE. Auto-computed from defaults if None.
540    pub min_value: Option<i64>,
541    /// MAXVALUE. Auto-computed from defaults if None.
542    pub max_value: Option<i64>,
543    /// CYCLE behavior. Default: false (NO CYCLE).
544    pub cycle: Option<bool>,
545}
546
547/// DROP SEQUENCE statement.
548#[derive(Debug, Clone, PartialEq)]
549pub struct DropSequence {
550    pub name: String,
551    pub if_exists: bool,
552}
553
554/// CREATE MACRO statement — defines a Cypher scalar macro.
555///
556/// Syntax: `CREATE MACRO macroName(param1, param2, ...) AS expression`
557///
558/// Macros are expanded at binding time: macro invocations are replaced
559/// with the macro body expression (with parameters substituted).
560///
561/// Ported from C++ `parser/create_macro.h`.
562#[derive(Debug, Clone, PartialEq)]
563pub struct CreateMacro {
564    /// The macro name.
565    pub name: String,
566    /// Positional parameter names (no default value).
567    pub positional_args: Vec<String>,
568    /// Parameters with default values (name, default expression).
569    pub default_args: Vec<(String, Expression)>,
570    /// The macro body expression.
571    pub expression: Box<Expression>,
572}
573
574/// CREATE VECTOR INDEX statement — creates an HNSW index on a vector column.
575#[derive(Debug, Clone, PartialEq)]
576pub struct CreateVectorIndex {
577    pub index_name: String,
578    pub table_name: String,
579    pub column_name: String,
580    pub metric: String,
581    pub dimensions: u64,
582}
583
584#[derive(Debug, Clone, PartialEq)]
585pub struct ColumnDef {
586    pub name: String,
587    pub type_name: String,
588    pub compression: Option<String>,
589}
590
591/// CREATE TYPE name AS type — user-defined type alias.
592#[derive(Debug, Clone, PartialEq)]
593pub struct CreateType {
594    pub name: String,
595    pub type_name: String,
596}
597
598/// COMMENT ON TABLE name IS 'string' — add a comment to a table.
599#[derive(Debug, Clone, PartialEq)]
600pub struct CommentOnTable {
601    pub table_name: String,
602    pub comment: String,
603}
604
605/// CREATE [PROJECTION] GRAPH name [ANY] — create a projected graph.
606#[derive(Debug, Clone, PartialEq)]
607pub struct CreateGraph {
608    pub name: String,
609    pub is_any: bool,
610}
611
612/// USE GRAPH name — set the current graph context.
613#[derive(Debug, Clone, PartialEq)]
614pub struct UseGraph {
615    pub name: String,
616}
617
618/// DROP GRAPH name — remove a projected graph.
619#[derive(Debug, Clone, PartialEq)]
620pub struct DropGraph {
621    pub name: String,
622}