1#[allow(clippy::wildcard_imports)]
4use super::ast::*;
5use super::lexer::{Lexer, Token, TokenKind};
6use grafeo_common::utils::error::{Error, QueryError, QueryErrorKind, Result, SourceSpan};
7
8fn unescape_string(s: &str) -> String {
10 let mut result = String::with_capacity(s.len());
11 let mut chars = s.chars();
12 while let Some(ch) = chars.next() {
13 if ch == '\\' {
14 match chars.next() {
15 Some('n') => result.push('\n'),
16 Some('r') => result.push('\r'),
17 Some('t') => result.push('\t'),
18 Some('\\') => result.push('\\'),
19 Some('\'') => result.push('\''),
20 Some('"') => result.push('"'),
21 Some(other) => {
22 result.push('\\');
23 result.push(other);
24 }
25 None => result.push('\\'),
26 }
27 } else {
28 result.push(ch);
29 }
30 }
31 result
32}
33
34pub struct Parser<'a> {
36 lexer: Lexer<'a>,
37 current: Token,
38 peeked: Option<Token>,
39 peeked_second: Option<Token>,
40 source: &'a str,
41}
42
43impl<'a> Parser<'a> {
44 pub fn new(input: &'a str) -> Self {
46 let mut lexer = Lexer::new(input);
47 let current = lexer.next_token();
48 Self {
49 lexer,
50 current,
51 peeked: None,
52 peeked_second: None,
53 source: input,
54 }
55 }
56
57 fn is_label_or_type_name(&self) -> bool {
61 matches!(
62 self.current.kind,
63 TokenKind::Identifier
64 | TokenKind::QuotedIdentifier
65 | TokenKind::Node
66 | TokenKind::Edge
67 | TokenKind::Type
68 | TokenKind::Match
69 | TokenKind::Return
70 | TokenKind::Where
71 | TokenKind::And
72 | TokenKind::Or
73 | TokenKind::Not
74 | TokenKind::Insert
75 | TokenKind::Delete
76 | TokenKind::Set
77 | TokenKind::Create
78 | TokenKind::As
79 | TokenKind::Distinct
80 | TokenKind::Order
81 | TokenKind::By
82 | TokenKind::Asc
83 | TokenKind::Desc
84 | TokenKind::Limit
85 | TokenKind::Skip
86 | TokenKind::With
87 | TokenKind::Optional
88 | TokenKind::Null
89 | TokenKind::True
90 | TokenKind::False
91 | TokenKind::In
92 | TokenKind::Is
93 | TokenKind::Like
94 | TokenKind::Case
95 | TokenKind::When
96 | TokenKind::Then
97 | TokenKind::Else
98 | TokenKind::End
99 | TokenKind::Exists
100 | TokenKind::Call
101 | TokenKind::Yield
102 | TokenKind::Detach
103 | TokenKind::Unwind
104 | TokenKind::Merge
105 | TokenKind::On
106 | TokenKind::Starts
107 | TokenKind::Ends
108 | TokenKind::Contains
109 | TokenKind::Nodetach
110 | TokenKind::Fetch
111 | TokenKind::First
112 | TokenKind::Next
113 | TokenKind::Rows
114 | TokenKind::Row
115 | TokenKind::Only
116 )
117 }
118
119 fn is_identifier(&self) -> bool {
121 matches!(
122 self.current.kind,
123 TokenKind::Identifier | TokenKind::QuotedIdentifier
124 ) || self.is_contextual_keyword()
125 }
126
127 fn is_contextual_keyword(&self) -> bool {
130 matches!(
131 self.current.kind,
132 TokenKind::End | TokenKind::Node | TokenKind::Edge | TokenKind::Type | TokenKind::Case | TokenKind::When | TokenKind::Then | TokenKind::Else | TokenKind::In | TokenKind::Is | TokenKind::And | TokenKind::Or | TokenKind::Not | TokenKind::Null | TokenKind::True | TokenKind::False | TokenKind::Vector | TokenKind::Index | TokenKind::Dimension | TokenKind::Metric | TokenKind::Set | TokenKind::All | TokenKind::Filter | TokenKind::Having | TokenKind::Fetch | TokenKind::First | TokenKind::Next | TokenKind::Rows | TokenKind::Row | TokenKind::Only )
163 }
164
165 fn get_identifier_name(&self) -> String {
168 let text = &self.current.text;
169 if self.current.kind == TokenKind::QuotedIdentifier {
170 text[1..text.len() - 1].to_string()
172 } else {
173 text.clone()
174 }
175 }
176
177 pub fn parse(&mut self) -> Result<Statement> {
179 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("EXPLAIN") {
181 self.advance(); let inner = self.parse()?;
183 return Ok(Statement::Explain(Box::new(inner)));
184 }
185 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("PROFILE") {
186 self.advance(); let inner = self.parse()?;
188 return Ok(Statement::Profile(Box::new(inner)));
189 }
190
191 let mut left = self.parse_single_statement()?;
192
193 while self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("NEXT") {
195 self.advance(); let right = self.parse_single_statement()?;
197 left = Statement::CompositeQuery {
200 left: Box::new(left),
201 op: CompositeOp::Next,
202 right: Box::new(right),
203 };
204 }
205
206 while matches!(
208 self.current.kind,
209 TokenKind::Union | TokenKind::Except | TokenKind::Intersect | TokenKind::Otherwise
210 ) {
211 let op = match self.current.kind {
212 TokenKind::Union => {
213 self.advance();
214 if self.current.kind == TokenKind::All {
215 self.advance();
216 CompositeOp::UnionAll
217 } else {
218 if self.current.kind == TokenKind::Distinct {
220 self.advance();
221 }
222 CompositeOp::Union
223 }
224 }
225 TokenKind::Except => {
226 self.advance();
227 if self.current.kind == TokenKind::All {
228 self.advance();
229 CompositeOp::ExceptAll
230 } else {
231 if self.current.kind == TokenKind::Distinct {
233 self.advance();
234 }
235 CompositeOp::Except
236 }
237 }
238 TokenKind::Intersect => {
239 self.advance();
240 if self.current.kind == TokenKind::All {
241 self.advance();
242 CompositeOp::IntersectAll
243 } else {
244 if self.current.kind == TokenKind::Distinct {
246 self.advance();
247 }
248 CompositeOp::Intersect
249 }
250 }
251 TokenKind::Otherwise => {
252 self.advance();
253 CompositeOp::Otherwise
254 }
255 _ => unreachable!(),
256 };
257 let right = self.parse_single_statement()?;
258 left = Statement::CompositeQuery {
259 left: Box::new(left),
260 op,
261 right: Box::new(right),
262 };
263 }
264
265 Ok(left)
266 }
267
268 fn parse_single_statement(&mut self) -> Result<Statement> {
269 match self.current.kind {
270 TokenKind::Match
271 | TokenKind::Optional
272 | TokenKind::Unwind
273 | TokenKind::Merge
274 | TokenKind::For
275 | TokenKind::Return => self.parse_query().map(Statement::Query),
276 TokenKind::Insert => self
277 .parse_insert()
278 .map(|s| Statement::DataModification(DataModificationStatement::Insert(s))),
279 TokenKind::Delete | TokenKind::Detach | TokenKind::Nodetach => self
280 .parse_delete()
281 .map(|s| Statement::DataModification(DataModificationStatement::Delete(s))),
282 TokenKind::Create => {
283 let next = self.peek_kind();
285 if next == TokenKind::LParen {
286 self.parse_create_as_insert()
288 .map(|s| Statement::DataModification(DataModificationStatement::Insert(s)))
289 } else {
290 self.parse_create_dispatch()
293 }
294 }
295 TokenKind::Call => {
296 if self.peek_kind() == TokenKind::LBrace {
297 self.parse_query().map(Statement::Query)
299 } else {
300 self.parse_call_statement().map(Statement::Call)
301 }
302 }
303 _ if self.is_identifier() => {
304 let name = self.get_identifier_name();
305 match name.to_uppercase().as_str() {
306 "DROP" => self.parse_drop(),
307 "USE" => self.parse_use_graph().map(Statement::SessionCommand),
308 "SESSION" => self.parse_session_command().map(Statement::SessionCommand),
309 "START" => self
310 .parse_start_transaction()
311 .map(Statement::SessionCommand),
312 "COMMIT" => {
313 self.advance();
314 Ok(Statement::SessionCommand(SessionCommand::Commit))
315 }
316 "ROLLBACK" => {
317 self.advance();
318 if self.is_identifier()
320 && self.get_identifier_name().eq_ignore_ascii_case("TO")
321 {
322 self.advance(); if !(self.is_identifier()
324 && self.get_identifier_name().eq_ignore_ascii_case("SAVEPOINT"))
325 {
326 return Err(self.error("Expected SAVEPOINT after ROLLBACK TO"));
327 }
328 self.advance(); let name = self.get_identifier_name();
330 self.advance(); Ok(Statement::SessionCommand(
332 SessionCommand::RollbackToSavepoint(name),
333 ))
334 } else {
335 Ok(Statement::SessionCommand(SessionCommand::Rollback))
336 }
337 }
338 "SAVEPOINT" => {
339 self.advance();
340 let name = self.get_identifier_name();
341 self.advance();
342 Ok(Statement::SessionCommand(SessionCommand::Savepoint(name)))
343 }
344 "RELEASE" => {
345 self.advance();
346 if !(self.is_identifier()
347 && self.get_identifier_name().eq_ignore_ascii_case("SAVEPOINT"))
348 {
349 return Err(self.error("Expected SAVEPOINT after RELEASE"));
350 }
351 self.advance(); let name = self.get_identifier_name();
353 self.advance();
354 Ok(Statement::SessionCommand(SessionCommand::ReleaseSavepoint(
355 name,
356 )))
357 }
358 "ALTER" => self.parse_alter(),
359 "SHOW" => self.parse_show().map(Statement::Schema),
360 "LOAD" => self.parse_query().map(Statement::Query),
361 _ => Err(self.error(
362 "Expected MATCH, INSERT, DELETE, MERGE, UNWIND, FOR, CREATE, CALL, \
363 DROP, ALTER, SHOW, LOAD, USE, SESSION, START, COMMIT, ROLLBACK, or SAVEPOINT",
364 )),
365 }
366 }
367 _ => Err(self.error(
368 "Expected MATCH, INSERT, DELETE, MERGE, UNWIND, FOR, CREATE, CALL, \
369 DROP, SHOW, LOAD, USE, SESSION, START, COMMIT, or ROLLBACK",
370 )),
371 }
372 }
373
374 fn parse_call_statement(&mut self) -> Result<CallStatement> {
380 let span_start = self.current.span.start;
381 self.expect(TokenKind::Call)?;
382
383 if !self.is_identifier() {
385 return Err(self.error("Expected procedure name after CALL"));
386 }
387 let mut name_parts = vec![self.get_identifier_name()];
388 self.advance();
389 while self.current.kind == TokenKind::Dot {
390 self.advance();
391 if !self.is_identifier() {
392 return Err(self.error("Expected identifier after '.'"));
393 }
394 name_parts.push(self.get_identifier_name());
395 self.advance();
396 }
397
398 self.expect(TokenKind::LParen)?;
400 let mut arguments = Vec::new();
401 if self.current.kind != TokenKind::RParen {
402 arguments.push(self.parse_expression()?);
403 while self.current.kind == TokenKind::Comma {
404 self.advance();
405 arguments.push(self.parse_expression()?);
406 }
407 }
408 self.expect(TokenKind::RParen)?;
409
410 let yield_items = if self.current.kind == TokenKind::Yield {
412 self.advance();
413 Some(self.parse_yield_list()?)
414 } else {
415 None
416 };
417
418 let where_clause = if yield_items.is_some() && self.current.kind == TokenKind::Where {
420 Some(self.parse_where_clause()?)
421 } else {
422 None
423 };
424
425 let return_clause = if yield_items.is_some() && self.current.kind == TokenKind::Return {
427 Some(self.parse_return_clause()?)
428 } else {
429 None
430 };
431
432 Ok(CallStatement {
433 procedure_name: name_parts,
434 arguments,
435 yield_items,
436 where_clause,
437 return_clause,
438 span: Some(SourceSpan::new(span_start, self.current.span.start, 1, 1)),
439 })
440 }
441
442 fn parse_inline_call(&mut self) -> Result<QueryStatement> {
448 self.expect(TokenKind::Call)?;
449 self.expect(TokenKind::LBrace)?;
450
451 let inner = self.parse_query()?;
453
454 self.expect(TokenKind::RBrace)?;
455 Ok(inner)
456 }
457
458 fn parse_yield_list(&mut self) -> Result<Vec<YieldItem>> {
460 let mut items = vec![self.parse_yield_item()?];
461 while self.current.kind == TokenKind::Comma {
462 self.advance();
463 items.push(self.parse_yield_item()?);
464 }
465 Ok(items)
466 }
467
468 fn parse_yield_item(&mut self) -> Result<YieldItem> {
470 let span_start = self.current.span.start;
471 if !self.is_identifier() {
472 return Err(self.error("Expected field name in YIELD"));
473 }
474 let field_name = self.get_identifier_name();
475 self.advance();
476 let alias = if self.current.kind == TokenKind::As {
477 self.advance();
478 if !self.is_identifier() {
479 return Err(self.error("Expected alias after AS"));
480 }
481 let alias_name = self.get_identifier_name();
482 self.advance();
483 Some(alias_name)
484 } else {
485 None
486 };
487 Ok(YieldItem {
488 field_name,
489 alias,
490 span: Some(SourceSpan::new(span_start, self.current.span.start, 1, 1)),
491 })
492 }
493
494 fn parse_query(&mut self) -> Result<QueryStatement> {
495 let span_start = self.current.span.start;
496
497 let mut match_clauses = Vec::new();
498 let mut unwind_clauses = Vec::new();
499 let mut merge_clauses = Vec::new();
500 let mut create_clauses = Vec::new();
501 let mut delete_clauses = Vec::new();
502 let mut ordered_clauses = Vec::new();
503
504 loop {
508 match self.current.kind {
509 TokenKind::Match => {
510 let clause = self.parse_match_clause()?;
511 ordered_clauses.push(QueryClause::Match(clause.clone()));
512 match_clauses.push(clause);
513 }
514 TokenKind::Optional => {
515 let pk = self.peek_kind();
517 if pk == TokenKind::Call {
518 self.advance(); if self.peek_kind() == TokenKind::LBrace {
520 let subquery = self.parse_inline_call()?;
522 ordered_clauses.push(QueryClause::InlineCall {
523 subquery,
524 optional: true,
525 });
526 } else {
527 let call = self.parse_call_statement()?;
529 ordered_clauses.push(QueryClause::CallProcedure(call));
530 }
531 } else {
532 let clause = self.parse_match_clause()?;
533 ordered_clauses.push(QueryClause::Match(clause.clone()));
534 match_clauses.push(clause);
535 }
536 }
537 TokenKind::Unwind => {
538 let clause = self.parse_unwind_clause()?;
539 ordered_clauses.push(QueryClause::Unwind(clause.clone()));
540 unwind_clauses.push(clause);
541 }
542 TokenKind::For => {
543 let clause = self.parse_for_clause()?;
544 ordered_clauses.push(QueryClause::For(clause.clone()));
545 unwind_clauses.push(clause);
546 }
547 TokenKind::Merge => {
548 let clause = self.parse_merge_clause()?;
549 ordered_clauses.push(QueryClause::Merge(clause.clone()));
550 merge_clauses.push(clause);
551 }
552 TokenKind::Create => {
553 let clause = self.parse_create_clause_in_query()?;
554 ordered_clauses.push(QueryClause::Create(clause.clone()));
555 create_clauses.push(clause);
556 }
557 TokenKind::Insert => {
558 let clause = self.parse_insert()?;
559 ordered_clauses.push(QueryClause::Create(clause.clone()));
560 create_clauses.push(clause);
561 }
562 TokenKind::Delete | TokenKind::Detach | TokenKind::Nodetach => {
563 let clause = self.parse_delete_clause_in_query()?;
564 ordered_clauses.push(QueryClause::Delete(clause.clone()));
565 delete_clauses.push(clause);
566 }
567 TokenKind::Call => {
568 if self.peek_kind() == TokenKind::LBrace {
570 let subquery = self.parse_inline_call()?;
571 ordered_clauses.push(QueryClause::InlineCall {
572 subquery,
573 optional: false,
574 });
575 } else {
576 let call = self.parse_call_statement()?;
577 ordered_clauses.push(QueryClause::CallProcedure(call));
578 }
579 }
580 _ if self.is_identifier()
581 && self.get_identifier_name().eq_ignore_ascii_case("LET") =>
582 {
583 let bindings = self.parse_let_clause()?;
584 ordered_clauses.push(QueryClause::Let(bindings));
585 }
586 _ if self.is_identifier()
587 && self.get_identifier_name().eq_ignore_ascii_case("LOAD") =>
588 {
589 let clause = self.parse_load_data_clause()?;
590 ordered_clauses.push(QueryClause::LoadData(clause));
591 }
592 _ => break,
593 }
594 }
595
596 let where_clause = if matches!(self.current.kind, TokenKind::Where | TokenKind::Filter) {
598 Some(self.parse_where_or_filter_clause()?)
599 } else {
600 None
601 };
602
603 loop {
605 match self.current.kind {
606 TokenKind::Create => {
607 let clause = self.parse_create_clause_in_query()?;
608 ordered_clauses.push(QueryClause::Create(clause.clone()));
609 create_clauses.push(clause);
610 }
611 TokenKind::Insert => {
612 let clause = self.parse_insert()?;
613 ordered_clauses.push(QueryClause::Create(clause.clone()));
614 create_clauses.push(clause);
615 }
616 TokenKind::Delete | TokenKind::Detach | TokenKind::Nodetach => {
617 let clause = self.parse_delete_clause_in_query()?;
618 ordered_clauses.push(QueryClause::Delete(clause.clone()));
619 delete_clauses.push(clause);
620 }
621 _ => break,
622 }
623 }
624
625 let mut set_clauses = Vec::new();
627 while self.current.kind == TokenKind::Set {
628 let clause = self.parse_set_clause()?;
629 ordered_clauses.push(QueryClause::Set(clause.clone()));
630 set_clauses.push(clause);
631 }
632
633 let mut remove_clauses = Vec::new();
635 while self.current.kind == TokenKind::Remove {
636 remove_clauses.push(self.parse_remove_clause()?);
637 }
638
639 let mut with_clauses = Vec::new();
641 while self.current.kind == TokenKind::With {
642 let mut wc = self.parse_with_clause()?;
643
644 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("LET") {
646 wc.let_bindings = self.parse_let_clause()?;
647 }
648
649 with_clauses.push(wc);
650
651 loop {
653 match self.current.kind {
654 TokenKind::Match | TokenKind::Optional => {
655 let clause = self.parse_match_clause()?;
656 ordered_clauses.push(QueryClause::Match(clause.clone()));
657 match_clauses.push(clause);
658 }
659 TokenKind::Unwind => {
660 let clause = self.parse_unwind_clause()?;
661 ordered_clauses.push(QueryClause::Unwind(clause.clone()));
662 unwind_clauses.push(clause);
663 }
664 TokenKind::For => {
665 let clause = self.parse_for_clause()?;
666 ordered_clauses.push(QueryClause::For(clause.clone()));
667 unwind_clauses.push(clause);
668 }
669 TokenKind::Merge => {
670 let clause = self.parse_merge_clause()?;
671 ordered_clauses.push(QueryClause::Merge(clause.clone()));
672 merge_clauses.push(clause);
673 }
674 _ => break,
675 }
676 }
677 }
678
679 let return_clause = if self.current.kind == TokenKind::Return {
681 self.parse_return_clause()?
682 } else if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("FINISH")
683 {
684 self.advance();
686 ReturnClause {
687 distinct: false,
688 items: Vec::new(),
689 is_wildcard: false,
690 group_by: Vec::new(),
691 order_by: None,
692 skip: None,
693 limit: None,
694 is_finish: true,
695 span: None,
696 }
697 } else if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("SELECT")
698 {
699 self.advance(); self.parse_select_clause()?
702 } else if !set_clauses.is_empty()
703 || !remove_clauses.is_empty()
704 || !merge_clauses.is_empty()
705 || !create_clauses.is_empty()
706 || !delete_clauses.is_empty()
707 {
708 ReturnClause {
710 distinct: false,
711 items: Vec::new(),
712 is_wildcard: false,
713 group_by: Vec::new(),
714 order_by: None,
715 skip: None,
716 limit: None,
717 is_finish: false,
718 span: None,
719 }
720 } else {
721 return Err(self.error("Expected RETURN, FINISH, or SELECT"));
722 };
723
724 let having_clause = if self.current.kind == TokenKind::Having {
726 Some(self.parse_having_clause()?)
727 } else {
728 None
729 };
730
731 Ok(QueryStatement {
732 match_clauses,
733 where_clause,
734 set_clauses,
735 remove_clauses,
736 with_clauses,
737 unwind_clauses,
738 merge_clauses,
739 create_clauses,
740 delete_clauses,
741 return_clause,
742 having_clause,
743 ordered_clauses,
744 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
745 })
746 }
747
748 fn parse_for_clause(&mut self) -> Result<UnwindClause> {
751 let span_start = self.current.span.start;
752 self.expect(TokenKind::For)?;
753
754 if !self.is_identifier() {
756 return Err(self.error("Expected variable name after FOR"));
757 }
758 let alias = self.get_identifier_name();
759 self.advance();
760
761 self.expect(TokenKind::In)?;
763
764 let expression = self.parse_expression()?;
766
767 let (ordinality_var, offset_var) = if self.current.kind == TokenKind::With {
769 self.advance(); if self.current.kind == TokenKind::Ordinality {
771 self.advance(); if !self.is_identifier() {
773 return Err(self.error("Expected variable name after ORDINALITY"));
774 }
775 let var = self.get_identifier_name();
776 self.advance();
777 (Some(var), None)
778 } else if self.current.kind == TokenKind::Offset {
779 self.advance(); if !self.is_identifier() {
781 return Err(self.error("Expected variable name after OFFSET"));
782 }
783 let var = self.get_identifier_name();
784 self.advance();
785 (None, Some(var))
786 } else {
787 return Err(self.error("Expected ORDINALITY or OFFSET after WITH"));
788 }
789 } else {
790 (None, None)
791 };
792
793 Ok(UnwindClause {
794 expression,
795 alias,
796 ordinality_var,
797 offset_var,
798 span: Some(SourceSpan::new(span_start, self.current.span.start, 1, 1)),
799 })
800 }
801
802 fn parse_set_clause(&mut self) -> Result<SetClause> {
803 let span_start = self.current.span.start;
804 self.expect(TokenKind::Set)?;
805
806 let mut assignments = Vec::new();
807 let mut map_assignments = Vec::new();
808 let mut label_operations = Vec::new();
809
810 loop {
811 if !self.is_identifier() {
813 return Err(self.error("Expected variable name in SET"));
814 }
815 let variable = self.current.text.clone();
816 self.advance();
817
818 if self.current.kind == TokenKind::Colon {
821 let mut labels = Vec::new();
823 while self.current.kind == TokenKind::Colon {
824 self.advance();
825 if !self.is_label_or_type_name() {
826 return Err(self.error("Expected label name after colon in SET"));
827 }
828 labels.push(self.current.text.clone());
829 self.advance();
830 }
831 label_operations.push(LabelOperation { variable, labels });
832 } else if self.current.kind == TokenKind::Dot {
833 self.advance();
835
836 if !self.is_label_or_type_name() {
837 return Err(self.error("Expected property name in SET"));
838 }
839 let property = self.current.text.clone();
840 self.advance();
841
842 self.expect(TokenKind::Eq)?;
843
844 let value = self.parse_expression()?;
845
846 assignments.push(PropertyAssignment {
847 variable,
848 property,
849 value,
850 });
851 } else if self.current.kind == TokenKind::Eq {
852 self.advance();
854 let map_expr = self.parse_expression()?;
855 map_assignments.push(MapAssignment {
856 variable,
857 map_expr,
858 replace: true,
859 });
860 } else if self.current.kind == TokenKind::Plus {
861 self.advance();
863 self.expect(TokenKind::Eq)?;
864 let map_expr = self.parse_expression()?;
865 map_assignments.push(MapAssignment {
866 variable,
867 map_expr,
868 replace: false,
869 });
870 } else {
871 return Err(self.error("Expected '.', ':', '=', or '+=' after variable in SET"));
872 }
873
874 if self.current.kind != TokenKind::Comma {
876 break;
877 }
878 self.advance();
879 }
880
881 Ok(SetClause {
882 assignments,
883 map_assignments,
884 label_operations,
885 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
886 })
887 }
888
889 fn parse_remove_clause(&mut self) -> Result<RemoveClause> {
890 let span_start = self.current.span.start;
891 self.expect(TokenKind::Remove)?;
892
893 let mut label_operations = Vec::new();
894 let mut property_removals = Vec::new();
895
896 loop {
897 if !self.is_identifier() {
899 return Err(self.error("Expected variable name in REMOVE"));
900 }
901 let variable = self.current.text.clone();
902 self.advance();
903
904 if self.current.kind == TokenKind::Colon {
906 let mut labels = Vec::new();
908 while self.current.kind == TokenKind::Colon {
909 self.advance();
910 if !self.is_label_or_type_name() {
911 return Err(self.error("Expected label name after colon in REMOVE"));
912 }
913 labels.push(self.current.text.clone());
914 self.advance();
915 }
916 label_operations.push(LabelOperation { variable, labels });
917 } else if self.current.kind == TokenKind::Dot {
918 self.advance();
920
921 if !self.is_label_or_type_name() {
922 return Err(self.error("Expected property name in REMOVE"));
923 }
924 let property = self.current.text.clone();
925 self.advance();
926
927 property_removals.push((variable, property));
928 } else {
929 return Err(self.error("Expected '.' or ':' after variable in REMOVE"));
930 }
931
932 if self.current.kind != TokenKind::Comma {
934 break;
935 }
936 self.advance();
937 }
938
939 Ok(RemoveClause {
940 label_operations,
941 property_removals,
942 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
943 })
944 }
945
946 fn parse_unwind_clause(&mut self) -> Result<UnwindClause> {
947 let span_start = self.current.span.start;
948 self.expect(TokenKind::Unwind)?;
949
950 let expression = self.parse_expression()?;
952
953 self.expect(TokenKind::As)?;
955
956 if !self.is_identifier() {
958 return Err(self.error("Expected alias after AS in UNWIND"));
959 }
960 let alias = self.get_identifier_name();
961 self.advance();
962
963 Ok(UnwindClause {
964 expression,
965 alias,
966 ordinality_var: None,
967 offset_var: None,
968 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
969 })
970 }
971
972 fn parse_let_clause(&mut self) -> Result<Vec<(String, Expression)>> {
974 self.advance(); let mut bindings = Vec::new();
976 loop {
977 if !self.is_identifier() {
978 return Err(self.error("Expected variable name in LET clause"));
979 }
980 let var = self.get_identifier_name();
981 self.advance();
982 self.expect(TokenKind::Eq)?;
983 let expr = self.parse_expression()?;
984 bindings.push((var, expr));
985 if self.current.kind != TokenKind::Comma {
986 break;
987 }
988 self.advance(); }
990 Ok(bindings)
991 }
992
993 fn parse_load_data_clause(&mut self) -> Result<LoadDataClause> {
996 let span_start = self.current.span.start;
997 self.advance(); if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("CSV") {
1001 return self.parse_load_csv_compat(span_start);
1002 }
1003
1004 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("DATA") {
1006 return Err(self.error("Expected DATA or CSV after LOAD"));
1007 }
1008 self.advance(); if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("FROM") {
1012 return Err(self.error("Expected FROM after DATA in LOAD DATA"));
1013 }
1014 self.advance(); let path = self.parse_string_value()?;
1016
1017 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("FORMAT") {
1019 return Err(self.error("Expected FORMAT after file path in LOAD DATA"));
1020 }
1021 self.advance(); let format = if self.is_identifier() {
1024 let name = self.get_identifier_name();
1025 self.advance();
1026 match name.to_ascii_uppercase().as_str() {
1027 "CSV" => LoadFormat::Csv,
1028 "JSONL" | "NDJSON" => LoadFormat::Jsonl,
1029 "PARQUET" => LoadFormat::Parquet,
1030 _ => {
1031 return Err(self.error(&format!(
1032 "Unknown format '{name}', expected CSV, JSONL, or PARQUET"
1033 )));
1034 }
1035 }
1036 } else {
1037 return Err(self.error("Expected format name (CSV, JSONL, or PARQUET)"));
1038 };
1039
1040 let with_headers = if self.current.kind == TokenKind::With {
1042 self.advance();
1043 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("HEADERS")
1044 {
1045 return Err(self.error("Expected HEADERS after WITH in LOAD DATA"));
1046 }
1047 self.advance();
1048 true
1049 } else {
1050 false
1051 };
1052
1053 self.expect(TokenKind::As)?;
1055 if !self.is_identifier() {
1056 return Err(self.error("Expected variable name after AS in LOAD DATA"));
1057 }
1058 let variable = self.get_identifier_name();
1059 self.advance();
1060
1061 let field_terminator = self.parse_optional_field_terminator()?;
1063
1064 Ok(LoadDataClause {
1065 path,
1066 format,
1067 with_headers,
1068 variable,
1069 field_terminator,
1070 span: SourceSpan::new(span_start, self.current.span.end, 1, 1),
1071 })
1072 }
1073
1074 fn parse_load_csv_compat(&mut self, span_start: usize) -> Result<LoadDataClause> {
1076 self.advance(); let with_headers = if self.current.kind == TokenKind::With {
1080 self.advance();
1081 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("HEADERS")
1082 {
1083 return Err(self.error("Expected HEADERS after WITH"));
1084 }
1085 self.advance();
1086 true
1087 } else {
1088 false
1089 };
1090
1091 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("FROM") {
1093 return Err(self.error("Expected FROM after WITH HEADERS or CSV"));
1094 }
1095 self.advance(); let path = self.parse_string_value()?;
1097
1098 self.expect(TokenKind::As)?;
1100 if !self.is_identifier() {
1101 return Err(self.error("Expected variable name after AS"));
1102 }
1103 let variable = self.get_identifier_name();
1104 self.advance();
1105
1106 let field_terminator = self.parse_optional_field_terminator()?;
1108
1109 Ok(LoadDataClause {
1110 path,
1111 format: LoadFormat::Csv,
1112 with_headers,
1113 variable,
1114 field_terminator,
1115 span: SourceSpan::new(span_start, self.current.span.end, 1, 1),
1116 })
1117 }
1118
1119 fn parse_string_value(&mut self) -> Result<String> {
1121 if self.current.kind != TokenKind::String {
1122 return Err(self.error("Expected string literal"));
1123 }
1124 let text = &self.current.text;
1125 let inner = &text[1..text.len() - 1];
1126 let value = unescape_string(inner);
1127 self.advance();
1128 Ok(value)
1129 }
1130
1131 fn parse_optional_field_terminator(&mut self) -> Result<Option<char>> {
1133 if self.is_identifier()
1134 && self
1135 .get_identifier_name()
1136 .eq_ignore_ascii_case("FIELDTERMINATOR")
1137 {
1138 self.advance();
1139 let term = self.parse_string_value()?;
1140 Ok(term.chars().next())
1141 } else {
1142 Ok(None)
1143 }
1144 }
1145
1146 fn parse_merge_clause(&mut self) -> Result<MergeClause> {
1147 let span_start = self.current.span.start;
1148 self.expect(TokenKind::Merge)?;
1149
1150 let pattern = self.parse_pattern()?;
1152
1153 let mut on_create = None;
1155 let mut on_match = None;
1156
1157 while self.current.kind == TokenKind::On {
1158 self.advance();
1159
1160 if self.current.kind == TokenKind::Create {
1161 self.advance();
1162 self.expect(TokenKind::Set)?;
1163 on_create = Some(self.parse_property_assignments()?);
1164 } else if self.current.kind == TokenKind::Match {
1165 self.advance();
1166 self.expect(TokenKind::Set)?;
1167 on_match = Some(self.parse_property_assignments()?);
1168 } else {
1169 return Err(self.error("Expected CREATE or MATCH after ON in MERGE"));
1170 }
1171 }
1172
1173 Ok(MergeClause {
1174 pattern,
1175 on_create,
1176 on_match,
1177 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
1178 })
1179 }
1180
1181 fn parse_property_assignments(&mut self) -> Result<Vec<PropertyAssignment>> {
1182 let mut assignments = Vec::new();
1183 loop {
1184 if !self.is_identifier() {
1186 return Err(self.error("Expected variable name"));
1187 }
1188 let variable = self.get_identifier_name();
1189 self.advance();
1190
1191 self.expect(TokenKind::Dot)?;
1192
1193 if !self.is_label_or_type_name() {
1194 return Err(self.error("Expected property name"));
1195 }
1196 let property = self.get_identifier_name();
1197 self.advance();
1198
1199 self.expect(TokenKind::Eq)?;
1200
1201 let value = self.parse_expression()?;
1202
1203 assignments.push(PropertyAssignment {
1204 variable,
1205 property,
1206 value,
1207 });
1208
1209 if self.current.kind != TokenKind::Comma {
1211 break;
1212 }
1213 self.advance();
1214 }
1215
1216 Ok(assignments)
1217 }
1218
1219 fn parse_match_clause(&mut self) -> Result<MatchClause> {
1220 let span_start = self.current.span.start;
1221
1222 let optional = if self.current.kind == TokenKind::Optional {
1224 self.advance();
1225 true
1226 } else {
1227 false
1228 };
1229
1230 self.expect(TokenKind::Match)?;
1231
1232 let path_mode = match self.current.kind {
1234 TokenKind::Walk => {
1235 self.advance();
1236 Some(PathMode::Walk)
1237 }
1238 TokenKind::Trail => {
1239 self.advance();
1240 Some(PathMode::Trail)
1241 }
1242 TokenKind::Simple => {
1243 self.advance();
1244 Some(PathMode::Simple)
1245 }
1246 TokenKind::Acyclic => {
1247 self.advance();
1248 Some(PathMode::Acyclic)
1249 }
1250 _ => None,
1251 };
1252
1253 let match_mode = if self.is_identifier()
1255 && self.get_identifier_name().eq_ignore_ascii_case("DIFFERENT")
1256 {
1257 self.advance(); if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("EDGES") {
1260 self.advance();
1261 }
1262 Some(MatchMode::DifferentEdges)
1263 } else if self.is_identifier()
1264 && self
1265 .get_identifier_name()
1266 .eq_ignore_ascii_case("REPEATABLE")
1267 {
1268 self.advance(); if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("ELEMENTS") {
1271 self.advance();
1272 }
1273 Some(MatchMode::RepeatableElements)
1274 } else {
1275 None
1276 };
1277
1278 let search_prefix = self.parse_path_search_prefix()?;
1280
1281 let mut patterns = Vec::new();
1282 patterns.push(self.parse_aliased_pattern()?);
1283
1284 while self.current.kind == TokenKind::Comma {
1285 self.advance();
1286 patterns.push(self.parse_aliased_pattern()?);
1287 }
1288
1289 Ok(MatchClause {
1290 optional,
1291 path_mode,
1292 search_prefix,
1293 match_mode,
1294 patterns,
1295 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
1296 })
1297 }
1298
1299 fn parse_path_search_prefix(&mut self) -> Result<Option<PathSearchPrefix>> {
1308 if self.current.kind == TokenKind::All {
1309 let next = self.peek_kind();
1310 if next == TokenKind::Shortest {
1311 self.advance(); self.advance(); return Ok(Some(PathSearchPrefix::AllShortest));
1315 }
1316 if next == TokenKind::LParen {
1317 self.advance(); return Ok(Some(PathSearchPrefix::All));
1320 }
1321 }
1322 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("ANY") {
1323 let next = self.peek_kind();
1324 if next == TokenKind::Shortest {
1325 self.advance(); self.advance(); return Ok(Some(PathSearchPrefix::AnyShortest));
1329 }
1330 if next == TokenKind::Integer {
1331 self.advance(); let k: usize = self.current.text.parse().unwrap_or(1);
1334 self.advance(); return Ok(Some(PathSearchPrefix::AnyK(k)));
1336 }
1337 if next == TokenKind::LParen {
1338 self.advance(); return Ok(Some(PathSearchPrefix::Any));
1341 }
1342 }
1343 if self.current.kind == TokenKind::Shortest {
1344 self.advance(); if self.current.kind == TokenKind::Integer {
1346 let k: usize = self.current.text.parse().unwrap_or(1);
1347 self.advance(); if self.current.kind == TokenKind::Groups {
1349 self.advance(); return Ok(Some(PathSearchPrefix::ShortestKGroups(k)));
1351 }
1352 return Ok(Some(PathSearchPrefix::ShortestK(k)));
1353 }
1354 return Ok(Some(PathSearchPrefix::ShortestK(1)));
1356 }
1357 Ok(None)
1358 }
1359
1360 fn parse_aliased_pattern(&mut self) -> Result<AliasedPattern> {
1363 let mut alias = None;
1364 let mut path_function = None;
1365
1366 if self.is_identifier() && self.peek_kind() == TokenKind::Eq {
1368 alias = Some(self.get_identifier_name());
1369 self.advance(); self.advance(); if self.is_identifier() {
1374 let func_name = self.get_identifier_name().to_lowercase();
1375 if func_name == "shortestpath" {
1376 path_function = Some(PathFunction::ShortestPath);
1377 self.advance(); self.expect(TokenKind::LParen)?;
1379 } else if func_name == "allshortestpaths" {
1380 path_function = Some(PathFunction::AllShortestPaths);
1381 self.advance(); self.expect(TokenKind::LParen)?;
1383 }
1384 }
1385 }
1386
1387 let pattern = self.parse_pattern()?;
1388
1389 if path_function.is_some() {
1390 self.expect(TokenKind::RParen)?;
1391 }
1392
1393 let keep =
1395 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("KEEP") {
1396 self.advance(); if self.is_identifier() {
1398 let mode_name = self.get_identifier_name().to_uppercase();
1399 match mode_name.as_str() {
1400 "DIFFERENT" => {
1401 self.advance();
1402 if self.is_identifier()
1404 && self.get_identifier_name().eq_ignore_ascii_case("EDGES")
1405 {
1406 self.advance();
1407 }
1408 Some(MatchMode::DifferentEdges)
1409 }
1410 "REPEATABLE" => {
1411 self.advance();
1412 if self.is_identifier()
1414 && self.get_identifier_name().eq_ignore_ascii_case("ELEMENTS")
1415 {
1416 self.advance();
1417 }
1418 Some(MatchMode::RepeatableElements)
1419 }
1420 _ => return Err(self.error("Expected DIFFERENT or REPEATABLE after KEEP")),
1421 }
1422 } else {
1423 return Err(self.error("Expected DIFFERENT or REPEATABLE after KEEP"));
1424 }
1425 } else {
1426 None
1427 };
1428
1429 Ok(AliasedPattern {
1430 alias,
1431 path_function,
1432 keep,
1433 pattern,
1434 })
1435 }
1436
1437 fn parse_with_clause(&mut self) -> Result<WithClause> {
1438 let span_start = self.current.span.start;
1439 self.expect(TokenKind::With)?;
1440
1441 let distinct = if self.current.kind == TokenKind::Distinct {
1442 self.advance();
1443 true
1444 } else {
1445 false
1446 };
1447
1448 let is_wildcard = if self.current.kind == TokenKind::Star {
1450 self.advance();
1451 true
1452 } else {
1453 false
1454 };
1455
1456 let mut items = Vec::new();
1457 if !is_wildcard {
1458 items.push(self.parse_return_item()?);
1459
1460 while self.current.kind == TokenKind::Comma {
1461 self.advance();
1462 items.push(self.parse_return_item()?);
1463 }
1464 }
1465
1466 let where_clause = if self.current.kind == TokenKind::Where {
1468 Some(self.parse_where_clause()?)
1469 } else {
1470 None
1471 };
1472
1473 Ok(WithClause {
1474 distinct,
1475 items,
1476 is_wildcard,
1477 where_clause,
1478 let_bindings: Vec::new(),
1479 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
1480 })
1481 }
1482
1483 fn parse_pattern(&mut self) -> Result<Pattern> {
1484 if self.current.kind == TokenKind::LParen {
1489 let peek = self.peek_kind();
1490 if matches!(
1491 peek,
1492 TokenKind::LParen
1493 | TokenKind::Walk
1494 | TokenKind::Trail
1495 | TokenKind::Simple
1496 | TokenKind::Acyclic
1497 ) {
1498 return self.parse_parenthesized_pattern();
1499 }
1500 if matches!(peek, TokenKind::Identifier | TokenKind::QuotedIdentifier)
1502 && self.peek_second_kind() == TokenKind::Eq
1503 {
1504 return self.parse_parenthesized_pattern();
1505 }
1506 }
1507
1508 let node = self.parse_node_pattern()?;
1509
1510 if matches!(
1513 self.current.kind,
1514 TokenKind::Arrow
1515 | TokenKind::LeftArrow
1516 | TokenKind::DoubleDash
1517 | TokenKind::Minus
1518 | TokenKind::Tilde
1519 ) {
1520 let mut edges = Vec::new();
1521
1522 while matches!(
1523 self.current.kind,
1524 TokenKind::Arrow
1525 | TokenKind::LeftArrow
1526 | TokenKind::DoubleDash
1527 | TokenKind::Minus
1528 | TokenKind::Tilde
1529 ) {
1530 edges.push(self.parse_edge_pattern()?);
1531 }
1532
1533 Ok(Pattern::Path(PathPattern {
1534 source: node,
1535 edges,
1536 span: None,
1537 }))
1538 } else {
1539 Ok(Pattern::Node(node))
1540 }
1541 }
1542
1543 fn parse_parenthesized_pattern(&mut self) -> Result<Pattern> {
1553 self.expect(TokenKind::LParen)?;
1554
1555 let path_mode = match self.current.kind {
1557 TokenKind::Walk => {
1558 self.advance();
1559 Some(PathMode::Walk)
1560 }
1561 TokenKind::Trail => {
1562 self.advance();
1563 Some(PathMode::Trail)
1564 }
1565 TokenKind::Simple => {
1566 self.advance();
1567 Some(PathMode::Simple)
1568 }
1569 TokenKind::Acyclic => {
1570 self.advance();
1571 Some(PathMode::Acyclic)
1572 }
1573 _ => None,
1574 };
1575
1576 let subpath_var = if self.is_identifier() && self.peek_kind() == TokenKind::Eq {
1580 let name = self.get_identifier_name();
1581 self.advance(); self.advance(); Some(name)
1584 } else {
1585 None
1586 };
1587
1588 let mut patterns = vec![self.parse_pattern()?];
1590 let mut is_multiset = false;
1591 while self.current.kind == TokenKind::Pipe || self.current.kind == TokenKind::PipePlusPipe {
1592 if self.current.kind == TokenKind::PipePlusPipe {
1593 is_multiset = true;
1594 }
1595 self.advance();
1596 patterns.push(self.parse_pattern()?);
1597 }
1598
1599 let where_clause = if self.current.kind == TokenKind::Where {
1601 self.advance();
1602 Some(self.parse_expression()?)
1603 } else {
1604 None
1605 };
1606
1607 self.expect(TokenKind::RParen)?;
1608
1609 let inner = if patterns.len() == 1 {
1610 patterns.remove(0)
1611 } else if is_multiset {
1612 Pattern::MultisetUnion(patterns)
1613 } else {
1614 Pattern::Union(patterns)
1615 };
1616
1617 if self.current.kind == TokenKind::LBrace {
1619 let (min, max) = self.parse_path_quantifier()?;
1620 Ok(Pattern::Quantified {
1621 pattern: Box::new(inner),
1622 min: min.unwrap_or(1),
1623 max,
1624 subpath_var,
1625 path_mode,
1626 where_clause,
1627 })
1628 } else if subpath_var.is_some() || path_mode.is_some() || where_clause.is_some() {
1629 Ok(Pattern::Quantified {
1631 pattern: Box::new(inner),
1632 min: 1,
1633 max: Some(1),
1634 subpath_var,
1635 path_mode,
1636 where_clause,
1637 })
1638 } else {
1639 Ok(inner)
1641 }
1642 }
1643
1644 fn parse_node_pattern(&mut self) -> Result<NodePattern> {
1645 self.expect(TokenKind::LParen)?;
1646
1647 let variable = if self.is_identifier() {
1648 let name = self.get_identifier_name();
1649 self.advance();
1650 Some(name)
1651 } else {
1652 None
1653 };
1654
1655 let mut labels = Vec::new();
1656 let mut label_expression = None;
1657
1658 if self.current.kind == TokenKind::Is {
1659 self.advance();
1661 label_expression = Some(self.parse_label_expression()?);
1662 } else {
1663 while self.current.kind == TokenKind::Colon {
1665 self.advance();
1666 if !self.is_label_or_type_name() {
1667 return Err(self.error("Expected label name"));
1668 }
1669 labels.push(self.get_identifier_name());
1670 self.advance();
1671 }
1672 }
1673
1674 let properties = if self.current.kind == TokenKind::LBrace {
1676 self.parse_property_map()?
1677 } else {
1678 Vec::new()
1679 };
1680
1681 let where_clause = if self.current.kind == TokenKind::Where {
1683 self.advance();
1684 Some(self.parse_expression()?)
1685 } else {
1686 None
1687 };
1688
1689 self.expect(TokenKind::RParen)?;
1690
1691 Ok(NodePattern {
1692 variable,
1693 labels,
1694 label_expression,
1695 properties,
1696 where_clause,
1697 span: None,
1698 })
1699 }
1700
1701 fn parse_label_expression(&mut self) -> Result<LabelExpression> {
1703 let mut left = self.parse_label_conjunction()?;
1704
1705 while self.current.kind == TokenKind::Pipe {
1706 let mut operands = vec![left];
1707 while self.current.kind == TokenKind::Pipe {
1708 self.advance();
1709 operands.push(self.parse_label_conjunction()?);
1710 }
1711 left = LabelExpression::Disjunction(operands);
1712 }
1713
1714 Ok(left)
1715 }
1716
1717 fn parse_label_conjunction(&mut self) -> Result<LabelExpression> {
1718 let mut left = self.parse_label_negation()?;
1719
1720 while self.current.kind == TokenKind::Ampersand {
1721 let mut operands = vec![left];
1722 while self.current.kind == TokenKind::Ampersand {
1723 self.advance();
1724 operands.push(self.parse_label_negation()?);
1725 }
1726 left = LabelExpression::Conjunction(operands);
1727 }
1728
1729 Ok(left)
1730 }
1731
1732 fn parse_label_negation(&mut self) -> Result<LabelExpression> {
1733 if self.current.kind == TokenKind::Exclamation {
1734 self.advance();
1735 let inner = self.parse_label_primary()?;
1736 return Ok(LabelExpression::Negation(Box::new(inner)));
1737 }
1738 self.parse_label_primary()
1739 }
1740
1741 fn parse_label_primary(&mut self) -> Result<LabelExpression> {
1742 if self.current.kind == TokenKind::Percent {
1743 self.advance();
1744 return Ok(LabelExpression::Wildcard);
1745 }
1746 if self.current.kind == TokenKind::LParen {
1747 self.advance();
1748 let expr = self.parse_label_expression()?;
1749 self.expect(TokenKind::RParen)?;
1750 return Ok(expr);
1751 }
1752 if self.is_label_or_type_name() {
1753 let name = self.get_identifier_name();
1754 self.advance();
1755 return Ok(LabelExpression::Label(name));
1756 }
1757 Err(self.error("Expected label name, %, or ("))
1758 }
1759
1760 fn parse_edge_pattern(&mut self) -> Result<EdgePattern> {
1761 let mut edge_where_clause = None;
1766 let (variable, types, min_hops, max_hops, properties, direction) =
1767 if self.current.kind == TokenKind::Minus {
1768 self.advance();
1770
1771 if self.current.kind == TokenKind::Slash {
1773 return self.parse_simplified_edge(false);
1774 }
1775
1776 let (var, edge_types, min_h, max_h, props) =
1778 if self.current.kind == TokenKind::LBracket {
1779 self.advance();
1780
1781 let v = if self.is_identifier() {
1785 let peek = self.peek_kind();
1786 if matches!(
1787 peek,
1788 TokenKind::Colon
1789 | TokenKind::Star
1790 | TokenKind::LBrace
1791 | TokenKind::RBracket
1792 | TokenKind::Where
1793 ) {
1794 let name = self.get_identifier_name();
1795 self.advance();
1796 Some(name)
1797 } else {
1798 None
1799 }
1800 } else {
1801 None
1802 };
1803
1804 let mut tps = Vec::new();
1805 while self.current.kind == TokenKind::Colon {
1806 self.advance();
1807 if !self.is_label_or_type_name() {
1808 return Err(self.error("Expected edge type"));
1809 }
1810 tps.push(self.get_identifier_name());
1811 self.advance();
1812 while self.current.kind == TokenKind::Pipe {
1814 self.advance();
1815 if !self.is_label_or_type_name() {
1816 return Err(self.error("Expected edge type after |"));
1817 }
1818 tps.push(self.get_identifier_name());
1819 self.advance();
1820 }
1821 }
1822
1823 let (min_h, max_h) = self.parse_path_quantifier()?;
1825
1826 let edge_props = if self.current.kind == TokenKind::LBrace {
1828 self.parse_property_map()?
1829 } else {
1830 Vec::new()
1831 };
1832
1833 if self.current.kind == TokenKind::Where {
1835 self.advance();
1836 edge_where_clause = Some(self.parse_expression()?);
1837 }
1838
1839 self.expect(TokenKind::RBracket)?;
1840 (v, tps, min_h, max_h, edge_props)
1841 } else {
1842 (None, Vec::new(), None, None, Vec::new())
1843 };
1844
1845 let dir = if self.current.kind == TokenKind::Arrow {
1847 self.advance();
1848 EdgeDirection::Outgoing
1849 } else if self.current.kind == TokenKind::Minus {
1850 self.advance();
1851 EdgeDirection::Undirected
1852 } else {
1853 return Err(self.error("Expected -> or - after edge pattern"));
1854 };
1855
1856 (var, edge_types, min_h, max_h, props, dir)
1857 } else if self.current.kind == TokenKind::LeftArrow {
1858 self.advance();
1860
1861 if self.current.kind == TokenKind::Slash {
1863 return self.parse_simplified_edge(true);
1864 }
1865
1866 let (var, edge_types, min_h, max_h, props) =
1867 if self.current.kind == TokenKind::LBracket {
1868 self.advance();
1869
1870 let v = if self.is_identifier() {
1874 let peek = self.peek_kind();
1875 if matches!(
1876 peek,
1877 TokenKind::Colon
1878 | TokenKind::Star
1879 | TokenKind::LBrace
1880 | TokenKind::RBracket
1881 | TokenKind::Where
1882 ) {
1883 let name = self.get_identifier_name();
1884 self.advance();
1885 Some(name)
1886 } else {
1887 None
1888 }
1889 } else {
1890 None
1891 };
1892
1893 let mut tps = Vec::new();
1894 while self.current.kind == TokenKind::Colon {
1895 self.advance();
1896 if !self.is_label_or_type_name() {
1897 return Err(self.error("Expected edge type"));
1898 }
1899 tps.push(self.get_identifier_name());
1900 self.advance();
1901 while self.current.kind == TokenKind::Pipe {
1903 self.advance();
1904 if !self.is_label_or_type_name() {
1905 return Err(self.error("Expected edge type after |"));
1906 }
1907 tps.push(self.get_identifier_name());
1908 self.advance();
1909 }
1910 }
1911
1912 let (min_h, max_h) = self.parse_path_quantifier()?;
1914
1915 let edge_props = if self.current.kind == TokenKind::LBrace {
1917 self.parse_property_map()?
1918 } else {
1919 Vec::new()
1920 };
1921
1922 if self.current.kind == TokenKind::Where {
1924 self.advance();
1925 edge_where_clause = Some(self.parse_expression()?);
1926 }
1927
1928 self.expect(TokenKind::RBracket)?;
1929 (v, tps, min_h, max_h, edge_props)
1930 } else {
1931 (None, Vec::new(), None, None, Vec::new())
1932 };
1933
1934 if self.current.kind == TokenKind::Minus {
1936 self.advance();
1937 }
1938
1939 (
1940 var,
1941 edge_types,
1942 min_h,
1943 max_h,
1944 props,
1945 EdgeDirection::Incoming,
1946 )
1947 } else if self.current.kind == TokenKind::Arrow {
1948 self.advance();
1950 (
1951 None,
1952 Vec::new(),
1953 None,
1954 None,
1955 Vec::new(),
1956 EdgeDirection::Outgoing,
1957 )
1958 } else if self.current.kind == TokenKind::DoubleDash {
1959 self.advance();
1961 if self.current.kind == TokenKind::Gt {
1962 self.advance();
1964 (
1965 None,
1966 Vec::new(),
1967 None,
1968 None,
1969 Vec::new(),
1970 EdgeDirection::Outgoing,
1971 )
1972 } else {
1973 (
1974 None,
1975 Vec::new(),
1976 None,
1977 None,
1978 Vec::new(),
1979 EdgeDirection::Undirected,
1980 )
1981 }
1982 } else if self.current.kind == TokenKind::Tilde {
1983 self.advance();
1985
1986 if self.current.kind == TokenKind::Slash {
1988 return self.parse_simplified_edge_undirected();
1989 }
1990
1991 let (var, edge_types, min_h, max_h, props) =
1992 if self.current.kind == TokenKind::LBracket {
1993 self.advance();
1994
1995 let v = if self.is_identifier() {
1996 let peek = self.peek_kind();
1997 if matches!(
1998 peek,
1999 TokenKind::Colon
2000 | TokenKind::Star
2001 | TokenKind::LBrace
2002 | TokenKind::RBracket
2003 | TokenKind::Where
2004 ) {
2005 let name = self.get_identifier_name();
2006 self.advance();
2007 Some(name)
2008 } else {
2009 None
2010 }
2011 } else {
2012 None
2013 };
2014
2015 let mut tps = Vec::new();
2016 while self.current.kind == TokenKind::Colon {
2017 self.advance();
2018 if !self.is_label_or_type_name() {
2019 return Err(self.error("Expected edge type"));
2020 }
2021 tps.push(self.get_identifier_name());
2022 self.advance();
2023 while self.current.kind == TokenKind::Pipe {
2024 self.advance();
2025 if !self.is_label_or_type_name() {
2026 return Err(self.error("Expected edge type after |"));
2027 }
2028 tps.push(self.get_identifier_name());
2029 self.advance();
2030 }
2031 }
2032
2033 let (min_h, max_h) = self.parse_path_quantifier()?;
2034
2035 let edge_props = if self.current.kind == TokenKind::LBrace {
2036 self.parse_property_map()?
2037 } else {
2038 Vec::new()
2039 };
2040
2041 if self.current.kind == TokenKind::Where {
2043 self.advance();
2044 edge_where_clause = Some(self.parse_expression()?);
2045 }
2046
2047 self.expect(TokenKind::RBracket)?;
2048 (v, tps, min_h, max_h, edge_props)
2049 } else {
2050 (None, Vec::new(), None, None, Vec::new())
2051 };
2052
2053 if self.current.kind == TokenKind::Tilde {
2055 self.advance();
2056 }
2057
2058 (
2059 var,
2060 edge_types,
2061 min_h,
2062 max_h,
2063 props,
2064 EdgeDirection::Undirected,
2065 )
2066 } else {
2067 return Err(self.error("Expected edge pattern"));
2068 };
2069
2070 let questioned = if self.current.kind == TokenKind::QuestionMark {
2072 self.advance();
2073 true
2074 } else {
2075 false
2076 };
2077
2078 let target = self.parse_node_pattern()?;
2079
2080 Ok(EdgePattern {
2081 variable,
2082 types,
2083 direction,
2084 target,
2085 min_hops,
2086 max_hops,
2087 properties,
2088 where_clause: edge_where_clause,
2089 questioned,
2090 span: None,
2091 })
2092 }
2093
2094 fn parse_simplified_edge(&mut self, incoming: bool) -> Result<EdgePattern> {
2101 self.expect(TokenKind::Slash)?; let mut types = Vec::new();
2105 if self.current.kind == TokenKind::Colon {
2106 self.advance();
2107 if !self.is_label_or_type_name() {
2108 return Err(self.error("Expected label in simplified path pattern"));
2109 }
2110 types.push(self.get_identifier_name());
2111 self.advance();
2112 while self.current.kind == TokenKind::Pipe {
2114 self.advance();
2115 if !self.is_label_or_type_name() {
2116 return Err(self.error("Expected label after | in simplified path pattern"));
2117 }
2118 types.push(self.get_identifier_name());
2119 self.advance();
2120 }
2121 }
2122
2123 self.expect(TokenKind::Slash)?; let direction = if incoming {
2127 if self.current.kind == TokenKind::Minus {
2129 self.advance();
2130 }
2131 EdgeDirection::Incoming
2132 } else if self.current.kind == TokenKind::Arrow {
2133 self.advance();
2135 EdgeDirection::Outgoing
2136 } else if self.current.kind == TokenKind::Minus {
2137 self.advance();
2139 EdgeDirection::Undirected
2140 } else {
2141 return Err(self.error("Expected ->, -, or end after simplified path pattern"));
2142 };
2143
2144 let target = self.parse_node_pattern()?;
2145
2146 Ok(EdgePattern {
2147 variable: None,
2148 types,
2149 direction,
2150 target,
2151 min_hops: None,
2152 max_hops: None,
2153 properties: Vec::new(),
2154 where_clause: None,
2155 questioned: false,
2156 span: None,
2157 })
2158 }
2159
2160 fn parse_simplified_edge_undirected(&mut self) -> Result<EdgePattern> {
2165 self.expect(TokenKind::Slash)?; let mut types = Vec::new();
2168 if self.current.kind == TokenKind::Colon {
2169 self.advance();
2170 if !self.is_label_or_type_name() {
2171 return Err(self.error("Expected label in simplified path pattern"));
2172 }
2173 types.push(self.get_identifier_name());
2174 self.advance();
2175 while self.current.kind == TokenKind::Pipe {
2176 self.advance();
2177 if !self.is_label_or_type_name() {
2178 return Err(self.error("Expected label after | in simplified path pattern"));
2179 }
2180 types.push(self.get_identifier_name());
2181 self.advance();
2182 }
2183 }
2184
2185 self.expect(TokenKind::Slash)?; if self.current.kind == TokenKind::Tilde {
2189 self.advance();
2190 }
2191
2192 let target = self.parse_node_pattern()?;
2193
2194 Ok(EdgePattern {
2195 variable: None,
2196 types,
2197 direction: EdgeDirection::Undirected,
2198 target,
2199 min_hops: None,
2200 max_hops: None,
2201 properties: Vec::new(),
2202 where_clause: None,
2203 questioned: false,
2204 span: None,
2205 })
2206 }
2207
2208 fn parse_path_quantifier(&mut self) -> Result<(Option<u32>, Option<u32>)> {
2212 if self.current.kind == TokenKind::LBrace {
2216 let next = self.peek_kind();
2217 if next != TokenKind::Integer && next != TokenKind::Comma {
2218 return Ok((None, None));
2220 }
2221 self.advance(); if self.current.kind == TokenKind::Comma {
2223 self.advance();
2225 let max_text = self.current.text.clone();
2226 let max: u32 = max_text
2227 .parse()
2228 .map_err(|_| self.error("Invalid path length"))?;
2229 self.advance();
2230 self.expect(TokenKind::RBrace)?;
2231 return Ok((Some(1), Some(max)));
2232 }
2233 let min_text = self.current.text.clone();
2234 let min: u32 = min_text
2235 .parse()
2236 .map_err(|_| self.error("Invalid path length"))?;
2237 self.advance();
2238 if self.current.kind == TokenKind::RBrace {
2239 self.advance();
2241 return Ok((Some(min), Some(min)));
2242 }
2243 self.expect(TokenKind::Comma)?;
2244 if self.current.kind == TokenKind::RBrace {
2245 self.advance();
2247 return Ok((Some(min), None));
2248 }
2249 let max_text = self.current.text.clone();
2250 let max: u32 = max_text
2251 .parse()
2252 .map_err(|_| self.error("Invalid path length"))?;
2253 self.advance();
2254 self.expect(TokenKind::RBrace)?;
2255 return Ok((Some(min), Some(max)));
2256 }
2257
2258 if self.current.kind != TokenKind::Star {
2259 return Ok((None, None));
2260 }
2261 self.advance(); if self.current.kind == TokenKind::Integer {
2265 let min_text = self.current.text.clone();
2266 let min: u32 = min_text
2267 .parse()
2268 .map_err(|_| self.error("Invalid path length"))?;
2269 self.advance();
2270
2271 if self.current.kind == TokenKind::Dot {
2272 self.advance();
2273 self.expect(TokenKind::Dot)?; if self.current.kind == TokenKind::Integer {
2276 let max_text = self.current.text.clone();
2277 let max: u32 = max_text
2278 .parse()
2279 .map_err(|_| self.error("Invalid path length"))?;
2280 self.advance();
2281 Ok((Some(min), Some(max))) } else {
2283 Ok((Some(min), None)) }
2285 } else {
2286 Ok((Some(min), Some(min))) }
2288 } else if self.current.kind == TokenKind::Dot {
2289 self.advance();
2290 self.expect(TokenKind::Dot)?; if self.current.kind == TokenKind::Integer {
2293 let max_text = self.current.text.clone();
2294 let max: u32 = max_text
2295 .parse()
2296 .map_err(|_| self.error("Invalid path length"))?;
2297 self.advance();
2298 Ok((Some(1), Some(max))) } else {
2300 Err(self.error("Expected max hops after .."))
2301 }
2302 } else {
2303 Ok((Some(1), None)) }
2305 }
2306
2307 fn parse_where_clause(&mut self) -> Result<WhereClause> {
2308 self.expect(TokenKind::Where)?;
2309 let expression = self.parse_expression()?;
2310
2311 Ok(WhereClause {
2312 expression,
2313 span: None,
2314 })
2315 }
2316
2317 fn parse_where_or_filter_clause(&mut self) -> Result<WhereClause> {
2319 if self.current.kind == TokenKind::Filter {
2321 self.advance();
2322 } else {
2323 self.expect(TokenKind::Where)?;
2324 }
2325 let expression = self.parse_expression()?;
2326
2327 Ok(WhereClause {
2328 expression,
2329 span: None,
2330 })
2331 }
2332
2333 fn parse_having_clause(&mut self) -> Result<HavingClause> {
2334 self.expect(TokenKind::Having)?;
2335 let expression = self.parse_expression()?;
2336
2337 Ok(HavingClause {
2338 expression,
2339 span: None,
2340 })
2341 }
2342
2343 fn parse_return_clause(&mut self) -> Result<ReturnClause> {
2344 self.expect(TokenKind::Return)?;
2345
2346 let distinct = if self.current.kind == TokenKind::Distinct {
2347 self.advance();
2348 true
2349 } else {
2350 false
2351 };
2352
2353 let is_wildcard = if self.current.kind == TokenKind::Star {
2355 self.advance();
2356 true
2357 } else {
2358 false
2359 };
2360
2361 let mut items = Vec::new();
2362 if !is_wildcard {
2363 items.push(self.parse_return_item()?);
2364
2365 while self.current.kind == TokenKind::Comma {
2366 self.advance();
2367 items.push(self.parse_return_item()?);
2368 }
2369 }
2370
2371 let group_by = if self.current.kind == TokenKind::Group {
2373 self.advance();
2374 self.expect(TokenKind::By)?;
2375 let mut exprs = vec![self.parse_expression()?];
2376 while self.current.kind == TokenKind::Comma {
2377 self.advance();
2378 exprs.push(self.parse_expression()?);
2379 }
2380 exprs
2381 } else {
2382 Vec::new()
2383 };
2384
2385 let order_by = if self.current.kind == TokenKind::Order {
2386 Some(self.parse_order_by()?)
2387 } else {
2388 None
2389 };
2390
2391 let skip = if matches!(self.current.kind, TokenKind::Skip | TokenKind::Offset) {
2392 self.advance();
2393 Some(self.parse_expression()?)
2394 } else {
2395 None
2396 };
2397
2398 let limit = if self.current.kind == TokenKind::Limit {
2399 self.advance();
2400 Some(self.parse_expression()?)
2401 } else if self.current.kind == TokenKind::Fetch {
2402 Some(self.parse_fetch_first()?)
2403 } else {
2404 None
2405 };
2406
2407 Ok(ReturnClause {
2408 distinct,
2409 items,
2410 is_wildcard,
2411 group_by,
2412 order_by,
2413 skip,
2414 limit,
2415 is_finish: false,
2416 span: None,
2417 })
2418 }
2419
2420 fn parse_select_clause(&mut self) -> Result<ReturnClause> {
2423 let distinct = if self.current.kind == TokenKind::Distinct {
2424 self.advance();
2425 true
2426 } else {
2427 false
2428 };
2429
2430 let mut items = Vec::new();
2431 items.push(self.parse_return_item()?);
2432 while self.current.kind == TokenKind::Comma {
2433 self.advance();
2434 items.push(self.parse_return_item()?);
2435 }
2436
2437 let group_by = if self.current.kind == TokenKind::Group {
2439 self.advance();
2440 self.expect(TokenKind::By)?;
2441 let mut exprs = vec![self.parse_expression()?];
2442 while self.current.kind == TokenKind::Comma {
2443 self.advance();
2444 exprs.push(self.parse_expression()?);
2445 }
2446 exprs
2447 } else {
2448 Vec::new()
2449 };
2450
2451 let order_by = if self.current.kind == TokenKind::Order {
2452 Some(self.parse_order_by()?)
2453 } else {
2454 None
2455 };
2456
2457 let skip = if matches!(self.current.kind, TokenKind::Skip | TokenKind::Offset) {
2458 self.advance();
2459 Some(self.parse_expression()?)
2460 } else {
2461 None
2462 };
2463
2464 let limit = if self.current.kind == TokenKind::Limit {
2465 self.advance();
2466 Some(self.parse_expression()?)
2467 } else if self.current.kind == TokenKind::Fetch {
2468 Some(self.parse_fetch_first()?)
2469 } else {
2470 None
2471 };
2472
2473 Ok(ReturnClause {
2474 distinct,
2475 items,
2476 is_wildcard: false,
2477 group_by,
2478 order_by,
2479 skip,
2480 limit,
2481 is_finish: false,
2482 span: None,
2483 })
2484 }
2485
2486 fn parse_return_item(&mut self) -> Result<ReturnItem> {
2487 let expression = self.parse_expression()?;
2488
2489 let alias = if self.current.kind == TokenKind::As {
2490 self.advance();
2491 if !self.is_identifier() {
2492 return Err(self.error("Expected alias name"));
2493 }
2494 let name = self.get_identifier_name();
2495 self.advance();
2496 Some(name)
2497 } else {
2498 None
2499 };
2500
2501 Ok(ReturnItem {
2502 expression,
2503 alias,
2504 span: None,
2505 })
2506 }
2507
2508 fn parse_fetch_first(&mut self) -> Result<Expression> {
2511 self.expect(TokenKind::Fetch)?;
2512 if !matches!(self.current.kind, TokenKind::First | TokenKind::Next) {
2514 return Err(self.error("Expected FIRST or NEXT after FETCH"));
2515 }
2516 self.advance();
2517 let count = self.parse_expression()?;
2519 if matches!(self.current.kind, TokenKind::Rows | TokenKind::Row) {
2521 self.advance();
2522 }
2523 if self.current.kind == TokenKind::Only {
2525 self.advance();
2526 }
2527 Ok(count)
2528 }
2529
2530 fn parse_list_comprehension_inner(&mut self) -> Result<Expression> {
2534 let variable = self.get_identifier_name();
2535 self.advance(); self.expect(TokenKind::In)?;
2537 let list_expr = self.parse_expression()?;
2538
2539 let filter_expr = if self.current.kind == TokenKind::Where {
2541 self.advance();
2542 Some(Box::new(self.parse_expression()?))
2543 } else {
2544 None
2545 };
2546
2547 let map_expr = if self.current.kind == TokenKind::Pipe {
2549 self.advance();
2550 Box::new(self.parse_expression()?)
2551 } else {
2552 Box::new(Expression::Variable(variable.clone()))
2554 };
2555
2556 self.expect(TokenKind::RBracket)?;
2557 Ok(Expression::ListComprehension {
2558 variable,
2559 list_expr: Box::new(list_expr),
2560 filter_expr,
2561 map_expr,
2562 })
2563 }
2564
2565 fn parse_list_predicate(&mut self, kind: ListPredicateKind) -> Result<Expression> {
2568 self.expect(TokenKind::LParen)?;
2569 if !self.is_identifier() {
2570 return Err(self.error("Expected variable name in list predicate"));
2571 }
2572 let variable = self.get_identifier_name();
2573 self.advance();
2574 self.expect(TokenKind::In)?;
2575 let list_expr = self.parse_expression()?;
2576 self.expect(TokenKind::Where)?;
2578 let predicate = self.parse_expression()?;
2579 self.expect(TokenKind::RParen)?;
2580 Ok(Expression::ListPredicate {
2581 kind,
2582 variable,
2583 list_expr: Box::new(list_expr),
2584 predicate: Box::new(predicate),
2585 })
2586 }
2587
2588 fn parse_reduce(&mut self) -> Result<Expression> {
2591 self.expect(TokenKind::LParen)?;
2592 if !self.is_identifier() {
2593 return Err(self.error("Expected accumulator variable in reduce"));
2594 }
2595 let accumulator = self.get_identifier_name();
2596 self.advance();
2597 self.expect(TokenKind::Eq)?;
2598 let initial = self.parse_expression()?;
2599 self.expect(TokenKind::Comma)?;
2600 if !self.is_identifier() {
2601 return Err(self.error("Expected iteration variable in reduce"));
2602 }
2603 let variable = self.get_identifier_name();
2604 self.advance();
2605 self.expect(TokenKind::In)?;
2606 let list = self.parse_expression()?;
2607 self.expect(TokenKind::Pipe)?;
2608 let expression = self.parse_expression()?;
2609 self.expect(TokenKind::RParen)?;
2610 Ok(Expression::Reduce {
2611 accumulator,
2612 initial: Box::new(initial),
2613 variable,
2614 list: Box::new(list),
2615 expression: Box::new(expression),
2616 })
2617 }
2618
2619 fn parse_order_by(&mut self) -> Result<OrderByClause> {
2620 self.expect(TokenKind::Order)?;
2621 self.expect(TokenKind::By)?;
2622
2623 let mut items = Vec::new();
2624 items.push(self.parse_order_item()?);
2625
2626 while self.current.kind == TokenKind::Comma {
2627 self.advance();
2628 items.push(self.parse_order_item()?);
2629 }
2630
2631 Ok(OrderByClause { items, span: None })
2632 }
2633
2634 fn parse_order_item(&mut self) -> Result<OrderByItem> {
2635 let expression = self.parse_expression()?;
2636
2637 let order = match self.current.kind {
2638 TokenKind::Asc => {
2639 self.advance();
2640 SortOrder::Asc
2641 }
2642 TokenKind::Desc => {
2643 self.advance();
2644 SortOrder::Desc
2645 }
2646 _ => SortOrder::Asc,
2647 };
2648
2649 let nulls =
2651 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("NULLS") {
2652 self.advance();
2653 if self.is_identifier() {
2654 let kw = self.get_identifier_name().to_uppercase();
2655 match kw.as_str() {
2656 "FIRST" => {
2657 self.advance();
2658 Some(NullsOrdering::First)
2659 }
2660 "LAST" => {
2661 self.advance();
2662 Some(NullsOrdering::Last)
2663 }
2664 _ => return Err(self.error("Expected FIRST or LAST after NULLS")),
2665 }
2666 } else {
2667 return Err(self.error("Expected FIRST or LAST after NULLS"));
2668 }
2669 } else {
2670 None
2671 };
2672
2673 Ok(OrderByItem {
2674 expression,
2675 order,
2676 nulls,
2677 })
2678 }
2679
2680 fn parse_expression(&mut self) -> Result<Expression> {
2681 self.parse_or_expression()
2682 }
2683
2684 fn parse_or_expression(&mut self) -> Result<Expression> {
2685 let mut left = self.parse_xor_expression()?;
2686
2687 while self.current.kind == TokenKind::Or {
2688 self.advance();
2689 let right = self.parse_xor_expression()?;
2690 left = Expression::Binary {
2691 left: Box::new(left),
2692 op: BinaryOp::Or,
2693 right: Box::new(right),
2694 };
2695 }
2696
2697 Ok(left)
2698 }
2699
2700 fn parse_xor_expression(&mut self) -> Result<Expression> {
2701 let mut left = self.parse_and_expression()?;
2702
2703 while self.current.kind == TokenKind::Xor {
2704 self.advance();
2705 let right = self.parse_and_expression()?;
2706 left = Expression::Binary {
2707 left: Box::new(left),
2708 op: BinaryOp::Xor,
2709 right: Box::new(right),
2710 };
2711 }
2712
2713 Ok(left)
2714 }
2715
2716 fn parse_and_expression(&mut self) -> Result<Expression> {
2717 let mut left = self.parse_not_expression()?;
2718
2719 while self.current.kind == TokenKind::And {
2720 self.advance();
2721 let right = self.parse_not_expression()?;
2722 left = Expression::Binary {
2723 left: Box::new(left),
2724 op: BinaryOp::And,
2725 right: Box::new(right),
2726 };
2727 }
2728
2729 Ok(left)
2730 }
2731
2732 fn parse_not_expression(&mut self) -> Result<Expression> {
2733 if self.current.kind == TokenKind::Not {
2734 self.advance();
2735 let operand = self.parse_not_expression()?;
2736 return Ok(Expression::Unary {
2737 op: UnaryOp::Not,
2738 operand: Box::new(operand),
2739 });
2740 }
2741 self.parse_comparison_expression()
2742 }
2743
2744 fn parse_comparison_expression(&mut self) -> Result<Expression> {
2745 let left = self.parse_additive_expression()?;
2746
2747 let op = match self.current.kind {
2749 TokenKind::Eq => Some(BinaryOp::Eq),
2750 TokenKind::Ne => Some(BinaryOp::Ne),
2751 TokenKind::Lt => Some(BinaryOp::Lt),
2752 TokenKind::Le => Some(BinaryOp::Le),
2753 TokenKind::Gt => Some(BinaryOp::Gt),
2754 TokenKind::Ge => Some(BinaryOp::Ge),
2755 _ => None,
2756 };
2757
2758 if let Some(op) = op {
2759 self.advance();
2760 let right = self.parse_additive_expression()?;
2761 return Ok(Expression::Binary {
2762 left: Box::new(left),
2763 op,
2764 right: Box::new(right),
2765 });
2766 }
2767
2768 match self.current.kind {
2770 TokenKind::In => {
2771 self.advance(); let right = self.parse_primary_expression()?;
2773 return Ok(Expression::Binary {
2774 left: Box::new(left),
2775 op: BinaryOp::In,
2776 right: Box::new(right),
2777 });
2778 }
2779 TokenKind::Starts => {
2780 self.advance(); self.expect(TokenKind::With)?; let right = self.parse_additive_expression()?;
2783 return Ok(Expression::Binary {
2784 left: Box::new(left),
2785 op: BinaryOp::StartsWith,
2786 right: Box::new(right),
2787 });
2788 }
2789 TokenKind::Ends => {
2790 self.advance(); self.expect(TokenKind::With)?; let right = self.parse_additive_expression()?;
2793 return Ok(Expression::Binary {
2794 left: Box::new(left),
2795 op: BinaryOp::EndsWith,
2796 right: Box::new(right),
2797 });
2798 }
2799 TokenKind::Contains => {
2800 self.advance(); let right = self.parse_additive_expression()?;
2802 return Ok(Expression::Binary {
2803 left: Box::new(left),
2804 op: BinaryOp::Contains,
2805 right: Box::new(right),
2806 });
2807 }
2808 TokenKind::Like => {
2809 self.advance(); let right = self.parse_additive_expression()?;
2811 return Ok(Expression::Binary {
2812 left: Box::new(left),
2813 op: BinaryOp::Like,
2814 right: Box::new(right),
2815 });
2816 }
2817 TokenKind::Is => {
2818 self.advance(); let negated = self.current.kind == TokenKind::Not;
2820 if negated {
2821 self.advance(); }
2823
2824 let predicate = if self.current.kind == TokenKind::Null {
2825 self.advance();
2827 Expression::Unary {
2828 op: if negated {
2829 UnaryOp::IsNotNull
2830 } else {
2831 UnaryOp::IsNull
2832 },
2833 operand: Box::new(left),
2834 }
2835 } else if self.is_identifier() {
2836 let kw = self.get_identifier_name().to_uppercase();
2837 match kw.as_str() {
2838 "TYPED" => {
2839 self.advance();
2842 let type_name = if self.is_identifier() {
2843 let base = self.get_identifier_name().to_uppercase();
2844 self.advance();
2845 if base == "LIST" && self.current.kind == TokenKind::Lt {
2847 self.advance(); if self.is_identifier() {
2849 let elem = self.get_identifier_name().to_uppercase();
2850 self.advance();
2851 self.expect(TokenKind::Gt)?;
2852 format!("LIST<{elem}>")
2853 } else {
2854 return Err(self.error("Expected element type after LIST<"));
2855 }
2856 } else {
2857 base
2858 }
2859 } else {
2860 return Err(self.error("Expected type name after IS TYPED"));
2861 };
2862 let call = Expression::FunctionCall {
2863 name: "isTyped".to_string(),
2864 args: vec![left, Expression::Literal(Literal::String(type_name))],
2865 distinct: false,
2866 };
2867 if negated {
2868 Expression::Unary {
2869 op: UnaryOp::Not,
2870 operand: Box::new(call),
2871 }
2872 } else {
2873 call
2874 }
2875 }
2876 "DIRECTED" => {
2877 self.advance();
2879 let call = Expression::FunctionCall {
2880 name: "isDirected".to_string(),
2881 args: vec![left],
2882 distinct: false,
2883 };
2884 if negated {
2885 Expression::Unary {
2886 op: UnaryOp::Not,
2887 operand: Box::new(call),
2888 }
2889 } else {
2890 call
2891 }
2892 }
2893 "LABELED" => {
2894 self.advance();
2896 let label = if self.is_identifier() {
2897 self.get_identifier_name()
2898 } else {
2899 return Err(self.error("Expected label name after IS LABELED"));
2900 };
2901 self.advance();
2902 let call = Expression::FunctionCall {
2903 name: "hasLabel".to_string(),
2904 args: vec![left, Expression::Literal(Literal::String(label))],
2905 distinct: false,
2906 };
2907 if negated {
2908 Expression::Unary {
2909 op: UnaryOp::Not,
2910 operand: Box::new(call),
2911 }
2912 } else {
2913 call
2914 }
2915 }
2916 "SOURCE" => {
2917 self.advance();
2919 if !(self.is_identifier()
2920 && self.get_identifier_name().eq_ignore_ascii_case("OF"))
2921 {
2922 return Err(self.error("Expected OF after IS SOURCE"));
2923 }
2924 self.advance(); let var = if self.is_identifier() {
2926 self.get_identifier_name()
2927 } else {
2928 return Err(self.error("Expected variable after IS SOURCE OF"));
2929 };
2930 self.advance();
2931 let call = Expression::FunctionCall {
2932 name: "isSource".to_string(),
2933 args: vec![left, Expression::Variable(var)],
2934 distinct: false,
2935 };
2936 if negated {
2937 Expression::Unary {
2938 op: UnaryOp::Not,
2939 operand: Box::new(call),
2940 }
2941 } else {
2942 call
2943 }
2944 }
2945 "DESTINATION" => {
2946 self.advance();
2948 if !(self.is_identifier()
2949 && self.get_identifier_name().eq_ignore_ascii_case("OF"))
2950 {
2951 return Err(self.error("Expected OF after IS DESTINATION"));
2952 }
2953 self.advance(); let var = if self.is_identifier() {
2955 self.get_identifier_name()
2956 } else {
2957 return Err(self.error("Expected variable after IS DESTINATION OF"));
2958 };
2959 self.advance();
2960 let call = Expression::FunctionCall {
2961 name: "isDestination".to_string(),
2962 args: vec![left, Expression::Variable(var)],
2963 distinct: false,
2964 };
2965 if negated {
2966 Expression::Unary {
2967 op: UnaryOp::Not,
2968 operand: Box::new(call),
2969 }
2970 } else {
2971 call
2972 }
2973 }
2974 "NFC" | "NFD" | "NFKC" | "NFKD" => {
2975 let form = kw.clone();
2977 self.advance();
2978 if !(self.is_identifier()
2979 && self
2980 .get_identifier_name()
2981 .eq_ignore_ascii_case("NORMALIZED"))
2982 {
2983 return Err(
2984 self.error(&format!("Expected NORMALIZED after IS {form}"))
2985 );
2986 }
2987 self.advance();
2988 let call = Expression::FunctionCall {
2989 name: "isNormalized".to_string(),
2990 args: vec![left, Expression::Literal(Literal::String(form))],
2991 distinct: false,
2992 };
2993 if negated {
2994 Expression::Unary {
2995 op: UnaryOp::Not,
2996 operand: Box::new(call),
2997 }
2998 } else {
2999 call
3000 }
3001 }
3002 "NORMALIZED" => {
3003 self.advance();
3005 let call = Expression::FunctionCall {
3006 name: "isNormalized".to_string(),
3007 args: vec![
3008 left,
3009 Expression::Literal(Literal::String("NFC".to_string())),
3010 ],
3011 distinct: false,
3012 };
3013 if negated {
3014 Expression::Unary {
3015 op: UnaryOp::Not,
3016 operand: Box::new(call),
3017 }
3018 } else {
3019 call
3020 }
3021 }
3022 _ => {
3023 return Err(self.error(
3024 "Expected NULL, TYPED, DIRECTED, LABELED, SOURCE, DESTINATION, NORMALIZED, or NFC/NFD/NFKC/NFKD after IS",
3025 ));
3026 }
3027 }
3028 } else {
3029 return Err(self.error(
3030 "Expected NULL, TYPED, DIRECTED, LABELED, SOURCE, DESTINATION, NORMALIZED, or NFC/NFD/NFKC/NFKD after IS",
3031 ));
3032 };
3033
3034 return Ok(predicate);
3035 }
3036 _ => {}
3037 }
3038
3039 Ok(left)
3040 }
3041
3042 fn parse_additive_expression(&mut self) -> Result<Expression> {
3043 let mut left = self.parse_multiplicative_expression()?;
3044
3045 loop {
3046 let op = match self.current.kind {
3047 TokenKind::Plus => BinaryOp::Add,
3048 TokenKind::Minus => BinaryOp::Sub,
3049 TokenKind::Concat => BinaryOp::Concat,
3050 _ => break,
3051 };
3052 self.advance();
3053 let right = self.parse_multiplicative_expression()?;
3054 left = Expression::Binary {
3055 left: Box::new(left),
3056 op,
3057 right: Box::new(right),
3058 };
3059 }
3060
3061 Ok(left)
3062 }
3063
3064 fn parse_multiplicative_expression(&mut self) -> Result<Expression> {
3065 let mut left = self.parse_unary_expression()?;
3066
3067 loop {
3068 let op = match self.current.kind {
3069 TokenKind::Star => BinaryOp::Mul,
3070 TokenKind::Slash => BinaryOp::Div,
3071 TokenKind::Percent => BinaryOp::Mod,
3072 _ => break,
3073 };
3074 self.advance();
3075 let right = self.parse_unary_expression()?;
3076 left = Expression::Binary {
3077 left: Box::new(left),
3078 op,
3079 right: Box::new(right),
3080 };
3081 }
3082
3083 Ok(left)
3084 }
3085
3086 fn parse_unary_expression(&mut self) -> Result<Expression> {
3087 match self.current.kind {
3088 TokenKind::Minus => {
3089 self.advance();
3090 let operand = self.parse_unary_expression()?;
3091 Ok(Expression::Unary {
3092 op: UnaryOp::Neg,
3093 operand: Box::new(operand),
3094 })
3095 }
3096 TokenKind::Plus => {
3097 self.advance();
3098 let operand = self.parse_unary_expression()?;
3099 Ok(Expression::Unary {
3100 op: UnaryOp::Pos,
3101 operand: Box::new(operand),
3102 })
3103 }
3104 _ => self.parse_postfix_expression(),
3105 }
3106 }
3107
3108 fn parse_postfix_expression(&mut self) -> Result<Expression> {
3109 let mut expr = self.parse_primary_expression()?;
3110
3111 loop {
3112 match self.current.kind {
3113 TokenKind::LBracket => {
3114 self.advance();
3115 let index = self.parse_expression()?;
3116 self.expect(TokenKind::RBracket)?;
3117 expr = Expression::IndexAccess {
3118 base: Box::new(expr),
3119 index: Box::new(index),
3120 };
3121 }
3122 TokenKind::Colon => {
3125 let base = expr;
3126 let mut combined: Option<Expression> = None;
3127 while self.current.kind == TokenKind::Colon {
3128 self.advance();
3129 if !self.is_label_or_type_name() {
3130 return Err(self.error("Expected label name after ':'"));
3131 }
3132 let label = self.get_identifier_name();
3133 self.advance();
3134 let check = Expression::FunctionCall {
3135 name: "hasLabel".to_string(),
3136 args: vec![base.clone(), Expression::Literal(Literal::String(label))],
3137 distinct: false,
3138 };
3139 combined = Some(match combined {
3140 None => check,
3141 Some(prev) => Expression::Binary {
3142 left: Box::new(prev),
3143 op: BinaryOp::And,
3144 right: Box::new(check),
3145 },
3146 });
3147 }
3148 expr = combined
3149 .ok_or_else(|| self.error("Expected at least one label after ':'"))?;
3150 }
3151 _ => break,
3152 }
3153 }
3154
3155 Ok(expr)
3156 }
3157
3158 fn parse_primary_expression(&mut self) -> Result<Expression> {
3159 match self.current.kind {
3160 TokenKind::Null => {
3161 self.advance();
3162 Ok(Expression::Literal(Literal::Null))
3163 }
3164 TokenKind::True => {
3165 self.advance();
3166 Ok(Expression::Literal(Literal::Bool(true)))
3167 }
3168 TokenKind::False => {
3169 self.advance();
3170 Ok(Expression::Literal(Literal::Bool(false)))
3171 }
3172 TokenKind::Integer => {
3173 let text = &self.current.text;
3174 let value = if text.starts_with("0x") || text.starts_with("0X") {
3175 i64::from_str_radix(&text[2..], 16)
3176 } else if text.starts_with("0o") || text.starts_with("0O") {
3177 i64::from_str_radix(&text[2..], 8)
3178 } else if text.starts_with("0b") || text.starts_with("0B") {
3179 i64::from_str_radix(&text[2..], 2)
3180 } else {
3181 text.parse()
3182 }
3183 .map_err(|_| self.error("Invalid integer"))?;
3184 self.advance();
3185 Ok(Expression::Literal(Literal::Integer(value)))
3186 }
3187 TokenKind::Float => {
3188 let value = self
3189 .current
3190 .text
3191 .parse()
3192 .map_err(|_| self.error("Invalid float"))?;
3193 self.advance();
3194 Ok(Expression::Literal(Literal::Float(value)))
3195 }
3196 TokenKind::String => {
3197 let text = &self.current.text;
3198 let inner = &text[1..text.len() - 1]; let value = unescape_string(inner);
3200 self.advance();
3201 Ok(Expression::Literal(Literal::String(value)))
3202 }
3203 TokenKind::Case => {
3205 let next = self.peek_kind();
3208 if matches!(
3209 next,
3210 TokenKind::Colon
3211 | TokenKind::Comma
3212 | TokenKind::RParen
3213 | TokenKind::RBracket
3214 | TokenKind::As
3215 | TokenKind::Order
3216 | TokenKind::Limit
3217 | TokenKind::Skip
3218 | TokenKind::Eof
3219 ) {
3220 let name = "case".to_string();
3222 self.advance();
3223 Ok(Expression::Variable(name))
3224 } else {
3225 self.parse_case_expression()
3227 }
3228 }
3229 TokenKind::Type => {
3231 let name = "type".to_string();
3232 self.advance();
3233 if self.current.kind != TokenKind::LParen {
3234 return Ok(Expression::Variable(name));
3236 }
3237 self.advance();
3238 let mut args = Vec::new();
3239 if self.current.kind != TokenKind::RParen {
3240 args.push(self.parse_expression()?);
3241 while self.current.kind == TokenKind::Comma {
3242 self.advance();
3243 args.push(self.parse_expression()?);
3244 }
3245 }
3246 self.expect(TokenKind::RParen)?;
3247 Ok(Expression::FunctionCall {
3248 name,
3249 args,
3250 distinct: false,
3251 })
3252 }
3253 _ if self.is_identifier() => {
3254 let name = self.get_identifier_name();
3255
3256 if name.eq_ignore_ascii_case("SESSION_USER") {
3258 self.advance();
3259 return Ok(Expression::FunctionCall {
3260 name: "session_user".to_string(),
3261 args: Vec::new(),
3262 distinct: false,
3263 });
3264 }
3265
3266 if name.eq_ignore_ascii_case("CURRENT_SCHEMA") {
3268 self.advance();
3269 return Ok(Expression::FunctionCall {
3270 name: "current_schema".to_string(),
3271 args: Vec::new(),
3272 distinct: false,
3273 });
3274 }
3275 if name.eq_ignore_ascii_case("CURRENT_GRAPH")
3276 || name.eq_ignore_ascii_case("CURRENT_PROPERTY_GRAPH")
3277 {
3278 self.advance();
3279 return Ok(Expression::FunctionCall {
3280 name: "current_graph".to_string(),
3281 args: Vec::new(),
3282 distinct: false,
3283 });
3284 }
3285 if name.eq_ignore_ascii_case("HOME_SCHEMA") {
3286 self.advance();
3287 return Ok(Expression::FunctionCall {
3288 name: "home_schema".to_string(),
3289 args: Vec::new(),
3290 distinct: false,
3291 });
3292 }
3293 if name.eq_ignore_ascii_case("HOME_GRAPH")
3294 || name.eq_ignore_ascii_case("HOME_PROPERTY_GRAPH")
3295 {
3296 self.advance();
3297 return Ok(Expression::FunctionCall {
3298 name: "home_graph".to_string(),
3299 args: Vec::new(),
3300 distinct: false,
3301 });
3302 }
3303
3304 if name.eq_ignore_ascii_case("NULLIF") && self.peek_kind() == TokenKind::LParen {
3306 self.advance(); self.advance(); let expr1 = self.parse_expression()?;
3309 self.expect(TokenKind::Comma)?;
3310 let expr2 = self.parse_expression()?;
3311 self.expect(TokenKind::RParen)?;
3312 return Ok(Expression::FunctionCall {
3313 name: "nullif".to_string(),
3314 args: vec![expr1, expr2],
3315 distinct: false,
3316 });
3317 }
3318
3319 if name.eq_ignore_ascii_case("COALESCE") && self.peek_kind() == TokenKind::LParen {
3321 self.advance(); self.advance(); let mut args = vec![self.parse_expression()?];
3324 while self.current.kind == TokenKind::Comma {
3325 self.advance();
3326 args.push(self.parse_expression()?);
3327 }
3328 self.expect(TokenKind::RParen)?;
3329 return Ok(Expression::FunctionCall {
3330 name: "coalesce".to_string(),
3331 args,
3332 distinct: false,
3333 });
3334 }
3335
3336 if name.eq_ignore_ascii_case("TRIM") && self.peek_kind() == TokenKind::LParen {
3339 self.advance(); self.advance(); let mut mode = 0i64; let mut trim_chars: Option<Expression> = None;
3344
3345 if self.is_identifier() {
3347 let kw = self.get_identifier_name().to_uppercase();
3348 match kw.as_str() {
3349 "BOTH" => {
3350 self.advance();
3351 }
3352 "LEADING" => {
3353 mode = 1;
3354 self.advance();
3355 }
3356 "TRAILING" => {
3357 mode = 2;
3358 self.advance();
3359 }
3360 "FROM" => {
3361 self.advance();
3363 let string_expr = self.parse_expression()?;
3364 self.expect(TokenKind::RParen)?;
3365 return Ok(Expression::FunctionCall {
3366 name: "trim".to_string(),
3367 args: vec![string_expr],
3368 distinct: false,
3369 });
3370 }
3371 _ => {
3372 let expr = self.parse_expression()?;
3374 self.expect(TokenKind::RParen)?;
3375 return Ok(Expression::FunctionCall {
3376 name: "trim".to_string(),
3377 args: vec![expr],
3378 distinct: false,
3379 });
3380 }
3381 }
3382 }
3383
3384 if self.is_identifier()
3386 && self.get_identifier_name().eq_ignore_ascii_case("FROM")
3387 {
3388 self.advance(); let string_expr = self.parse_expression()?;
3391 self.expect(TokenKind::RParen)?;
3392 return Ok(Expression::FunctionCall {
3393 name: "trim".to_string(),
3394 args: vec![
3395 string_expr,
3396 Expression::Literal(Literal::String(" ".into())),
3397 Expression::Literal(Literal::Integer(mode)),
3398 ],
3399 distinct: false,
3400 });
3401 }
3402
3403 if self.current.kind != TokenKind::RParen {
3405 trim_chars = Some(self.parse_expression()?);
3406 }
3407
3408 if self.is_identifier()
3410 && self.get_identifier_name().eq_ignore_ascii_case("FROM")
3411 {
3412 self.advance(); let string_expr = self.parse_expression()?;
3414 self.expect(TokenKind::RParen)?;
3415 let chars_expr =
3416 trim_chars.unwrap_or(Expression::Literal(Literal::String(" ".into())));
3417 return Ok(Expression::FunctionCall {
3418 name: "trim".to_string(),
3419 args: vec![
3420 string_expr,
3421 chars_expr,
3422 Expression::Literal(Literal::Integer(mode)),
3423 ],
3424 distinct: false,
3425 });
3426 }
3427
3428 self.expect(TokenKind::RParen)?;
3430 let arg = trim_chars.unwrap_or(Expression::Literal(Literal::Null));
3431 return Ok(Expression::FunctionCall {
3432 name: "trim".to_string(),
3433 args: vec![arg],
3434 distinct: false,
3435 });
3436 }
3437
3438 if self.peek_kind() == TokenKind::LParen {
3441 let lower = name.to_lowercase();
3442 let predicate_kind = match lower.as_str() {
3443 "all" => Some(ListPredicateKind::All),
3444 "any" => Some(ListPredicateKind::Any),
3445 "none" => Some(ListPredicateKind::None),
3446 "single" => Some(ListPredicateKind::Single),
3447 _ => None,
3448 };
3449 if let Some(kind) = predicate_kind {
3450 self.advance(); return self.parse_list_predicate(kind);
3456 }
3457
3458 if lower == "reduce" {
3460 self.advance(); return self.parse_reduce();
3462 }
3463 }
3464
3465 if name.eq_ignore_ascii_case("LET") {
3467 self.advance(); let mut bindings = Vec::new();
3469 loop {
3470 if !self.is_identifier() {
3471 return Err(self.error("Expected variable name in LET expression"));
3472 }
3473 let var = self.get_identifier_name();
3474 self.advance();
3475 self.expect(TokenKind::Eq)?;
3476 let expr = self.parse_additive_expression()?;
3480 bindings.push((var, expr));
3481 if self.current.kind != TokenKind::Comma {
3482 break;
3483 }
3484 self.advance(); }
3486 if self.current.kind != TokenKind::In {
3488 return Err(self.error("Expected IN after LET bindings"));
3489 }
3490 self.advance(); let body = self.parse_expression()?;
3492 self.expect(TokenKind::End)?;
3493 return Ok(Expression::LetIn {
3494 bindings,
3495 body: Box::new(body),
3496 });
3497 }
3498
3499 self.advance();
3500
3501 if self.current.kind == TokenKind::String {
3503 let upper = name.to_uppercase();
3504 let make_val = |parser: &Self| {
3505 let text = &parser.current.text;
3506 let inner = &text[1..text.len() - 1];
3507 unescape_string(inner)
3508 };
3509 let typed_lit = match upper.as_str() {
3510 "DATE" => Some(Literal::Date(make_val(self))),
3511 "TIME" => Some(Literal::Time(make_val(self))),
3512 "DURATION" => Some(Literal::Duration(make_val(self))),
3513 "DATETIME" => Some(Literal::Datetime(make_val(self))),
3514 _ => None,
3515 };
3516 if let Some(lit) = typed_lit {
3517 self.advance();
3518 return Ok(Expression::Literal(lit));
3519 }
3520 }
3521
3522 if name.eq_ignore_ascii_case("ZONED") && self.is_identifier() {
3524 let sub = self.get_identifier_name().to_uppercase();
3525 if sub == "DATETIME" || sub == "TIME" {
3526 self.advance(); if self.current.kind == TokenKind::String {
3528 let text = &self.current.text;
3529 let inner = &text[1..text.len() - 1];
3530 let val = unescape_string(inner);
3531 self.advance();
3532 return Ok(Expression::Literal(if sub == "DATETIME" {
3533 Literal::ZonedDatetime(val)
3534 } else {
3535 Literal::ZonedTime(val)
3536 }));
3537 }
3538 }
3539 }
3540
3541 if self.current.kind == TokenKind::Dot {
3542 self.advance();
3543 if !self.is_identifier() {
3544 return Err(self.error("Expected property name"));
3545 }
3546 let property = self.get_identifier_name();
3547 self.advance();
3548 Ok(Expression::PropertyAccess {
3549 variable: name,
3550 property,
3551 })
3552 } else if self.current.kind == TokenKind::LBrace
3553 && name.eq_ignore_ascii_case("count")
3554 {
3555 self.advance(); let inner_query = self.parse_exists_inner_query()?;
3558 self.expect(TokenKind::RBrace)?;
3559 Ok(Expression::CountSubquery {
3560 query: Box::new(inner_query),
3561 })
3562 } else if self.current.kind == TokenKind::LBrace
3563 && name.eq_ignore_ascii_case("value")
3564 {
3565 self.advance(); let inner_query = self.parse_value_subquery_inner()?;
3568 self.expect(TokenKind::RBrace)?;
3569 Ok(Expression::ValueSubquery {
3570 query: Box::new(inner_query),
3571 })
3572 } else if self.current.kind == TokenKind::LParen {
3573 self.advance();
3575 if name.eq_ignore_ascii_case("count") && self.current.kind == TokenKind::Star {
3577 self.advance(); self.expect(TokenKind::RParen)?;
3579 return Ok(Expression::FunctionCall {
3580 name,
3581 args: Vec::new(),
3582 distinct: false,
3583 });
3584 }
3585 let distinct = if self.current.kind == TokenKind::Distinct {
3587 self.advance();
3588 true
3589 } else {
3590 false
3591 };
3592 let mut args = Vec::new();
3593 if self.current.kind != TokenKind::RParen {
3594 args.push(self.parse_expression()?);
3595 while self.current.kind == TokenKind::Comma {
3596 self.advance();
3597 args.push(self.parse_expression()?);
3598 }
3599 }
3600 self.expect(TokenKind::RParen)?;
3601 Ok(Expression::FunctionCall {
3602 name,
3603 args,
3604 distinct,
3605 })
3606 } else {
3607 Ok(Expression::Variable(name))
3608 }
3609 }
3610 TokenKind::LParen => {
3611 self.advance();
3612 let expr = self.parse_expression()?;
3613 self.expect(TokenKind::RParen)?;
3614 Ok(expr)
3615 }
3616 TokenKind::LBracket => {
3617 self.advance(); if self.is_identifier() && self.peek_kind() == TokenKind::In {
3621 return self.parse_list_comprehension_inner();
3622 }
3623 let mut elements = Vec::new();
3624 if self.current.kind != TokenKind::RBracket {
3625 elements.push(self.parse_expression()?);
3626 while self.current.kind == TokenKind::Comma {
3627 self.advance();
3628 elements.push(self.parse_expression()?);
3629 }
3630 }
3631 self.expect(TokenKind::RBracket)?;
3632 Ok(Expression::List(elements))
3633 }
3634 TokenKind::Parameter => {
3635 let full_text = &self.current.text;
3637 let name = full_text.trim_start_matches('$').to_string();
3638 self.advance();
3639 Ok(Expression::Parameter(name))
3640 }
3641 TokenKind::Exists => {
3642 self.advance();
3643 if self.current.kind == TokenKind::LBrace {
3644 self.advance(); let inner_query = self.parse_exists_inner_query()?;
3647 self.expect(TokenKind::RBrace)?;
3648 Ok(Expression::ExistsSubquery {
3649 query: Box::new(inner_query),
3650 })
3651 } else {
3652 self.expect(TokenKind::LParen)?;
3654 let arg = self.parse_expression()?;
3655 self.expect(TokenKind::RParen)?;
3656 Ok(Expression::FunctionCall {
3657 name: "exists".to_string(),
3658 args: vec![arg],
3659 distinct: false,
3660 })
3661 }
3662 }
3663 TokenKind::LBrace => {
3664 let entries = self.parse_property_map()?;
3666 Ok(Expression::Map(entries))
3667 }
3668 TokenKind::Cast => {
3669 self.advance();
3671 self.expect(TokenKind::LParen)?;
3672 let expr = self.parse_expression()?;
3673 self.expect(TokenKind::As)?;
3674 let type_name = if self.is_identifier() {
3675 let mut name = self.get_identifier_name().to_uppercase();
3676 self.advance();
3677 if name == "ZONED" && self.is_identifier() {
3679 let sub = self.get_identifier_name().to_uppercase();
3680 if sub == "DATETIME" || sub == "TIME" {
3681 name = format!("ZONED {sub}");
3682 self.advance();
3683 }
3684 }
3685 if name == "LIST" && self.current.kind == TokenKind::Lt {
3687 self.advance(); if self.is_identifier() {
3689 let elem = self.get_identifier_name().to_uppercase();
3690 self.advance();
3691 self.expect(TokenKind::Gt)?;
3692 name = format!("LIST<{elem}>");
3693 } else {
3694 return Err(self.error("Expected element type after LIST<"));
3695 }
3696 }
3697 name
3698 } else {
3699 return Err(self.error("Expected type name after AS"));
3700 };
3701 self.expect(TokenKind::RParen)?;
3702 let (func_name, extra_arg) = match type_name.as_str() {
3703 "INTEGER" | "INT" | "INT64" | "BIGINT" => ("toInteger", None),
3704 "FLOAT" | "DOUBLE" | "FLOAT64" | "REAL" => ("toFloat", None),
3705 "STRING" | "VARCHAR" | "TEXT" => ("toString", None),
3706 "BOOLEAN" | "BOOL" => ("toBoolean", None),
3707 "DATE" => ("toDate", None),
3708 "TIME" | "LOCALTIME" => ("toTime", None),
3709 "DATETIME" | "TIMESTAMP" | "LOCALDATETIME" => ("toDatetime", None),
3710 "DURATION" => ("toDuration", None),
3711 "ZONED DATETIME" => ("toZonedDatetime", None),
3712 "ZONED TIME" => ("toZonedTime", None),
3713 "LIST" => ("toList", None),
3714 s if s.starts_with("LIST<") => {
3715 let elem_type = &s[5..s.len() - 1]; ("toTypedList", Some(elem_type.to_string()))
3717 }
3718 _ => return Err(self.error(&format!("Unsupported CAST type: {type_name}"))),
3719 };
3720 let mut args = vec![expr];
3721 if let Some(elem) = extra_arg {
3722 args.push(Expression::Literal(Literal::String(elem)));
3723 }
3724 Ok(Expression::FunctionCall {
3725 name: func_name.to_string(),
3726 args,
3727 distinct: false,
3728 })
3729 }
3730 _ => Err(self.error("Expected expression")),
3731 }
3732 }
3733
3734 fn parse_case_expression(&mut self) -> Result<Expression> {
3737 self.expect(TokenKind::Case)?;
3738
3739 let input = if self.current.kind != TokenKind::When {
3742 Some(Box::new(self.parse_expression()?))
3743 } else {
3744 None
3745 };
3746
3747 let mut whens = Vec::new();
3749 while self.current.kind == TokenKind::When {
3750 self.advance();
3751 let condition = self.parse_expression()?;
3752 self.expect(TokenKind::Then)?;
3753 let result = self.parse_expression()?;
3754 whens.push((condition, result));
3755 }
3756
3757 if whens.is_empty() {
3758 return Err(self.error("CASE requires at least one WHEN clause"));
3759 }
3760
3761 let else_clause = if self.current.kind == TokenKind::Else {
3763 self.advance();
3764 Some(Box::new(self.parse_expression()?))
3765 } else {
3766 None
3767 };
3768
3769 self.expect(TokenKind::End)?;
3770
3771 Ok(Expression::Case {
3772 input,
3773 whens,
3774 else_clause,
3775 })
3776 }
3777
3778 fn parse_exists_inner_query(&mut self) -> Result<QueryStatement> {
3781 let mut match_clauses = Vec::new();
3782
3783 while self.current.kind == TokenKind::Match || self.current.kind == TokenKind::Optional {
3785 match_clauses.push(self.parse_match_clause()?);
3786 }
3787
3788 if match_clauses.is_empty() && self.current.kind == TokenKind::LParen {
3791 let span_start = self.current.span.start;
3792 let mut patterns = Vec::new();
3793 patterns.push(self.parse_aliased_pattern()?);
3794 while self.current.kind == TokenKind::Comma {
3795 self.advance();
3796 patterns.push(self.parse_aliased_pattern()?);
3797 }
3798 match_clauses.push(MatchClause {
3799 optional: false,
3800 path_mode: None,
3801 search_prefix: None,
3802 match_mode: None,
3803 patterns,
3804 span: Some(SourceSpan::new(span_start, self.current.span.end, 1, 1)),
3805 });
3806 }
3807
3808 if match_clauses.is_empty() {
3809 return Err(self.error("EXISTS subquery requires at least one MATCH clause"));
3810 }
3811
3812 let where_clause = if self.current.kind == TokenKind::Where {
3814 Some(self.parse_where_clause()?)
3815 } else {
3816 None
3817 };
3818
3819 Ok(QueryStatement {
3821 match_clauses,
3822 where_clause,
3823 set_clauses: vec![],
3824 remove_clauses: vec![],
3825 with_clauses: vec![],
3826 unwind_clauses: vec![],
3827 merge_clauses: vec![],
3828 create_clauses: vec![],
3829 delete_clauses: vec![],
3830 return_clause: ReturnClause {
3831 distinct: false,
3832 items: vec![],
3833 is_wildcard: false,
3834 group_by: vec![],
3835 order_by: None,
3836 skip: None,
3837 limit: None,
3838 is_finish: false,
3839 span: None,
3840 },
3841 having_clause: None,
3842 ordered_clauses: vec![],
3843 span: None,
3844 })
3845 }
3846
3847 fn parse_value_subquery_inner(&mut self) -> Result<QueryStatement> {
3850 let mut match_clauses = Vec::new();
3851
3852 while self.current.kind == TokenKind::Match || self.current.kind == TokenKind::Optional {
3854 match_clauses.push(self.parse_match_clause()?);
3855 }
3856
3857 if match_clauses.is_empty() {
3858 return Err(self.error("VALUE subquery requires at least one MATCH clause"));
3859 }
3860
3861 let where_clause = if self.current.kind == TokenKind::Where {
3863 Some(self.parse_where_clause()?)
3864 } else {
3865 None
3866 };
3867
3868 let return_clause = if self.current.kind == TokenKind::Return {
3870 self.parse_return_clause()?
3871 } else {
3872 return Err(self.error("VALUE subquery requires a RETURN clause"));
3873 };
3874
3875 Ok(QueryStatement {
3876 match_clauses,
3877 where_clause,
3878 set_clauses: vec![],
3879 remove_clauses: vec![],
3880 with_clauses: vec![],
3881 unwind_clauses: vec![],
3882 merge_clauses: vec![],
3883 create_clauses: vec![],
3884 delete_clauses: vec![],
3885 return_clause,
3886 having_clause: None,
3887 ordered_clauses: vec![],
3888 span: None,
3889 })
3890 }
3891
3892 fn parse_property_map(&mut self) -> Result<Vec<(String, Expression)>> {
3893 self.expect(TokenKind::LBrace)?;
3894
3895 let mut properties = Vec::new();
3896
3897 if self.current.kind != TokenKind::RBrace {
3898 loop {
3899 if !self.is_identifier() {
3900 return Err(self.error("Expected property name"));
3901 }
3902 let key = self.get_identifier_name();
3903 self.advance();
3904
3905 self.expect(TokenKind::Colon)?;
3906
3907 let value = self.parse_expression()?;
3908 properties.push((key, value));
3909
3910 if self.current.kind != TokenKind::Comma {
3911 break;
3912 }
3913 self.advance();
3914 }
3915 }
3916
3917 self.expect(TokenKind::RBrace)?;
3918 Ok(properties)
3919 }
3920
3921 fn parse_insert(&mut self) -> Result<InsertStatement> {
3922 self.expect(TokenKind::Insert)?;
3923
3924 let mut patterns = Vec::new();
3925 patterns.push(self.parse_pattern()?);
3926
3927 while self.current.kind == TokenKind::Comma {
3928 self.advance();
3929 patterns.push(self.parse_pattern()?);
3930 }
3931
3932 Ok(InsertStatement {
3933 patterns,
3934 span: None,
3935 })
3936 }
3937
3938 fn parse_create_as_insert(&mut self) -> Result<InsertStatement> {
3940 self.expect(TokenKind::Create)?;
3941
3942 let mut patterns = Vec::new();
3943 patterns.push(self.parse_pattern()?);
3944
3945 while self.current.kind == TokenKind::Comma {
3946 self.advance();
3947 patterns.push(self.parse_pattern()?);
3948 }
3949
3950 Ok(InsertStatement {
3951 patterns,
3952 span: None,
3953 })
3954 }
3955
3956 fn parse_create_clause_in_query(&mut self) -> Result<InsertStatement> {
3958 self.expect(TokenKind::Create)?;
3959
3960 let mut patterns = Vec::new();
3961 patterns.push(self.parse_pattern()?);
3962
3963 while self.current.kind == TokenKind::Comma {
3964 self.advance();
3965 patterns.push(self.parse_pattern()?);
3966 }
3967
3968 Ok(InsertStatement {
3969 patterns,
3970 span: None,
3971 })
3972 }
3973
3974 fn parse_delete_target(&mut self) -> Result<DeleteTarget> {
3976 let expr = self.parse_expression()?;
3979 if let Expression::Variable(name) = expr {
3981 Ok(DeleteTarget::Variable(name))
3982 } else {
3983 Ok(DeleteTarget::Expression(expr))
3984 }
3985 }
3986
3987 fn parse_delete_prefix(&mut self) -> Result<bool> {
3989 let detach = if self.current.kind == TokenKind::Detach {
3990 self.advance();
3991 true
3992 } else {
3993 if self.current.kind == TokenKind::Nodetach {
3995 self.advance();
3996 }
3997 false
3998 };
3999 self.expect(TokenKind::Delete)?;
4000 Ok(detach)
4001 }
4002
4003 fn parse_delete_clause_in_query(&mut self) -> Result<DeleteStatement> {
4005 let detach = self.parse_delete_prefix()?;
4006
4007 let mut targets = Vec::new();
4008 targets.push(self.parse_delete_target()?);
4009
4010 while self.current.kind == TokenKind::Comma {
4011 self.advance();
4012 targets.push(self.parse_delete_target()?);
4013 }
4014
4015 Ok(DeleteStatement {
4016 targets,
4017 detach,
4018 span: None,
4019 })
4020 }
4021
4022 fn parse_delete(&mut self) -> Result<DeleteStatement> {
4023 let detach = self.parse_delete_prefix()?;
4024
4025 let mut targets = Vec::new();
4026 targets.push(self.parse_delete_target()?);
4027
4028 while self.current.kind == TokenKind::Comma {
4029 self.advance();
4030 targets.push(self.parse_delete_target()?);
4031 }
4032
4033 Ok(DeleteStatement {
4034 targets,
4035 detach,
4036 span: None,
4037 })
4038 }
4039
4040 fn parse_create_schema(&mut self) -> Result<SchemaStatement> {
4041 self.expect(TokenKind::Create)?;
4042
4043 let or_replace = self.try_parse_or_replace();
4045
4046 match self.current.kind {
4047 TokenKind::Node => {
4048 self.advance();
4049 self.expect(TokenKind::Type)?;
4050
4051 let if_not_exists = self.try_parse_if_not_exists();
4053
4054 if !self.is_identifier() {
4055 return Err(self.error("Expected type name"));
4056 }
4057 let name = self.get_identifier_name();
4058 self.advance();
4059
4060 let parent_types = if self.is_identifier()
4062 && self.get_identifier_name().eq_ignore_ascii_case("EXTENDS")
4063 {
4064 self.advance();
4065 let mut parents = Vec::new();
4066 if self.is_identifier() || self.is_label_or_type_name() {
4067 parents.push(self.get_identifier_name());
4068 self.advance();
4069 while self.current.kind == TokenKind::Comma {
4070 self.advance();
4071 if self.is_identifier() || self.is_label_or_type_name() {
4072 parents.push(self.get_identifier_name());
4073 self.advance();
4074 }
4075 }
4076 }
4077 parents
4078 } else {
4079 Vec::new()
4080 };
4081
4082 let properties = if self.current.kind == TokenKind::LParen {
4084 self.parse_property_definitions()?
4085 } else {
4086 Vec::new()
4087 };
4088
4089 Ok(SchemaStatement::CreateNodeType(CreateNodeTypeStatement {
4090 name,
4091 properties,
4092 parent_types,
4093 if_not_exists,
4094 or_replace,
4095 span: None,
4096 }))
4097 }
4098 TokenKind::Edge => {
4099 self.advance();
4100 self.expect(TokenKind::Type)?;
4101
4102 let if_not_exists = self.try_parse_if_not_exists();
4104
4105 if !self.is_identifier() {
4106 return Err(self.error("Expected type name"));
4107 }
4108 let name = self.get_identifier_name();
4109 self.advance();
4110
4111 let (source_node_types, target_node_types) = if self.is_identifier()
4113 && self.get_identifier_name().eq_ignore_ascii_case("CONNECTING")
4114 {
4115 self.advance();
4116 self.expect(TokenKind::LParen)?;
4117 let mut sources = Vec::new();
4118 while self.is_identifier() || self.is_label_or_type_name() {
4119 sources.push(self.get_identifier_name());
4120 self.advance();
4121 if self.current.kind == TokenKind::Comma {
4122 self.advance();
4123 } else {
4124 break;
4125 }
4126 }
4127 self.expect(TokenKind::RParen)?;
4128 if !(self.is_identifier()
4129 && self.get_identifier_name().eq_ignore_ascii_case("TO"))
4130 {
4131 return Err(self.error("Expected 'TO' after source node types"));
4132 }
4133 self.advance();
4134 self.expect(TokenKind::LParen)?;
4135 let mut targets = Vec::new();
4136 while self.is_identifier() || self.is_label_or_type_name() {
4137 targets.push(self.get_identifier_name());
4138 self.advance();
4139 if self.current.kind == TokenKind::Comma {
4140 self.advance();
4141 } else {
4142 break;
4143 }
4144 }
4145 self.expect(TokenKind::RParen)?;
4146 (sources, targets)
4147 } else {
4148 (Vec::new(), Vec::new())
4149 };
4150
4151 let properties = if self.current.kind == TokenKind::LParen {
4152 self.parse_property_definitions()?
4153 } else {
4154 Vec::new()
4155 };
4156
4157 Ok(SchemaStatement::CreateEdgeType(CreateEdgeTypeStatement {
4158 name,
4159 properties,
4160 source_node_types,
4161 target_node_types,
4162 if_not_exists,
4163 or_replace,
4164 span: None,
4165 }))
4166 }
4167 TokenKind::Vector => {
4168 self.advance();
4169 self.expect(TokenKind::Index)?;
4170
4171 if !self.is_identifier() {
4173 return Err(self.error("Expected index name"));
4174 }
4175 let name = self.get_identifier_name();
4176 self.advance();
4177
4178 self.expect(TokenKind::On)?;
4180
4181 self.expect(TokenKind::Colon)?;
4183
4184 if !self.is_identifier() && !self.is_label_or_type_name() {
4185 return Err(self.error("Expected node label"));
4186 }
4187 let node_label = self.get_identifier_name();
4188 self.advance();
4189
4190 self.expect(TokenKind::LParen)?;
4191
4192 if !self.is_identifier() {
4193 return Err(self.error("Expected property name"));
4194 }
4195 let property = self.get_identifier_name();
4196 self.advance();
4197
4198 self.expect(TokenKind::RParen)?;
4199
4200 let dimensions = if self.current.kind == TokenKind::Dimension {
4202 self.advance();
4203 if self.current.kind != TokenKind::Integer {
4204 return Err(self.error("Expected integer dimension"));
4205 }
4206 let dim: usize = self
4207 .current
4208 .text
4209 .parse()
4210 .map_err(|_| self.error("Invalid dimension value"))?;
4211 self.advance();
4212 Some(dim)
4213 } else {
4214 None
4215 };
4216
4217 let metric = if self.current.kind == TokenKind::Metric {
4219 self.advance();
4220 if self.current.kind != TokenKind::String {
4221 return Err(self.error("Expected metric name as string"));
4222 }
4223 let metric_str = self
4225 .current
4226 .text
4227 .trim_matches('\'')
4228 .trim_matches('"')
4229 .to_string();
4230 self.advance();
4231 Some(metric_str)
4232 } else {
4233 None
4234 };
4235
4236 Ok(SchemaStatement::CreateVectorIndex(
4237 CreateVectorIndexStatement {
4238 name,
4239 node_label,
4240 property,
4241 dimensions,
4242 metric,
4243 span: None,
4244 },
4245 ))
4246 }
4247 TokenKind::Index => {
4248 self.advance();
4250
4251 let if_not_exists = self.try_parse_if_not_exists();
4253
4254 if !self.is_identifier() {
4255 return Err(self.error("Expected index name"));
4256 }
4257 let name = self.get_identifier_name();
4258 self.advance();
4259
4260 self.parse_create_index_body(name, if_not_exists)
4261 }
4262 _ if self.is_identifier()
4263 && self
4264 .get_identifier_name()
4265 .eq_ignore_ascii_case("CONSTRAINT") =>
4266 {
4267 self.advance(); let if_not_exists = self.try_parse_if_not_exists();
4272
4273 let name = if self.is_identifier()
4275 && !self.get_identifier_name().eq_ignore_ascii_case("FOR")
4276 {
4277 let n = self.get_identifier_name();
4278 self.advance();
4279 Some(n)
4280 } else {
4281 None
4282 };
4283
4284 self.parse_create_constraint_body(name, if_not_exists)
4285 }
4286 _ if self.is_identifier()
4287 && self.get_identifier_name().eq_ignore_ascii_case("GRAPH") =>
4288 {
4289 self.advance(); self.expect(TokenKind::Type)?;
4291
4292 let if_not_exists = self.try_parse_if_not_exists();
4293
4294 if !self.is_identifier() {
4295 return Err(self.error("Expected graph type name"));
4296 }
4297 let name = self.get_identifier_name();
4298 self.advance();
4299
4300 let like_graph = if self.current.kind == TokenKind::Like {
4302 self.advance();
4303 if !self.is_identifier() {
4304 return Err(self.error("Expected graph name after LIKE"));
4305 }
4306 let graph_name = self.get_identifier_name();
4307 self.advance();
4308 Some(graph_name)
4309 } else {
4310 None
4311 };
4312
4313 let (node_types, edge_types, inline_types, open) =
4315 if self.current.kind == TokenKind::LBrace {
4316 let (nt, et, open) = self.parse_graph_type_body()?;
4317 (nt, et, Vec::new(), open)
4318 } else if self.current.kind == TokenKind::LParen {
4319 let inline = self.parse_graph_type_iso_body()?;
4320 let nt: Vec<String> = inline
4321 .iter()
4322 .filter_map(|t| match t {
4323 InlineElementType::Node { name, .. } => Some(name.clone()),
4324 InlineElementType::Edge { .. } => None,
4325 })
4326 .collect();
4327 let et: Vec<String> = inline
4328 .iter()
4329 .filter_map(|t| match t {
4330 InlineElementType::Edge { name, .. } => Some(name.clone()),
4331 InlineElementType::Node { .. } => None,
4332 })
4333 .collect();
4334 (nt, et, inline, false)
4335 } else {
4336 (Vec::new(), Vec::new(), Vec::new(), true)
4337 };
4338
4339 Ok(SchemaStatement::CreateGraphType(CreateGraphTypeStatement {
4340 name,
4341 node_types,
4342 edge_types,
4343 inline_types,
4344 like_graph,
4345 open,
4346 if_not_exists,
4347 or_replace,
4348 span: None,
4349 }))
4350 }
4351 _ if self.is_identifier()
4352 && self.get_identifier_name().eq_ignore_ascii_case("SCHEMA") =>
4353 {
4354 self.advance(); let if_not_exists = self.try_parse_if_not_exists();
4357
4358 if !self.is_identifier() {
4359 return Err(self.error("Expected schema name"));
4360 }
4361 let name = self.get_identifier_name();
4362 self.advance();
4363
4364 Ok(SchemaStatement::CreateSchema {
4365 name,
4366 if_not_exists,
4367 })
4368 }
4369 _ if self.is_identifier()
4370 && self.get_identifier_name().eq_ignore_ascii_case("PROCEDURE") =>
4371 {
4372 self.advance(); self.parse_create_procedure(or_replace)
4374 }
4375 _ => Err(self.error(
4376 "Expected NODE, EDGE, VECTOR, INDEX, CONSTRAINT, GRAPH, SCHEMA, or PROCEDURE after CREATE",
4377 )),
4378 }
4379 }
4380
4381 fn parse_create_index_body(
4383 &mut self,
4384 name: String,
4385 if_not_exists: bool,
4386 ) -> Result<SchemaStatement> {
4387 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("FOR") {
4389 return Err(self.error("Expected FOR after index name"));
4390 }
4391 self.advance();
4392
4393 self.expect(TokenKind::LParen)?;
4395 if !self.is_identifier() {
4396 return Err(self.error("Expected variable in FOR clause"));
4397 }
4398 let var_name = self.get_identifier_name();
4399 self.advance();
4400 self.expect(TokenKind::Colon)?;
4401 if !self.is_identifier() && !self.is_label_or_type_name() {
4402 return Err(self.error("Expected label"));
4403 }
4404 let label = self.get_identifier_name();
4405 self.advance();
4406 self.expect(TokenKind::RParen)?;
4407
4408 self.expect(TokenKind::On)?;
4410
4411 self.expect(TokenKind::LParen)?;
4413 let mut properties = Vec::new();
4414 loop {
4415 if !self.is_identifier() {
4416 return Err(self.error("Expected variable.property"));
4417 }
4418 let prop_var = self.get_identifier_name();
4419 self.advance();
4420 self.expect(TokenKind::Dot)?;
4421 if !self.is_identifier() {
4422 return Err(self.error("Expected property name"));
4423 }
4424 if !prop_var.eq_ignore_ascii_case(&var_name) {
4426 return Err(self.error(&format!(
4427 "Variable '{prop_var}' does not match FOR variable '{var_name}'"
4428 )));
4429 }
4430 let prop = self.get_identifier_name();
4431 self.advance();
4432 properties.push(prop);
4433 if self.current.kind != TokenKind::Comma {
4434 break;
4435 }
4436 self.advance();
4437 }
4438 self.expect(TokenKind::RParen)?;
4439
4440 let mut index_kind = IndexKind::Property;
4442 let mut options = IndexOptions::default();
4443
4444 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("USING") {
4445 self.advance();
4446 if !self.is_identifier() && self.current.kind != TokenKind::Vector {
4447 return Err(self.error("Expected TEXT, VECTOR, or BTREE after USING"));
4448 }
4449 let kind_text = if self.current.kind == TokenKind::Vector {
4450 "VECTOR".to_string()
4451 } else {
4452 self.get_identifier_name()
4453 };
4454 self.advance();
4455 match kind_text.to_uppercase().as_str() {
4456 "TEXT" => index_kind = IndexKind::Text,
4457 "VECTOR" => {
4458 index_kind = IndexKind::Vector;
4459 if self.current.kind == TokenKind::LBrace {
4461 self.advance();
4462 while self.current.kind != TokenKind::RBrace {
4463 if !self.is_identifier() {
4464 return Err(self.error("Expected option name"));
4465 }
4466 let opt_name = self.get_identifier_name();
4467 self.advance();
4468 self.expect(TokenKind::Colon)?;
4469 match opt_name.to_uppercase().as_str() {
4470 "DIMENSIONS" | "DIMENSION" => {
4471 if self.current.kind != TokenKind::Integer {
4472 return Err(self.error("Expected integer for dimensions"));
4473 }
4474 let dim: usize = self
4475 .current
4476 .text
4477 .parse()
4478 .map_err(|_| self.error("Invalid dimension value"))?;
4479 self.advance();
4480 options.dimensions = Some(dim);
4481 }
4482 "METRIC" => {
4483 if self.current.kind != TokenKind::String {
4484 return Err(self.error("Expected string for metric"));
4485 }
4486 let metric = self
4487 .current
4488 .text
4489 .trim_matches('\'')
4490 .trim_matches('"')
4491 .to_string();
4492 self.advance();
4493 options.metric = Some(metric);
4494 }
4495 _ => {
4496 return Err(
4497 self.error(&format!("Unknown index option '{opt_name}'"))
4498 );
4499 }
4500 }
4501 if self.current.kind == TokenKind::Comma {
4502 self.advance();
4503 }
4504 }
4505 self.expect(TokenKind::RBrace)?;
4506 }
4507 }
4508 "BTREE" => index_kind = IndexKind::BTree,
4509 _ => {
4510 return Err(self.error(&format!("Unknown index type '{kind_text}'")));
4511 }
4512 }
4513 }
4514
4515 Ok(SchemaStatement::CreateIndex(CreateIndexStatement {
4516 name,
4517 index_kind,
4518 label,
4519 properties,
4520 options,
4521 if_not_exists,
4522 span: None,
4523 }))
4524 }
4525
4526 fn parse_create_constraint_body(
4528 &mut self,
4529 name: Option<String>,
4530 if_not_exists: bool,
4531 ) -> Result<SchemaStatement> {
4532 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("FOR") {
4534 return Err(self.error("Expected FOR after constraint name"));
4535 }
4536 self.advance();
4537
4538 self.expect(TokenKind::LParen)?;
4540 if !self.is_identifier() {
4541 return Err(self.error("Expected variable in FOR clause"));
4542 }
4543 let var_name = self.get_identifier_name();
4544 self.advance();
4545 self.expect(TokenKind::Colon)?;
4546 if !self.is_identifier() && !self.is_label_or_type_name() {
4547 return Err(self.error("Expected label"));
4548 }
4549 let label = self.get_identifier_name();
4550 self.advance();
4551 self.expect(TokenKind::RParen)?;
4552
4553 self.expect(TokenKind::On)?;
4555
4556 self.expect(TokenKind::LParen)?;
4558 let mut properties = Vec::new();
4559 loop {
4560 if !self.is_identifier() {
4561 return Err(self.error("Expected variable.property"));
4562 }
4563 let prop_var = self.get_identifier_name();
4564 self.advance();
4565 self.expect(TokenKind::Dot)?;
4566 if !self.is_identifier() {
4567 return Err(self.error("Expected property name"));
4568 }
4569 if !prop_var.eq_ignore_ascii_case(&var_name) {
4570 return Err(self.error(&format!(
4571 "Variable '{prop_var}' does not match FOR variable '{var_name}'"
4572 )));
4573 }
4574 let prop = self.get_identifier_name();
4575 self.advance();
4576 properties.push(prop);
4577 if self.current.kind != TokenKind::Comma {
4578 break;
4579 }
4580 self.advance();
4581 }
4582 self.expect(TokenKind::RParen)?;
4583
4584 let constraint_kind = if self.is_identifier()
4586 && self.get_identifier_name().eq_ignore_ascii_case("UNIQUE")
4587 {
4588 self.advance();
4589 ConstraintKind::Unique
4590 } else if self.current.kind == TokenKind::Not {
4591 self.advance();
4592 if self.current.kind != TokenKind::Null {
4593 return Err(self.error("Expected NULL after NOT"));
4594 }
4595 self.advance();
4596 ConstraintKind::NotNull
4597 } else if self.current.kind == TokenKind::Node {
4598 self.advance();
4599 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("KEY") {
4600 return Err(self.error("Expected KEY after NODE"));
4601 }
4602 self.advance();
4603 ConstraintKind::NodeKey
4604 } else if self.current.kind == TokenKind::Exists {
4605 self.advance();
4606 ConstraintKind::Exists
4607 } else {
4608 return Err(self.error("Expected UNIQUE, NOT NULL, NODE KEY, or EXISTS"));
4609 };
4610
4611 Ok(SchemaStatement::CreateConstraint(
4612 CreateConstraintStatement {
4613 name,
4614 constraint_kind,
4615 label,
4616 properties,
4617 if_not_exists,
4618 span: None,
4619 },
4620 ))
4621 }
4622
4623 fn try_parse_if_not_exists(&mut self) -> bool {
4625 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("IF") {
4626 self.advance();
4627 if self.current.kind == TokenKind::Not {
4628 self.advance();
4629 if self.current.kind == TokenKind::Exists {
4630 self.advance();
4631 return true;
4632 }
4633 }
4634 }
4635 false
4636 }
4637
4638 fn try_parse_if_exists(&mut self) -> bool {
4640 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("IF") {
4641 self.advance();
4642 if self.current.kind == TokenKind::Exists {
4643 self.advance();
4644 return true;
4645 }
4646 }
4647 false
4648 }
4649
4650 fn try_parse_or_replace(&mut self) -> bool {
4656 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("OR") {
4657 let pk = self.peek_kind();
4658 if pk == TokenKind::Identifier {
4659 let text = self.peek_text_upper();
4660 if text == "REPLACE" {
4661 self.advance(); self.advance(); return true;
4664 }
4665 }
4666 }
4667 false
4668 }
4669
4670 fn parse_create_dispatch(&mut self) -> Result<Statement> {
4676 if self.peek_is_graph_instance_keyword() {
4680 return self.parse_create_graph().map(Statement::SessionCommand);
4681 }
4682 self.parse_create_schema().map(Statement::Schema)
4683 }
4684
4685 fn parse_graph_type_body(&mut self) -> Result<(Vec<String>, Vec<String>, bool)> {
4689 self.expect(TokenKind::LBrace)?;
4690
4691 let mut node_types = Vec::new();
4692 let mut edge_types = Vec::new();
4693 let mut open = false;
4694
4695 while self.current.kind != TokenKind::RBrace && self.current.kind != TokenKind::Eof {
4696 if self.is_identifier() {
4697 let key = self.get_identifier_name();
4698 self.advance();
4699 self.expect(TokenKind::Colon)?;
4700
4701 match key.to_uppercase().as_str() {
4702 "NODE_TYPES" | "NODETYPES" => {
4703 node_types = self.parse_identifier_list()?;
4704 }
4705 "EDGE_TYPES" | "EDGETYPES" => {
4706 edge_types = self.parse_identifier_list()?;
4707 }
4708 "OPEN" => {
4709 if self.current.kind == TokenKind::True {
4710 open = true;
4711 self.advance();
4712 } else if self.current.kind == TokenKind::False {
4713 open = false;
4714 self.advance();
4715 } else {
4716 return Err(self.error("Expected true or false for 'open'"));
4717 }
4718 }
4719 _ => return Err(self.error("Expected node_types, edge_types, or open")),
4720 }
4721
4722 if self.current.kind == TokenKind::Comma {
4724 self.advance();
4725 }
4726 } else {
4727 return Err(self.error("Expected property name in graph type body"));
4728 }
4729 }
4730
4731 self.expect(TokenKind::RBrace)?;
4732 Ok((node_types, edge_types, open))
4733 }
4734
4735 fn parse_graph_type_iso_body(&mut self) -> Result<Vec<InlineElementType>> {
4743 self.expect(TokenKind::LParen)?;
4744
4745 if self.current.kind == TokenKind::LParen {
4748 self.parse_graph_type_pattern_body()
4749 } else {
4750 self.parse_graph_type_verbose_body()
4751 }
4752 }
4753
4754 fn parse_graph_type_verbose_body(&mut self) -> Result<Vec<InlineElementType>> {
4757 let mut types = Vec::new();
4758
4759 while self.current.kind != TokenKind::RParen && self.current.kind != TokenKind::Eof {
4760 let is_node = if self.current.kind == TokenKind::Node {
4761 self.advance();
4762 self.expect(TokenKind::Type)?;
4763 true
4764 } else if self.current.kind == TokenKind::Edge {
4765 self.advance();
4766 self.expect(TokenKind::Type)?;
4767 false
4768 } else {
4769 return Err(self.error("Expected NODE TYPE or EDGE TYPE in graph type body"));
4770 };
4771
4772 if !self.is_identifier() && !self.is_label_or_type_name() {
4773 return Err(self.error("Expected type name"));
4774 }
4775 let type_name = self.get_identifier_name();
4776 self.advance();
4777
4778 let key_labels =
4780 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("KEY") {
4781 self.advance();
4782 self.expect(TokenKind::LParen)?;
4783 let mut labels = Vec::new();
4784 loop {
4785 if !self.is_identifier() && !self.is_label_or_type_name() {
4786 return Err(self.error("Expected label name in KEY clause"));
4787 }
4788 labels.push(self.get_identifier_name());
4789 self.advance();
4790 if self.current.kind != TokenKind::Comma {
4791 break;
4792 }
4793 self.advance();
4794 }
4795 self.expect(TokenKind::RParen)?;
4796 labels
4797 } else {
4798 Vec::new()
4799 };
4800
4801 let properties = if self.current.kind == TokenKind::LParen {
4803 self.parse_property_definitions()?
4804 } else {
4805 Vec::new()
4806 };
4807
4808 if is_node {
4809 types.push(InlineElementType::Node {
4810 name: type_name,
4811 properties,
4812 key_labels,
4813 });
4814 } else {
4815 types.push(InlineElementType::Edge {
4816 name: type_name,
4817 properties,
4818 key_labels,
4819 source_node_types: Vec::new(),
4820 target_node_types: Vec::new(),
4821 });
4822 }
4823
4824 if self.current.kind == TokenKind::Comma {
4826 self.advance();
4827 }
4828 }
4829
4830 self.expect(TokenKind::RParen)?;
4831 Ok(types)
4832 }
4833
4834 fn parse_graph_type_pattern_body(&mut self) -> Result<Vec<InlineElementType>> {
4838 let mut types = Vec::new();
4839 let mut seen_node_types = std::collections::HashSet::new();
4841
4842 while self.current.kind != TokenKind::RParen && self.current.kind != TokenKind::Eof {
4843 let (src_label, src_props) = self.parse_graph_type_node_pattern()?;
4845
4846 if self.current.kind == TokenKind::Minus || self.current.kind == TokenKind::LeftArrow {
4848 let backward = self.current.kind == TokenKind::LeftArrow;
4849 if backward {
4850 self.advance(); } else {
4853 self.advance(); }
4856
4857 self.expect(TokenKind::LBracket)?;
4858
4859 self.expect(TokenKind::Colon)?;
4861 if !self.is_identifier() && !self.is_label_or_type_name() {
4862 return Err(self.error("Expected edge type name after `:` in pattern"));
4863 }
4864 let edge_label = self.get_identifier_name();
4865 self.advance();
4866
4867 let edge_props = if self.current.kind == TokenKind::LBrace {
4869 self.parse_property_definitions_braces()?
4870 } else {
4871 Vec::new()
4872 };
4873
4874 self.expect(TokenKind::RBracket)?;
4875
4876 let forward = if self.current.kind == TokenKind::Arrow {
4878 self.advance(); true
4880 } else if self.current.kind == TokenKind::Minus {
4881 self.advance(); false
4883 } else {
4884 return Err(self.error("Expected `->` or `-` after edge pattern `]`"));
4885 };
4886
4887 let (tgt_label, tgt_props) = self.parse_graph_type_node_pattern()?;
4889
4890 let (effective_src, effective_tgt) = if backward {
4892 (tgt_label.clone(), src_label.clone())
4893 } else {
4894 (src_label.clone(), tgt_label.clone())
4895 };
4896
4897 let (src_types, tgt_types) = if !forward && !backward {
4898 (
4900 vec![src_label.clone(), tgt_label.clone()],
4901 vec![src_label.clone(), tgt_label.clone()],
4902 )
4903 } else {
4904 (vec![effective_src], vec![effective_tgt])
4905 };
4906
4907 if seen_node_types.insert(src_label.clone()) {
4909 types.push(InlineElementType::Node {
4910 name: src_label,
4911 properties: src_props,
4912 key_labels: Vec::new(),
4913 });
4914 }
4915 if seen_node_types.insert(tgt_label.clone()) {
4916 types.push(InlineElementType::Node {
4917 name: tgt_label,
4918 properties: tgt_props,
4919 key_labels: Vec::new(),
4920 });
4921 }
4922
4923 types.push(InlineElementType::Edge {
4925 name: edge_label,
4926 properties: edge_props,
4927 key_labels: Vec::new(),
4928 source_node_types: src_types,
4929 target_node_types: tgt_types,
4930 });
4931 } else {
4932 if seen_node_types.insert(src_label.clone()) {
4934 types.push(InlineElementType::Node {
4935 name: src_label,
4936 properties: src_props,
4937 key_labels: Vec::new(),
4938 });
4939 }
4940 }
4941
4942 if self.current.kind == TokenKind::Comma {
4944 self.advance();
4945 }
4946 }
4947
4948 self.expect(TokenKind::RParen)?;
4949 Ok(types)
4950 }
4951
4952 fn parse_graph_type_node_pattern(&mut self) -> Result<(String, Vec<PropertyDefinition>)> {
4956 self.expect(TokenKind::LParen)?;
4957 self.expect(TokenKind::Colon)?;
4958
4959 if !self.is_identifier() && !self.is_label_or_type_name() {
4960 return Err(self.error("Expected label name in node pattern"));
4961 }
4962 let label = self.get_identifier_name();
4963 self.advance();
4964
4965 let properties = if self.current.kind == TokenKind::LBrace {
4967 self.parse_property_definitions_braces()?
4968 } else {
4969 Vec::new()
4970 };
4971
4972 self.expect(TokenKind::RParen)?;
4973 Ok((label, properties))
4974 }
4975
4976 fn parse_identifier_list(&mut self) -> Result<Vec<String>> {
4978 self.expect(TokenKind::LBracket)?;
4979 let mut items = Vec::new();
4980
4981 if self.current.kind != TokenKind::RBracket {
4982 loop {
4983 if !self.is_identifier() && !self.is_label_or_type_name() {
4984 return Err(self.error("Expected identifier in list"));
4985 }
4986 items.push(self.get_identifier_name());
4987 self.advance();
4988 if self.current.kind != TokenKind::Comma {
4989 break;
4990 }
4991 self.advance();
4992 }
4993 }
4994
4995 self.expect(TokenKind::RBracket)?;
4996 Ok(items)
4997 }
4998
4999 fn parse_drop(&mut self) -> Result<Statement> {
5004 self.advance(); match self.current.kind {
5007 TokenKind::Node => {
5008 self.advance();
5010 self.expect(TokenKind::Type)?;
5011 let if_exists = self.try_parse_if_exists();
5012 if !self.is_identifier() {
5013 return Err(self.error("Expected type name"));
5014 }
5015 let name = self.get_identifier_name();
5016 self.advance();
5017 Ok(Statement::Schema(SchemaStatement::DropNodeType {
5018 name,
5019 if_exists,
5020 }))
5021 }
5022 TokenKind::Edge => {
5023 self.advance();
5025 self.expect(TokenKind::Type)?;
5026 let if_exists = self.try_parse_if_exists();
5027 if !self.is_identifier() {
5028 return Err(self.error("Expected type name"));
5029 }
5030 let name = self.get_identifier_name();
5031 self.advance();
5032 Ok(Statement::Schema(SchemaStatement::DropEdgeType {
5033 name,
5034 if_exists,
5035 }))
5036 }
5037 TokenKind::Index => {
5038 self.advance();
5040 let if_exists = self.try_parse_if_exists();
5041 if !self.is_identifier() {
5042 return Err(self.error("Expected index name"));
5043 }
5044 let name = self.get_identifier_name();
5045 self.advance();
5046 Ok(Statement::Schema(SchemaStatement::DropIndex {
5047 name,
5048 if_exists,
5049 }))
5050 }
5051 _ if self.is_identifier()
5052 && self
5053 .get_identifier_name()
5054 .eq_ignore_ascii_case("CONSTRAINT") =>
5055 {
5056 self.advance(); let if_exists = self.try_parse_if_exists();
5059 if !self.is_identifier() {
5060 return Err(self.error("Expected constraint name"));
5061 }
5062 let name = self.get_identifier_name();
5063 self.advance();
5064 Ok(Statement::Schema(SchemaStatement::DropConstraint {
5065 name,
5066 if_exists,
5067 }))
5068 }
5069 _ if self.is_identifier()
5070 && self.get_identifier_name().eq_ignore_ascii_case("SCHEMA") =>
5071 {
5072 self.advance(); let if_exists = self.try_parse_if_exists();
5075 if !self.is_identifier() {
5076 return Err(self.error("Expected schema name"));
5077 }
5078 let name = self.get_identifier_name();
5079 self.advance();
5080 Ok(Statement::Schema(SchemaStatement::DropSchema {
5081 name,
5082 if_exists,
5083 }))
5084 }
5085 _ if self.is_identifier()
5086 && self.get_identifier_name().eq_ignore_ascii_case("PROCEDURE") =>
5087 {
5088 self.advance(); let if_exists = self.try_parse_if_exists();
5091 if !self.is_identifier() {
5092 return Err(self.error("Expected procedure name"));
5093 }
5094 let name = self.get_identifier_name();
5095 self.advance();
5096 Ok(Statement::Schema(SchemaStatement::DropProcedure {
5097 name,
5098 if_exists,
5099 }))
5100 }
5101 _ if self.is_identifier()
5102 && self.get_identifier_name().eq_ignore_ascii_case("GRAPH") =>
5103 {
5104 if self.peek_kind() == TokenKind::Type {
5107 self.advance(); self.advance(); let if_exists = self.try_parse_if_exists();
5111 if !self.is_identifier() {
5112 return Err(self.error("Expected graph type name"));
5113 }
5114 let name = self.get_identifier_name();
5115 self.advance();
5116 Ok(Statement::Schema(SchemaStatement::DropGraphType {
5117 name,
5118 if_exists,
5119 }))
5120 } else {
5121 self.parse_drop_graph_body().map(Statement::SessionCommand)
5123 }
5124 }
5125 _ => {
5126 self.parse_drop_graph_body().map(Statement::SessionCommand)
5128 }
5129 }
5130 }
5131
5132 fn parse_alter(&mut self) -> Result<Statement> {
5134 let span_start = self.current.span.start;
5135 self.advance(); match self.current.kind {
5138 TokenKind::Node => {
5139 self.advance();
5141 self.expect(TokenKind::Type)?;
5142 self.parse_alter_type(true, span_start)
5143 }
5144 TokenKind::Edge => {
5145 self.advance();
5147 self.expect(TokenKind::Type)?;
5148 self.parse_alter_type(false, span_start)
5149 }
5150 _ if self.is_identifier()
5151 && self.get_identifier_name().eq_ignore_ascii_case("GRAPH") =>
5152 {
5153 self.advance(); self.expect(TokenKind::Type)?;
5156 self.parse_alter_graph_type(span_start)
5157 }
5158 _ => Err(self.error("Expected NODE, EDGE, or GRAPH after ALTER")),
5159 }
5160 }
5161
5162 fn parse_alter_type(&mut self, is_node: bool, span_start: usize) -> Result<Statement> {
5164 if !self.is_identifier() {
5165 return Err(self.error("Expected type name"));
5166 }
5167 let name = self.get_identifier_name();
5168 self.advance();
5169
5170 let mut alterations = Vec::new();
5171 loop {
5172 if !self.is_identifier() {
5173 break;
5174 }
5175 let action = self.get_identifier_name().to_uppercase();
5176 match action.as_str() {
5177 "ADD" => {
5178 self.advance();
5179 if !self.is_identifier() {
5181 return Err(self.error("Expected property name after ADD"));
5182 }
5183 let prop_name = self.get_identifier_name();
5184 self.advance();
5185 if !self.is_identifier() {
5186 return Err(self.error("Expected type name"));
5187 }
5188 let data_type = self.get_identifier_name();
5189 self.advance();
5190 let nullable = if self.current.kind == TokenKind::Not {
5191 self.advance();
5192 if self.current.kind != TokenKind::Null {
5193 return Err(self.error("Expected NULL after NOT"));
5194 }
5195 self.advance();
5196 false
5197 } else {
5198 true
5199 };
5200 let default_value = if self.is_identifier()
5202 && self.get_identifier_name().eq_ignore_ascii_case("DEFAULT")
5203 {
5204 self.advance();
5205 let lit = match self.current.kind {
5206 TokenKind::String
5207 | TokenKind::Integer
5208 | TokenKind::Float
5209 | TokenKind::True
5210 | TokenKind::False
5211 | TokenKind::Null => self.current.text.clone(),
5212 _ => return Err(self.error("Expected literal value after DEFAULT")),
5213 };
5214 self.advance();
5215 Some(lit)
5216 } else {
5217 None
5218 };
5219 alterations.push(TypeAlteration::AddProperty(PropertyDefinition {
5220 name: prop_name,
5221 data_type,
5222 nullable,
5223 default_value,
5224 }));
5225 }
5226 "DROP" => {
5227 self.advance();
5228 if !self.is_identifier() {
5229 return Err(self.error("Expected property name after DROP"));
5230 }
5231 let prop_name = self.get_identifier_name();
5232 self.advance();
5233 alterations.push(TypeAlteration::DropProperty(prop_name));
5234 }
5235 _ => break,
5236 }
5237 }
5238
5239 if alterations.is_empty() {
5240 return Err(self.error("Expected ADD or DROP alteration"));
5241 }
5242
5243 let span = Some(SourceSpan::new(span_start, self.current.span.end, 1, 1));
5244 let stmt = AlterTypeStatement {
5245 name,
5246 alterations,
5247 span,
5248 };
5249 if is_node {
5250 Ok(Statement::Schema(SchemaStatement::AlterNodeType(stmt)))
5251 } else {
5252 Ok(Statement::Schema(SchemaStatement::AlterEdgeType(stmt)))
5253 }
5254 }
5255
5256 fn parse_alter_graph_type(&mut self, span_start: usize) -> Result<Statement> {
5258 if !self.is_identifier() {
5259 return Err(self.error("Expected graph type name"));
5260 }
5261 let name = self.get_identifier_name();
5262 self.advance();
5263
5264 let mut alterations = Vec::new();
5265 loop {
5266 if !self.is_identifier() {
5267 break;
5268 }
5269 let action = self.get_identifier_name().to_uppercase();
5270 match action.as_str() {
5271 "ADD" => {
5272 self.advance();
5273 let kind = self.current.kind;
5275 match kind {
5276 TokenKind::Node => {
5277 self.advance();
5278 self.expect(TokenKind::Type)?;
5279 if !self.is_identifier() {
5280 return Err(self.error("Expected node type name"));
5281 }
5282 let type_name = self.get_identifier_name();
5283 self.advance();
5284 alterations.push(GraphTypeAlteration::AddNodeType(type_name));
5285 }
5286 TokenKind::Edge => {
5287 self.advance();
5288 self.expect(TokenKind::Type)?;
5289 if !self.is_identifier() {
5290 return Err(self.error("Expected edge type name"));
5291 }
5292 let type_name = self.get_identifier_name();
5293 self.advance();
5294 alterations.push(GraphTypeAlteration::AddEdgeType(type_name));
5295 }
5296 _ => return Err(self.error("Expected NODE or EDGE after ADD")),
5297 }
5298 }
5299 "DROP" => {
5300 self.advance();
5301 let kind = self.current.kind;
5302 match kind {
5303 TokenKind::Node => {
5304 self.advance();
5305 self.expect(TokenKind::Type)?;
5306 if !self.is_identifier() {
5307 return Err(self.error("Expected node type name"));
5308 }
5309 let type_name = self.get_identifier_name();
5310 self.advance();
5311 alterations.push(GraphTypeAlteration::DropNodeType(type_name));
5312 }
5313 TokenKind::Edge => {
5314 self.advance();
5315 self.expect(TokenKind::Type)?;
5316 if !self.is_identifier() {
5317 return Err(self.error("Expected edge type name"));
5318 }
5319 let type_name = self.get_identifier_name();
5320 self.advance();
5321 alterations.push(GraphTypeAlteration::DropEdgeType(type_name));
5322 }
5323 _ => return Err(self.error("Expected NODE or EDGE after DROP")),
5324 }
5325 }
5326 _ => break,
5327 }
5328 }
5329
5330 if alterations.is_empty() {
5331 return Err(self.error("Expected ADD or DROP alteration"));
5332 }
5333
5334 let span = Some(SourceSpan::new(span_start, self.current.span.end, 1, 1));
5335 Ok(Statement::Schema(SchemaStatement::AlterGraphType(
5336 AlterGraphTypeStatement {
5337 name,
5338 alterations,
5339 span,
5340 },
5341 )))
5342 }
5343
5344 fn parse_property_definitions(&mut self) -> Result<Vec<PropertyDefinition>> {
5345 self.expect(TokenKind::LParen)?;
5346
5347 let mut defs = Vec::new();
5348
5349 if self.current.kind != TokenKind::RParen {
5350 loop {
5351 if !self.is_identifier() {
5352 return Err(self.error("Expected property name"));
5353 }
5354 let name = self.get_identifier_name();
5355 self.advance();
5356
5357 if !self.is_identifier() {
5358 return Err(self.error("Expected type name"));
5359 }
5360 let data_type = self.get_identifier_name();
5361 self.advance();
5362
5363 let nullable = if self.current.kind == TokenKind::Not {
5364 self.advance();
5365 if self.current.kind != TokenKind::Null {
5366 return Err(self.error("Expected NULL after NOT"));
5367 }
5368 self.advance();
5369 false
5370 } else {
5371 true
5372 };
5373
5374 let default_value = if self.is_identifier()
5376 && self.get_identifier_name().eq_ignore_ascii_case("DEFAULT")
5377 {
5378 self.advance();
5379 let lit = match self.current.kind {
5380 TokenKind::String
5381 | TokenKind::Integer
5382 | TokenKind::Float
5383 | TokenKind::True
5384 | TokenKind::False
5385 | TokenKind::Null => self.current.text.clone(),
5386 _ => return Err(self.error("Expected literal value after DEFAULT")),
5387 };
5388 self.advance();
5389 Some(lit)
5390 } else {
5391 None
5392 };
5393
5394 defs.push(PropertyDefinition {
5395 name,
5396 data_type,
5397 nullable,
5398 default_value,
5399 });
5400
5401 if self.current.kind != TokenKind::Comma {
5402 break;
5403 }
5404 self.advance();
5405 }
5406 }
5407
5408 self.expect(TokenKind::RParen)?;
5409 Ok(defs)
5410 }
5411
5412 fn parse_property_definitions_braces(&mut self) -> Result<Vec<PropertyDefinition>> {
5416 self.expect(TokenKind::LBrace)?;
5417
5418 let mut defs = Vec::new();
5419
5420 if self.current.kind != TokenKind::RBrace {
5421 loop {
5422 if !self.is_identifier() {
5423 return Err(self.error("Expected property name"));
5424 }
5425 let name = self.get_identifier_name();
5426 self.advance();
5427
5428 if !self.is_identifier() {
5429 return Err(self.error("Expected type name"));
5430 }
5431 let data_type = self.get_identifier_name();
5432 self.advance();
5433
5434 let nullable = if self.current.kind == TokenKind::Not {
5435 self.advance();
5436 if self.current.kind != TokenKind::Null {
5437 return Err(self.error("Expected NULL after NOT"));
5438 }
5439 self.advance();
5440 false
5441 } else {
5442 true
5443 };
5444
5445 let default_value = if self.is_identifier()
5447 && self.get_identifier_name().eq_ignore_ascii_case("DEFAULT")
5448 {
5449 self.advance();
5450 let lit = match self.current.kind {
5451 TokenKind::String
5452 | TokenKind::Integer
5453 | TokenKind::Float
5454 | TokenKind::True
5455 | TokenKind::False
5456 | TokenKind::Null => self.current.text.clone(),
5457 _ => return Err(self.error("Expected literal value after DEFAULT")),
5458 };
5459 self.advance();
5460 Some(lit)
5461 } else {
5462 None
5463 };
5464
5465 defs.push(PropertyDefinition {
5466 name,
5467 data_type,
5468 nullable,
5469 default_value,
5470 });
5471
5472 if self.current.kind != TokenKind::Comma {
5473 break;
5474 }
5475 self.advance();
5476 }
5477 }
5478
5479 self.expect(TokenKind::RBrace)?;
5480 Ok(defs)
5481 }
5482
5483 fn parse_show(&mut self) -> Result<SchemaStatement> {
5494 self.advance(); if !self.is_identifier()
5497 && self.current.kind != TokenKind::Node
5498 && self.current.kind != TokenKind::Edge
5499 && self.current.kind != TokenKind::Index
5500 {
5501 return Err(self.error(
5502 "Expected CONSTRAINTS, INDEXES, NODE TYPES, EDGE TYPES, GRAPHS, GRAPH TYPES, or GRAPH TYPE <name> after SHOW",
5503 ));
5504 }
5505
5506 match self.current.kind {
5507 TokenKind::Node => {
5508 self.advance();
5510 if self.current.kind != TokenKind::Type
5511 && !(self.is_identifier()
5512 && self.get_identifier_name().eq_ignore_ascii_case("TYPES"))
5513 {
5514 return Err(self.error("Expected TYPES after SHOW NODE"));
5515 }
5516 self.advance();
5517 Ok(SchemaStatement::ShowNodeTypes)
5518 }
5519 TokenKind::Edge => {
5520 self.advance();
5522 if self.current.kind != TokenKind::Type
5523 && !(self.is_identifier()
5524 && self.get_identifier_name().eq_ignore_ascii_case("TYPES"))
5525 {
5526 return Err(self.error("Expected TYPES after SHOW EDGE"));
5527 }
5528 self.advance();
5529 Ok(SchemaStatement::ShowEdgeTypes)
5530 }
5531 TokenKind::Index => {
5532 self.advance();
5534 Ok(SchemaStatement::ShowIndexes)
5537 }
5538 _ => {
5539 let name = self.get_identifier_name();
5540 match name.to_uppercase().as_str() {
5541 "CONSTRAINTS" => {
5542 self.advance();
5543 Ok(SchemaStatement::ShowConstraints)
5544 }
5545 "INDEXES" => {
5546 self.advance();
5547 Ok(SchemaStatement::ShowIndexes)
5548 }
5549 "GRAPHS" => {
5550 self.advance();
5551 Ok(SchemaStatement::ShowGraphs)
5552 }
5553 "SCHEMAS" => {
5554 self.advance();
5555 Ok(SchemaStatement::ShowSchemas)
5556 }
5557 "GRAPH" => {
5558 self.advance();
5559 if self.current.kind == TokenKind::Type {
5561 self.advance();
5562 if !self.is_identifier() {
5564 return Err(self.error("Expected graph type name after SHOW GRAPH TYPE"));
5565 }
5566 let type_name = self.get_identifier_name();
5567 self.advance();
5568 Ok(SchemaStatement::ShowGraphType(type_name))
5569 } else if self.is_identifier()
5570 && self.get_identifier_name().eq_ignore_ascii_case("TYPES")
5571 {
5572 self.advance();
5574 Ok(SchemaStatement::ShowGraphTypes)
5575 } else {
5576 Err(self.error("Expected TYPE <name> or TYPES after SHOW GRAPH"))
5577 }
5578 }
5579 _ => Err(self.error(
5580 "Expected CONSTRAINTS, INDEXES, NODE TYPES, EDGE TYPES, GRAPHS, GRAPH TYPES, or GRAPH TYPE <name> after SHOW",
5581 )),
5582 }
5583 }
5584 }
5585 }
5586
5587 fn advance(&mut self) {
5588 if let Some(peeked) = self.peeked.take() {
5589 self.current = peeked;
5590 self.peeked = self.peeked_second.take();
5592 } else {
5593 self.current = self.lexer.next_token();
5594 }
5595 }
5596
5597 fn expect(&mut self, kind: TokenKind) -> Result<()> {
5598 if self.current.kind == kind {
5599 self.advance();
5600 Ok(())
5601 } else {
5602 Err(self.error(&format!("Expected {:?}", kind)))
5603 }
5604 }
5605
5606 fn peek_kind(&mut self) -> TokenKind {
5607 if self.peeked.is_none() {
5608 self.peeked = Some(self.lexer.next_token());
5609 }
5610 self.peeked
5611 .as_ref()
5612 .expect("peeked token was just populated")
5613 .kind
5614 }
5615
5616 fn peek_second_kind(&mut self) -> TokenKind {
5618 let _ = self.peek_kind();
5620 if self.peeked_second.is_none() {
5621 self.peeked_second = Some(self.lexer.next_token());
5622 }
5623 self.peeked_second
5624 .as_ref()
5625 .expect("peeked_second token was just populated")
5626 .kind
5627 }
5628
5629 fn peek_text_upper(&self) -> String {
5632 self.peeked
5633 .as_ref()
5634 .map(|t| t.text.to_uppercase())
5635 .unwrap_or_default()
5636 }
5637
5638 fn peek_is_graph_instance_keyword(&mut self) -> bool {
5643 let pk = self.peek_kind();
5644 if pk != TokenKind::Identifier {
5645 return false;
5646 }
5647 let text = self.peek_text_upper();
5648 if text == "PROPERTY" {
5649 return true; }
5651 if text == "GRAPH" {
5652 let peeked_token = self
5655 .peeked
5656 .as_ref()
5657 .expect("peek_kind guarantees peeked is Some");
5658 let remaining = &self.source[peeked_token.span.end..];
5659 let mut temp_lexer = Lexer::new(remaining);
5660 let next_after_graph = temp_lexer.next_token();
5661 return next_after_graph.kind != TokenKind::Type;
5663 }
5664 false
5665 }
5666
5667 fn parse_create_procedure(&mut self, or_replace: bool) -> Result<SchemaStatement> {
5669 let if_not_exists = self.try_parse_if_not_exists();
5670
5671 if !self.is_identifier() {
5672 return Err(self.error("Expected procedure name"));
5673 }
5674 let name = self.get_identifier_name();
5675 self.advance();
5676
5677 self.expect(TokenKind::LParen)?;
5679 let mut params = Vec::new();
5680 if self.current.kind != TokenKind::RParen {
5681 loop {
5682 if !self.is_identifier() {
5683 return Err(self.error("Expected parameter name"));
5684 }
5685 let param_name = self.get_identifier_name();
5686 self.advance();
5687
5688 if !self.is_identifier() {
5689 return Err(self.error("Expected parameter type"));
5690 }
5691 let param_type = self.get_identifier_name().to_uppercase();
5692 self.advance();
5693
5694 params.push(ProcedureParam {
5695 name: param_name,
5696 param_type,
5697 });
5698
5699 if self.current.kind != TokenKind::Comma {
5700 break;
5701 }
5702 self.advance();
5703 }
5704 }
5705 self.expect(TokenKind::RParen)?;
5706
5707 let mut returns = Vec::new();
5709 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("RETURNS") {
5710 self.advance();
5711 self.expect(TokenKind::LParen)?;
5712 if self.current.kind != TokenKind::RParen {
5713 loop {
5714 if !self.is_identifier() {
5715 return Err(self.error("Expected return column name"));
5716 }
5717 let col_name = self.get_identifier_name();
5718 self.advance();
5719
5720 if !self.is_identifier() {
5721 return Err(self.error("Expected return column type"));
5722 }
5723 let col_type = self.get_identifier_name().to_uppercase();
5724 self.advance();
5725
5726 returns.push(ProcedureReturn {
5727 name: col_name,
5728 return_type: col_type,
5729 });
5730
5731 if self.current.kind != TokenKind::Comma {
5732 break;
5733 }
5734 self.advance();
5735 }
5736 }
5737 self.expect(TokenKind::RParen)?;
5738 }
5739
5740 if self.current.kind == TokenKind::As {
5742 self.advance();
5743 } else {
5744 return Err(self.error("Expected AS before procedure body"));
5745 }
5746
5747 self.expect(TokenKind::LBrace)?;
5749 let body_start = self.current.span.start;
5750 let mut depth = 1u32;
5751 while depth > 0 && self.current.kind != TokenKind::Eof {
5752 if self.current.kind == TokenKind::LBrace {
5753 depth += 1;
5754 } else if self.current.kind == TokenKind::RBrace {
5755 depth -= 1;
5756 if depth == 0 {
5757 break;
5758 }
5759 }
5760 self.advance();
5761 }
5762 let body_end = self.current.span.start;
5763 let body = self.source[body_start..body_end].trim().to_string();
5764 self.expect(TokenKind::RBrace)?;
5765
5766 Ok(SchemaStatement::CreateProcedure(CreateProcedureStatement {
5767 name,
5768 params,
5769 returns,
5770 body,
5771 if_not_exists,
5772 or_replace,
5773 span: None,
5774 }))
5775 }
5776
5777 fn parse_create_graph(&mut self) -> Result<SessionCommand> {
5779 self.expect(TokenKind::Create)?;
5780
5781 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("PROPERTY") {
5783 self.advance();
5784 }
5785
5786 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("GRAPH") {
5788 return Err(self.error("Expected GRAPH after CREATE"));
5789 }
5790 self.advance();
5791
5792 let if_not_exists = if self.is_identifier()
5794 && self.get_identifier_name().eq_ignore_ascii_case("IF")
5795 {
5796 self.advance();
5797 if !(self.current.kind == TokenKind::Not
5798 || (self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("NOT")))
5799 {
5800 return Err(self.error("Expected NOT after IF"));
5801 }
5802 self.advance();
5803 if self.current.kind != TokenKind::Exists
5804 && (!self.is_identifier()
5805 || !self.get_identifier_name().eq_ignore_ascii_case("EXISTS"))
5806 {
5807 return Err(self.error("Expected EXISTS after IF NOT"));
5808 }
5809 self.advance();
5810 true
5811 } else {
5812 false
5813 };
5814
5815 if !self.is_identifier() {
5817 return Err(self.error("Expected graph name"));
5818 }
5819 let name = self.get_identifier_name();
5820 self.advance();
5821
5822 let mut open = false;
5824 let typed = if self.is_identifier()
5825 && self.get_identifier_name().eq_ignore_ascii_case("TYPED")
5826 {
5827 self.advance();
5828 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("ANY") {
5830 self.advance();
5831 if self.is_identifier()
5833 && self.get_identifier_name().eq_ignore_ascii_case("PROPERTY")
5834 {
5835 self.advance();
5836 }
5837 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("GRAPH")
5839 {
5840 self.advance();
5841 }
5842 open = true;
5843 None } else if self.is_identifier() {
5845 let type_name = self.get_identifier_name();
5846 self.advance();
5847 Some(type_name)
5848 } else {
5849 return Err(self.error("Expected graph type name or ANY after TYPED"));
5850 }
5851 } else if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("ANY") {
5852 self.advance();
5854 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("PROPERTY") {
5855 self.advance();
5856 }
5857 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("GRAPH") {
5858 self.advance();
5859 }
5860 open = true;
5861 None } else {
5863 None
5864 };
5865
5866 let like_graph = if self.current.kind == TokenKind::Like {
5868 self.advance();
5869 if !self.is_identifier() {
5870 return Err(self.error("Expected graph name after LIKE"));
5871 }
5872 let source = self.get_identifier_name();
5873 self.advance();
5874 Some(source)
5875 } else {
5876 None
5877 };
5878
5879 let copy_of = if self.current.kind == TokenKind::As {
5881 self.advance();
5882 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("COPY") {
5883 return Err(self.error("Expected COPY after AS"));
5884 }
5885 self.advance();
5886 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("OF") {
5887 return Err(self.error("Expected OF after COPY"));
5888 }
5889 self.advance();
5890 if !self.is_identifier() {
5891 return Err(self.error("Expected graph name after AS COPY OF"));
5892 }
5893 let source = self.get_identifier_name();
5894 self.advance();
5895 Some(source)
5896 } else {
5897 None
5898 };
5899
5900 Ok(SessionCommand::CreateGraph {
5901 name,
5902 if_not_exists,
5903 typed,
5904 like_graph,
5905 copy_of,
5906 open,
5907 })
5908 }
5909
5910 fn parse_drop_graph_body(&mut self) -> Result<SessionCommand> {
5913 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("PROPERTY") {
5915 self.advance();
5916 }
5917
5918 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("GRAPH") {
5920 return Err(
5921 self.error("Expected GRAPH, NODE TYPE, EDGE TYPE, INDEX, or CONSTRAINT after DROP")
5922 );
5923 }
5924 self.advance();
5925
5926 let if_exists = self.try_parse_if_exists();
5928
5929 if !self.is_identifier() {
5931 return Err(self.error("Expected graph name"));
5932 }
5933 let name = self.get_identifier_name();
5934 self.advance();
5935
5936 Ok(SessionCommand::DropGraph { name, if_exists })
5937 }
5938
5939 fn parse_use_graph(&mut self) -> Result<SessionCommand> {
5941 self.advance(); if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("GRAPH") {
5945 return Err(self.error("Expected GRAPH after USE"));
5946 }
5947 self.advance();
5948
5949 if !self.is_identifier() {
5951 return Err(self.error("Expected graph name"));
5952 }
5953 let name = self.get_identifier_name();
5954 self.advance();
5955
5956 Ok(SessionCommand::UseGraph(name))
5957 }
5958
5959 fn parse_session_command(&mut self) -> Result<SessionCommand> {
5961 self.advance(); if !self.is_identifier() {
5964 return Err(self.error("Expected SET, RESET, or CLOSE after SESSION"));
5965 }
5966
5967 let action = self.get_identifier_name();
5968 match action.to_uppercase().as_str() {
5969 "SET" => {
5970 self.advance(); self.parse_session_set()
5972 }
5973 "RESET" => {
5974 self.advance(); self.parse_session_reset()
5977 }
5978 "CLOSE" => {
5979 self.advance(); Ok(SessionCommand::SessionClose)
5981 }
5982 _ => Err(self.error("Expected SET, RESET, or CLOSE after SESSION")),
5983 }
5984 }
5985
5986 fn parse_session_set(&mut self) -> Result<SessionCommand> {
5988 if !self.is_identifier() {
5989 return Err(self.error("Expected GRAPH, TIME, SCHEMA, or PARAMETER after SESSION SET"));
5990 }
5991
5992 let keyword = self.get_identifier_name();
5993 match keyword.to_uppercase().as_str() {
5994 "GRAPH" => {
5995 self.advance(); if !self.is_identifier() {
5997 return Err(self.error("Expected graph name"));
5998 }
5999 let name = self.get_identifier_name();
6000 self.advance();
6001 Ok(SessionCommand::SessionSetGraph(name))
6002 }
6003 "TIME" => {
6004 self.advance(); if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("ZONE")
6007 {
6008 return Err(self.error("Expected ZONE after TIME"));
6009 }
6010 self.advance();
6011 if self.current.kind != TokenKind::String {
6013 return Err(self.error("Expected timezone string after TIME ZONE"));
6014 }
6015 let tz = self.current.text[1..self.current.text.len() - 1].to_string();
6016 self.advance();
6017 Ok(SessionCommand::SessionSetTimeZone(tz))
6018 }
6019 "SCHEMA" => {
6020 self.advance(); if !self.is_identifier() {
6022 return Err(self.error("Expected schema name"));
6023 }
6024 let name = self.get_identifier_name();
6025 self.advance();
6026 Ok(SessionCommand::SessionSetSchema(name))
6028 }
6029 "PARAMETER" => {
6030 self.advance(); let param_name = if self.current.kind == TokenKind::Parameter {
6033 let name = self.current.text[1..].to_string();
6034 self.advance();
6035 name
6036 } else if self.is_identifier() {
6037 let name = self.get_identifier_name();
6038 self.advance();
6039 name
6040 } else {
6041 return Err(self.error("Expected parameter name"));
6042 };
6043 self.expect(TokenKind::Eq)?;
6045 let value = self.parse_expression()?;
6047 Ok(SessionCommand::SessionSetParameter(param_name, value))
6048 }
6049 _ => Err(self.error("Expected GRAPH, TIME, SCHEMA, or PARAMETER after SESSION SET")),
6050 }
6051 }
6052
6053 fn parse_session_reset(&mut self) -> Result<SessionCommand> {
6062 use SessionResetTarget as T;
6063
6064 if self.current.kind == TokenKind::Eof {
6066 return Ok(SessionCommand::SessionReset(T::All));
6067 }
6068
6069 if self.current.kind == TokenKind::All {
6071 self.advance();
6072 if self.is_identifier() {
6073 let kw = self.get_identifier_name().to_uppercase();
6074 if kw == "PARAMETERS" {
6075 self.advance();
6076 return Ok(SessionCommand::SessionReset(T::Parameters));
6077 }
6078 if kw == "CHARACTERISTICS" {
6079 self.advance();
6080 }
6081 }
6082 return Ok(SessionCommand::SessionReset(T::All));
6083 }
6084
6085 if !self.is_identifier() {
6086 return Err(
6087 self.error("Expected SCHEMA, GRAPH, TIME, PARAMETERS, or ALL after SESSION RESET")
6088 );
6089 }
6090
6091 let kw = self.get_identifier_name().to_uppercase();
6092 match kw.as_str() {
6093 "SCHEMA" => {
6094 self.advance();
6095 Ok(SessionCommand::SessionReset(T::Schema))
6096 }
6097 "GRAPH" | "PROPERTY" => {
6098 self.advance();
6099 if kw == "PROPERTY"
6101 && self.is_identifier()
6102 && self.get_identifier_name().eq_ignore_ascii_case("GRAPH")
6103 {
6104 self.advance();
6105 }
6106 Ok(SessionCommand::SessionReset(T::Graph))
6107 }
6108 "TIME" => {
6109 self.advance();
6110 if self.is_identifier() && self.get_identifier_name().eq_ignore_ascii_case("ZONE") {
6111 self.advance();
6112 }
6113 Ok(SessionCommand::SessionReset(T::TimeZone))
6114 }
6115 "PARAMETERS" => {
6116 self.advance();
6117 Ok(SessionCommand::SessionReset(T::Parameters))
6118 }
6119 "CHARACTERISTICS" => {
6120 self.advance();
6121 Ok(SessionCommand::SessionReset(T::All))
6122 }
6123 _ => {
6124 Err(self
6125 .error("Expected SCHEMA, GRAPH, TIME, PARAMETERS, or ALL after SESSION RESET"))
6126 }
6127 }
6128 }
6129
6130 fn parse_start_transaction(&mut self) -> Result<SessionCommand> {
6132 self.advance(); if !self.is_identifier()
6134 || !self
6135 .get_identifier_name()
6136 .eq_ignore_ascii_case("TRANSACTION")
6137 {
6138 return Err(self.error("Expected TRANSACTION after START"));
6139 }
6140 self.advance(); let mut read_only = false;
6143 let mut isolation_level = None;
6144
6145 for _ in 0..2 {
6147 if !self.is_identifier() {
6148 break;
6149 }
6150 let kw = self.get_identifier_name().to_uppercase();
6151 match kw.as_str() {
6152 "READ" => {
6153 self.advance(); if !self.is_identifier() {
6155 return Err(self.error("Expected ONLY or WRITE after READ"));
6156 }
6157 let mode = self.get_identifier_name().to_uppercase();
6158 match mode.as_str() {
6159 "ONLY" => {
6160 self.advance();
6161 read_only = true;
6162 }
6163 "WRITE" | "COMMITTED" if mode == "WRITE" => {
6164 self.advance();
6165 read_only = false;
6166 }
6167 _ => return Err(self.error("Expected ONLY or WRITE after READ")),
6168 }
6169 }
6170 "ISOLATION" => {
6171 self.advance(); if !self.is_identifier()
6173 || !self.get_identifier_name().eq_ignore_ascii_case("LEVEL")
6174 {
6175 return Err(self.error("Expected LEVEL after ISOLATION"));
6176 }
6177 self.advance(); isolation_level = Some(self.parse_isolation_level_name()?);
6179 }
6180 _ => break,
6181 }
6182 }
6183
6184 Ok(SessionCommand::StartTransaction {
6185 read_only,
6186 isolation_level,
6187 })
6188 }
6189
6190 fn parse_isolation_level_name(&mut self) -> Result<TransactionIsolationLevel> {
6193 if !self.is_identifier() {
6194 return Err(self.error("Expected isolation level name"));
6195 }
6196 let name = self.get_identifier_name().to_uppercase();
6197 match name.as_str() {
6198 "READ" => {
6199 self.advance();
6200 if !self.is_identifier()
6201 || !self.get_identifier_name().eq_ignore_ascii_case("COMMITTED")
6202 {
6203 return Err(self.error("Expected COMMITTED after READ"));
6204 }
6205 self.advance();
6206 Ok(TransactionIsolationLevel::ReadCommitted)
6207 }
6208 "SNAPSHOT" => {
6209 self.advance();
6210 if self.is_identifier()
6212 && self.get_identifier_name().eq_ignore_ascii_case("ISOLATION")
6213 {
6214 self.advance();
6215 }
6216 Ok(TransactionIsolationLevel::SnapshotIsolation)
6217 }
6218 "REPEATABLE" => {
6219 self.advance();
6220 if !self.is_identifier() || !self.get_identifier_name().eq_ignore_ascii_case("READ")
6221 {
6222 return Err(self.error("Expected READ after REPEATABLE"));
6223 }
6224 self.advance();
6225 Ok(TransactionIsolationLevel::SnapshotIsolation)
6226 }
6227 "SERIALIZABLE" => {
6228 self.advance();
6229 Ok(TransactionIsolationLevel::Serializable)
6230 }
6231 _ => Err(self.error(&format!("Unknown isolation level: {name}"))),
6232 }
6233 }
6234
6235 fn error(&self, message: &str) -> Error {
6236 Error::Query(
6237 QueryError::new(QueryErrorKind::Syntax, message)
6238 .with_span(self.current.span)
6239 .with_source(self.source.to_string()),
6240 )
6241 }
6242}
6243
6244#[cfg(test)]
6245mod tests {
6246 use super::*;
6247
6248 #[test]
6249 fn test_parse_simple_match() {
6250 let mut parser = Parser::new("MATCH (n) RETURN n");
6251 let result = parser.parse();
6252 assert!(result.is_ok());
6253
6254 let stmt = result.unwrap();
6255 assert!(matches!(stmt, Statement::Query(_)));
6256 }
6257
6258 #[test]
6259 fn test_parse_match_with_label() {
6260 let mut parser = Parser::new("MATCH (n:Person) RETURN n");
6261 let result = parser.parse().unwrap();
6262 if let Statement::Query(query) = result {
6263 assert_eq!(query.match_clauses.len(), 1);
6264 if let Pattern::Node(node) = &query.match_clauses[0].patterns[0].pattern {
6265 assert_eq!(node.variable, Some("n".to_string()));
6266 assert_eq!(node.labels, vec!["Person".to_string()]);
6267 } else {
6268 panic!("Expected node pattern");
6269 }
6270 } else {
6271 panic!("Expected Query statement");
6272 }
6273 }
6274
6275 #[test]
6276 fn test_parse_match_with_where() {
6277 let mut parser = Parser::new("MATCH (n:Person) WHERE n.age > 30 RETURN n");
6278 let result = parser.parse().unwrap();
6279 if let Statement::Query(query) = result {
6280 assert!(
6281 query.where_clause.is_some(),
6282 "WHERE clause should be parsed"
6283 );
6284 let where_clause = query.where_clause.as_ref().unwrap();
6285 if let Expression::Binary { op, .. } = &where_clause.expression {
6286 assert_eq!(*op, BinaryOp::Gt);
6287 } else {
6288 panic!("Expected binary expression in WHERE clause");
6289 }
6290 } else {
6291 panic!("Expected Query statement");
6292 }
6293 }
6294
6295 #[test]
6296 fn test_parse_path_pattern() {
6297 let mut parser = Parser::new("MATCH (a)-[:KNOWS]->(b) RETURN a, b");
6298 let result = parser.parse().unwrap();
6299 if let Statement::Query(query) = result {
6300 if let Pattern::Path(path) = &query.match_clauses[0].patterns[0].pattern {
6301 assert_eq!(path.source.variable, Some("a".to_string()));
6302 assert_eq!(path.edges.len(), 1);
6303 assert_eq!(path.edges[0].types, vec!["KNOWS".to_string()]);
6304 assert_eq!(
6305 path.edges[0].direction,
6306 EdgeDirection::Outgoing,
6307 "Arrow should point outward"
6308 );
6309 assert_eq!(path.edges[0].target.variable, Some("b".to_string()));
6310 } else {
6311 panic!("Expected path pattern");
6312 }
6313 } else {
6314 panic!("Expected Query statement");
6315 }
6316 }
6317
6318 #[test]
6319 fn test_parse_insert() {
6320 let mut parser = Parser::new("INSERT (n:Person {name: 'Alix'})");
6321 let result = parser.parse().unwrap();
6322 if let Statement::DataModification(DataModificationStatement::Insert(insert)) = result {
6323 assert_eq!(insert.patterns.len(), 1);
6324 if let Pattern::Node(node) = &insert.patterns[0] {
6325 assert_eq!(node.labels, vec!["Person".to_string()]);
6326 assert_eq!(node.properties.len(), 1);
6327 assert_eq!(node.properties[0].0, "name");
6328 } else {
6329 panic!("Expected node pattern");
6330 }
6331 } else {
6332 panic!("Expected Insert statement");
6333 }
6334 }
6335
6336 #[test]
6337 fn test_parse_optional_match() {
6338 let mut parser =
6339 Parser::new("MATCH (a:Person) OPTIONAL MATCH (a)-[:KNOWS]->(b) RETURN a, b");
6340 let result = parser.parse();
6341 assert!(result.is_ok());
6342
6343 if let Statement::Query(query) = result.unwrap() {
6344 assert_eq!(query.match_clauses.len(), 2);
6345 assert!(!query.match_clauses[0].optional);
6346 assert!(query.match_clauses[1].optional);
6347 } else {
6348 panic!("Expected Query statement");
6349 }
6350 }
6351
6352 #[test]
6353 fn test_parse_with_clause() {
6354 let mut parser =
6355 Parser::new("MATCH (n:Person) WITH n.name AS name, n.age AS age RETURN name, age");
6356 let result = parser.parse();
6357 assert!(result.is_ok());
6358
6359 if let Statement::Query(query) = result.unwrap() {
6360 assert_eq!(query.with_clauses.len(), 1);
6361 assert_eq!(query.with_clauses[0].items.len(), 2);
6362 } else {
6363 panic!("Expected Query statement");
6364 }
6365 }
6366
6367 #[test]
6368 fn test_parse_order_by() {
6369 let mut parser = Parser::new("MATCH (n:Person) RETURN n.name ORDER BY n.age DESC");
6370 let result = parser.parse();
6371 assert!(result.is_ok());
6372
6373 if let Statement::Query(query) = result.unwrap() {
6374 let order_by = query.return_clause.order_by.as_ref().unwrap();
6375 assert_eq!(order_by.items.len(), 1);
6376 assert_eq!(order_by.items[0].order, SortOrder::Desc);
6377 } else {
6378 panic!("Expected Query statement");
6379 }
6380 }
6381
6382 #[test]
6383 fn test_parse_limit_skip() {
6384 let mut parser = Parser::new("MATCH (n) RETURN n SKIP 10 LIMIT 5");
6385 let result = parser.parse();
6386 assert!(result.is_ok());
6387
6388 if let Statement::Query(query) = result.unwrap() {
6389 assert!(query.return_clause.skip.is_some());
6390 assert!(query.return_clause.limit.is_some());
6391 } else {
6392 panic!("Expected Query statement");
6393 }
6394 }
6395
6396 #[test]
6397 fn test_parse_aggregation() {
6398 let mut parser = Parser::new("MATCH (n:Person) RETURN count(n), avg(n.age)");
6399 let result = parser.parse();
6400 assert!(result.is_ok());
6401
6402 if let Statement::Query(query) = result.unwrap() {
6403 assert_eq!(query.return_clause.items.len(), 2);
6404 if let Expression::FunctionCall { name, .. } = &query.return_clause.items[0].expression
6406 {
6407 assert_eq!(name, "count");
6408 } else {
6409 panic!("Expected function call");
6410 }
6411 } else {
6412 panic!("Expected Query statement");
6413 }
6414 }
6415
6416 #[test]
6417 fn test_parse_with_parameter() {
6418 let mut parser = Parser::new("MATCH (n:Person) WHERE n.age > $min_age RETURN n");
6419 let result = parser.parse();
6420 assert!(result.is_ok());
6421
6422 if let Statement::Query(query) = result.unwrap() {
6423 let where_clause = query.where_clause.as_ref().expect("Expected WHERE clause");
6425 if let Expression::Binary { right, .. } = &where_clause.expression {
6426 if let Expression::Parameter(name) = right.as_ref() {
6427 assert_eq!(name, "min_age");
6428 } else {
6429 panic!("Expected parameter, got {:?}", right);
6430 }
6431 } else {
6432 panic!("Expected binary expression in WHERE clause");
6433 }
6434 } else {
6435 panic!("Expected Query statement");
6436 }
6437 }
6438
6439 #[test]
6440 fn test_parse_insert_with_parameter() {
6441 let mut parser = Parser::new("INSERT (n:Person {name: $name, age: $age})");
6442 let result = parser.parse();
6443 assert!(result.is_ok());
6444
6445 if let Statement::DataModification(DataModificationStatement::Insert(insert)) =
6446 result.unwrap()
6447 {
6448 if let Pattern::Node(node) = &insert.patterns[0] {
6449 assert_eq!(node.properties.len(), 2);
6450 if let Expression::Parameter(name) = &node.properties[0].1 {
6452 assert_eq!(name, "name");
6453 } else {
6454 panic!("Expected parameter for name property");
6455 }
6456 } else {
6457 panic!("Expected node pattern");
6458 }
6459 } else {
6460 panic!("Expected Insert statement");
6461 }
6462 }
6463
6464 #[test]
6465 fn test_parse_variable_length_path() {
6466 let mut parser = Parser::new("MATCH (a)-[:KNOWS*1..3]->(b) RETURN a, b");
6467 let result = parser.parse();
6468 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6469
6470 if let Statement::Query(query) = result.unwrap() {
6471 if let Pattern::Path(path) = &query.match_clauses[0].patterns[0].pattern {
6472 let edge = &path.edges[0];
6473 assert_eq!(edge.min_hops, Some(1));
6474 assert_eq!(edge.max_hops, Some(3));
6475 } else {
6476 panic!("Expected path pattern");
6477 }
6478 } else {
6479 panic!("Expected Query statement");
6480 }
6481 }
6482
6483 #[test]
6484 fn test_parse_variable_length_path_unbounded() {
6485 let mut parser = Parser::new("MATCH (a)-[:KNOWS*]->(b) RETURN a, b");
6486 let result = parser.parse();
6487 assert!(result.is_ok());
6488
6489 if let Statement::Query(query) = result.unwrap() {
6490 if let Pattern::Path(path) = &query.match_clauses[0].patterns[0].pattern {
6491 let edge = &path.edges[0];
6492 assert_eq!(edge.min_hops, Some(1)); assert_eq!(edge.max_hops, None); } else {
6495 panic!("Expected path pattern");
6496 }
6497 } else {
6498 panic!("Expected Query statement");
6499 }
6500 }
6501
6502 #[test]
6503 fn test_parse_variable_length_path_exact() {
6504 let mut parser = Parser::new("MATCH (a)-[:KNOWS*2]->(b) RETURN a, b");
6505 let result = parser.parse();
6506 assert!(result.is_ok());
6507
6508 if let Statement::Query(query) = result.unwrap() {
6509 if let Pattern::Path(path) = &query.match_clauses[0].patterns[0].pattern {
6510 let edge = &path.edges[0];
6511 assert_eq!(edge.min_hops, Some(2));
6512 assert_eq!(edge.max_hops, Some(2)); } else {
6514 panic!("Expected path pattern");
6515 }
6516 } else {
6517 panic!("Expected Query statement");
6518 }
6519 }
6520
6521 #[test]
6522 fn test_parse_variable_length_path_with_properties() {
6523 let query = "MATCH (start:Node {name: 'a'})-[:NEXT*1..3]->(end:Node) RETURN end.name";
6525 let mut parser = Parser::new(query);
6526 let result = parser.parse();
6527 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6528
6529 if let Statement::Query(query) = result.unwrap() {
6530 if let Pattern::Path(path) = &query.match_clauses[0].patterns[0].pattern {
6531 let edge = &path.edges[0];
6532 assert_eq!(edge.min_hops, Some(1));
6533 assert_eq!(edge.max_hops, Some(3));
6534 assert_eq!(path.source.variable, Some("start".to_string()));
6536 assert_eq!(path.source.labels, vec!["Node".to_string()]);
6537 assert_eq!(edge.target.variable, Some("end".to_string()));
6538 assert_eq!(edge.target.labels, vec!["Node".to_string()]);
6539 } else {
6540 panic!("Expected path pattern");
6541 }
6542 } else {
6543 panic!("Expected Query statement");
6544 }
6545 }
6546
6547 #[test]
6548 fn test_reserved_keywords_as_identifiers() {
6549 let queries = [
6551 ("MATCH (end:Node) RETURN end", "end"),
6552 ("MATCH (node:Person) RETURN node", "node"),
6553 ("MATCH (type:Category) RETURN type", "type"),
6554 ("MATCH (case:Test) RETURN case", "case"),
6555 ];
6556
6557 for (query, expected_var) in queries {
6558 let mut parser = Parser::new(query);
6559 let result = parser.parse();
6560 assert!(
6561 result.is_ok(),
6562 "Parse error for '{}': {:?}",
6563 expected_var,
6564 result.err()
6565 );
6566
6567 if let Statement::Query(q) = result.unwrap()
6568 && let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern
6569 {
6570 assert_eq!(node.variable, Some(expected_var.to_string()));
6571 }
6572 }
6573 }
6574
6575 #[test]
6576 fn test_parse_quoted_identifier_label() {
6577 let mut parser = Parser::new("MATCH (n:`rdf:type`) RETURN n");
6578 let result = parser.parse();
6579 assert!(result.is_ok());
6580
6581 if let Statement::Query(query) = result.unwrap() {
6582 if let Pattern::Node(node) = &query.match_clauses[0].patterns[0].pattern {
6583 assert_eq!(node.labels[0], "rdf:type");
6584 } else {
6585 panic!("Expected node pattern");
6586 }
6587 } else {
6588 panic!("Expected Query statement");
6589 }
6590 }
6591
6592 #[test]
6593 fn test_parse_unwind() {
6594 let mut parser = Parser::new("UNWIND [1, 2, 3] AS x RETURN x");
6595 let result = parser.parse();
6596 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6597
6598 if let Statement::Query(query) = result.unwrap() {
6599 assert_eq!(query.unwind_clauses.len(), 1);
6600 assert_eq!(query.unwind_clauses[0].alias, "x");
6601 } else {
6602 panic!("Expected Query statement");
6603 }
6604 }
6605
6606 #[test]
6607 fn test_parse_merge() {
6608 let mut parser = Parser::new("MERGE (n:Person {name: 'Alix'}) RETURN n");
6609 let result = parser.parse();
6610 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6611
6612 if let Statement::Query(query) = result.unwrap() {
6613 assert_eq!(query.merge_clauses.len(), 1);
6614 if let Pattern::Node(node) = &query.merge_clauses[0].pattern {
6615 assert_eq!(node.labels[0], "Person");
6616 } else {
6617 panic!("Expected node pattern in MERGE");
6618 }
6619 } else {
6620 panic!("Expected Query statement");
6621 }
6622 }
6623
6624 #[test]
6625 fn test_parse_merge_on_create() {
6626 let mut parser =
6627 Parser::new("MERGE (n:Person {name: 'Alix'}) ON CREATE SET n.created = true RETURN n");
6628 let result = parser.parse();
6629 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6630
6631 if let Statement::Query(query) = result.unwrap() {
6632 assert_eq!(query.merge_clauses.len(), 1);
6633 let merge = &query.merge_clauses[0];
6634 assert!(merge.on_create.is_some());
6635 assert_eq!(merge.on_create.as_ref().unwrap().len(), 1);
6636 } else {
6637 panic!("Expected Query statement");
6638 }
6639 }
6640
6641 #[test]
6642 fn test_parse_remove_label() {
6643 let mut parser = Parser::new("MATCH (n:Person) REMOVE n:Employee RETURN n");
6644 let result = parser.parse();
6645 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6646
6647 if let Statement::Query(query) = result.unwrap() {
6648 assert_eq!(query.remove_clauses.len(), 1);
6649 assert_eq!(query.remove_clauses[0].label_operations.len(), 1);
6650 assert_eq!(query.remove_clauses[0].label_operations[0].variable, "n");
6651 assert_eq!(
6652 query.remove_clauses[0].label_operations[0].labels,
6653 vec!["Employee"]
6654 );
6655 } else {
6656 panic!("Expected Query statement");
6657 }
6658 }
6659
6660 #[test]
6661 fn test_parse_remove_property() {
6662 let mut parser = Parser::new("MATCH (n:Person) REMOVE n.age RETURN n");
6663 let result = parser.parse();
6664 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6665
6666 if let Statement::Query(query) = result.unwrap() {
6667 assert_eq!(query.remove_clauses.len(), 1);
6668 assert_eq!(query.remove_clauses[0].property_removals.len(), 1);
6669 assert_eq!(query.remove_clauses[0].property_removals[0].0, "n");
6670 assert_eq!(query.remove_clauses[0].property_removals[0].1, "age");
6671 } else {
6672 panic!("Expected Query statement");
6673 }
6674 }
6675
6676 #[test]
6677 fn test_parse_remove_multiple() {
6678 let mut parser =
6679 Parser::new("MATCH (n:Person) REMOVE n:Employee, n.age, n:Contractor RETURN n");
6680 let result = parser.parse();
6681 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6682
6683 if let Statement::Query(query) = result.unwrap() {
6684 assert_eq!(query.remove_clauses.len(), 1);
6685 let remove = &query.remove_clauses[0];
6686 assert_eq!(remove.label_operations.len(), 2);
6688 assert_eq!(remove.property_removals.len(), 1);
6689 } else {
6690 panic!("Expected Query statement");
6691 }
6692 }
6693
6694 #[test]
6695 fn test_parse_vector_function_call() {
6696 let mut parser = Parser::new("MATCH (n) RETURN vector([0.1, 0.2, 0.3])");
6697 let result = parser.parse();
6698 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6699
6700 if let Statement::Query(query) = result.unwrap() {
6701 assert_eq!(query.return_clause.items.len(), 1);
6702 if let Expression::FunctionCall { name, args, .. } =
6703 &query.return_clause.items[0].expression
6704 {
6705 assert_eq!(name, "vector");
6706 assert_eq!(args.len(), 1);
6707 if let Expression::List(elements) = &args[0] {
6709 assert_eq!(elements.len(), 3);
6710 } else {
6711 panic!("Expected list argument, got {:?}", args[0]);
6712 }
6713 } else {
6714 panic!("Expected function call");
6715 }
6716 } else {
6717 panic!("Expected Query statement");
6718 }
6719 }
6720
6721 #[test]
6722 fn test_parse_cosine_similarity() {
6723 let mut parser =
6724 Parser::new("MATCH (n) WHERE cosine_similarity(n.embedding, $query) > 0.8 RETURN n");
6725 let result = parser.parse();
6726 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6727
6728 if let Statement::Query(query) = result.unwrap() {
6729 let where_clause = query.where_clause.as_ref().expect("Expected WHERE clause");
6730 if let Expression::Binary { left, .. } = &where_clause.expression {
6731 if let Expression::FunctionCall { name, args, .. } = left.as_ref() {
6732 assert_eq!(name, "cosine_similarity");
6733 assert_eq!(args.len(), 2);
6734 } else {
6735 panic!("Expected function call, got {:?}", left);
6736 }
6737 } else {
6738 panic!("Expected binary expression");
6739 }
6740 } else {
6741 panic!("Expected Query statement");
6742 }
6743 }
6744
6745 #[test]
6746 fn test_parse_euclidean_distance() {
6747 let mut parser =
6748 Parser::new("MATCH (n) RETURN euclidean_distance(n.embedding, [1.0, 2.0]) AS dist");
6749 let result = parser.parse();
6750 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6751
6752 if let Statement::Query(query) = result.unwrap() {
6753 assert_eq!(query.return_clause.items.len(), 1);
6754 if let Expression::FunctionCall { name, args, .. } =
6755 &query.return_clause.items[0].expression
6756 {
6757 assert_eq!(name, "euclidean_distance");
6758 assert_eq!(args.len(), 2);
6759 } else {
6760 panic!("Expected function call");
6761 }
6762 } else {
6763 panic!("Expected Query statement");
6764 }
6765 }
6766
6767 #[test]
6768 fn test_parse_create_vector_index() {
6769 let mut parser = Parser::new("CREATE VECTOR INDEX movie_embeddings ON :Movie(embedding)");
6770 let result = parser.parse();
6771 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6772
6773 if let Statement::Schema(SchemaStatement::CreateVectorIndex(stmt)) = result.unwrap() {
6774 assert_eq!(stmt.name, "movie_embeddings");
6775 assert_eq!(stmt.node_label, "Movie");
6776 assert_eq!(stmt.property, "embedding");
6777 assert!(stmt.dimensions.is_none());
6778 assert!(stmt.metric.is_none());
6779 } else {
6780 panic!("Expected CreateVectorIndex statement");
6781 }
6782 }
6783
6784 #[test]
6785 fn test_parse_create_vector_index_with_options() {
6786 let mut parser = Parser::new(
6787 "CREATE VECTOR INDEX embeddings ON :Document(vec) DIMENSION 384 METRIC 'cosine'",
6788 );
6789 let result = parser.parse();
6790 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6791
6792 if let Statement::Schema(SchemaStatement::CreateVectorIndex(stmt)) = result.unwrap() {
6793 assert_eq!(stmt.name, "embeddings");
6794 assert_eq!(stmt.node_label, "Document");
6795 assert_eq!(stmt.property, "vec");
6796 assert_eq!(stmt.dimensions, Some(384));
6797 assert_eq!(stmt.metric, Some("cosine".to_string()));
6798 } else {
6799 panic!("Expected CreateVectorIndex statement");
6800 }
6801 }
6802
6803 #[test]
6804 fn test_in_operator_with_list() {
6805 let mut parser =
6806 Parser::new("MATCH (n:Person) WHERE n.name IN ['Alix', 'Gus'] RETURN n.name");
6807 let result = parser.parse();
6808 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6809
6810 if let Statement::Query(q) = result.unwrap() {
6811 let where_clause = q.where_clause.expect("Expected WHERE clause");
6812 if let WhereClause {
6813 expression: Expression::Binary { op, right, .. },
6814 ..
6815 } = where_clause
6816 {
6817 assert_eq!(op, BinaryOp::In);
6818 assert!(matches!(right.as_ref(), Expression::List(elems) if elems.len() == 2));
6819 } else {
6820 panic!("Expected Binary IN expression");
6821 }
6822 } else {
6823 panic!("Expected Query statement");
6824 }
6825 }
6826
6827 #[test]
6828 fn test_in_operator_with_integers() {
6829 let mut parser = Parser::new("MATCH (n:Item) WHERE n.status IN [1, 2, 3] RETURN n");
6830 let result = parser.parse();
6831 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6832 }
6833
6834 #[test]
6835 fn test_string_escape_single_quotes() {
6836 let mut parser = Parser::new(r#"MATCH (n) WHERE n.name = 'O\'Brien' RETURN n"#);
6837 let result = parser.parse();
6838 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6839
6840 if let Statement::Query(q) = result.unwrap() {
6841 let where_clause = q.where_clause.expect("Expected WHERE clause");
6842 if let WhereClause {
6843 expression: Expression::Binary { right, .. },
6844 ..
6845 } = where_clause
6846 {
6847 if let Expression::Literal(Literal::String(s)) = right.as_ref() {
6848 assert_eq!(s, "O'Brien");
6849 } else {
6850 panic!("Expected string literal");
6851 }
6852 }
6853 }
6854 }
6855
6856 #[test]
6857 fn test_string_escape_sequences() {
6858 let mut parser = Parser::new(r#"MATCH (n) WHERE n.text = 'line1\nline2' RETURN n"#);
6859 let result = parser.parse();
6860 assert!(result.is_ok(), "Parse error: {:?}", result.err());
6861
6862 if let Statement::Query(q) = result.unwrap() {
6863 let where_clause = q.where_clause.expect("Expected WHERE clause");
6864 if let WhereClause {
6865 expression: Expression::Binary { right, .. },
6866 ..
6867 } = where_clause
6868 {
6869 if let Expression::Literal(Literal::String(s)) = right.as_ref() {
6870 assert_eq!(s, "line1\nline2");
6871 } else {
6872 panic!("Expected string literal");
6873 }
6874 }
6875 }
6876 }
6877
6878 #[test]
6881 fn test_parse_error_empty_input() {
6882 let mut parser = Parser::new("");
6883 let result = parser.parse();
6884 assert!(result.is_err(), "Empty input should fail");
6885 }
6886
6887 #[test]
6888 fn test_parse_error_just_match() {
6889 let mut parser = Parser::new("MATCH");
6890 let result = parser.parse();
6891 assert!(result.is_err(), "MATCH alone should fail");
6892 }
6893
6894 #[test]
6895 fn test_parse_error_unclosed_node_pattern() {
6896 let mut parser = Parser::new("MATCH (n:Person RETURN n");
6897 let result = parser.parse();
6898 assert!(result.is_err(), "Unclosed node pattern should fail");
6899 }
6900
6901 #[test]
6902 fn test_parse_error_unclosed_edge_pattern() {
6903 let mut parser = Parser::new("MATCH (a)-[:KNOWS->(b) RETURN a");
6904 let result = parser.parse();
6905 assert!(result.is_err(), "Unclosed edge pattern should fail");
6906 }
6907
6908 #[test]
6909 fn test_parse_error_missing_return() {
6910 let mut parser = Parser::new("MATCH (n:Person) WHERE n.age > 25");
6911 let result = parser.parse();
6912 assert!(
6913 result.is_err(),
6914 "Query without RETURN or mutation should fail"
6915 );
6916 }
6917
6918 #[test]
6919 fn test_parse_error_double_where() {
6920 let mut parser = Parser::new("MATCH (n) WHERE n.a = 1 WHERE n.b = 2 RETURN n");
6921 let result = parser.parse();
6922 assert!(result.is_err(), "Double WHERE should fail");
6923 }
6924
6925 #[test]
6926 fn test_parse_error_invalid_literal() {
6927 let mut parser = Parser::new("MATCH (n) WHERE n.x = @invalid RETURN n");
6928 let result = parser.parse();
6929 assert!(result.is_err(), "Invalid literal should fail");
6930 }
6931
6932 #[test]
6933 fn test_parse_error_unclosed_string() {
6934 let mut parser = Parser::new("MATCH (n) WHERE n.name = 'hello RETURN n");
6935 let result = parser.parse();
6936 assert!(result.is_err(), "Unclosed string should fail");
6937 }
6938
6939 #[test]
6940 fn test_parse_error_unclosed_property_map() {
6941 let mut parser = Parser::new("MATCH (n:Person {name: 'Alix') RETURN n");
6942 let result = parser.parse();
6943 assert!(result.is_err(), "Unclosed property map should fail");
6944 }
6945
6946 #[test]
6947 fn test_parse_error_return_only() {
6948 let mut parser = Parser::new("RETURN RETURN");
6949 let result = parser.parse();
6950 assert!(result.is_err(), "RETURN RETURN should fail");
6951 }
6952
6953 #[test]
6954 fn test_parse_error_insert_without_pattern() {
6955 let mut parser = Parser::new("INSERT RETURN n");
6956 let result = parser.parse();
6957 assert!(result.is_err(), "INSERT without pattern should fail");
6958 }
6959
6960 #[test]
6965 fn test_parse_with_line_comment() {
6966 let mut parser = Parser::new("MATCH (n) -- find all nodes\nRETURN n");
6967 let result = parser.parse();
6968 assert!(
6969 result.is_ok(),
6970 "Line comment should be skipped: {:?}",
6971 result.err()
6972 );
6973 }
6974
6975 #[test]
6976 fn test_parse_with_block_comment() {
6977 let mut parser = Parser::new("MATCH /* nodes */ (n:Person) RETURN n");
6978 let result = parser.parse();
6979 assert!(
6980 result.is_ok(),
6981 "Block comment should be skipped: {:?}",
6982 result.err()
6983 );
6984 }
6985
6986 #[test]
6989 fn test_parse_xor_expression() {
6990 let mut parser = Parser::new("MATCH (n) WHERE n.a = 1 XOR n.b = 2 RETURN n");
6991 let result = parser.parse();
6992 assert!(result.is_ok(), "XOR should parse: {:?}", result.err());
6993
6994 if let Statement::Query(q) = result.unwrap() {
6995 let where_clause = q.where_clause.expect("Expected WHERE clause");
6996 if let Expression::Binary { op, .. } = &where_clause.expression {
6997 assert_eq!(*op, BinaryOp::Xor);
6998 } else {
6999 panic!("Expected binary XOR expression");
7000 }
7001 } else {
7002 panic!("Expected Query statement");
7003 }
7004 }
7005
7006 #[test]
7009 fn test_parse_iso_path_quantifier_range() {
7010 let mut parser = Parser::new("MATCH (a)-[:KNOWS{2,5}]->(b) RETURN a, b");
7011 let result = parser.parse();
7012 assert!(
7013 result.is_ok(),
7014 "ISO {{m,n}} quantifier should parse: {:?}",
7015 result.err()
7016 );
7017
7018 if let Statement::Query(q) = result.unwrap() {
7019 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
7020 assert_eq!(path.edges[0].min_hops, Some(2));
7021 assert_eq!(path.edges[0].max_hops, Some(5));
7022 } else {
7023 panic!("Expected path pattern");
7024 }
7025 } else {
7026 panic!("Expected Query statement");
7027 }
7028 }
7029
7030 #[test]
7031 fn test_parse_iso_path_quantifier_exact() {
7032 let mut parser = Parser::new("MATCH (a)-[:KNOWS{3}]->(b) RETURN a, b");
7033 let result = parser.parse();
7034 assert!(
7035 result.is_ok(),
7036 "ISO {{n}} quantifier should parse: {:?}",
7037 result.err()
7038 );
7039
7040 if let Statement::Query(q) = result.unwrap() {
7041 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
7042 assert_eq!(path.edges[0].min_hops, Some(3));
7043 assert_eq!(path.edges[0].max_hops, Some(3));
7044 } else {
7045 panic!("Expected path pattern");
7046 }
7047 } else {
7048 panic!("Expected Query statement");
7049 }
7050 }
7051
7052 #[test]
7053 fn test_parse_iso_path_quantifier_lower_only() {
7054 let mut parser = Parser::new("MATCH (a)-[:KNOWS{2,}]->(b) RETURN a, b");
7055 let result = parser.parse();
7056 assert!(
7057 result.is_ok(),
7058 "ISO {{m,}} quantifier should parse: {:?}",
7059 result.err()
7060 );
7061
7062 if let Statement::Query(q) = result.unwrap() {
7063 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
7064 assert_eq!(path.edges[0].min_hops, Some(2));
7065 assert_eq!(path.edges[0].max_hops, None);
7066 } else {
7067 panic!("Expected path pattern");
7068 }
7069 } else {
7070 panic!("Expected Query statement");
7071 }
7072 }
7073
7074 #[test]
7077 fn test_parse_list_index_access() {
7078 let mut parser = Parser::new("MATCH (n) RETURN [1, 2, 3][0]");
7079 let result = parser.parse();
7080 assert!(
7081 result.is_ok(),
7082 "List index access should parse: {:?}",
7083 result.err()
7084 );
7085
7086 if let Statement::Query(q) = result.unwrap() {
7087 if let Expression::IndexAccess { .. } = &q.return_clause.items[0].expression {
7088 } else {
7090 panic!(
7091 "Expected IndexAccess expression, got {:?}",
7092 q.return_clause.items[0].expression
7093 );
7094 }
7095 } else {
7096 panic!("Expected Query statement");
7097 }
7098 }
7099
7100 #[test]
7103 fn test_parse_cast_to_integer() {
7104 let mut parser = Parser::new("MATCH (n) RETURN CAST('42' AS INTEGER)");
7105 let result = parser.parse();
7106 assert!(
7107 result.is_ok(),
7108 "CAST AS INTEGER should parse: {:?}",
7109 result.err()
7110 );
7111
7112 if let Statement::Query(q) = result.unwrap() {
7113 if let Expression::FunctionCall { name, .. } = &q.return_clause.items[0].expression {
7114 assert_eq!(name, "toInteger");
7115 } else {
7116 panic!("Expected function call from CAST");
7117 }
7118 } else {
7119 panic!("Expected Query statement");
7120 }
7121 }
7122
7123 #[test]
7124 fn test_parse_cast_to_float() {
7125 let mut parser = Parser::new("MATCH (n) RETURN CAST(n.val AS FLOAT)");
7126 let result = parser.parse();
7127 assert!(
7128 result.is_ok(),
7129 "CAST AS FLOAT should parse: {:?}",
7130 result.err()
7131 );
7132
7133 if let Statement::Query(q) = result.unwrap() {
7134 if let Expression::FunctionCall { name, .. } = &q.return_clause.items[0].expression {
7135 assert_eq!(name, "toFloat");
7136 } else {
7137 panic!("Expected function call from CAST");
7138 }
7139 } else {
7140 panic!("Expected Query statement");
7141 }
7142 }
7143
7144 #[test]
7145 fn test_parse_cast_to_string() {
7146 let mut parser = Parser::new("MATCH (n) RETURN CAST(42 AS STRING)");
7147 let result = parser.parse();
7148 assert!(
7149 result.is_ok(),
7150 "CAST AS STRING should parse: {:?}",
7151 result.err()
7152 );
7153
7154 if let Statement::Query(q) = result.unwrap() {
7155 if let Expression::FunctionCall { name, .. } = &q.return_clause.items[0].expression {
7156 assert_eq!(name, "toString");
7157 } else {
7158 panic!("Expected function call from CAST");
7159 }
7160 } else {
7161 panic!("Expected Query statement");
7162 }
7163 }
7164
7165 #[test]
7166 fn test_parse_cast_to_boolean() {
7167 let mut parser = Parser::new("MATCH (n) RETURN CAST('true' AS BOOLEAN)");
7168 let result = parser.parse();
7169 assert!(
7170 result.is_ok(),
7171 "CAST AS BOOLEAN should parse: {:?}",
7172 result.err()
7173 );
7174
7175 if let Statement::Query(q) = result.unwrap() {
7176 if let Expression::FunctionCall { name, .. } = &q.return_clause.items[0].expression {
7177 assert_eq!(name, "toBoolean");
7178 } else {
7179 panic!("Expected function call from CAST");
7180 }
7181 } else {
7182 panic!("Expected Query statement");
7183 }
7184 }
7185
7186 #[test]
7189 fn test_parse_offset_as_skip_alias() {
7190 let mut parser = Parser::new("MATCH (n) RETURN n OFFSET 10 LIMIT 5");
7191 let result = parser.parse();
7192 assert!(
7193 result.is_ok(),
7194 "OFFSET should parse as SKIP alias: {:?}",
7195 result.err()
7196 );
7197
7198 if let Statement::Query(q) = result.unwrap() {
7199 assert!(q.return_clause.skip.is_some());
7200 assert!(q.return_clause.limit.is_some());
7201 } else {
7202 panic!("Expected Query statement");
7203 }
7204 }
7205
7206 #[test]
7209 fn test_parse_is_label_single() {
7210 let mut parser = Parser::new("MATCH (n IS Person) RETURN n");
7211 let result = parser.parse();
7212 assert!(result.is_ok(), "IS label should parse: {:?}", result.err());
7213
7214 if let Statement::Query(q) = result.unwrap() {
7215 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7216 match &node.label_expression {
7217 Some(LabelExpression::Label(name)) => assert_eq!(name, "Person"),
7218 other => panic!("Expected Label(Person), got {:?}", other),
7219 }
7220 } else {
7221 panic!("Expected node pattern");
7222 }
7223 } else {
7224 panic!("Expected Query statement");
7225 }
7226 }
7227
7228 #[test]
7229 fn test_parse_is_label_disjunction() {
7230 let mut parser = Parser::new("MATCH (n IS Person | Company) RETURN n");
7231 let result = parser.parse();
7232 assert!(
7233 result.is_ok(),
7234 "IS label disjunction should parse: {:?}",
7235 result.err()
7236 );
7237
7238 if let Statement::Query(q) = result.unwrap() {
7239 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7240 assert!(matches!(
7241 &node.label_expression,
7242 Some(LabelExpression::Disjunction(_))
7243 ));
7244 } else {
7245 panic!("Expected node pattern");
7246 }
7247 } else {
7248 panic!("Expected Query statement");
7249 }
7250 }
7251
7252 #[test]
7253 fn test_parse_is_label_conjunction() {
7254 let mut parser = Parser::new("MATCH (n IS Person & Employee) RETURN n");
7255 let result = parser.parse();
7256 assert!(
7257 result.is_ok(),
7258 "IS label conjunction should parse: {:?}",
7259 result.err()
7260 );
7261
7262 if let Statement::Query(q) = result.unwrap() {
7263 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7264 assert!(matches!(
7265 &node.label_expression,
7266 Some(LabelExpression::Conjunction(_))
7267 ));
7268 } else {
7269 panic!("Expected node pattern");
7270 }
7271 } else {
7272 panic!("Expected Query statement");
7273 }
7274 }
7275
7276 #[test]
7277 fn test_parse_is_label_negation() {
7278 let mut parser = Parser::new("MATCH (n IS !Inactive) RETURN n");
7279 let result = parser.parse();
7280 assert!(
7281 result.is_ok(),
7282 "IS label negation should parse: {:?}",
7283 result.err()
7284 );
7285
7286 if let Statement::Query(q) = result.unwrap() {
7287 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7288 assert!(matches!(
7289 &node.label_expression,
7290 Some(LabelExpression::Negation(_))
7291 ));
7292 } else {
7293 panic!("Expected node pattern");
7294 }
7295 } else {
7296 panic!("Expected Query statement");
7297 }
7298 }
7299
7300 #[test]
7301 fn test_parse_is_label_wildcard() {
7302 let mut parser = Parser::new("MATCH (n IS %) RETURN n");
7303 let result = parser.parse();
7304 assert!(
7305 result.is_ok(),
7306 "IS wildcard should parse: {:?}",
7307 result.err()
7308 );
7309
7310 if let Statement::Query(q) = result.unwrap() {
7311 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7312 assert!(matches!(
7313 &node.label_expression,
7314 Some(LabelExpression::Wildcard)
7315 ));
7316 } else {
7317 panic!("Expected node pattern");
7318 }
7319 } else {
7320 panic!("Expected Query statement");
7321 }
7322 }
7323
7324 #[test]
7325 fn test_parse_is_label_complex() {
7326 let mut parser = Parser::new("MATCH (n IS (Person | Company) & !Inactive) RETURN n");
7328 let result = parser.parse();
7329 assert!(
7330 result.is_ok(),
7331 "Complex label expression should parse: {:?}",
7332 result.err()
7333 );
7334
7335 if let Statement::Query(q) = result.unwrap() {
7336 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
7337 assert!(node.label_expression.is_some());
7338 } else {
7339 panic!("Expected node pattern");
7340 }
7341 } else {
7342 panic!("Expected Query statement");
7343 }
7344 }
7345
7346 #[test]
7347 fn test_parse_is_label_on_edge_colon_syntax() {
7348 let mut parser = Parser::new("MATCH (a)-[e:KNOWS]->(b) RETURN a, b");
7350 let result = parser.parse();
7351 assert!(
7352 result.is_ok(),
7353 "Edge colon syntax should parse: {:?}",
7354 result.err()
7355 );
7356 }
7357
7358 #[test]
7361 fn test_parse_path_mode_walk() {
7362 let mut parser = Parser::new("MATCH WALK (a)-[:KNOWS*]->(b) RETURN a, b");
7363 let result = parser.parse();
7364 assert!(result.is_ok(), "WALK mode should parse: {:?}", result.err());
7365
7366 if let Statement::Query(q) = result.unwrap() {
7367 assert_eq!(q.match_clauses[0].path_mode, Some(PathMode::Walk));
7368 } else {
7369 panic!("Expected Query statement");
7370 }
7371 }
7372
7373 #[test]
7374 fn test_parse_path_mode_trail() {
7375 let mut parser = Parser::new("MATCH TRAIL (a)-[:KNOWS*]->(b) RETURN a, b");
7376 let result = parser.parse();
7377 assert!(
7378 result.is_ok(),
7379 "TRAIL mode should parse: {:?}",
7380 result.err()
7381 );
7382
7383 if let Statement::Query(q) = result.unwrap() {
7384 assert_eq!(q.match_clauses[0].path_mode, Some(PathMode::Trail));
7385 } else {
7386 panic!("Expected Query statement");
7387 }
7388 }
7389
7390 #[test]
7391 fn test_parse_path_mode_simple() {
7392 let mut parser = Parser::new("MATCH SIMPLE (a)-[:KNOWS*]->(b) RETURN a, b");
7393 let result = parser.parse();
7394 assert!(
7395 result.is_ok(),
7396 "SIMPLE mode should parse: {:?}",
7397 result.err()
7398 );
7399
7400 if let Statement::Query(q) = result.unwrap() {
7401 assert_eq!(q.match_clauses[0].path_mode, Some(PathMode::Simple));
7402 } else {
7403 panic!("Expected Query statement");
7404 }
7405 }
7406
7407 #[test]
7408 fn test_parse_path_mode_acyclic() {
7409 let mut parser = Parser::new("MATCH ACYCLIC (a)-[:KNOWS*]->(b) RETURN a, b");
7410 let result = parser.parse();
7411 assert!(
7412 result.is_ok(),
7413 "ACYCLIC mode should parse: {:?}",
7414 result.err()
7415 );
7416
7417 if let Statement::Query(q) = result.unwrap() {
7418 assert_eq!(q.match_clauses[0].path_mode, Some(PathMode::Acyclic));
7419 } else {
7420 panic!("Expected Query statement");
7421 }
7422 }
7423
7424 #[test]
7425 fn test_parse_no_path_mode_default() {
7426 let mut parser = Parser::new("MATCH (a)-[:KNOWS*]->(b) RETURN a, b");
7427 let result = parser.parse();
7428 assert!(result.is_ok());
7429
7430 if let Statement::Query(q) = result.unwrap() {
7431 assert_eq!(q.match_clauses[0].path_mode, None);
7432 } else {
7433 panic!("Expected Query statement");
7434 }
7435 }
7436
7437 #[test]
7440 fn test_parse_union() {
7441 let mut parser =
7442 Parser::new("MATCH (n:Person) RETURN n.name UNION MATCH (n:Company) RETURN n.name");
7443 let result = parser.parse();
7444 assert!(result.is_ok(), "UNION should parse: {:?}", result.err());
7445
7446 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
7447 assert_eq!(op, CompositeOp::Union);
7448 } else {
7449 panic!("Expected CompositeQuery");
7450 }
7451 }
7452
7453 #[test]
7454 fn test_parse_union_all() {
7455 let mut parser =
7456 Parser::new("MATCH (n:Person) RETURN n.name UNION ALL MATCH (n:Company) RETURN n.name");
7457 let result = parser.parse();
7458 assert!(result.is_ok(), "UNION ALL should parse: {:?}", result.err());
7459
7460 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
7461 assert_eq!(op, CompositeOp::UnionAll);
7462 } else {
7463 panic!("Expected CompositeQuery");
7464 }
7465 }
7466
7467 #[test]
7468 fn test_parse_except() {
7469 let mut parser =
7470 Parser::new("MATCH (n:Person) RETURN n.name EXCEPT MATCH (n:Employee) RETURN n.name");
7471 let result = parser.parse();
7472 assert!(result.is_ok(), "EXCEPT should parse: {:?}", result.err());
7473
7474 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
7475 assert_eq!(op, CompositeOp::Except);
7476 } else {
7477 panic!("Expected CompositeQuery");
7478 }
7479 }
7480
7481 #[test]
7482 fn test_parse_intersect() {
7483 let mut parser = Parser::new(
7484 "MATCH (n:Person) RETURN n.name INTERSECT MATCH (n:Employee) RETURN n.name",
7485 );
7486 let result = parser.parse();
7487 assert!(result.is_ok(), "INTERSECT should parse: {:?}", result.err());
7488
7489 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
7490 assert_eq!(op, CompositeOp::Intersect);
7491 } else {
7492 panic!("Expected CompositeQuery");
7493 }
7494 }
7495
7496 #[test]
7497 fn test_parse_otherwise() {
7498 let mut parser =
7499 Parser::new("MATCH (n:Person) RETURN n.name OTHERWISE MATCH (n:Company) RETURN n.name");
7500 let result = parser.parse();
7501 assert!(result.is_ok(), "OTHERWISE should parse: {:?}", result.err());
7502
7503 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
7504 assert_eq!(op, CompositeOp::Otherwise);
7505 } else {
7506 panic!("Expected CompositeQuery");
7507 }
7508 }
7509
7510 #[test]
7513 fn test_parse_filter_as_where_synonym() {
7514 let mut parser = Parser::new("MATCH (n:Person) FILTER n.age > 25 RETURN n");
7515 let result = parser.parse();
7516 assert!(
7517 result.is_ok(),
7518 "FILTER should parse as WHERE synonym: {:?}",
7519 result.err()
7520 );
7521
7522 if let Statement::Query(q) = result.unwrap() {
7523 assert!(q.where_clause.is_some());
7524 } else {
7525 panic!("Expected Query statement");
7526 }
7527 }
7528
7529 #[test]
7532 fn test_parse_group_by() {
7533 let mut parser = Parser::new("MATCH (n:Person) RETURN n.city, count(n) GROUP BY n.city");
7534 let result = parser.parse();
7535 assert!(result.is_ok(), "GROUP BY should parse: {:?}", result.err());
7536
7537 if let Statement::Query(q) = result.unwrap() {
7538 assert_eq!(q.return_clause.group_by.len(), 1);
7539 if let Expression::PropertyAccess { property, .. } = &q.return_clause.group_by[0] {
7540 assert_eq!(property, "city");
7541 } else {
7542 panic!("Expected property access in GROUP BY");
7543 }
7544 } else {
7545 panic!("Expected Query statement");
7546 }
7547 }
7548
7549 #[test]
7550 fn test_parse_group_by_multiple() {
7551 let mut parser =
7552 Parser::new("MATCH (n:Person) RETURN n.city, n.age, count(n) GROUP BY n.city, n.age");
7553 let result = parser.parse();
7554 assert!(
7555 result.is_ok(),
7556 "Multiple GROUP BY should parse: {:?}",
7557 result.err()
7558 );
7559
7560 if let Statement::Query(q) = result.unwrap() {
7561 assert_eq!(q.return_clause.group_by.len(), 2);
7562 } else {
7563 panic!("Expected Query statement");
7564 }
7565 }
7566
7567 #[test]
7570 fn test_parse_element_id_function() {
7571 let mut parser = Parser::new("MATCH (n) RETURN element_id(n)");
7572 let result = parser.parse();
7573 assert!(
7574 result.is_ok(),
7575 "element_id should parse: {:?}",
7576 result.err()
7577 );
7578
7579 if let Statement::Query(q) = result.unwrap() {
7580 if let Expression::FunctionCall { name, args, .. } =
7581 &q.return_clause.items[0].expression
7582 {
7583 assert_eq!(name, "element_id");
7584 assert_eq!(args.len(), 1);
7585 } else {
7586 panic!("Expected function call");
7587 }
7588 } else {
7589 panic!("Expected Query statement");
7590 }
7591 }
7592
7593 #[test]
7596 fn test_parse_error_cast_missing_as() {
7597 let mut parser = Parser::new("MATCH (n) RETURN CAST(42 INTEGER)");
7598 let result = parser.parse();
7599 assert!(result.is_err(), "CAST without AS should fail");
7600 }
7601
7602 #[test]
7603 fn test_parse_error_cast_invalid_type() {
7604 let mut parser = Parser::new("MATCH (n) RETURN CAST(42 AS VECTOR)");
7605 let result = parser.parse();
7606 assert!(result.is_err(), "CAST to unsupported type should fail");
7607 }
7608
7609 #[test]
7610 fn test_parse_error_group_by_without_expressions() {
7611 let mut parser = Parser::new("MATCH (n) RETURN n GROUP BY");
7612 let result = parser.parse();
7613 assert!(result.is_err(), "GROUP BY without expressions should fail");
7614 }
7615
7616 #[test]
7617 fn test_parse_hex_integer_literal() {
7618 let mut parser = Parser::new("MATCH (n) RETURN 0xFF");
7619 let result = parser.parse();
7620 assert!(
7621 result.is_ok(),
7622 "Hex literal should parse: {:?}",
7623 result.err()
7624 );
7625 if let Statement::Query(q) = result.unwrap() {
7626 let item = &q.return_clause.items[0];
7627 if let Expression::Literal(Literal::Integer(val)) = &item.expression {
7628 assert_eq!(*val, 255, "0xFF should parse to 255");
7629 } else {
7630 panic!("Expected integer literal");
7631 }
7632 }
7633 }
7634
7635 #[test]
7636 fn test_parse_octal_integer_literal() {
7637 let mut parser = Parser::new("MATCH (n) RETURN 0o77");
7638 let result = parser.parse();
7639 assert!(
7640 result.is_ok(),
7641 "Octal literal should parse: {:?}",
7642 result.err()
7643 );
7644 if let Statement::Query(q) = result.unwrap() {
7645 let item = &q.return_clause.items[0];
7646 if let Expression::Literal(Literal::Integer(val)) = &item.expression {
7647 assert_eq!(*val, 63, "0o77 should parse to 63");
7648 } else {
7649 panic!("Expected integer literal");
7650 }
7651 }
7652 }
7653
7654 #[test]
7655 fn test_parse_scientific_float_literal() {
7656 let mut parser = Parser::new("MATCH (n) RETURN 1.5e10");
7657 let result = parser.parse();
7658 assert!(
7659 result.is_ok(),
7660 "Scientific literal should parse: {:?}",
7661 result.err()
7662 );
7663 if let Statement::Query(q) = result.unwrap() {
7664 let item = &q.return_clause.items[0];
7665 if let Expression::Literal(Literal::Float(val)) = &item.expression {
7666 assert!((val - 1.5e10).abs() < 1.0, "1.5e10 should parse correctly");
7667 } else {
7668 panic!("Expected float literal");
7669 }
7670 }
7671 }
7672
7673 fn get_first_path_edges(stmt: &Statement) -> &[EdgePattern] {
7675 if let Statement::Query(q) = stmt
7676 && let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern
7677 {
7678 return &path.edges;
7679 }
7680 panic!("Expected query with path pattern");
7681 }
7682
7683 #[test]
7684 fn test_parse_edge_type_pipe_alternatives() {
7685 let mut parser = Parser::new("MATCH (a)-[:KNOWS|LIKES|FOLLOWS]->(b) RETURN a, b");
7686 let result = parser.parse().expect("Edge type pipe should parse");
7687 let edges = get_first_path_edges(&result);
7688 assert_eq!(edges.len(), 1);
7689 assert_eq!(edges[0].types, vec!["KNOWS", "LIKES", "FOLLOWS"]);
7690 }
7691
7692 #[test]
7693 fn test_parse_edge_type_pipe_with_variable() {
7694 let mut parser = Parser::new("MATCH (a)-[r:KNOWS|LIKES]->(b) RETURN r");
7695 let result = parser
7696 .parse()
7697 .expect("Edge type pipe with var should parse");
7698 let edges = get_first_path_edges(&result);
7699 assert_eq!(edges[0].variable, Some("r".to_string()));
7700 assert_eq!(edges[0].types, vec!["KNOWS", "LIKES"]);
7701 }
7702
7703 #[test]
7704 fn test_parse_tilde_undirected_edge() {
7705 let mut parser = Parser::new("MATCH (a)~[e:KNOWS]~(b) RETURN a, b");
7706 let result = parser.parse().expect("Tilde edge should parse");
7707 let edges = get_first_path_edges(&result);
7708 assert_eq!(edges.len(), 1);
7709 assert_eq!(edges[0].variable, Some("e".to_string()));
7710 assert_eq!(edges[0].types, vec!["KNOWS"]);
7711 assert_eq!(edges[0].direction, EdgeDirection::Undirected);
7712 }
7713
7714 #[test]
7715 fn test_parse_tilde_simple() {
7716 let mut parser = Parser::new("MATCH (a)~(b) RETURN a");
7717 let result = parser.parse().expect("Simple tilde should parse");
7718 let edges = get_first_path_edges(&result);
7719 assert_eq!(edges[0].direction, EdgeDirection::Undirected);
7720 assert!(edges[0].variable.is_none());
7721 assert!(edges[0].types.is_empty());
7722 }
7723
7724 #[test]
7725 fn test_parse_tilde_with_pipe_types() {
7726 let mut parser = Parser::new("MATCH (a)~[:KNOWS|LIKES]~(b) RETURN a");
7727 let result = parser.parse().expect("Tilde with pipe types should parse");
7728 let edges = get_first_path_edges(&result);
7729 assert_eq!(edges[0].types, vec!["KNOWS", "LIKES"]);
7730 assert_eq!(edges[0].direction, EdgeDirection::Undirected);
7731 }
7732
7733 #[test]
7736 fn test_parse_shorthand_outgoing_arrow() {
7737 let mut parser = Parser::new("MATCH (a)-->(b) RETURN b");
7739 let result = parser.parse().expect("Shorthand --> should parse");
7740 let edges = get_first_path_edges(&result);
7741 assert_eq!(edges.len(), 1);
7742 assert_eq!(edges[0].direction, EdgeDirection::Outgoing);
7743 assert!(edges[0].variable.is_none());
7744 assert!(edges[0].types.is_empty());
7745 }
7746
7747 #[test]
7748 fn test_parse_shorthand_incoming_arrow() {
7749 let mut parser = Parser::new("MATCH (a)<--(b) RETURN a");
7751 let result = parser.parse().expect("Shorthand <-- should parse");
7752 let edges = get_first_path_edges(&result);
7753 assert_eq!(edges.len(), 1);
7754 assert_eq!(edges[0].direction, EdgeDirection::Incoming);
7755 assert!(edges[0].variable.is_none());
7756 assert!(edges[0].types.is_empty());
7757 }
7758
7759 #[test]
7760 fn test_parse_shorthand_arrow_chain() {
7761 let mut parser = Parser::new("MATCH (a)-->(b)-->(c) RETURN c");
7763 let result = parser.parse().expect("Chained --> should parse");
7764 let edges = get_first_path_edges(&result);
7765 assert_eq!(edges.len(), 2);
7766 assert_eq!(edges[0].direction, EdgeDirection::Outgoing);
7767 assert_eq!(edges[1].direction, EdgeDirection::Outgoing);
7768 }
7769
7770 #[test]
7771 fn test_parse_shorthand_mixed_directions() {
7772 let mut parser = Parser::new("MATCH (a)<--(b)-->(c) RETURN c");
7774 let result = parser.parse().expect("Mixed <-- and --> should parse");
7775 let edges = get_first_path_edges(&result);
7776 assert_eq!(edges.len(), 2);
7777 assert_eq!(edges[0].direction, EdgeDirection::Incoming);
7778 assert_eq!(edges[1].direction, EdgeDirection::Outgoing);
7779 }
7780
7781 #[test]
7782 fn test_parse_shorthand_undirected_still_works() {
7783 let mut parser = Parser::new("MATCH (a)--(b) RETURN b");
7785 let result = parser.parse().expect("Undirected -- should still parse");
7786 let edges = get_first_path_edges(&result);
7787 assert_eq!(edges[0].direction, EdgeDirection::Undirected);
7788 }
7789
7790 #[test]
7793 fn test_unescape_string_newline() {
7794 assert_eq!(unescape_string(r"hello\nworld"), "hello\nworld");
7795 }
7796
7797 #[test]
7798 fn test_unescape_string_carriage_return() {
7799 assert_eq!(unescape_string(r"line\rend"), "line\rend");
7800 }
7801
7802 #[test]
7803 fn test_unescape_string_tab() {
7804 assert_eq!(unescape_string(r"col1\tcol2"), "col1\tcol2");
7805 }
7806
7807 #[test]
7808 fn test_unescape_string_backslash() {
7809 assert_eq!(unescape_string(r"path\\to"), "path\\to");
7810 }
7811
7812 #[test]
7813 fn test_unescape_string_single_quote() {
7814 assert_eq!(unescape_string(r"it\'s"), "it's");
7815 }
7816
7817 #[test]
7818 fn test_unescape_string_double_quote() {
7819 assert_eq!(unescape_string(r#"say\"hello\""#), "say\"hello\"");
7820 }
7821
7822 #[test]
7823 fn test_unescape_string_unknown_escape() {
7824 assert_eq!(unescape_string(r"\z"), "\\z");
7826 }
7827
7828 #[test]
7829 fn test_unescape_string_trailing_backslash() {
7830 assert_eq!(unescape_string("trailing\\"), "trailing\\");
7832 }
7833
7834 #[test]
7837 fn test_parse_create_graph() {
7838 let mut parser = Parser::new("CREATE GRAPH mydb");
7839 let result = parser.parse();
7840 assert!(
7841 result.is_ok(),
7842 "CREATE GRAPH should parse: {:?}",
7843 result.err()
7844 );
7845
7846 if let Statement::SessionCommand(SessionCommand::CreateGraph {
7847 name,
7848 if_not_exists,
7849 ..
7850 }) = result.unwrap()
7851 {
7852 assert_eq!(name, "mydb");
7853 assert!(!if_not_exists);
7854 } else {
7855 panic!("Expected CreateGraph session command");
7856 }
7857 }
7858
7859 #[test]
7860 fn test_parse_create_graph_if_not_exists() {
7861 let mut parser = Parser::new("CREATE GRAPH IF NOT EXISTS mydb");
7862 let result = parser.parse();
7863 assert!(
7864 result.is_ok(),
7865 "CREATE GRAPH IF NOT EXISTS should parse: {:?}",
7866 result.err()
7867 );
7868
7869 if let Statement::SessionCommand(SessionCommand::CreateGraph {
7870 name,
7871 if_not_exists,
7872 ..
7873 }) = result.unwrap()
7874 {
7875 assert_eq!(name, "mydb");
7876 assert!(if_not_exists);
7877 } else {
7878 panic!("Expected CreateGraph session command");
7879 }
7880 }
7881
7882 #[test]
7883 fn test_parse_create_property_graph() {
7884 let mut parser = Parser::new("CREATE PROPERTY GRAPH pg1");
7885 let result = parser.parse();
7886 assert!(
7887 result.is_ok(),
7888 "CREATE PROPERTY GRAPH should parse: {:?}",
7889 result.err()
7890 );
7891
7892 if let Statement::SessionCommand(SessionCommand::CreateGraph {
7893 name,
7894 if_not_exists,
7895 ..
7896 }) = result.unwrap()
7897 {
7898 assert_eq!(name, "pg1");
7899 assert!(!if_not_exists);
7900 } else {
7901 panic!("Expected CreateGraph session command");
7902 }
7903 }
7904
7905 #[test]
7906 fn test_parse_drop_graph() {
7907 let mut parser = Parser::new("DROP GRAPH mydb");
7908 let result = parser.parse();
7909 assert!(
7910 result.is_ok(),
7911 "DROP GRAPH should parse: {:?}",
7912 result.err()
7913 );
7914
7915 if let Statement::SessionCommand(SessionCommand::DropGraph { name, if_exists }) =
7916 result.unwrap()
7917 {
7918 assert_eq!(name, "mydb");
7919 assert!(!if_exists);
7920 } else {
7921 panic!("Expected DropGraph session command");
7922 }
7923 }
7924
7925 #[test]
7926 fn test_parse_drop_graph_if_exists() {
7927 let mut parser = Parser::new("DROP GRAPH IF EXISTS mydb");
7928 let result = parser.parse();
7929 assert!(
7930 result.is_ok(),
7931 "DROP GRAPH IF EXISTS should parse: {:?}",
7932 result.err()
7933 );
7934
7935 if let Statement::SessionCommand(SessionCommand::DropGraph { name, if_exists }) =
7936 result.unwrap()
7937 {
7938 assert_eq!(name, "mydb");
7939 assert!(if_exists);
7940 } else {
7941 panic!("Expected DropGraph session command");
7942 }
7943 }
7944
7945 #[test]
7946 fn test_parse_drop_property_graph() {
7947 let mut parser = Parser::new("DROP PROPERTY GRAPH pg1");
7948 let result = parser.parse();
7949 assert!(
7950 result.is_ok(),
7951 "DROP PROPERTY GRAPH should parse: {:?}",
7952 result.err()
7953 );
7954
7955 if let Statement::SessionCommand(SessionCommand::DropGraph { name, if_exists }) =
7956 result.unwrap()
7957 {
7958 assert_eq!(name, "pg1");
7959 assert!(!if_exists);
7960 } else {
7961 panic!("Expected DropGraph session command");
7962 }
7963 }
7964
7965 #[test]
7966 fn test_parse_use_graph() {
7967 let mut parser = Parser::new("USE GRAPH workspace");
7968 let result = parser.parse();
7969 assert!(result.is_ok(), "USE GRAPH should parse: {:?}", result.err());
7970
7971 if let Statement::SessionCommand(SessionCommand::UseGraph(name)) = result.unwrap() {
7972 assert_eq!(name, "workspace");
7973 } else {
7974 panic!("Expected UseGraph session command");
7975 }
7976 }
7977
7978 #[test]
7979 fn test_parse_session_set_graph() {
7980 let mut parser = Parser::new("SESSION SET GRAPH analytics");
7981 let result = parser.parse();
7982 assert!(
7983 result.is_ok(),
7984 "SESSION SET GRAPH should parse: {:?}",
7985 result.err()
7986 );
7987
7988 if let Statement::SessionCommand(SessionCommand::SessionSetGraph(name)) = result.unwrap() {
7989 assert_eq!(name, "analytics");
7990 } else {
7991 panic!("Expected SessionSetGraph session command");
7992 }
7993 }
7994
7995 #[test]
7996 fn test_parse_session_set_time_zone() {
7997 let mut parser = Parser::new("SESSION SET TIME ZONE 'UTC+5'");
7998 let result = parser.parse();
7999 assert!(
8000 result.is_ok(),
8001 "SESSION SET TIME ZONE should parse: {:?}",
8002 result.err()
8003 );
8004
8005 if let Statement::SessionCommand(SessionCommand::SessionSetTimeZone(tz)) = result.unwrap() {
8006 assert_eq!(tz, "UTC+5");
8007 } else {
8008 panic!("Expected SessionSetTimeZone session command");
8009 }
8010 }
8011
8012 #[test]
8013 fn test_parse_session_set_schema() {
8014 let mut parser = Parser::new("SESSION SET SCHEMA myschema");
8016 let result = parser.parse();
8017 assert!(
8018 result.is_ok(),
8019 "SESSION SET SCHEMA should parse: {:?}",
8020 result.err()
8021 );
8022
8023 if let Statement::SessionCommand(SessionCommand::SessionSetSchema(name)) = result.unwrap() {
8024 assert_eq!(name, "myschema");
8025 } else {
8026 panic!("Expected SessionSetSchema session command");
8027 }
8028 }
8029
8030 #[test]
8031 fn test_parse_session_set_parameter() {
8032 let mut parser = Parser::new("SESSION SET PARAMETER timeout = 30");
8033 let result = parser.parse();
8034 assert!(
8035 result.is_ok(),
8036 "SESSION SET PARAMETER should parse: {:?}",
8037 result.err()
8038 );
8039
8040 if let Statement::SessionCommand(SessionCommand::SessionSetParameter(name, _value)) =
8041 result.unwrap()
8042 {
8043 assert_eq!(name, "timeout");
8044 } else {
8045 panic!("Expected SessionSetParameter session command");
8046 }
8047 }
8048
8049 #[test]
8050 fn test_parse_session_reset() {
8051 let mut parser = Parser::new("SESSION RESET");
8053 let result = parser.parse();
8054 assert!(
8055 result.is_ok(),
8056 "SESSION RESET should parse: {:?}",
8057 result.err()
8058 );
8059
8060 assert!(matches!(
8061 result.unwrap(),
8062 Statement::SessionCommand(SessionCommand::SessionReset(SessionResetTarget::All))
8063 ));
8064 }
8065
8066 #[test]
8067 fn test_parse_session_reset_all() {
8068 let mut parser = Parser::new("SESSION RESET ALL");
8069 let result = parser.parse();
8070 assert!(
8071 result.is_ok(),
8072 "SESSION RESET ALL should parse: {:?}",
8073 result.err()
8074 );
8075
8076 assert!(matches!(
8077 result.unwrap(),
8078 Statement::SessionCommand(SessionCommand::SessionReset(SessionResetTarget::All))
8079 ));
8080 }
8081
8082 #[test]
8083 fn test_parse_session_reset_schema() {
8084 let mut parser = Parser::new("SESSION RESET SCHEMA");
8086 let result = parser.parse();
8087 assert!(
8088 result.is_ok(),
8089 "SESSION RESET SCHEMA should parse: {:?}",
8090 result.err()
8091 );
8092
8093 assert!(matches!(
8094 result.unwrap(),
8095 Statement::SessionCommand(SessionCommand::SessionReset(SessionResetTarget::Schema))
8096 ));
8097 }
8098
8099 #[test]
8100 fn test_parse_session_reset_graph() {
8101 let mut parser = Parser::new("SESSION RESET GRAPH");
8103 let result = parser.parse();
8104 assert!(
8105 result.is_ok(),
8106 "SESSION RESET GRAPH should parse: {:?}",
8107 result.err()
8108 );
8109
8110 assert!(matches!(
8111 result.unwrap(),
8112 Statement::SessionCommand(SessionCommand::SessionReset(SessionResetTarget::Graph))
8113 ));
8114 }
8115
8116 #[test]
8117 fn test_parse_session_reset_property_graph() {
8118 let mut parser = Parser::new("SESSION RESET PROPERTY GRAPH");
8120 let result = parser.parse();
8121 assert!(
8122 result.is_ok(),
8123 "SESSION RESET PROPERTY GRAPH should parse: {:?}",
8124 result.err()
8125 );
8126
8127 assert!(matches!(
8128 result.unwrap(),
8129 Statement::SessionCommand(SessionCommand::SessionReset(SessionResetTarget::Graph))
8130 ));
8131 }
8132
8133 #[test]
8134 fn test_parse_session_close() {
8135 let mut parser = Parser::new("SESSION CLOSE");
8136 let result = parser.parse();
8137 assert!(
8138 result.is_ok(),
8139 "SESSION CLOSE should parse: {:?}",
8140 result.err()
8141 );
8142
8143 assert!(matches!(
8144 result.unwrap(),
8145 Statement::SessionCommand(SessionCommand::SessionClose)
8146 ));
8147 }
8148
8149 #[test]
8150 fn test_parse_start_transaction() {
8151 let mut parser = Parser::new("START TRANSACTION");
8152 let result = parser.parse();
8153 assert!(
8154 result.is_ok(),
8155 "START TRANSACTION should parse: {:?}",
8156 result.err()
8157 );
8158 match result.unwrap() {
8159 Statement::SessionCommand(SessionCommand::StartTransaction {
8160 read_only,
8161 isolation_level,
8162 }) => {
8163 assert!(!read_only);
8164 assert!(isolation_level.is_none());
8165 }
8166 other => panic!("Expected StartTransaction, got {other:?}"),
8167 }
8168 }
8169
8170 #[test]
8171 fn test_parse_start_transaction_read_only() {
8172 let mut parser = Parser::new("START TRANSACTION READ ONLY");
8173 let result = parser.parse().unwrap();
8174 match result {
8175 Statement::SessionCommand(SessionCommand::StartTransaction {
8176 read_only,
8177 isolation_level,
8178 }) => {
8179 assert!(read_only);
8180 assert!(isolation_level.is_none());
8181 }
8182 other => panic!("Expected StartTransaction READ ONLY, got {other:?}"),
8183 }
8184 }
8185
8186 #[test]
8187 fn test_parse_start_transaction_isolation_level() {
8188 let mut parser = Parser::new("START TRANSACTION ISOLATION LEVEL SERIALIZABLE");
8189 let result = parser.parse().unwrap();
8190 match result {
8191 Statement::SessionCommand(SessionCommand::StartTransaction {
8192 read_only,
8193 isolation_level,
8194 }) => {
8195 assert!(!read_only);
8196 assert_eq!(
8197 isolation_level,
8198 Some(TransactionIsolationLevel::Serializable)
8199 );
8200 }
8201 other => panic!("Expected StartTransaction with isolation, got {other:?}"),
8202 }
8203 }
8204
8205 #[test]
8206 fn test_parse_start_transaction_read_only_with_isolation() {
8207 let mut parser = Parser::new("START TRANSACTION READ ONLY ISOLATION LEVEL READ COMMITTED");
8208 let result = parser.parse().unwrap();
8209 match result {
8210 Statement::SessionCommand(SessionCommand::StartTransaction {
8211 read_only,
8212 isolation_level,
8213 }) => {
8214 assert!(read_only);
8215 assert_eq!(
8216 isolation_level,
8217 Some(TransactionIsolationLevel::ReadCommitted)
8218 );
8219 }
8220 other => panic!("Expected StartTransaction READ ONLY + isolation, got {other:?}"),
8221 }
8222 }
8223
8224 #[test]
8225 fn test_parse_commit() {
8226 let mut parser = Parser::new("COMMIT");
8227 let result = parser.parse();
8228 assert!(result.is_ok(), "COMMIT should parse: {:?}", result.err());
8229
8230 assert!(matches!(
8231 result.unwrap(),
8232 Statement::SessionCommand(SessionCommand::Commit)
8233 ));
8234 }
8235
8236 #[test]
8237 fn test_parse_rollback() {
8238 let mut parser = Parser::new("ROLLBACK");
8239 let result = parser.parse();
8240 assert!(result.is_ok(), "ROLLBACK should parse: {:?}", result.err());
8241
8242 assert!(matches!(
8243 result.unwrap(),
8244 Statement::SessionCommand(SessionCommand::Rollback)
8245 ));
8246 }
8247
8248 #[test]
8251 fn test_parse_edge_where_clause() {
8252 let mut parser = Parser::new("MATCH (a)-[e:KNOWS WHERE e.since >= 2020]->(b) RETURN a, b");
8253 let result = parser.parse();
8254 assert!(
8255 result.is_ok(),
8256 "Edge WHERE clause should parse: {:?}",
8257 result.err()
8258 );
8259
8260 let stmt = result.unwrap();
8261 let edges = get_first_path_edges(&stmt);
8262 assert_eq!(edges.len(), 1);
8263 assert_eq!(edges[0].variable, Some("e".to_string()));
8264 assert_eq!(edges[0].types, vec!["KNOWS"]);
8265 assert!(
8266 edges[0].where_clause.is_some(),
8267 "Edge where_clause should be Some"
8268 );
8269 }
8270
8271 #[test]
8274 fn test_parse_path_quantifier_vs_property_map() {
8275 let mut parser = Parser::new("MATCH (a)-[:KNOWS{1,3}]->(b) RETURN a, b");
8277 let result = parser.parse();
8278 assert!(
8279 result.is_ok(),
8280 "{{1,3}} quantifier should parse: {:?}",
8281 result.err()
8282 );
8283
8284 if let Statement::Query(q) = result.unwrap() {
8285 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8286 assert_eq!(path.edges[0].min_hops, Some(1));
8287 assert_eq!(path.edges[0].max_hops, Some(3));
8288 } else {
8289 panic!("Expected path pattern");
8290 }
8291 } else {
8292 panic!("Expected Query statement");
8293 }
8294
8295 let mut parser2 = Parser::new("MATCH (n:Person {since: 2020}) RETURN n");
8297 let result2 = parser2.parse();
8298 assert!(
8299 result2.is_ok(),
8300 "Property map should parse: {:?}",
8301 result2.err()
8302 );
8303
8304 if let Statement::Query(q) = result2.unwrap() {
8305 if let Pattern::Node(node) = &q.match_clauses[0].patterns[0].pattern {
8306 assert_eq!(node.properties.len(), 1);
8307 assert_eq!(node.properties[0].0, "since");
8308 } else {
8309 panic!("Expected node pattern");
8310 }
8311 } else {
8312 panic!("Expected Query statement");
8313 }
8314 }
8315
8316 #[test]
8319 fn test_parse_next_composition() {
8320 let mut parser =
8321 Parser::new("MATCH (n:Person) RETURN n.name NEXT MATCH (m:Company) RETURN m.name");
8322 let result = parser.parse();
8323 assert!(
8324 result.is_ok(),
8325 "NEXT composition should parse: {:?}",
8326 result.err()
8327 );
8328
8329 if let Statement::CompositeQuery { op, .. } = result.unwrap() {
8330 assert_eq!(op, CompositeOp::Next);
8331 } else {
8332 panic!("Expected CompositeQuery with Next op");
8333 }
8334 }
8335
8336 #[test]
8339 fn test_parse_finish_statement() {
8340 let mut parser = Parser::new("MATCH (n) FINISH");
8341 let result = parser.parse();
8342 assert!(result.is_ok(), "FINISH should parse: {:?}", result.err());
8343
8344 if let Statement::Query(q) = result.unwrap() {
8345 assert!(q.return_clause.is_finish, "Expected is_finish to be true");
8346 assert!(
8347 q.return_clause.items.is_empty(),
8348 "FINISH should have no return items"
8349 );
8350 } else {
8351 panic!("Expected Query statement");
8352 }
8353 }
8354
8355 #[test]
8358 fn test_parse_select_statement() {
8359 let mut parser = Parser::new("MATCH (n:Person) SELECT n.name");
8360 let result = parser.parse();
8361 assert!(result.is_ok(), "SELECT should parse: {:?}", result.err());
8362
8363 if let Statement::Query(q) = result.unwrap() {
8364 assert!(!q.return_clause.is_finish);
8365 assert_eq!(q.return_clause.items.len(), 1);
8366 } else {
8367 panic!("Expected Query statement");
8368 }
8369 }
8370
8371 #[test]
8374 fn test_parse_error_drop_nothing() {
8375 let mut parser = Parser::new("DROP NOTHING");
8376 let result = parser.parse();
8377 assert!(result.is_err(), "DROP NOTHING should fail");
8378 }
8379
8380 #[test]
8381 fn test_parse_error_session_destroy() {
8382 let mut parser = Parser::new("SESSION DESTROY");
8383 let result = parser.parse();
8384 assert!(result.is_err(), "SESSION DESTROY should fail");
8385 }
8386
8387 #[test]
8388 fn test_parse_error_start_something() {
8389 let mut parser = Parser::new("START SOMETHING");
8390 let result = parser.parse();
8391 assert!(result.is_err(), "START SOMETHING should fail");
8392 }
8393
8394 #[test]
8395 fn test_parse_error_use_something() {
8396 let mut parser = Parser::new("USE SOMETHING");
8397 let result = parser.parse();
8398 assert!(result.is_err(), "USE SOMETHING should fail");
8399 }
8400
8401 #[test]
8406 fn test_parse_order_by_nulls_first() {
8407 let mut parser =
8408 Parser::new("MATCH (n:Person) RETURN n.name ORDER BY n.age ASC NULLS FIRST");
8409 let stmt = parser.parse().unwrap();
8410 if let Statement::Query(q) = stmt {
8411 let order = q.return_clause.order_by.unwrap();
8412 assert_eq!(order.items[0].nulls, Some(NullsOrdering::First));
8413 } else {
8414 panic!("Expected query");
8415 }
8416 }
8417
8418 #[test]
8419 fn test_parse_order_by_nulls_last() {
8420 let mut parser =
8421 Parser::new("MATCH (n:Person) RETURN n.name ORDER BY n.age DESC NULLS LAST");
8422 let stmt = parser.parse().unwrap();
8423 if let Statement::Query(q) = stmt {
8424 let order = q.return_clause.order_by.unwrap();
8425 assert_eq!(order.items[0].nulls, Some(NullsOrdering::Last));
8426 } else {
8427 panic!("Expected query");
8428 }
8429 }
8430
8431 #[test]
8432 fn test_parse_order_by_no_nulls_clause() {
8433 let mut parser = Parser::new("MATCH (n:Person) RETURN n.name ORDER BY n.age ASC");
8434 let stmt = parser.parse().unwrap();
8435 if let Statement::Query(q) = stmt {
8436 let order = q.return_clause.order_by.unwrap();
8437 assert_eq!(order.items[0].nulls, None);
8438 } else {
8439 panic!("Expected query");
8440 }
8441 }
8442
8443 #[test]
8448 fn test_parse_nullif() {
8449 let mut parser = Parser::new("MATCH (n:Person) RETURN NULLIF(n.age, 30) AS val");
8450 let stmt = parser.parse().unwrap();
8451 if let Statement::Query(q) = stmt {
8452 match &q.return_clause.items[0].expression {
8453 Expression::FunctionCall { name, args, .. } => {
8454 assert_eq!(name, "nullif");
8455 assert_eq!(args.len(), 2);
8456 }
8457 other => panic!("Expected FunctionCall, got {other:?}"),
8458 }
8459 } else {
8460 panic!("Expected query");
8461 }
8462 }
8463
8464 #[test]
8465 fn test_parse_coalesce() {
8466 let mut parser =
8467 Parser::new("MATCH (n:Person) RETURN COALESCE(null, n.name, 'default') AS val");
8468 let stmt = parser.parse().unwrap();
8469 if let Statement::Query(q) = stmt {
8470 match &q.return_clause.items[0].expression {
8471 Expression::FunctionCall { name, args, .. } => {
8472 assert_eq!(name, "coalesce");
8473 assert_eq!(args.len(), 3);
8474 }
8475 other => panic!("Expected FunctionCall, got {other:?}"),
8476 }
8477 } else {
8478 panic!("Expected query");
8479 }
8480 }
8481
8482 #[test]
8487 fn test_parse_is_nfc_normalized() {
8488 let mut parser = Parser::new("MATCH (n:Person) RETURN n.name IS NFC NORMALIZED AS norm");
8489 let stmt = parser.parse().unwrap();
8490 if let Statement::Query(q) = stmt {
8491 match &q.return_clause.items[0].expression {
8492 Expression::FunctionCall { name, args, .. } => {
8493 assert_eq!(name, "isNormalized");
8494 assert_eq!(args.len(), 2);
8495 match &args[1] {
8497 Expression::Literal(Literal::String(s)) => assert_eq!(s, "NFC"),
8498 other => panic!("Expected string literal, got {other:?}"),
8499 }
8500 }
8501 other => panic!("Expected FunctionCall, got {other:?}"),
8502 }
8503 } else {
8504 panic!("Expected query");
8505 }
8506 }
8507
8508 #[test]
8509 fn test_parse_is_not_nfkd_normalized() {
8510 let mut parser =
8511 Parser::new("MATCH (n:Person) RETURN n.name IS NOT NFKD NORMALIZED AS norm");
8512 let stmt = parser.parse().unwrap();
8513 if let Statement::Query(q) = stmt {
8514 match &q.return_clause.items[0].expression {
8515 Expression::Unary { op, operand } => {
8516 assert_eq!(*op, UnaryOp::Not);
8517 match operand.as_ref() {
8518 Expression::FunctionCall { name, args, .. } => {
8519 assert_eq!(name, "isNormalized");
8520 match &args[1] {
8521 Expression::Literal(Literal::String(s)) => {
8522 assert_eq!(s, "NFKD");
8523 }
8524 other => panic!("Expected string literal, got {other:?}"),
8525 }
8526 }
8527 other => panic!("Expected FunctionCall, got {other:?}"),
8528 }
8529 }
8530 other => panic!("Expected Unary NOT, got {other:?}"),
8531 }
8532 } else {
8533 panic!("Expected query");
8534 }
8535 }
8536
8537 #[test]
8538 fn test_parse_is_normalized_default_form() {
8539 let mut parser = Parser::new("MATCH (n:Person) RETURN n.name IS NORMALIZED AS norm");
8540 let stmt = parser.parse().unwrap();
8541 if let Statement::Query(q) = stmt {
8542 match &q.return_clause.items[0].expression {
8543 Expression::FunctionCall { name, args, .. } => {
8544 assert_eq!(name, "isNormalized");
8545 assert_eq!(args.len(), 2);
8546 match &args[1] {
8547 Expression::Literal(Literal::String(s)) => assert_eq!(s, "NFC"),
8548 other => panic!("Expected string literal NFC, got {other:?}"),
8549 }
8550 }
8551 other => panic!("Expected FunctionCall, got {other:?}"),
8552 }
8553 } else {
8554 panic!("Expected query");
8555 }
8556 }
8557
8558 #[test]
8561 fn test_parse_parenthesized_path_mode_prefix() {
8562 let mut parser = Parser::new("MATCH (TRAIL (a)-[e]->(b)){2,5} RETURN a, b");
8564 let result = parser.parse();
8565 assert!(
8566 result.is_ok(),
8567 "Parenthesized path with mode prefix should parse: {:?}",
8568 result.err()
8569 );
8570
8571 if let Statement::Query(q) = result.unwrap() {
8572 let pat = &q.match_clauses[0].patterns[0].pattern;
8573 if let Pattern::Quantified {
8574 min,
8575 max,
8576 path_mode,
8577 ..
8578 } = pat
8579 {
8580 assert_eq!(*min, 2);
8581 assert_eq!(*max, Some(5));
8582 assert_eq!(*path_mode, Some(PathMode::Trail));
8583 } else {
8584 panic!("Expected Quantified pattern, got {pat:?}");
8585 }
8586 } else {
8587 panic!("Expected Query statement");
8588 }
8589 }
8590
8591 #[test]
8592 fn test_parse_parenthesized_where_clause() {
8593 let mut parser = Parser::new("MATCH ((a)-[e]->(b) WHERE e.weight > 5){1,3} RETURN a, b");
8595 let result = parser.parse();
8596 assert!(
8597 result.is_ok(),
8598 "Parenthesized path with WHERE should parse: {:?}",
8599 result.err()
8600 );
8601
8602 if let Statement::Query(q) = result.unwrap() {
8603 let pat = &q.match_clauses[0].patterns[0].pattern;
8604 if let Pattern::Quantified {
8605 min,
8606 max,
8607 where_clause,
8608 ..
8609 } = pat
8610 {
8611 assert_eq!(*min, 1);
8612 assert_eq!(*max, Some(3));
8613 assert!(where_clause.is_some(), "WHERE clause should be present");
8614 } else {
8615 panic!("Expected Quantified pattern, got {pat:?}");
8616 }
8617 } else {
8618 panic!("Expected Query statement");
8619 }
8620 }
8621
8622 #[test]
8623 fn test_parse_parenthesized_all_features() {
8624 let mut parser =
8626 Parser::new("MATCH (ACYCLIC (a)-[e]->(b) WHERE e.active = true){2,4} RETURN a, b");
8627 let result = parser.parse();
8628 assert!(
8629 result.is_ok(),
8630 "Full parenthesized path should parse: {:?}",
8631 result.err()
8632 );
8633
8634 if let Statement::Query(q) = result.unwrap() {
8635 let pat = &q.match_clauses[0].patterns[0].pattern;
8636 if let Pattern::Quantified {
8637 min,
8638 max,
8639 path_mode,
8640 where_clause,
8641 subpath_var,
8642 ..
8643 } = pat
8644 {
8645 assert_eq!(*min, 2);
8646 assert_eq!(*max, Some(4));
8647 assert_eq!(*path_mode, Some(PathMode::Acyclic));
8648 assert!(where_clause.is_some());
8649 assert!(subpath_var.is_none());
8650 } else {
8651 panic!("Expected Quantified pattern, got {pat:?}");
8652 }
8653 } else {
8654 panic!("Expected Query statement");
8655 }
8656 }
8657
8658 #[test]
8661 fn test_parse_simplified_outgoing() {
8662 let mut parser = Parser::new("MATCH (a:Person)-/:KNOWS/->(b:Person) RETURN b.name");
8664 let result = parser.parse();
8665 assert!(
8666 result.is_ok(),
8667 "Simplified outgoing path should parse: {:?}",
8668 result.err()
8669 );
8670
8671 if let Statement::Query(q) = result.unwrap() {
8672 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8673 assert_eq!(path.edges.len(), 1);
8674 assert_eq!(path.edges[0].types, vec!["KNOWS"]);
8675 assert_eq!(path.edges[0].direction, EdgeDirection::Outgoing);
8676 } else {
8677 panic!("Expected Path pattern");
8678 }
8679 } else {
8680 panic!("Expected Query");
8681 }
8682 }
8683
8684 #[test]
8685 fn test_parse_simplified_incoming() {
8686 let mut parser = Parser::new("MATCH (a:Person)<-/:KNOWS/-(b:Person) RETURN b.name");
8688 let result = parser.parse();
8689 assert!(
8690 result.is_ok(),
8691 "Simplified incoming path should parse: {:?}",
8692 result.err()
8693 );
8694
8695 if let Statement::Query(q) = result.unwrap() {
8696 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8697 assert_eq!(path.edges.len(), 1);
8698 assert_eq!(path.edges[0].types, vec!["KNOWS"]);
8699 assert_eq!(path.edges[0].direction, EdgeDirection::Incoming);
8700 } else {
8701 panic!("Expected Path pattern");
8702 }
8703 } else {
8704 panic!("Expected Query");
8705 }
8706 }
8707
8708 #[test]
8709 fn test_parse_simplified_undirected() {
8710 let mut parser = Parser::new("MATCH (a:Person)-/:KNOWS/-(b:Person) RETURN b.name");
8712 let result = parser.parse();
8713 assert!(
8714 result.is_ok(),
8715 "Simplified undirected path should parse: {:?}",
8716 result.err()
8717 );
8718
8719 if let Statement::Query(q) = result.unwrap() {
8720 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8721 assert_eq!(path.edges.len(), 1);
8722 assert_eq!(path.edges[0].types, vec!["KNOWS"]);
8723 assert_eq!(path.edges[0].direction, EdgeDirection::Undirected);
8724 } else {
8725 panic!("Expected Path pattern");
8726 }
8727 } else {
8728 panic!("Expected Query");
8729 }
8730 }
8731
8732 #[test]
8733 fn test_parse_simplified_multi_label() {
8734 let mut parser =
8736 Parser::new("MATCH (a:Person)-/:KNOWS|WORKS_WITH/->(b:Person) RETURN b.name");
8737 let result = parser.parse();
8738 assert!(
8739 result.is_ok(),
8740 "Simplified multi-label path should parse: {:?}",
8741 result.err()
8742 );
8743
8744 if let Statement::Query(q) = result.unwrap() {
8745 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8746 assert_eq!(path.edges[0].types, vec!["KNOWS", "WORKS_WITH"]);
8747 assert_eq!(path.edges[0].direction, EdgeDirection::Outgoing);
8748 } else {
8749 panic!("Expected Path pattern");
8750 }
8751 } else {
8752 panic!("Expected Query");
8753 }
8754 }
8755
8756 #[test]
8757 fn test_parse_simplified_tilde() {
8758 let mut parser = Parser::new("MATCH (a:Person)~/:KNOWS/~(b:Person) RETURN b.name");
8760 let result = parser.parse();
8761 assert!(
8762 result.is_ok(),
8763 "Simplified tilde path should parse: {:?}",
8764 result.err()
8765 );
8766
8767 if let Statement::Query(q) = result.unwrap() {
8768 if let Pattern::Path(path) = &q.match_clauses[0].patterns[0].pattern {
8769 assert_eq!(path.edges[0].types, vec!["KNOWS"]);
8770 assert_eq!(path.edges[0].direction, EdgeDirection::Undirected);
8771 } else {
8772 panic!("Expected Path pattern");
8773 }
8774 } else {
8775 panic!("Expected Query");
8776 }
8777 }
8778
8779 #[test]
8782 fn test_parse_multiset_alternation() {
8783 let mut parser = Parser::new(
8785 "MATCH ((a)-[:KNOWS]->(b) |+| (a)-[:WORKS_WITH]->(b)) RETURN a.name, b.name",
8786 );
8787 let result = parser.parse();
8788 assert!(
8789 result.is_ok(),
8790 "Multiset alternation should parse: {:?}",
8791 result.err()
8792 );
8793
8794 if let Statement::Query(q) = result.unwrap() {
8795 let pattern = &q.match_clauses[0].patterns[0].pattern;
8796 assert!(
8797 matches!(pattern, Pattern::MultisetUnion(_)),
8798 "Expected MultisetUnion pattern, got {:?}",
8799 pattern
8800 );
8801 if let Pattern::MultisetUnion(alternatives) = pattern {
8802 assert_eq!(alternatives.len(), 2);
8803 }
8804 } else {
8805 panic!("Expected Query");
8806 }
8807 }
8808
8809 #[test]
8810 fn test_parse_set_alternation() {
8811 let mut parser =
8813 Parser::new("MATCH ((a)-[:KNOWS]->(b) | (a)-[:WORKS_WITH]->(b)) RETURN a.name");
8814 let result = parser.parse();
8815 assert!(
8816 result.is_ok(),
8817 "Set alternation should parse: {:?}",
8818 result.err()
8819 );
8820
8821 if let Statement::Query(q) = result.unwrap() {
8822 let pattern = &q.match_clauses[0].patterns[0].pattern;
8823 assert!(
8824 matches!(pattern, Pattern::Union(_)),
8825 "Expected Union pattern, got {:?}",
8826 pattern
8827 );
8828 } else {
8829 panic!("Expected Query");
8830 }
8831 }
8832
8833 #[test]
8834 fn test_parse_delete_variable() {
8835 let mut parser = Parser::new("MATCH (n:Person) DELETE n");
8837 let result = parser.parse();
8838 assert!(
8839 result.is_ok(),
8840 "DELETE variable should parse: {:?}",
8841 result.err()
8842 );
8843 if let Statement::Query(q) = result.unwrap() {
8844 assert_eq!(q.delete_clauses.len(), 1);
8845 assert_eq!(q.delete_clauses[0].targets.len(), 1);
8846 assert!(
8847 matches!(&q.delete_clauses[0].targets[0], DeleteTarget::Variable(name) if name == "n"),
8848 "Expected Variable target"
8849 );
8850 } else {
8851 panic!("Expected Query");
8852 }
8853 }
8854
8855 #[test]
8856 fn test_parse_delete_expression() {
8857 let mut parser = Parser::new("MATCH (n:Person) DELETE n.friend");
8859 let result = parser.parse();
8860 assert!(
8861 result.is_ok(),
8862 "DELETE expression should parse: {:?}",
8863 result.err()
8864 );
8865 if let Statement::Query(q) = result.unwrap() {
8866 assert_eq!(q.delete_clauses.len(), 1);
8867 assert_eq!(q.delete_clauses[0].targets.len(), 1);
8868 assert!(
8869 matches!(&q.delete_clauses[0].targets[0], DeleteTarget::Expression(_)),
8870 "Expected Expression target, got {:?}",
8871 q.delete_clauses[0].targets[0]
8872 );
8873 } else {
8874 panic!("Expected Query");
8875 }
8876 }
8877
8878 #[test]
8879 fn test_parse_delete_multiple_mixed_targets() {
8880 let mut parser = Parser::new("MATCH (n:Person)-[r:KNOWS]->(m) DELETE n, r");
8882 let result = parser.parse();
8883 assert!(
8884 result.is_ok(),
8885 "DELETE mixed targets should parse: {:?}",
8886 result.err()
8887 );
8888 if let Statement::Query(q) = result.unwrap() {
8889 assert_eq!(q.delete_clauses[0].targets.len(), 2);
8890 assert!(matches!(
8891 &q.delete_clauses[0].targets[0],
8892 DeleteTarget::Variable(name) if name == "n"
8893 ));
8894 assert!(matches!(
8895 &q.delete_clauses[0].targets[1],
8896 DeleteTarget::Variable(name) if name == "r"
8897 ));
8898 } else {
8899 panic!("Expected Query");
8900 }
8901 }
8902
8903 #[test]
8904 fn test_parse_detach_delete_expression() {
8905 let mut parser = Parser::new("MATCH (n:Person) DETACH DELETE n");
8907 let result = parser.parse();
8908 assert!(
8909 result.is_ok(),
8910 "DETACH DELETE should parse: {:?}",
8911 result.err()
8912 );
8913 if let Statement::Query(q) = result.unwrap() {
8914 assert!(q.delete_clauses[0].detach);
8915 assert_eq!(q.delete_clauses[0].targets.len(), 1);
8916 } else {
8917 panic!("Expected Query");
8918 }
8919 }
8920
8921 #[test]
8926 fn test_parse_create_graph_type_iso_syntax() {
8927 let mut parser = Parser::new(
8928 "CREATE GRAPH TYPE social (\
8929 NODE TYPE Person (name STRING NOT NULL, age INTEGER),\
8930 EDGE TYPE KNOWS (since INTEGER)\
8931 )",
8932 );
8933 let result = parser.parse();
8934 assert!(result.is_ok(), "Failed to parse ISO graph type: {result:?}");
8935 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
8936 assert_eq!(stmt.name, "social");
8937 assert_eq!(stmt.inline_types.len(), 2);
8938 assert!(stmt.node_types.contains(&"Person".to_string()));
8939 assert!(stmt.edge_types.contains(&"KNOWS".to_string()));
8940 } else {
8941 panic!("Expected CreateGraphType");
8942 }
8943 }
8944
8945 #[test]
8946 fn test_parse_create_graph_type_like() {
8947 let mut parser = Parser::new("CREATE GRAPH TYPE cloned LIKE original_graph");
8948 let result = parser.parse();
8949 assert!(result.is_ok(), "Failed to parse LIKE: {result:?}");
8950 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
8951 assert_eq!(stmt.name, "cloned");
8952 assert_eq!(stmt.like_graph, Some("original_graph".to_string()));
8953 } else {
8954 panic!("Expected CreateGraphType");
8955 }
8956 }
8957
8958 #[test]
8959 fn test_parse_create_graph_type_key_labels() {
8960 let mut parser = Parser::new(
8961 "CREATE GRAPH TYPE keyed (\
8962 NODE TYPE Person KEY (PersonLabel, NamedEntity) (name STRING NOT NULL)\
8963 )",
8964 );
8965 let result = parser.parse();
8966 assert!(result.is_ok(), "Failed to parse key labels: {result:?}");
8967 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
8968 assert_eq!(stmt.inline_types.len(), 1);
8969 match &stmt.inline_types[0] {
8970 InlineElementType::Node { key_labels, .. } => {
8971 assert_eq!(key_labels.len(), 2);
8972 assert_eq!(key_labels[0], "PersonLabel");
8973 assert_eq!(key_labels[1], "NamedEntity");
8974 }
8975 _ => panic!("Expected Node"),
8976 }
8977 } else {
8978 panic!("Expected CreateGraphType");
8979 }
8980 }
8981
8982 #[test]
8985 fn test_parse_exists_with_match() {
8986 let mut parser = Parser::new("MATCH (n) WHERE EXISTS { MATCH (n)-[:KNOWS]->() } RETURN n");
8988 let result = parser.parse();
8989 assert!(result.is_ok(), "EXISTS with MATCH should parse: {result:?}");
8990 }
8991
8992 #[test]
8993 fn test_parse_exists_bare_pattern() {
8994 let mut parser = Parser::new("MATCH (n) WHERE EXISTS { (n)-[:KNOWS]->() } RETURN n");
8996 let result = parser.parse();
8997 assert!(
8998 result.is_ok(),
8999 "EXISTS bare pattern should parse: {result:?}"
9000 );
9001 }
9002
9003 #[test]
9004 fn test_parse_exists_bare_pattern_with_where() {
9005 let mut parser = Parser::new(
9007 "MATCH (a), (b) WHERE NOT EXISTS { (a)-[r]->(b) WHERE type(r) = 'KNOWS' } RETURN a",
9008 );
9009 let result = parser.parse();
9010 assert!(
9011 result.is_ok(),
9012 "EXISTS bare pattern with WHERE should parse: {result:?}"
9013 );
9014 }
9015
9016 #[test]
9019 fn test_parse_graph_type_pattern_form_simple() {
9020 let mut parser = Parser::new(
9021 "CREATE GRAPH TYPE social (\
9022 (:Person {name STRING NOT NULL})-[:KNOWS {since INTEGER}]->(:Person)\
9023 )",
9024 );
9025 let result = parser.parse();
9026 assert!(
9027 result.is_ok(),
9028 "Pattern-form graph type should parse: {result:?}"
9029 );
9030 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
9031 assert_eq!(stmt.name, "social");
9032 assert!(stmt.node_types.contains(&"Person".to_string()));
9033 assert!(stmt.edge_types.contains(&"KNOWS".to_string()));
9034 let node_count = stmt
9036 .inline_types
9037 .iter()
9038 .filter(|t| matches!(t, InlineElementType::Node { .. }))
9039 .count();
9040 let edge_count = stmt
9041 .inline_types
9042 .iter()
9043 .filter(|t| matches!(t, InlineElementType::Edge { .. }))
9044 .count();
9045 assert_eq!(
9046 node_count, 1,
9047 "Should have 1 node type (Person, deduplicated)"
9048 );
9049 assert_eq!(edge_count, 1, "Should have 1 edge type (KNOWS)");
9050 for t in &stmt.inline_types {
9052 if let InlineElementType::Edge {
9053 name,
9054 source_node_types,
9055 target_node_types,
9056 ..
9057 } = t
9058 {
9059 assert_eq!(name, "KNOWS");
9060 assert_eq!(source_node_types, &["Person"]);
9061 assert_eq!(target_node_types, &["Person"]);
9062 }
9063 }
9064 } else {
9065 panic!("Expected CreateGraphType");
9066 }
9067 }
9068
9069 #[test]
9070 fn test_parse_graph_type_pattern_form_multiple_patterns() {
9071 let mut parser = Parser::new(
9072 "CREATE GRAPH TYPE social (\
9073 (:Person {name STRING NOT NULL})-[:KNOWS {since INTEGER}]->(:Person),\
9074 (:Person)-[:LIVES_IN]->(:City)\
9075 )",
9076 );
9077 let result = parser.parse();
9078 assert!(
9079 result.is_ok(),
9080 "Multiple pattern-form entries should parse: {result:?}"
9081 );
9082 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
9083 assert_eq!(stmt.name, "social");
9084 assert!(stmt.node_types.contains(&"Person".to_string()));
9085 assert!(stmt.node_types.contains(&"City".to_string()));
9086 assert!(stmt.edge_types.contains(&"KNOWS".to_string()));
9087 assert!(stmt.edge_types.contains(&"LIVES_IN".to_string()));
9088 let node_count = stmt
9090 .inline_types
9091 .iter()
9092 .filter(|t| matches!(t, InlineElementType::Node { .. }))
9093 .count();
9094 assert_eq!(node_count, 2, "Should have 2 node types (Person, City)");
9095 } else {
9096 panic!("Expected CreateGraphType");
9097 }
9098 }
9099
9100 #[test]
9101 fn test_parse_graph_type_pattern_form_standalone_node() {
9102 let mut parser = Parser::new(
9103 "CREATE GRAPH TYPE basic_nodes (\
9104 (:Person {name STRING})\
9105 )",
9106 );
9107 let result = parser.parse();
9108 assert!(
9109 result.is_ok(),
9110 "Standalone node pattern should parse: {result:?}"
9111 );
9112 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
9113 assert_eq!(stmt.inline_types.len(), 1);
9114 assert!(matches!(
9115 &stmt.inline_types[0],
9116 InlineElementType::Node { name, .. } if name == "Person"
9117 ));
9118 } else {
9119 panic!("Expected CreateGraphType");
9120 }
9121 }
9122
9123 #[test]
9124 fn test_parse_graph_type_pattern_form_no_props() {
9125 let mut parser = Parser::new(
9126 "CREATE GRAPH TYPE bare (\
9127 (:Person)-[:KNOWS]->(:Person)\
9128 )",
9129 );
9130 let result = parser.parse();
9131 assert!(
9132 result.is_ok(),
9133 "Pattern without properties should parse: {result:?}"
9134 );
9135 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
9136 for t in &stmt.inline_types {
9138 if let InlineElementType::Node { properties, .. } = t {
9139 assert!(properties.is_empty());
9140 }
9141 if let InlineElementType::Edge { properties, .. } = t {
9142 assert!(properties.is_empty());
9143 }
9144 }
9145 } else {
9146 panic!("Expected CreateGraphType");
9147 }
9148 }
9149
9150 #[test]
9151 fn test_parse_graph_type_pattern_form_backward_edge() {
9152 let mut parser = Parser::new(
9153 "CREATE GRAPH TYPE rev (\
9154 (:City)<-[:LIVES_IN]-(:Person)\
9155 )",
9156 );
9157 let result = parser.parse();
9158 assert!(
9159 result.is_ok(),
9160 "Backward edge pattern should parse: {result:?}"
9161 );
9162 if let Statement::Schema(SchemaStatement::CreateGraphType(stmt)) = result.unwrap() {
9163 for t in &stmt.inline_types {
9164 if let InlineElementType::Edge {
9165 name,
9166 source_node_types,
9167 target_node_types,
9168 ..
9169 } = t
9170 {
9171 assert_eq!(name, "LIVES_IN");
9172 assert_eq!(source_node_types, &["Person"]);
9174 assert_eq!(target_node_types, &["City"]);
9175 }
9176 }
9177 } else {
9178 panic!("Expected CreateGraphType");
9179 }
9180 }
9181
9182 #[test]
9185 fn test_parse_show_constraints() {
9186 let mut parser = Parser::new("SHOW CONSTRAINTS");
9187 let result = parser.parse();
9188 assert!(result.is_ok(), "SHOW CONSTRAINTS should parse: {result:?}");
9189 assert!(matches!(
9190 result.unwrap(),
9191 Statement::Schema(SchemaStatement::ShowConstraints)
9192 ));
9193 }
9194
9195 #[test]
9196 fn test_parse_show_indexes() {
9197 let mut parser = Parser::new("SHOW INDEXES");
9198 let result = parser.parse();
9199 assert!(result.is_ok(), "SHOW INDEXES should parse: {result:?}");
9200 assert!(matches!(
9201 result.unwrap(),
9202 Statement::Schema(SchemaStatement::ShowIndexes)
9203 ));
9204 }
9205
9206 #[test]
9207 fn test_parse_show_index_singular() {
9208 let mut parser = Parser::new("SHOW INDEX");
9210 let result = parser.parse();
9211 assert!(result.is_ok(), "SHOW INDEX should parse: {result:?}");
9212 assert!(matches!(
9213 result.unwrap(),
9214 Statement::Schema(SchemaStatement::ShowIndexes)
9215 ));
9216 }
9217
9218 #[test]
9219 fn test_parse_show_node_types() {
9220 let mut parser = Parser::new("SHOW NODE TYPES");
9221 let result = parser.parse();
9222 assert!(result.is_ok(), "SHOW NODE TYPES should parse: {result:?}");
9223 assert!(matches!(
9224 result.unwrap(),
9225 Statement::Schema(SchemaStatement::ShowNodeTypes)
9226 ));
9227 }
9228
9229 #[test]
9230 fn test_parse_show_edge_types() {
9231 let mut parser = Parser::new("SHOW EDGE TYPES");
9232 let result = parser.parse();
9233 assert!(result.is_ok(), "SHOW EDGE TYPES should parse: {result:?}");
9234 assert!(matches!(
9235 result.unwrap(),
9236 Statement::Schema(SchemaStatement::ShowEdgeTypes)
9237 ));
9238 }
9239
9240 #[test]
9241 fn test_parse_show_graph_types() {
9242 let mut parser = Parser::new("SHOW GRAPH TYPES");
9243 let result = parser.parse();
9244 assert!(result.is_ok(), "SHOW GRAPH TYPES should parse: {result:?}");
9245 assert!(matches!(
9246 result.unwrap(),
9247 Statement::Schema(SchemaStatement::ShowGraphTypes)
9248 ));
9249 }
9250
9251 #[test]
9252 fn test_parse_show_graphs() {
9253 let mut parser = Parser::new("SHOW GRAPHS");
9254 let result = parser.parse();
9255 assert!(result.is_ok(), "SHOW GRAPHS should parse: {result:?}");
9256 assert!(matches!(
9257 result.unwrap(),
9258 Statement::Schema(SchemaStatement::ShowGraphs)
9259 ));
9260 }
9261
9262 #[test]
9263 fn test_parse_show_graph_type_named() {
9264 let mut parser = Parser::new("SHOW GRAPH TYPE social");
9265 let result = parser.parse();
9266 assert!(
9267 result.is_ok(),
9268 "SHOW GRAPH TYPE <name> should parse: {result:?}"
9269 );
9270 if let Statement::Schema(SchemaStatement::ShowGraphType(name)) = result.unwrap() {
9271 assert_eq!(name, "social");
9272 } else {
9273 panic!("Expected ShowGraphType");
9274 }
9275 }
9276
9277 #[test]
9280 fn test_parse_load_data_csv() {
9281 let mut parser = Parser::new(
9282 "LOAD DATA FROM 'people.csv' FORMAT CSV WITH HEADERS AS row RETURN row.name",
9283 );
9284 let result = parser.parse();
9285 assert!(result.is_ok(), "LOAD DATA CSV parse failed: {result:?}");
9286 if let Statement::Query(query) = result.unwrap() {
9287 assert!(!query.ordered_clauses.is_empty());
9288 assert!(matches!(query.ordered_clauses[0], QueryClause::LoadData(_)));
9289 if let QueryClause::LoadData(ref ld) = query.ordered_clauses[0] {
9290 assert_eq!(ld.path, "people.csv");
9291 assert_eq!(ld.format, LoadFormat::Csv);
9292 assert!(ld.with_headers);
9293 assert_eq!(ld.variable, "row");
9294 }
9295 } else {
9296 panic!("Expected Query statement");
9297 }
9298 }
9299
9300 #[test]
9301 fn test_parse_load_data_csv_no_headers() {
9302 let mut parser = Parser::new("LOAD DATA FROM 'data.csv' FORMAT CSV AS r RETURN r[0]");
9303 let result = parser.parse();
9304 assert!(
9305 result.is_ok(),
9306 "LOAD DATA CSV no headers parse failed: {result:?}"
9307 );
9308 if let Statement::Query(query) = result.unwrap()
9309 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9310 {
9311 assert!(!ld.with_headers);
9312 assert_eq!(ld.variable, "r");
9313 }
9314 }
9315
9316 #[test]
9317 fn test_parse_load_data_jsonl() {
9318 let mut parser =
9319 Parser::new("LOAD DATA FROM 'events.jsonl' FORMAT JSONL AS row RETURN row.title");
9320 let result = parser.parse();
9321 assert!(result.is_ok(), "LOAD DATA JSONL parse failed: {result:?}");
9322 if let Statement::Query(query) = result.unwrap()
9323 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9324 {
9325 assert_eq!(ld.format, LoadFormat::Jsonl);
9326 assert_eq!(ld.path, "events.jsonl");
9327 }
9328 }
9329
9330 #[test]
9331 fn test_parse_load_data_ndjson() {
9332 let mut parser =
9333 Parser::new("LOAD DATA FROM 'data.ndjson' FORMAT NDJSON AS row RETURN row");
9334 let result = parser.parse();
9335 assert!(
9336 result.is_ok(),
9337 "LOAD DATA NDJSON alias parse failed: {result:?}"
9338 );
9339 if let Statement::Query(query) = result.unwrap()
9340 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9341 {
9342 assert_eq!(ld.format, LoadFormat::Jsonl);
9343 }
9344 }
9345
9346 #[test]
9347 fn test_parse_load_data_parquet() {
9348 let mut parser =
9349 Parser::new("LOAD DATA FROM 'data.parquet' FORMAT PARQUET AS row RETURN row.id");
9350 let result = parser.parse();
9351 assert!(result.is_ok(), "LOAD DATA PARQUET parse failed: {result:?}");
9352 if let Statement::Query(query) = result.unwrap()
9353 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9354 {
9355 assert_eq!(ld.format, LoadFormat::Parquet);
9356 }
9357 }
9358
9359 #[test]
9360 fn test_parse_load_csv_compat() {
9361 let mut parser =
9363 Parser::new("LOAD CSV WITH HEADERS FROM 'file.csv' AS row RETURN row.name");
9364 let result = parser.parse();
9365 assert!(result.is_ok(), "LOAD CSV compat parse failed: {result:?}");
9366 if let Statement::Query(query) = result.unwrap()
9367 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9368 {
9369 assert_eq!(ld.format, LoadFormat::Csv);
9370 assert!(ld.with_headers);
9371 assert_eq!(ld.path, "file.csv");
9372 }
9373 }
9374
9375 #[test]
9376 fn test_parse_load_data_with_fieldterminator() {
9377 let mut parser = Parser::new(
9378 "LOAD DATA FROM 'data.tsv' FORMAT CSV WITH HEADERS AS row FIELDTERMINATOR '\\t' RETURN row",
9379 );
9380 let result = parser.parse();
9381 assert!(
9382 result.is_ok(),
9383 "LOAD DATA with FIELDTERMINATOR parse failed: {result:?}"
9384 );
9385 if let Statement::Query(query) = result.unwrap()
9386 && let QueryClause::LoadData(ref ld) = query.ordered_clauses[0]
9387 {
9388 assert_eq!(ld.field_terminator, Some('\t'));
9389 }
9390 }
9391
9392 #[test]
9393 fn test_parse_load_data_with_insert() {
9394 let mut parser = Parser::new(
9395 "LOAD DATA FROM 'people.csv' FORMAT CSV WITH HEADERS AS row INSERT (:Person {name: row.name})",
9396 );
9397 let result = parser.parse();
9398 assert!(
9399 result.is_ok(),
9400 "LOAD DATA + INSERT parse failed: {result:?}"
9401 );
9402 }
9403
9404 #[test]
9405 fn test_parse_load_data_bad_format() {
9406 let mut parser = Parser::new("LOAD DATA FROM 'data.xml' FORMAT XML AS row RETURN row");
9407 let result = parser.parse();
9408 assert!(result.is_err(), "Should fail with unknown format XML");
9409 }
9410
9411 #[test]
9414 fn test_parse_lowercase_keywords() {
9415 let upper = Parser::new("MATCH (n:Person) WHERE n.age > 30 RETURN n.name")
9417 .parse()
9418 .unwrap();
9419 let lower = Parser::new("match (n:Person) where n.age > 30 return n.name")
9420 .parse()
9421 .unwrap();
9422
9423 let (Statement::Query(q_upper), Statement::Query(q_lower)) = (&upper, &lower) else {
9425 panic!("Expected Query statements");
9426 };
9427 assert_eq!(q_upper.match_clauses.len(), q_lower.match_clauses.len());
9428 assert!(q_upper.where_clause.is_some());
9429 assert!(q_lower.where_clause.is_some());
9430 assert_eq!(
9431 q_upper.return_clause.items.len(),
9432 q_lower.return_clause.items.len()
9433 );
9434 }
9435
9436 #[test]
9437 fn test_parse_mixed_case_keywords() {
9438 let result = Parser::new("Match (n:Person) Return n").parse();
9439 assert!(
9440 result.is_ok(),
9441 "Mixed-case keywords should parse: {result:?}"
9442 );
9443 }
9444
9445 #[test]
9448 fn test_parse_date_literal() {
9449 let mut parser = Parser::new("RETURN DATE '2024-01-15'");
9450 let result = parser.parse().unwrap();
9451 if let Statement::Query(query) = result {
9452 if let Expression::Literal(Literal::Date(s)) = &query.return_clause.items[0].expression
9453 {
9454 assert_eq!(s, "2024-01-15");
9455 } else {
9456 panic!(
9457 "Expected Date literal, got: {:?}",
9458 query.return_clause.items[0].expression
9459 );
9460 }
9461 } else {
9462 panic!("Expected Query statement");
9463 }
9464 }
9465
9466 #[test]
9467 fn test_parse_time_literal() {
9468 let mut parser = Parser::new("RETURN TIME '10:30:00'");
9469 let result = parser.parse().unwrap();
9470 if let Statement::Query(query) = result {
9471 if let Expression::Literal(Literal::Time(s)) = &query.return_clause.items[0].expression
9472 {
9473 assert_eq!(s, "10:30:00");
9474 } else {
9475 panic!(
9476 "Expected Time literal, got: {:?}",
9477 query.return_clause.items[0].expression
9478 );
9479 }
9480 } else {
9481 panic!("Expected Query statement");
9482 }
9483 }
9484
9485 #[test]
9486 fn test_parse_duration_literal() {
9487 let mut parser = Parser::new("RETURN DURATION 'P1Y2M'");
9488 let result = parser.parse().unwrap();
9489 if let Statement::Query(query) = result {
9490 if let Expression::Literal(Literal::Duration(s)) =
9491 &query.return_clause.items[0].expression
9492 {
9493 assert_eq!(s, "P1Y2M");
9494 } else {
9495 panic!(
9496 "Expected Duration literal, got: {:?}",
9497 query.return_clause.items[0].expression
9498 );
9499 }
9500 } else {
9501 panic!("Expected Query statement");
9502 }
9503 }
9504
9505 #[test]
9506 fn test_parse_datetime_literal() {
9507 let mut parser = Parser::new("RETURN DATETIME '2024-01-15T14:30:00'");
9508 let result = parser.parse().unwrap();
9509 if let Statement::Query(query) = result {
9510 if let Expression::Literal(Literal::Datetime(s)) =
9511 &query.return_clause.items[0].expression
9512 {
9513 assert_eq!(s, "2024-01-15T14:30:00");
9514 } else {
9515 panic!(
9516 "Expected Datetime literal, got: {:?}",
9517 query.return_clause.items[0].expression
9518 );
9519 }
9520 } else {
9521 panic!("Expected Query statement");
9522 }
9523 }
9524
9525 #[test]
9526 fn test_parse_zoned_datetime_literal() {
9527 let mut parser = Parser::new("RETURN ZONED DATETIME '2024-01-15T14:30:00+05:30'");
9528 let result = parser.parse().unwrap();
9529 if let Statement::Query(query) = result {
9530 if let Expression::Literal(Literal::ZonedDatetime(s)) =
9531 &query.return_clause.items[0].expression
9532 {
9533 assert_eq!(s, "2024-01-15T14:30:00+05:30");
9534 } else {
9535 panic!(
9536 "Expected ZonedDatetime literal, got: {:?}",
9537 query.return_clause.items[0].expression
9538 );
9539 }
9540 } else {
9541 panic!("Expected Query statement");
9542 }
9543 }
9544
9545 #[test]
9546 fn test_parse_zoned_time_literal() {
9547 let mut parser = Parser::new("RETURN ZONED TIME '14:30:00+01:00'");
9548 let result = parser.parse().unwrap();
9549 if let Statement::Query(query) = result {
9550 if let Expression::Literal(Literal::ZonedTime(s)) =
9551 &query.return_clause.items[0].expression
9552 {
9553 assert_eq!(s, "14:30:00+01:00");
9554 } else {
9555 panic!(
9556 "Expected ZonedTime literal, got: {:?}",
9557 query.return_clause.items[0].expression
9558 );
9559 }
9560 } else {
9561 panic!("Expected Query statement");
9562 }
9563 }
9564}