gqlite 1.8.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +8 -8
  3. data/ext/db-index/Cargo.toml +2 -2
  4. data/ext/gqlitedb/Cargo.toml +0 -2
  5. data/ext/gqlitedb/src/aggregators.rs +28 -0
  6. data/ext/gqlitedb/src/compiler/expression_analyser.rs +33 -0
  7. data/ext/gqlitedb/src/compiler/variables_manager.rs +111 -11
  8. data/ext/gqlitedb/src/compiler.rs +506 -48
  9. data/ext/gqlitedb/src/connection.rs +14 -2
  10. data/ext/gqlitedb/src/consts.rs +1 -1
  11. data/ext/gqlitedb/src/error.rs +31 -0
  12. data/ext/gqlitedb/src/interpreter/evaluators.rs +153 -331
  13. data/ext/gqlitedb/src/interpreter/instructions.rs +77 -0
  14. data/ext/gqlitedb/src/interpreter/mod.rs +1 -0
  15. data/ext/gqlitedb/src/interpreter/path/bfs.rs +494 -0
  16. data/ext/gqlitedb/src/interpreter/path/dfs.rs +267 -0
  17. data/ext/gqlitedb/src/interpreter/path/group.rs +418 -0
  18. data/ext/gqlitedb/src/interpreter/path.rs +542 -0
  19. data/ext/gqlitedb/src/planner.rs +231 -6
  20. data/ext/gqlitedb/src/query_result.rs +19 -4
  21. data/ext/gqlitedb/src/store/redb.rs +1 -1
  22. data/ext/gqlitedb/src/tests/compiler.rs +2454 -1
  23. data/ext/gqlitedb/src/tests/connection/postgres.rs +22 -0
  24. data/ext/gqlitedb/src/tests/connection/redb.rs +24 -0
  25. data/ext/gqlitedb/src/tests/connection/sqlite.rs +16 -0
  26. data/ext/gqlitedb/src/tests/connection.rs +101 -0
  27. data/ext/gqlitedb/src/tests/evaluators.rs +2206 -1
  28. data/ext/gqlitedb/src/tests/parser.rs +1225 -0
  29. data/ext/gqlitedb/src/tests/planner.rs +433 -2
  30. data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +5 -5
  31. data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +3 -1
  32. data/ext/gqlitedb/src/tests/templates/ast.rs +294 -1
  33. data/ext/gqlitedb/src/tests/templates/programs.rs +318 -0
  34. data/ext/gqliterb/Cargo.toml +0 -1
  35. data/ext/gqlparser/src/oc/ast.rs +72 -3
  36. data/ext/gqlparser/src/oc/error.rs +18 -0
  37. data/ext/gqlparser/src/oc/lexer.rs +157 -2
  38. data/ext/gqlparser/src/oc/parser/tests.rs +735 -29
  39. data/ext/gqlparser/src/oc/parser.rs +1312 -182
  40. data/ext/gqlparser/src/oc/string.rs +172 -0
  41. data/ext/gqlparser/src/oc.rs +1 -0
  42. data/ext/graphcore/src/value/value_map.rs +2 -2
  43. data/ext/graphcore/src/value.rs +13 -1
  44. metadata +6 -2
  45. data/ext/gqlitedb/src/parser/gql.pest +0 -198
@@ -73,6 +73,7 @@ pub(crate) fn create_named_node() -> Program
73
73
  limit: None,
74
74
  skip: None,
75
75
  order_by: vec![],
76
+ distinct: false,
76
77
  },
77
78
  variables_sizes: create_variable_size(2, 0),
78
79
  },
@@ -138,6 +139,7 @@ pub(crate) fn create_named_node_double_return() -> Program
138
139
  limit: None,
139
140
  skip: None,
140
141
  order_by: vec![],
142
+ distinct: false,
141
143
  },
142
144
  variables_sizes: create_variable_size(3, 0),
