Skip to main content

akar_binder/
bound_statement.rs

1//! Bound statement types — AST nodes after semantic analysis.
2
3use akar_catalog::IndexType;
4use akar_common::types::LogicalTypeID;
5use akar_parser::ast::{Expression, ExtensionAction, TransactionAction};
6use std::collections::HashMap;
7
8/// A bound statement after semantic analysis.
9#[derive(Debug, Clone)]
10pub enum BoundStatement {
11    BoundQuery(BoundQuery),
12    BoundStandaloneCall(BoundStandaloneCall),
13    BoundCreateNodeTable(BoundCreateNodeTable),
14    BoundCreateRelTable(BoundCreateRelTable),
15    BoundDropTable(BoundDropTable),
16    BoundCopyFrom(BoundCopyFrom),
17    BoundCopyTo(BoundCopyTo),
18    BoundAlterTable(BoundAlterTable),
19    BoundCreateVectorIndex(BoundCreateVectorIndex),
20    BoundCreateIndex(BoundCreateIndex),
21    BoundDropIndex(BoundDropIndex),
22    BoundUnion(BoundUnion),
23    BoundMerge(BoundMerge),
24    BoundCreateDml(BoundCreateDml),
25    BoundExplain(BoundExplain),
26    BoundCreateSequence(BoundCreateSequence),
27    BoundDropSequence(BoundDropSequence),
28    BoundCreateMacro(BoundCreateMacro),
29    BoundExportDatabase(BoundExportDatabase),
30    BoundImportDatabase(BoundImportDatabase),
31    BoundCreateFtsIndex(BoundCreateFtsIndex),
32    BoundAnalyze(BoundAnalyze),
33    BoundTransaction(BoundTransaction),
34    BoundExtension(BoundExtension),
35    BoundAttachDatabase(BoundAttachDatabase),
36    BoundDetachDatabase(BoundDetachDatabase),
37    BoundUseDatabase(BoundUseDatabase),
38    BoundLoadFrom(BoundLoadFrom),
39    BoundCreateType(BoundCreateType),
40    BoundCommentOnTable(BoundCommentOnTable),
41    BoundCreateGraph(BoundCreateGraph),
42    BoundUseGraph(BoundUseGraph),
43    BoundDropGraph(BoundDropGraph),
44}
45
46/// Bound TRANSACTION statement.
47#[derive(Debug, Clone)]
48pub struct BoundTransaction {
49    pub action: TransactionAction,
50}
51
52/// Bound EXTENSION management statement.
53#[derive(Debug, Clone)]
54pub struct BoundExtension {
55    pub action: ExtensionAction,
56    pub name: String,
57}
58
59/// Bound ATTACH DATABASE statement.
60#[derive(Debug, Clone)]
61pub struct BoundAttachDatabase {
62    pub path: String,
63    pub alias: String,
64    pub options: HashMap<String, String>,
65}
66
67/// Bound DETACH DATABASE statement.
68#[derive(Debug, Clone)]
69pub struct BoundDetachDatabase {
70    pub alias: String,
71}
72
73/// Bound USE DATABASE statement.
74#[derive(Debug, Clone)]
75pub struct BoundUseDatabase {
76    pub alias: String,
77}
78
79/// Bound LOAD FROM statement.
80#[derive(Debug, Clone)]
81pub struct BoundLoadFrom {
82    pub path: String,
83    pub options: HashMap<String, String>,
84}
85
86/// Bound ANALYZE statement.
87#[derive(Debug, Clone)]
88pub struct BoundAnalyze {
89    /// Table name to analyze, or None for all tables.
90    pub table_name: Option<String>,
91    /// Resolved table IDs for the tables to analyze.
92    pub table_ids: Vec<u64>,
93}
94
95/// COPY FROM statement — load data from a file into a table.
96#[derive(Debug, Clone)]
97pub struct BoundCopyFrom {
98    pub table_name: String,
99    pub table_id: u64,
100    pub file_path: String,
101    pub options: HashMap<String, String>,
102    /// Resolved column schema from the catalog (column names + types).
103    pub columns: Vec<akar_catalog::CatalogColumn>,
104}
105
106/// COPY TO statement — export query results to a file.
107#[derive(Debug, Clone)]
108pub struct BoundCopyTo {
109    pub file_path: String,
110    pub format: akar_parser::ast::CopyToFormat,
111    pub header: bool,
112    /// The inner query to execute.
113    pub query: BoundQuery,
114}
115
116/// A resolved variable in scope (from MATCH patterns).
117#[derive(Debug, Clone)]
118pub struct BoundVariable {
119    pub name: String,
120    pub table_id: u64,
121    pub label: Option<String>,
122    pub is_node: bool,
123}
124
125#[derive(Debug, Clone)]
126pub struct BoundQuery {
127    pub clauses: Vec<BoundClause>,
128    /// Variables in scope (accumulated across clauses).
129    pub variables: Vec<BoundVariable>,
130}
131
132#[derive(Debug, Clone)]
133pub enum BoundClause {
134    BoundMatch(BoundMatchClause),
135    BoundReturn(BoundReturnClause),
136    BoundWhere(BoundWhereClause),
137    BoundDelete(BoundDeleteClause),
138    BoundSet(BoundSetClause),
139    BoundOptionalMatch(BoundMatchClause),
140    BoundWith(BoundReturnClause),
141    BoundUnwind(BoundUnwindClause),
142    BoundForeach(BoundForeachClause),
143    BoundCreate(BoundMatchClause),
144    BoundMerge(BoundMerge),
145}
146
147#[derive(Debug, Clone)]
148pub struct BoundSetItem {
149    pub property: akar_parser::ast::Expression,
150    pub value: akar_parser::ast::Expression,
151    pub column_name: String,
152    pub column_idx: usize,
153    pub table_name: String,
154    pub table_id: u64,
155    pub is_node: bool,
156}
157
158#[derive(Debug, Clone)]
159pub struct BoundSetClause {
160    pub items: Vec<BoundSetItem>,
161}
162
163#[derive(Debug, Clone)]
164pub struct BoundDeleteItem {
165    pub expression: Expression,
166    pub table_name: String,
167    pub table_id: u64,
168    pub primary_key_column: String,
169    pub is_node: bool,
170}
171
172#[derive(Debug, Clone)]
173pub struct BoundDeleteClause {
174    pub detach: bool,
175    pub items: Vec<BoundDeleteItem>,
176}
177
178#[derive(Debug, Clone)]
179pub struct BoundUnwindClause {
180    pub expression: akar_parser::ast::Expression,
181    pub variable: String,
182}
183
184/// Bound EXPLAIN statement — wraps an inner bound statement.
185#[derive(Debug, Clone)]
186pub struct BoundExplain {
187    /// The inner bound statement to explain.
188    pub inner: Box<BoundStatement>,
189    /// The type of explain output.
190    pub explain_type: akar_parser::ast::ExplainType,
191}
192
193/// Bound FOREACH clause — iterate over list and execute sub-statements.
194#[derive(Debug, Clone)]
195pub struct BoundForeachClause {
196    pub variable: String,
197    pub expression: akar_parser::ast::Expression,
198    /// Bound sub-statements (CREATE, SET, DELETE) produced by bind_foreach.
199    pub sub_statements: Vec<BoundStatement>,
200}
201
202#[derive(Debug, Clone)]
203pub struct BoundMatchClause {
204    pub patterns: Vec<BoundPattern>,
205    /// New variables introduced by this MATCH clause.
206    pub new_variables: Vec<BoundVariable>,
207    /// Optional FTS query (from USING FTS INDEX clause).
208    pub fts_query: Option<BoundFtsQuery>,
209}
210
211/// A bound USING FTS INDEX query.
212#[derive(Debug, Clone)]
213pub struct BoundFtsQuery {
214    pub index_name: String,
215    pub query_string: String,
216    /// The macro table names derived from the FTS index.
217    pub docs_table: String,
218    pub terms_table: String,
219    pub posting_table: String,
220    /// The source node table/column the index was created on (P52.39), used
221    /// to keep the derived macro tables in sync with live DML.
222    pub table_name: String,
223    pub column_name: String,
224}
225
226#[derive(Debug, Clone)]
227pub struct BoundPattern {
228    pub node_variable: Option<String>,
229    pub node_label: Option<String>,
230    pub node_table_id: Option<u64>,
231    pub properties: Vec<(String, akar_parser::ast::Expression)>,
232    pub edge: Option<BoundEdgePattern>,
233}
234
235#[derive(Debug, Clone)]
236pub struct BoundEdgePattern {
237    pub variable: Option<String>,
238    pub label: Option<String>,
239    pub rel_table_id: Option<u64>,
240    pub direction: akar_parser::ast::EdgeDirection,
241    pub properties: Vec<(String, akar_parser::ast::Expression)>,
242    pub lower_bound: Option<u64>,
243    pub upper_bound: Option<u64>,
244}
245
246/// A bound expression with resolved type information.
247#[derive(Debug, Clone)]
248pub struct BoundExpression {
249    pub expression: Expression,
250    pub resolved_type: LogicalTypeID,
251    pub is_constant: bool,
252    /// Output column name override from `AS alias` in RETURN/WITH (P53.16).
253    pub alias: Option<String>,
254}
255
256#[derive(Debug, Clone)]
257pub struct BoundReturnClause {
258    pub expressions: Vec<BoundExpression>,
259    pub distinct: bool,
260    /// Bound ORDER BY items.
261    pub order_by: Option<Vec<BoundOrderByItem>>,
262    /// Bound LIMIT.
263    pub limit: Option<u64>,
264    /// Bound SKIP.
265    pub skip: Option<u64>,
266    /// Parameter name referenced by LIMIT (resolved to `limit` at substitution).
267    pub limit_param: Option<String>,
268    /// Parameter name referenced by SKIP (resolved to `skip` at substitution).
269    pub skip_param: Option<String>,
270}
271
272/// A bound sort item for ORDER BY.
273#[derive(Debug, Clone)]
274pub struct BoundOrderByItem {
275    pub expression: BoundExpression,
276    pub ascending: bool,
277}
278
279#[derive(Debug, Clone)]
280pub struct BoundWhereClause {
281    pub expression: BoundExpression,
282}
283
284// DDL
285#[derive(Debug, Clone)]
286pub struct BoundCreateNodeTable {
287    pub name: String,
288    pub columns: Vec<akar_catalog::CatalogColumn>,
289    pub primary_key: String,
290    pub if_not_exists: bool,
291}
292
293#[derive(Debug, Clone)]
294pub struct BoundCreateRelTable {
295    pub name: String,
296    pub from: String,
297    pub to: String,
298    pub src_table_id: u64,
299    pub dst_table_id: u64,
300    pub columns: Vec<akar_catalog::CatalogColumn>,
301    pub if_not_exists: bool,
302}
303
304#[derive(Debug, Clone)]
305pub struct BoundDropTable {
306    pub name: String,
307}
308
309#[derive(Debug, Clone)]
310pub struct BoundAlterTable {
311    pub table_name: String,
312    pub action: akar_parser::ast::AlterAction,
313}
314
315#[derive(Debug, Clone)]
316pub struct BoundUnion {
317    pub left: Box<BoundQuery>,
318    pub right: Box<BoundQuery>,
319    pub all: bool,
320}
321
322/// Bound CREATE VECTOR INDEX statement.
323#[derive(Debug, Clone)]
324pub struct BoundCreateVectorIndex {
325    pub index_name: String,
326    pub table_name: String,
327    pub column_name: String,
328    pub metric: String,
329    pub dimensions: u64,
330}
331
332/// Bound `CREATE [ART|HASH] INDEX` statement.
333#[derive(Debug, Clone)]
334pub struct BoundCreateIndex {
335    pub index_type: IndexType,
336    pub index_name: String,
337    pub table_name: String,
338    pub column_name: String,
339}
340
341/// Bound `DROP INDEX` statement.
342#[derive(Debug, Clone)]
343pub struct BoundDropIndex {
344    pub index_name: String,
345    pub table_name: String,
346}
347
348/// Bound CALL statement — invoke a table function.
349#[derive(Debug, Clone)]
350pub struct BoundStandaloneCall {
351    pub function_name: String,
352    pub args: Vec<akar_parser::ast::Expression>,
353}
354
355/// Bound EXPORT DATABASE statement.
356#[derive(Debug, Clone)]
357pub struct BoundExportDatabase {
358    pub file_path: String,
359    pub file_type: String,
360    pub schema_only: bool,
361    pub options: std::collections::HashMap<String, String>,
362}
363
364/// Bound IMPORT DATABASE statement.
365#[derive(Debug, Clone)]
366pub struct BoundImportDatabase {
367    pub file_path: String,
368    pub query: String,
369    pub index_query: String,
370}
371
372/// Bound CREATE SEQUENCE statement.
373#[derive(Debug, Clone)]
374pub struct BoundCreateSequence {
375    pub name: String,
376    pub if_not_exists: bool,
377    pub or_replace: bool,
378    pub start_with: i64,
379    pub increment: i64,
380    pub min_value: i64,
381    pub max_value: i64,
382    pub cycle: bool,
383}
384
385/// Bound DROP SEQUENCE statement.
386#[derive(Debug, Clone)]
387pub struct BoundDropSequence {
388    pub name: String,
389    pub if_exists: bool,
390}
391
392/// Bound CREATE MACRO statement.
393#[derive(Debug, Clone)]
394pub struct BoundCreateMacro {
395    pub name: String,
396    pub positional_args: Vec<String>,
397    pub default_args: Vec<(String, String)>,
398    pub expression: String,
399}
400
401/// A node element of a CREATE/MERGE pattern.
402#[derive(Debug, Clone)]
403pub struct BoundNodeCreate {
404    pub variable: Option<String>,
405    pub table_name: String,
406    pub table_id: u64,
407    pub properties: Vec<(String, akar_parser::ast::Expression)>,
408}
409
410/// An edge element of a CREATE/MERGE pattern with resolved endpoints.
411#[derive(Debug, Clone)]
412pub struct BoundEdgeCreate {
413    pub variable: Option<String>,
414    pub table_name: String,
415    pub table_id: u64,
416    pub src_var: String,
417    pub dst_var: String,
418    pub properties: Vec<(String, akar_parser::ast::Expression)>,
419}
420
421/// A single element of a CREATE/MERGE pattern path (node and/or edge).
422#[derive(Debug, Clone)]
423pub struct BoundCreatePattern {
424    pub node: Option<BoundNodeCreate>,
425    pub edge: Option<BoundEdgeCreate>,
426}
427
428/// Bound CREATE DML statement — create nodes and/or relationships.
429#[derive(Debug, Clone)]
430pub struct BoundCreateDml {
431    pub patterns: Vec<BoundCreatePattern>,
432}
433
434/// Bound MERGE statement — match or create a node/relationship pattern.
435#[derive(Debug, Clone)]
436pub struct BoundMerge {
437    pub table_name: String,
438    pub table_id: u64,
439    /// Properties from the primary (first) MERGE pattern node (used for matching and creation).
440    pub properties: Vec<(String, akar_parser::ast::Expression)>,
441    /// All bound patterns (nodes + edges) of the MERGE statement.
442    pub patterns: Vec<BoundCreatePattern>,
443    /// ON CREATE SET items: resolved column info.
444    pub on_create: Vec<BoundSetItem>,
445    /// ON MATCH SET items: resolved column info.
446    pub on_match: Vec<BoundSetItem>,
447}
448
449/// Bound CREATE FTS INDEX statement.
450#[derive(Debug, Clone)]
451pub struct BoundCreateFtsIndex {
452    pub index_name: String,
453    pub table_name: String,
454    pub column_name: String,
455    pub if_not_exists: bool,
456    /// The macro table names that will be created.
457    pub docs_table: String,
458    pub terms_table: String,
459    pub posting_table: String,
460}
461
462/// Bound CREATE TYPE — user-defined type alias.
463#[derive(Debug, Clone)]
464pub struct BoundCreateType {
465    pub name: String,
466    pub type_name: String,
467}
468
469/// Bound COMMENT ON TABLE — table comment.
470#[derive(Debug, Clone)]
471pub struct BoundCommentOnTable {
472    pub table_name: String,
473    pub comment: String,
474}
475
476/// Bound CREATE GRAPH — projected graph.
477#[derive(Debug, Clone)]
478pub struct BoundCreateGraph {
479    pub name: String,
480    pub is_any: bool,
481}
482
483/// Bound USE GRAPH — set graph context.
484#[derive(Debug, Clone)]
485pub struct BoundUseGraph {
486    pub name: String,
487}
488
489/// Bound DROP GRAPH — remove projected graph.
490#[derive(Debug, Clone)]
491pub struct BoundDropGraph {
492    pub name: String,
493}