143
145
  },
@@ -166,6 +168,7 @@ pub(crate) fn double_with_return() -> Program
166
168
  limit: None,
167
169
  skip: None,
168
170
  order_by: vec![],
171
+ distinct: false,
169
172
  },
170
173
  variables_sizes: create_variable_size(2, 0),
171
174
  },
@@ -187,6 +190,7 @@ pub(crate) fn double_with_return() -> Program
187
190
  limit: None,
188
191
  skip: None,
189
192
  order_by: vec![],
193
+ distinct: false,
190
194
  },
191
195
  variables_sizes: create_variable_size(4, 0),
192
196
  },
@@ -204,6 +208,7 @@ pub(crate) fn double_with_return() -> Program
204
208
  limit: None,
205
209
  skip: None,
206
210
  order_by: vec![],
211
+ distinct: false,
207
212
  },
208
213
  variables_sizes: create_variable_size(2, 0),
209
214
  },
@@ -239,6 +244,7 @@ pub(crate) fn unwind() -> Program
239
244
  limit: None,
240
245
  skip: None,
241
246
  order_by: vec![],
247
+ distinct: false,
242
248
  },
243
249
  variables_sizes: create_variable_size(1, 0),
244
250
  },
@@ -294,6 +300,7 @@ pub(crate) fn match_loop() -> Program
294
300
  limit: None,
295
301
  skip: None,
296
302
  order_by: vec![],
303
+ distinct: false,
297
304
  },
298
305
  variables_sizes: create_variable_size(1, 0),
299
306
  },
@@ -333,6 +340,7 @@ pub(crate) fn optional_match() -> Program
333
340
  limit: None,
334
341
  skip: None,
335
342
  order_by: vec![],
343
+ distinct: false,
336
344
  },
337
345
  variables_sizes: create_variable_size(1, 0),
338
346
  },
@@ -375,6 +383,7 @@ pub(crate) fn match_count(function_manager: &functions::Manager) -> Program
375
383
  aggregator: function_manager
376
384
  .get_aggregator::<error::CompileTimeError>("count")
377
385
  .unwrap(),
386
+ distinct: false,
378
387
  },
379
388
  )],
380
389
  },
@@ -384,6 +393,7 @@ pub(crate) fn match_count(function_manager: &functions::Manager) -> Program
384
393
  limit: None,
385
394
  skip: None,
386
395
  order_by: vec![],
396
+ distinct: false,
387
397
  },
388
398
  variables_sizes: create_variable_size(2, 1),
389
399
  },
@@ -445,6 +455,7 @@ pub(crate) fn aggregation(function_manager: &functions::Manager) -> Program
445
455
  aggregator: function_manager
446
456
  .get_aggregator::<error::CompileTimeError>("count")
447
457
  .unwrap(),
458
+ distinct: false,
448
459
  },
449
460
  )],
450
461
  },
@@ -455,8 +466,315 @@ pub(crate) fn aggregation(function_manager: &functions::Manager) -> Program
455
466
  limit: None,
456
467
  skip: None,
457
468
  order_by: vec![],
469
+ distinct: false,
458
470
  },
459
471
  variables_sizes: create_variable_size(3, 1),
460
472
  },
461
473
  ]
462
474
  }
475
+
476
+ /// Program for `MATCH (a) ((n)-[:R]->(m)){1,3} (b) RETURN a, b`.
477
+ /// Uses MatchQuantifiedPath since the group's inner nodes (n, m) differ
478
+ /// from the outer anchors (a, b) - this is an explicit group pattern.
479
+ pub(crate) fn group_single_edge_range() -> Program
480
+ {
481
+ vec![
482
+ Block::Match {
483
+ blocks: vec![BlockMatch::MatchQuantifiedPath {
484
+ source_instructions: vec![
485
+ Instruction::Push {
486
+ value: ValueMap::default().into(),
487
+ },
488
+ Instruction::CreateNodeQuery { labels: vec![] },
489
+ ],
490
+ source_variable: Some(0),
491
+ source_filter: vec![],
492
+ destination_variable: Some(1),
493
+ destination_filter: vec![],
494
+ path_variable: None,
495
+ quantifier: 1..3,
496
+ group_instructions: vec![BlockMatch::MatchEdge {
497
+ instructions: vec![
498
+ Instruction::GetVariable { col_id: 2 },
499
+ Instruction::CreateNodeQuery { labels: vec![] },
500
+ Instruction::Push {
501
+ value: ValueMap::default().into(),
502
+ },
503
+ Instruction::CreateNodeQuery { labels: vec![] },
504
+ Instruction::Push {
505
+ value: ValueMap::default().into(),
506
+ },
507
+ Instruction::CreateEdgeQuery {
508
+ labels: vec!["R".into()],
509
+ },
510
+ ],
511
+ left_variable: None,
512
+ edge_variable: Some(4),
513
+ right_variable: Some(3),
514
+ path_variable: None,
515
+ filter: vec![],
516
+ directivity: EdgeDirectivity::Directed,
517
+ recursive_range: None,
518
+ }],
519
+ group_variables: vec![2, 4, 3],
520
+ group_terminal_variable: 3,
521
+ group_entry_variable: 2,
522
+ group_where_filter: None,
523
+ path_filter: None,
524
+ strategy: PathStrategy::Dfs,
525
+ }],
526
+ filter: vec![],
527
+ optional: false,
528
+ variables_size: create_variable_size(5, 0),
529
+ },
530
+ Block::Return {
531
+ variables: vec![
532
+ (
533
+ "a".into(),
534
+ RWExpression {
535
+ col_id: 0,
536
+ instructions: vec![Instruction::GetVariable { col_id: 0 }],
537
+ aggregations: Default::default(),
538
+ },
539
+ ),
540
+ (
541
+ "b".into(),
542
+ RWExpression {
543
+ col_id: 1,
544
+ instructions: vec![Instruction::GetVariable { col_id: 1 }],
545
+ aggregations: Default::default(),
546
+ },
547
+ ),
548
+ ],
549
+ filter: vec![],
550
+ modifiers: Modifiers {
551
+ limit: None,
552
+ skip: None,
553
+ order_by: vec![],
554
+ distinct: false,
555
+ },
556
+ variables_sizes: create_variable_size(5, 0),
557
+ },
558
+ ]
559
+ }
560
+
561
+ /// Program for `MATCH (a) ((n)-[:R1]->(x)-[:R2]->(m)){1,3} (b) RETURN a, b`.
562
+ /// Two-edge group: compiler allocates edge columns (5, 6) for deduplication,
563
+ /// and adds filter logic to second edge to prevent revisiting the same edge.
564
+ pub(crate) fn group_two_edges_range() -> Program
565
+ {
566
+ vec![
567
+ Block::Match {
568
+ blocks: vec![BlockMatch::MatchQuantifiedPath {
569
+ source_instructions: vec![
570
+ Instruction::Push {
571
+ value: ValueMap::default().into(),
572
+ },
573
+ Instruction::CreateNodeQuery { labels: vec![] },
574
+ ],
575
+ source_variable: Some(0),
576
+ source_filter: vec![],
577
+ destination_variable: Some(1),
578
+ destination_filter: vec![],
579
+ path_variable: None,
580
+ quantifier: 1..3,
581
+ group_instructions: vec![
582
+ BlockMatch::MatchEdge {
583
+ instructions: vec![
584
+ Instruction::GetVariable { col_id: 2 },
585
+ Instruction::CreateNodeQuery { labels: vec![] },
586
+ Instruction::Push {
587
+ value: ValueMap::default().into(),
588
+ },
589
+ Instruction::CreateNodeQuery { labels: vec![] },
590
+ Instruction::Push {
591
+ value: ValueMap::default().into(),
592
+ },
593
+ Instruction::CreateEdgeQuery {
594
+ labels: vec!["R1".into()],
595
+ },
596
+ ],
597
+ left_variable: None,
598
+ edge_variable: Some(4),
599
+ right_variable: Some(3),
600
+ path_variable: None,
601
+ filter: vec![],
602
+ directivity: EdgeDirectivity::Directed,
603
+ recursive_range: None,
604
+ },
605
+ BlockMatch::MatchEdge {
606
+ instructions: vec![
607
+ Instruction::GetVariable { col_id: 3 },
608
+ Instruction::CreateNodeQuery { labels: vec![] },
609
+ Instruction::Push {
610
+ value: ValueMap::default().into(),
611
+ },
612
+ Instruction::CreateNodeQuery { labels: vec![] },
613
+ Instruction::Push {
614
+ value: ValueMap::default().into(),
615
+ },
616
+ Instruction::CreateEdgeQuery {
617
+ labels: vec!["R2".into()],
618
+ },
619
+ ],
620
+ left_variable: None,
621
+ edge_variable: Some(6),
622
+ right_variable: Some(5),
623
+ path_variable: None,
624
+ filter: vec![
625
+ Instruction::Duplicate,
626
+ Instruction::GetVariable { col_id: 4 },
627
+ Instruction::NotEqualBinaryOperator,
628
+ Instruction::InverseRot3,
629
+ Instruction::AndBinaryOperator,
630
+ Instruction::Swap,
631
+ ],
632
+ directivity: EdgeDirectivity::Directed,
633
+ recursive_range: None,
634
+ },
635
+ ],
636
+ group_variables: vec![2, 4, 3, 3, 6, 5],
637
+ group_terminal_variable: 5,
638
+ group_entry_variable: 2,
639
+ group_where_filter: None,
640
+ path_filter: None,
641
+ strategy: PathStrategy::Dfs,
642
+ }],
643
+ filter: vec![],
644
+ optional: false,
645
+ variables_size: create_variable_size(7, 0),
646
+ },
647
+ Block::Return {
648
+ variables: vec![
649
+ (
650
+ "a".into(),
651
+ RWExpression {
652
+ col_id: 0,
653
+ instructions: vec![Instruction::GetVariable { col_id: 0 }],
654
+ aggregations: Default::default(),
655
+ },
656
+ ),
657
+ (
658
+ "b".into(),
659
+ RWExpression {
660
+ col_id: 1,
661
+ instructions: vec![Instruction::GetVariable { col_id: 1 }],
662
+ aggregations: Default::default(),
663
+ },
664
+ ),
665
+ ],
666
+ filter: vec![],
667
+ modifiers: Modifiers {
668
+ limit: None,
669
+ skip: None,
670
+ order_by: vec![],
671
+ distinct: false,
672
+ },
673
+ variables_sizes: create_variable_size(7, 0),
674
+ },
675
+ ]
676
+ }
677
+
678
+ /// Program for `MATCH p = SHORTEST 1 (a)-[:R]-+(b) RETURN a, b, length(p)`
679
+ /// Shortest path uses BFS with stop condition. **KEY FINDING**: group_variables
680
+ /// DOES include source/destination columns [1, 2] - this was the open question
681
+ /// in WI721.
682
+ pub(crate) fn shortest_single_edge_full_return(function_manager: &functions::Manager) -> Program
683
+ {
684
+ vec![
685
+ Block::Match {
686
+ blocks: vec![BlockMatch::MatchQuantifiedPath {
687
+ source_instructions: vec![
688
+ Instruction::Push {
689
+ value: ValueMap::default().into(),
690
+ },
691
+ Instruction::CreateNodeQuery { labels: vec![] },
692
+ ],
693
+ source_variable: Some(1),
694
+ source_filter: vec![],
695
+ destination_variable: Some(2),
696
+ destination_filter: vec![],
697
+ path_variable: Some(0),
698
+ quantifier: 1..usize::MAX,
699
+ group_instructions: vec![BlockMatch::MatchEdge {
700
+ instructions: vec![
701
+ Instruction::GetVariable { col_id: 1 },
702
+ Instruction::CreateNodeQuery { labels: vec![] },
703
+ Instruction::Push {
704
+ value: ValueMap::default().into(),
705
+ },
706
+ Instruction::CreateNodeQuery { labels: vec![] },
707
+ Instruction::Push {
708
+ value: ValueMap::default().into(),
709
+ },
710
+ Instruction::CreateEdgeQuery {
711
+ labels: vec!["R".into()],
712
+ },
713
+ ],
714
+ left_variable: None,
715
+ edge_variable: Some(3),
716
+ right_variable: Some(2),
717
+ path_variable: None,
718
+ filter: vec![],
719
+ directivity: EdgeDirectivity::Undirected,
720
+ recursive_range: None,
721
+ }],
722
+ group_variables: vec![1, 3, 2],
723
+ group_terminal_variable: 2,
724
+ group_entry_variable: 1,
725
+ group_where_filter: None,
726
+ path_filter: None,
727
+ strategy: PathStrategy::Bfs {
728
+ stop_condition: StopCondition::Shortest(vec![Instruction::Push { value: 1.into() }]),
729
+ },
730
+ }],
731
+ filter: vec![],
732
+ optional: false,
733
+ variables_size: create_variable_size(4, 0),
734
+ },
735
+ Block::Return {
736
+ variables: vec![
737
+ (
738
+ "a".into(),
739
+ RWExpression {
740
+ col_id: 1,
741
+ instructions: vec![Instruction::GetVariable { col_id: 1 }],
742
+ aggregations: Default::default(),
743
+ },
744
+ ),
745
+ (
746
+ "b".into(),
747
+ RWExpression {
748
+ col_id: 2,
749
+ instructions: vec![Instruction::GetVariable { col_id: 2 }],
750
+ aggregations: Default::default(),
751
+ },
752
+ ),
753
+ (
754
+ "length(p)".into(),
755
+ RWExpression {
756
+ col_id: 4,
757
+ instructions: vec![
758
+ Instruction::GetVariable { col_id: 0 },
759
+ Instruction::FunctionCall {
760
+ function: function_manager
761
+ .get_function::<error::CompileTimeError>("length")
762
+ .unwrap(),
763
+ arguments_count: 1,
764
+ },
765
+ ],
766
+ aggregations: Default::default(),
767
+ },
768
+ ),
769
+ ],
770
+ filter: vec![],
771
+ modifiers: Modifiers {
772
+ limit: None,
773
+ skip: None,
774
+ order_by: vec![],
775
+ distinct: false,
776
+ },
777
+ variables_sizes: create_variable_size(5, 0),
778
+ },
779
+ ]
780
+ }
@@ -11,7 +11,6 @@ repository.workspace = true
11
11
  crate-type = ["cdylib"]
12
12
 
13
13
  [features]
14
- _cmake = []
15
14
 
16
15
  [dependencies]
17
16
  gqlitedb = { workspace = true, features = ["postgres", "redb", "sqlite"] }
@@ -378,11 +378,22 @@ pub struct OrderBy
378
378
  #[derive(Default, Debug)]
379
379
  pub struct Modifiers
380
380
  {
381
+ pub distinct: bool,
381
382
  pub skip: Option<Expression>,
382
383
  pub limit: Option<Expression>,
383
384
  pub order_by: Option<OrderBy>,
384
385
  }
385
386
 
387
+ impl Modifiers
388
+ {
389
+ /// Set the distinct field
390
+ pub(crate) fn set_distinct(mut self, distinct: bool) -> Self
391
+ {
392
+ self.distinct = distinct;
393
+ self
394
+ }
395
+ }
396
+
386
397
  // Expressions
387
398
 
388
399
  #[derive(Debug, Clone, PartialEq)]
@@ -411,6 +422,10 @@ pub enum Expression
411
422
  RelationalIn(Box<RelationalIn>),
412
423
  RelationalNotIn(Box<RelationalNotIn>),
413
424
 
425
+ Contains(Box<Contains>),
426
+ EndsWith(Box<EndsWith>),
427
+ StartsWith(Box<StartsWith>),
428
+
414
429
  Addition(Box<Addition>),
415
430
  Subtraction(Box<Subtraction>),
416
431
  Multiplication(Box<Multiplication>),
@@ -435,12 +450,13 @@ pub struct OrderByExpression
435
450
 
436
451
  // Values: CreatePatterns
437
452
 
438
- #[derive(Debug)]
453
+ #[derive(Debug, Clone)]
439
454
  pub enum Pattern
440
455
  {
441
456
  Node(NodePattern),
442
457
  Edge(EdgePattern),
443
458
  Path(PathPattern),
459
+ QuantifiedPath(QuantifiedPathPattern),
444
460
  }
445
461
 
446
462
  macro_rules! create_from_pattern {
@@ -455,6 +471,7 @@ pub struct NodePattern
455
471
  pub variable: Option<VariableIdentifier>,
456
472
  pub labels: LabelExpression,
457
473
  pub properties: Option<Expression>,
474
+ pub predicate: Option<Expression>,
458
475
  }
459
476
 
460
477
  create_from_pattern! {NodePattern, Node}
@@ -468,8 +485,7 @@ pub struct EdgePattern
468
485
  pub directivity: graphcore::EdgeDirectivity,
469
486
  pub labels: LabelExpression,
470
487
  pub properties: Option<Expression>,
471
- /// Indicates the range for a recursive match.
472
- pub recursive_range: Option<std::ops::Range<usize>>,
488
+ pub predicate: Option<Expression>,
473
489
  }
474
490
 
475
491
  create_from_pattern! {EdgePattern, Edge}
@@ -483,6 +499,54 @@ pub struct PathPattern
483
499
 
484
500
  create_from_pattern! {PathPattern, Path}
485
501
 
502
+ #[derive(Debug, Clone)]
503
+ pub struct QuantifiedPathPattern
504
+ {
505
+ /// Path variable, if bound via `p = ...`. `None` for a bare quantified
506
+ /// relationship/group with no path variable.
507
+ pub variable: Option<VariableIdentifier>,
508
+ /// The fixed source node anchor outside the repeated group. For
509
+ /// `(a) ((n)-[r]->(m)){1,5} (b)`, this is `a` (the left outer anchor).
510
+ pub source: NodePattern,
511
+ /// The repeated unit. For the single-edge case (legacy `[*min..max]` or
512
+ /// new `{min,max}`/`*`/`+` syntax — the only case Milestone 2 produces),
513
+ /// this is always exactly one `Pattern::Edge`. Multi-element groups
514
+ /// (Milestone 3) populate more than one element here.
515
+ pub group: Vec<Pattern>,
516
+ /// Optional inline `WHERE` scoped to the group (Milestone 3). Always
517
+ /// `None` for anything Milestone 2 produces. Applied per repetition during
518
+ /// group expansion (genuine groups only, never present on wrapper-promoted patterns).
519
+ pub group_where: Option<Expression>,
520
+ /// Optional `WHERE` for the whole assembled path, from a selector-scoped wrapper.
521
+ /// Evaluated once when a candidate reaches `destination`, distinct from
522
+ /// `group_where`'s per-repetition timing. Only populated by wrapper resolution
523
+ /// in `planner::plan_pattern`; genuine groups never have `path_where`.
524
+ pub path_where: Option<Expression>,
525
+ /// `Some(min..max)` for a repeatable group (everything Milestone 2
526
+ /// produces). `None` is reserved for the pre-filter scoping-wrapper use
527
+ /// (Milestone 5, design §1d) — not constructible yet.
528
+ pub quantifier: Option<std::ops::Range<usize>>,
529
+ /// The fixed destination node anchor outside the repeated group. For
530
+ /// `(a) ((n)-[r]->(m)){1,5} (b)`, this is `b` (the right outer anchor).
531
+ pub destination: NodePattern,
532
+ /// Path selector (`SHORTEST`/`ALL SHORTEST`/etc., design's `PathSelector`
533
+ /// below). Always `PathSelector::All` for anything Milestone 2 produces
534
+ /// — no grammar exists yet to populate the other variants.
535
+ pub selector: PathSelector,
536
+ }
537
+
538
+ create_from_pattern! {QuantifiedPathPattern, QuantifiedPath}
539
+
540
+ #[derive(Debug, Clone)]
541
+ pub enum PathSelector
542
+ {
543
+ All,
544
+ Any,
545
+ AllShortest,
546
+ Shortest(Expression),
547
+ ShortestGroups(Expression),
548
+ }
549
+
486
550
  // Label Expression
487
551
  #[derive(Debug, Clone, PartialEq)]
488
552
  pub enum LabelExpression
@@ -601,6 +665,7 @@ pub struct FunctionCall
601
665
  {
602
666
  pub name: String,
603
667
  pub arguments: Vec<Expression>,
668
+ pub distinct: bool,
604
669
  }
605
670
 
606
671
  create_from_expr! {FunctionCall}
@@ -630,6 +695,10 @@ create_binary_op! {RelationalSuperiorEqual}
630
695
  create_binary_op! {RelationalIn}
631
696
  create_binary_op! {RelationalNotIn}
632
697
 
698
+ create_binary_op! {Contains}
699
+ create_binary_op! {EndsWith}
700
+ create_binary_op! {StartsWith}
701
+
633
702
  create_binary_op! {Addition}
634
703
  create_binary_op! {Subtraction}
635
704
  create_binary_op! {Multiplication}
@@ -27,6 +27,9 @@ pub enum ErrorKind
27
27
  NoSingleRelationshipType,
28
28
  MixedUnionOperators,
29
29
  VariableNotFound,
30
+ CreatingWithPredicate,
31
+ ConflictingQuantifiers,
32
+ EmptyQuantifiedGroup,
30
33
  }
31
34
 
32
35
  pub(crate) fn parse_int_error_to_error_kind(e: std::num::ParseIntError) -> ErrorKind
@@ -157,6 +160,21 @@ impl std::fmt::Display for Error
157
160
  "NoSingleRelationshipType: edge patterns must have exactly one relationship type at {}..{}.",
158
161
  self.span.start, self.span.end
159
162
  ),
163
+ ErrorKind::CreatingWithPredicate => write!(
164
+ f,
165
+ "CreatingWithPredicate: CREATE patterns cannot use an inline WHERE predicate at {}..{}.",
166
+ self.span.start, self.span.end
167
+ ),
168
+ ErrorKind::ConflictingQuantifiers => write!(
169
+ f,
170
+ "ConflictingQuantifiers: cannot specify both a legacy `[*min..max]` range and a `{{min,max}}`/`*`/`+` quantifier on the same relationship at {}..{}.",
171
+ self.span.start, self.span.end
172
+ ),
173
+ ErrorKind::EmptyQuantifiedGroup => write!(
174
+ f,
175
+ "EmptyQuantifiedGroup: a quantified group must contain at least one relationship at {}..{}.",
176
+ self.span.start, self.span.end
177
+ ),
160
178
  ErrorKind::MixedUnionOperators => write!(
161
179
  f,
162
180
  "MixedUnionOperators: cannot mix UNION and UNION ALL in the same query at {}..{}.",