gqlite 1.5.1 → 1.7.0

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +10 -4
  3. data/ext/db-index/Cargo.toml +29 -0
  4. data/ext/db-index/src/hnsw/error.rs +66 -0
  5. data/ext/db-index/src/hnsw/graph_store.rs +272 -0
  6. data/ext/db-index/src/hnsw/id.rs +36 -0
  7. data/ext/db-index/src/hnsw/implementation.rs +1517 -0
  8. data/ext/db-index/src/hnsw/kernels.rs +1228 -0
  9. data/ext/db-index/src/hnsw/metric.rs +244 -0
  10. data/ext/db-index/src/hnsw/scalar.rs +72 -0
  11. data/ext/db-index/src/hnsw/simple_store.rs +140 -0
  12. data/ext/db-index/src/hnsw/store.rs +472 -0
  13. data/ext/db-index/src/hnsw/vector.rs +105 -0
  14. data/ext/db-index/src/hnsw/vectors.rs +568 -0
  15. data/ext/db-index/src/hnsw.rs +42 -0
  16. data/ext/db-index/src/lib.rs +3 -0
  17. data/ext/gqlitedb/Cargo.toml +19 -9
  18. data/ext/gqlitedb/benches/common/pokec.rs +62 -2
  19. data/ext/gqlitedb/benches/pokec_divan.rs +66 -2
  20. data/ext/gqlitedb/benches/pokec_iai.rs +60 -3
  21. data/ext/gqlitedb/release.toml +2 -2
  22. data/ext/gqlitedb/src/aggregators/arithmetic.rs +3 -1
  23. data/ext/gqlitedb/src/aggregators/containers.rs +1 -1
  24. data/ext/gqlitedb/src/aggregators/stats.rs +21 -12
  25. data/ext/gqlitedb/src/capi.rs +1 -1
  26. data/ext/gqlitedb/src/compiler/expression_analyser.rs +28 -20
  27. data/ext/gqlitedb/src/compiler/variables_manager.rs +97 -29
  28. data/ext/gqlitedb/src/compiler.rs +505 -225
  29. data/ext/gqlitedb/src/connection.rs +149 -11
  30. data/ext/gqlitedb/src/consts.rs +1 -2
  31. data/ext/gqlitedb/src/error.rs +123 -61
  32. data/ext/gqlitedb/src/functions/common.rs +39 -2
  33. data/ext/gqlitedb/src/functions/math.rs +8 -3
  34. data/ext/gqlitedb/src/functions/path.rs +48 -11
  35. data/ext/gqlitedb/src/functions/value.rs +1 -1
  36. data/ext/gqlitedb/src/functions.rs +23 -7
  37. data/ext/gqlitedb/src/graph.rs +1 -9
  38. data/ext/gqlitedb/src/interpreter/evaluators.rs +968 -130
  39. data/ext/gqlitedb/src/interpreter/instructions.rs +39 -2
  40. data/ext/gqlitedb/src/lib.rs +5 -4
  41. data/ext/gqlitedb/src/planner.rs +329 -0
  42. data/ext/gqlitedb/src/prelude.rs +3 -3
  43. data/ext/gqlitedb/src/store/pgrx.rs +1 -1
  44. data/ext/gqlitedb/src/store/postgres.rs +735 -7
  45. data/ext/gqlitedb/src/store/redb/hnsw_store.rs +702 -0
  46. data/ext/gqlitedb/src/store/redb/index.rs +274 -0
  47. data/ext/gqlitedb/src/store/redb.rs +1268 -113
  48. data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +28 -0
  49. data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +103 -0
  50. data/ext/gqlitedb/src/store/sqlbase.rs +146 -16
  51. data/ext/gqlitedb/src/store/sqlite.rs +569 -5
  52. data/ext/gqlitedb/src/store/vector_extract.rs +56 -0
  53. data/ext/gqlitedb/src/store.rs +123 -3
  54. data/ext/gqlitedb/src/tests/compiler.rs +207 -10
  55. data/ext/gqlitedb/src/tests/connection/postgres.rs +38 -3
  56. data/ext/gqlitedb/src/tests/connection/redb.rs +23 -0
  57. data/ext/gqlitedb/src/tests/connection/sqlite.rs +31 -0
  58. data/ext/gqlitedb/src/tests/connection.rs +61 -1
  59. data/ext/gqlitedb/src/tests/evaluators.rs +162 -7
  60. data/ext/gqlitedb/src/tests/parser.rs +54 -23
  61. data/ext/gqlitedb/src/tests/planner.rs +511 -0
  62. data/ext/gqlitedb/src/tests/store/postgres.rs +7 -0
  63. data/ext/gqlitedb/src/tests/store/redb.rs +8 -0
  64. data/ext/gqlitedb/src/tests/store/sqlite.rs +8 -0
  65. data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +182 -0
  66. data/ext/gqlitedb/src/tests/store/vector_index/redb.rs +386 -0
  67. data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +166 -0
  68. data/ext/gqlitedb/src/tests/store/vector_index.rs +2313 -0
  69. data/ext/gqlitedb/src/tests/store.rs +78 -14
  70. data/ext/gqlitedb/src/tests/templates/ast.rs +92 -16
  71. data/ext/gqlitedb/src/tests/templates/programs.rs +14 -7
  72. data/ext/gqlitedb/src/tests.rs +15 -9
  73. data/ext/gqlitedb/src/utils.rs +6 -1
  74. data/ext/gqlitedb/src/value/compare.rs +61 -3
  75. data/ext/gqlitedb/src/value.rs +136 -7
  76. data/ext/gqlitedb/templates/sql/postgres/metadata_delete.sql +1 -0
  77. data/ext/gqlitedb/templates/sql/postgres/node_select.sql +1 -1
  78. data/ext/gqlitedb/templates/sql/sqlite/metadata_delete.sql +1 -0
  79. data/ext/gqliterb/src/lib.rs +53 -8
  80. data/ext/gqlparser/Cargo.toml +25 -0
  81. data/ext/gqlparser/README.MD +9 -0
  82. data/ext/gqlparser/benches/pokec_divan.rs +34 -0
  83. data/ext/gqlparser/src/common.rs +69 -0
  84. data/ext/gqlparser/src/gqls/ast.rs +69 -0
  85. data/ext/gqlparser/src/gqls/constraint.rs +79 -0
  86. data/ext/gqlparser/src/gqls/error.rs +22 -0
  87. data/ext/gqlparser/src/gqls/parser.rs +813 -0
  88. data/ext/gqlparser/src/gqls/prelude.rs +8 -0
  89. data/ext/gqlparser/src/gqls/properties.rs +115 -0
  90. data/ext/gqlparser/src/gqls/resolve.rs +207 -0
  91. data/ext/gqlparser/src/gqls.rs +265 -0
  92. data/ext/gqlparser/src/lib.rs +7 -0
  93. data/ext/gqlparser/src/oc/ast.rs +680 -0
  94. data/ext/gqlparser/src/oc/error.rs +172 -0
  95. data/ext/gqlparser/src/oc/lexer.rs +429 -0
  96. data/ext/gqlparser/src/oc/parser/tests.rs +2284 -0
  97. data/ext/gqlparser/src/oc/parser.rs +2005 -0
  98. data/ext/gqlparser/src/oc.rs +33 -0
  99. data/ext/gqlparser/src/prelude.rs +3 -0
  100. data/ext/graphcore/Cargo.toml +1 -0
  101. data/ext/graphcore/src/error.rs +26 -0
  102. data/ext/graphcore/src/graph.rs +177 -51
  103. data/ext/graphcore/src/lib.rs +4 -2
  104. data/ext/graphcore/src/open_cypher.rs +12 -0
  105. data/ext/graphcore/src/table.rs +50 -2
  106. data/ext/graphcore/src/timestamp.rs +127 -104
  107. data/ext/graphcore/src/value/tensor.rs +739 -0
  108. data/ext/graphcore/src/value/value_map.rs +1 -1
  109. data/ext/graphcore/src/value.rs +343 -19
  110. metadata +90 -22
  111. data/ext/gqlitedb/src/parser/ast.rs +0 -604
  112. data/ext/gqlitedb/src/parser/parser_impl.rs +0 -1213
  113. data/ext/gqlitedb/src/parser.rs +0 -4
@@ -1,8 +1,9 @@
1
- pub(crate) mod expression_analyser;
2
- pub(crate) mod variables_manager;
1
+ use gqlparser::oc::ast;
3
2
 
4
3
  use crate::{
5
- compiler::variables_manager::VariablesManager, interpreter::instructions::VariablesSizes,
4
+ compiler::{expression_analyser::ExpressionType, variables_manager::VariablesManager},
5
+ interpreter::instructions::{CreateActionVariable, VariablesSizes},
6
+ planner::{LogicalPlan, LogicalPlans, ProjectionKind},
6
7
  prelude::*,
7
8
  };
8
9
 
@@ -10,7 +11,9 @@ use interpreter::instructions::{
10
11
  self, Block, BlockMatch, CreateAction, Instruction, Instructions, Modifiers, RWAggregation,
11
12
  RWExpression,
12
13
  };
13
- use parser::ast;
14
+
15
+ pub(crate) mod expression_analyser;
16
+ pub(crate) mod variables_manager;
14
17
 
15
18
  macro_rules! compile_binary_op {
16
19
  ( $this:tt, $x:tt, $instructions:tt, $aggregations:tt ) => {
@@ -27,6 +30,25 @@ struct CompiledReturnWith
27
30
  variables_sizes: VariablesSizes,
28
31
  }
29
32
 
33
+ struct PlannedProjection
34
+ {
35
+ kind: ProjectionKind,
36
+ all: bool,
37
+ expressions: Vec<ast::NamedExpression>,
38
+ where_expression: Option<ast::Expression>,
39
+ modifiers: ast::Modifiers,
40
+ }
41
+
42
+ fn is_scan_plan(plan: &LogicalPlan) -> bool
43
+ {
44
+ match plan
45
+ {
46
+ LogicalPlan::NodeScan { .. } => true,
47
+ LogicalPlan::Filter { source, .. } => is_scan_plan(source),
48
+ _ => false,
49
+ }
50
+ }
51
+
30
52
  struct Compiler
31
53
  {
32
54
  function_manager: functions::Manager,
@@ -54,7 +76,7 @@ impl Compiler
54
76
 
55
77
  fn compile_expression(
56
78
  &mut self,
57
- expression: &crate::parser::ast::Expression,
79
+ expression: &gqlparser::oc::ast::Expression,
58
80
  instructions: &mut Instructions,
59
81
  aggregations: &mut Option<&mut Vec<(value_table::ColId, RWAggregation)>>,
60
82
  ) -> Result<()>
@@ -321,16 +343,17 @@ impl Compiler
321
343
 
322
344
  fn compile_create_node(
323
345
  &mut self,
324
- node: &crate::parser::ast::NodePattern,
346
+ node: gqlparser::oc::ast::NodePattern,
325
347
  instructions: &mut Instructions,
326
- variables: &mut Vec<Option<value_table::ColId>>,
348
+ variables: &mut Vec<CreateActionVariable>,
327
349
  ) -> Result<()>
328
350
  {
329
- variables.push(
330
- self
351
+ variables.push(CreateActionVariable {
352
+ path: None,
353
+ element: self
331
354
  .variables_manager
332
355
  .get_variable_index_option(&node.variable)?,
333
- );
356
+ });
334
357
  self
335
358
  .variables_manager
336
359
  .mark_variables_as_set(&node.variable)?;
@@ -341,6 +364,84 @@ impl Compiler
341
364
  Ok(())
342
365
  }
343
366
 
367
+ fn compile_create_edge(
368
+ &mut self,
369
+ edge: gqlparser::oc::ast::EdgePattern,
370
+ instructions: &mut Instructions,
371
+ variables: &mut Vec<CreateActionVariable>,
372
+ path_variable: Option<ast::VariableIdentifier>,
373
+ ) -> Result<()>
374
+ {
375
+ let source_variable = edge.source.variable.clone();
376
+ let destination_variable = edge.destination.variable.clone();
377
+ // Generate source
378
+ if self
379
+ .variables_manager
380
+ .is_set_variable(&edge.source.variable)?
381
+ {
382
+ instructions.push(Instruction::GetVariable {
383
+ col_id: self
384
+ .variables_manager
385
+ .get_variable_index(edge.source.variable.as_ref().unwrap())?,
386
+ });
387
+ }
388
+ else
389
+ {
390
+ self.compile_create_node(edge.source, instructions, variables)?;
391
+ instructions.push(Instruction::Duplicate);
392
+ }
393
+ // Generate destination
394
+ if source_variable.is_some()
395
+ && destination_variable.is_some()
396
+ && source_variable == destination_variable
397
+ {
398
+ instructions.push(Instruction::Duplicate);
399
+ }
400
+ else if self
401
+ .variables_manager
402
+ .is_set_variable(&edge.destination.variable)?
403
+ {
404
+ instructions.push(Instruction::GetVariable {
405
+ col_id: self
406
+ .variables_manager
407
+ .get_variable_index(edge.destination.variable.as_ref().unwrap())?,
408
+ });
409
+ }
410
+ else
411
+ {
412
+ self.compile_create_node(edge.destination, instructions, variables)?;
413
+ instructions.push(Instruction::Duplicate);
414
+ instructions.push(Instruction::Rot3);
415
+ }
416
+ variables.push(CreateActionVariable {
417
+ element: self
418
+ .variables_manager
419
+ .get_variable_index_option(&edge.variable)?,
420
+ path: self
421
+ .variables_manager
422
+ .get_variable_index_option(&path_variable)?,
423
+ });
424
+ self
425
+ .variables_manager
426
+ .mark_variables_as_set(&edge.variable)?;
427
+ self.compile_optional_expression(&edge.properties, instructions)?;
428
+ // Reject variable-length relationships in CREATE statements
429
+ if edge.recursive_range.is_some()
430
+ {
431
+ return Err(CompileTimeError::CreatingVarLength.into());
432
+ }
433
+ if !edge.labels.is_string()
434
+ {
435
+ Err(CompileTimeError::NoSingleRelationshipType {
436
+ text: Default::default(),
437
+ span: Default::default(),
438
+ })?;
439
+ }
440
+ let mut labels = Default::default();
441
+ Self::compile_labels_expression(&mut labels, &edge.labels)?;
442
+ instructions.push(Instruction::CreateEdgeLiteral { labels });
443
+ Ok(())
444
+ }
344
445
  fn compile_labels_expression(
345
446
  labels: &mut Vec<String>,
346
447
  label_expressions: &ast::LabelExpression,
@@ -442,80 +543,35 @@ impl Compiler
442
543
  }
443
544
  }
444
545
 
445
- fn compile_create_patterns(&mut self, patterns: &[crate::parser::ast::Pattern]) -> Result<Block>
546
+ fn compile_create_patterns(
547
+ &mut self,
548
+ patterns: impl IntoIterator<Item = gqlparser::oc::ast::Pattern>,
549
+ ) -> Result<Block>
446
550
  {
447
- let actions = patterns.iter().map(|c| {
551
+ let actions = patterns.into_iter().map(|c| {
448
552
  let mut instructions = Instructions::new();
449
- let mut variables = Vec::<Option<value_table::ColId>>::new();
553
+ let mut variables = Vec::<CreateActionVariable>::new();
450
554
  match c
451
555
  {
452
- crate::parser::ast::Pattern::Node(node) =>
556
+ gqlparser::oc::ast::Pattern::Node(node) =>
453
557
  {
454
558
  self.compile_create_node(node, &mut instructions, &mut variables)?;
455
559
  }
456
- crate::parser::ast::Pattern::Edge(edge) =>
560
+ gqlparser::oc::ast::Pattern::Edge(edge) =>
457
561
  {
458
- // Generate source
459
- if self
460
- .variables_manager
461
- .is_set_variable(&edge.source.variable)?
462
- {
463
- instructions.push(Instruction::GetVariable {
464
- col_id: self
465
- .variables_manager
466
- .get_variable_index(edge.source.variable.as_ref().unwrap())?,
467
- });
468
- }
469
- else
470
- {
471
- self.compile_create_node(&edge.source, &mut instructions, &mut variables)?;
472
- instructions.push(Instruction::Duplicate);
473
- }
474
- // Generate destination
475
- if edge.source.variable.is_some()
476
- && edge.destination.variable.is_some()
477
- && edge.source.variable == edge.destination.variable
478
- {
479
- instructions.push(Instruction::Duplicate);
480
- }
481
- else if self
482
- .variables_manager
483
- .is_set_variable(&edge.destination.variable)?
484
- {
485
- instructions.push(Instruction::GetVariable {
486
- col_id: self
487
- .variables_manager
488
- .get_variable_index(edge.destination.variable.as_ref().unwrap())?,
489
- });
490
- }
491
- else
492
- {
493
- self.compile_create_node(&edge.destination, &mut instructions, &mut variables)?;
494
- instructions.push(Instruction::Duplicate);
495
- instructions.push(Instruction::Rot3);
496
- }
497
- variables.push(
498
- self
499
- .variables_manager
500
- .get_variable_index_option(&edge.variable)?,
501
- );
502
- self
503
- .variables_manager
504
- .mark_variables_as_set(&edge.variable)?;
505
- self.compile_optional_expression(&edge.properties, &mut instructions)?;
506
- if !edge.labels.is_string()
507
- {
508
- Err(CompileTimeError::NoSingleRelationshipType)?;
509
- }
510
- let mut labels = Default::default();
511
- Self::compile_labels_expression(&mut labels, &edge.labels)?;
512
- instructions.push(Instruction::CreateEdgeLiteral { labels });
562
+ self.compile_create_edge(edge, &mut instructions, &mut variables, None)?;
513
563
  }
514
- crate::parser::ast::Pattern::Path(_) =>
564
+ gqlparser::oc::ast::Pattern::Path(path) =>
515
565
  {
516
- Err(InternalError::PathPatternInCreateExpression {
517
- context: "compiler/compile_create_patterns",
518
- })?;
566
+ self
567
+ .variables_manager
568
+ .mark_variables_as_set(&path.variable)?;
569
+ self.compile_create_edge(
570
+ path.edge,
571
+ &mut instructions,
572
+ &mut variables,
573
+ Some(path.variable),
574
+ )?;
519
575
  }
520
576
  }
521
577
  Ok(CreateAction {
@@ -531,7 +587,7 @@ impl Compiler
531
587
 
532
588
  fn compile_match_node(
533
589
  &mut self,
534
- node: &crate::parser::ast::NodePattern,
590
+ node: &gqlparser::oc::ast::NodePattern,
535
591
  instructions: &mut Instructions,
536
592
  filter: &mut Instructions,
537
593
  get_node_function_name: Option<&'static str>,
@@ -570,7 +626,7 @@ impl Compiler
570
626
  fn compile_match_edge(
571
627
  &mut self,
572
628
  path_variable: Option<ast::VariableIdentifier>,
573
- edge: &crate::parser::ast::EdgePattern,
629
+ edge: &gqlparser::oc::ast::EdgePattern,
574
630
  single_match: bool,
575
631
  previous_edges: &mut Vec<usize>,
576
632
  ) -> Result<BlockMatch>
@@ -599,11 +655,13 @@ impl Compiler
599
655
  Some("get_source"),
600
656
  )?;
601
657
  }
602
- let mut destination_variable = None;
658
+ let destination_variable;
603
659
  if self
604
660
  .variables_manager
605
661
  .is_set_variable(&edge.destination.variable)?
606
662
  {
663
+ // Always capture the destination variable so the DFS can filter by pre-bound destination key.
664
+ destination_variable = edge.destination.variable.to_owned();
607
665
  instructions.push(Instruction::GetVariable {
608
666
  col_id: self
609
667
  .variables_manager
@@ -706,6 +764,7 @@ impl Compiler
706
764
  .get_variable_index_option(&path_variable)?,
707
765
  filter,
708
766
  directivity: edge.directivity,
767
+ recursive_range: edge.recursive_range.clone(),
709
768
  })
710
769
  }
711
770
 
@@ -796,8 +855,8 @@ impl Compiler
796
855
 
797
856
  fn compile_match_patterns(
798
857
  &mut self,
799
- patterns: &[crate::parser::ast::Pattern],
800
- where_expression: &Option<crate::parser::ast::Expression>,
858
+ patterns: &[gqlparser::oc::ast::Pattern],
859
+ where_expression: &Option<gqlparser::oc::ast::Expression>,
801
860
  optional: bool,
802
861
  ) -> Result<Block>
803
862
  {
@@ -805,7 +864,7 @@ impl Compiler
805
864
  let mut edge_variables = vec![];
806
865
  let blocks = patterns.iter().map(|c| match c
807
866
  {
808
- crate::parser::ast::Pattern::Node(node) =>
867
+ gqlparser::oc::ast::Pattern::Node(node) =>
809
868
  {
810
869
  let mut instructions = Instructions::new();
811
870
  let mut filter = Instructions::new();
@@ -821,11 +880,11 @@ impl Compiler
821
880
  filter,
822
881
  })
823
882
  }
824
- crate::parser::ast::Pattern::Edge(edge) =>
883
+ gqlparser::oc::ast::Pattern::Edge(edge) =>
825
884
  {
826
885
  self.compile_match_edge(None, edge, is_single_match, &mut edge_variables)
827
886
  }
828
- crate::parser::ast::Pattern::Path(path) => self.compile_match_edge(
887
+ gqlparser::oc::ast::Pattern::Path(path) => self.compile_match_edge(
829
888
  Some(path.variable.to_owned()),
830
889
  &path.edge,
831
890
  is_single_match,
@@ -852,11 +911,17 @@ impl Compiler
852
911
  })
853
912
  }
854
913
 
855
- fn check_for_constant_integer_expression(&mut self, x: &ast::Expression) -> Result<()>
914
+ fn check_for_positive_constant_integer_expression(&mut self, x: &ast::Expression) -> Result<()>
856
915
  {
916
+ if let ast::Expression::Value(value) = x
917
+ && let Ok(v) = <&graphcore::Value as TryInto<i64>>::try_into(&value.value)
918
+ && v < 0
919
+ {
920
+ return Err(error::CompileTimeError::NegativeIntegerArgument.into());
921
+ }
857
922
  let ei = expression_analyser::Analyser::new(&self.variables_manager, &self.function_manager)
858
923
  .analyse(x)?;
859
- if !ei.constant
924
+ if !ei.runtime_constant
860
925
  {
861
926
  Err(error::CompileTimeError::NonConstantExpression.into())
862
927
  }
@@ -880,7 +945,7 @@ impl Compiler
880
945
  .limit
881
946
  .as_ref()
882
947
  .map(|x| {
883
- self.check_for_constant_integer_expression(x)?;
948
+ self.check_for_positive_constant_integer_expression(x)?;
884
949
  let mut instructions = Instructions::new();
885
950
  self.compile_expression(x, &mut instructions, &mut None)?;
886
951
  Ok::<_, ErrorType>(instructions)
@@ -890,7 +955,7 @@ impl Compiler
890
955
  .skip
891
956
  .as_ref()
892
957
  .map(|x| {
893
- self.check_for_constant_integer_expression(x)?;
958
+ self.check_for_positive_constant_integer_expression(x)?;
894
959
  let mut instructions = Instructions::new();
895
960
  self.compile_expression(x, &mut instructions, &mut None)?;
896
961
  Ok::<_, ErrorType>(instructions)
@@ -920,11 +985,227 @@ impl Compiler
920
985
  order_by,
921
986
  })
922
987
  }
988
+
989
+ fn unpack_scan_plan(
990
+ logical_plan: LogicalPlan,
991
+ ) -> Result<(Vec<ast::Pattern>, Option<ast::Expression>, bool)>
992
+ {
993
+ match logical_plan
994
+ {
995
+ LogicalPlan::NodeScan { patterns, optional } => Ok((patterns, None, optional)),
996
+ LogicalPlan::Filter { source, expression } =>
997
+ {
998
+ let (patterns, filter, optional) = Self::unpack_scan_plan(*source)?;
999
+ if filter.is_some()
1000
+ {
1001
+ return Err(
1002
+ InternalError::Unreachable {
1003
+ context: "compile/unpack_scan_plan/filter",
1004
+ }
1005
+ .into(),
1006
+ );
1007
+ }
1008
+ Ok((patterns, Some(expression), optional))
1009
+ }
1010
+ _ => Err(
1011
+ InternalError::Unreachable {
1012
+ context: "compile/unpack_scan_plan",
1013
+ }
1014
+ .into(),
1015
+ ),
1016
+ }
1017
+ }
1018
+
1019
+ fn compile_scan_plan(&mut self, logical_plan: LogicalPlan) -> Result<Block>
1020
+ {
1021
+ let (patterns, where_expression, optional) = Self::unpack_scan_plan(logical_plan)?;
1022
+ self.compile_match_patterns(&patterns, &where_expression, optional)
1023
+ }
1024
+
1025
+ fn unpack_projection_plan(logical_plan: LogicalPlan) -> Result<PlannedProjection>
1026
+ {
1027
+ match logical_plan
1028
+ {
1029
+ LogicalPlan::Projection {
1030
+ kind,
1031
+ all,
1032
+ expressions,
1033
+ } => Ok(PlannedProjection {
1034
+ kind,
1035
+ all,
1036
+ expressions,
1037
+ where_expression: None,
1038
+ modifiers: Default::default(),
1039
+ }),
1040
+ LogicalPlan::Filter { source, expression } =>
1041
+ {
1042
+ let mut projection = Self::unpack_projection_plan(*source)?;
1043
+ if projection.where_expression.is_some()
1044
+ {
1045
+ return Err(
1046
+ InternalError::Unreachable {
1047
+ context: "compile/unpack_projection_plan/filter",
1048
+ }
1049
+ .into(),
1050
+ );
1051
+ }
1052
+ projection.where_expression = Some(expression);
1053
+ Ok(projection)
1054
+ }
1055
+ LogicalPlan::Sort {
1056
+ source,
1057
+ expressions,
1058
+ } =>
1059
+ {
1060
+ let mut projection = Self::unpack_projection_plan(*source)?;
1061
+ if projection.modifiers.order_by.is_some()
1062
+ {
1063
+ return Err(
1064
+ InternalError::Unreachable {
1065
+ context: "compile/unpack_projection_plan/sort",
1066
+ }
1067
+ .into(),
1068
+ );
1069
+ }
1070
+ projection.modifiers.order_by = Some(ast::OrderBy { expressions });
1071
+ Ok(projection)
1072
+ }
1073
+ LogicalPlan::Skip { source, expression } =>
1074
+ {
1075
+ let mut projection = Self::unpack_projection_plan(*source)?;
1076
+ if projection.modifiers.skip.is_some()
1077
+ {
1078
+ return Err(
1079
+ InternalError::Unreachable {
1080
+ context: "compile/unpack_projection_plan/skip",
1081
+ }
1082
+ .into(),
1083
+ );
1084
+ }
1085
+ projection.modifiers.skip = Some(expression);
1086
+ Ok(projection)
1087
+ }
1088
+ LogicalPlan::Limit { source, expression } =>
1089
+ {
1090
+ let mut projection = Self::unpack_projection_plan(*source)?;
1091
+ if projection.modifiers.limit.is_some()
1092
+ {
1093
+ return Err(
1094
+ InternalError::Unreachable {
1095
+ context: "compile/unpack_projection_plan/limit",
1096
+ }
1097
+ .into(),
1098
+ );
1099
+ }
1100
+ projection.modifiers.limit = Some(expression);
1101
+ Ok(projection)
1102
+ }
1103
+ _ => Err(
1104
+ InternalError::Unreachable {
1105
+ context: "compile/unpack_projection_plan",
1106
+ }
1107
+ .into(),
1108
+ ),
1109
+ }
1110
+ }
1111
+
1112
+ fn compile_projection_plan(&mut self, logical_plan: LogicalPlan) -> Result<Block>
1113
+ {
1114
+ let projection = Self::unpack_projection_plan(logical_plan)?;
1115
+ let compiled_return_with = self.compile_return_with(
1116
+ projection.all,
1117
+ &projection.expressions,
1118
+ &projection.where_expression,
1119
+ &projection.modifiers,
1120
+ )?;
1121
+
1122
+ match projection.kind
1123
+ {
1124
+ ProjectionKind::Return => Ok(Block::Return {
1125
+ variables: compiled_return_with.variables,
1126
+ filter: compiled_return_with.filter,
1127
+ modifiers: compiled_return_with.modifiers,
1128
+ variables_sizes: compiled_return_with.variables_sizes,
1129
+ }),
1130
+ ProjectionKind::With => Ok(Block::With {
1131
+ variables: compiled_return_with
1132
+ .variables
1133
+ .into_iter()
1134
+ .map(|(_, v)| v)
1135
+ .collect(),
1136
+ filter: compiled_return_with.filter,
1137
+ modifiers: compiled_return_with.modifiers,
1138
+ variables_sizes: compiled_return_with.variables_sizes,
1139
+ }),
1140
+ }
1141
+ }
1142
+
1143
+ fn compile_updates(&mut self, updates: &[ast::OneUpdate])
1144
+ -> Result<Vec<instructions::UpdateOne>>
1145
+ {
1146
+ updates
1147
+ .iter()
1148
+ .map(|x| match x
1149
+ {
1150
+ ast::OneUpdate::SetProperty(update_property)
1151
+ | ast::OneUpdate::AddProperty(update_property) =>
1152
+ {
1153
+ let mut instructions = Instructions::new();
1154
+ self.compile_expression(&update_property.expression, &mut instructions, &mut None)?;
1155
+
1156
+ match x
1157
+ {
1158
+ ast::OneUpdate::SetProperty(_) => Ok(instructions::UpdateOne::SetProperty {
1159
+ target: self
1160
+ .variables_manager
1161
+ .get_variable_index(&update_property.target)?,
1162
+ path: update_property.path.to_owned(),
1163
+ instructions,
1164
+ }),
1165
+ ast::OneUpdate::AddProperty(_) => Ok(instructions::UpdateOne::AddProperty {
1166
+ target: self
1167
+ .variables_manager
1168
+ .get_variable_index(&update_property.target)?,
1169
+ path: update_property.path.to_owned(),
1170
+ instructions,
1171
+ }),
1172
+ _ => Err(
1173
+ InternalError::Unreachable {
1174
+ context: "compile_updates/SetAddProperty",
1175
+ }
1176
+ .into(),
1177
+ ),
1178
+ }
1179
+ }
1180
+ ast::OneUpdate::RemoveProperty(remove_property) =>
1181
+ {
1182
+ Ok(instructions::UpdateOne::RemoveProperty {
1183
+ target: self
1184
+ .variables_manager
1185
+ .get_variable_index(&remove_property.target)?,
1186
+ path: remove_property.path.to_owned(),
1187
+ })
1188
+ }
1189
+ ast::OneUpdate::AddLabels(add_labels) => Ok(instructions::UpdateOne::AddLabels {
1190
+ target: self
1191
+ .variables_manager
1192
+ .get_variable_index(&add_labels.target)?,
1193
+ labels: add_labels.labels.to_owned(),
1194
+ }),
1195
+ ast::OneUpdate::RemoveLabels(rm_labels) => Ok(instructions::UpdateOne::RemoveLabels {
1196
+ target: self
1197
+ .variables_manager
1198
+ .get_variable_index(&rm_labels.target)?,
1199
+ labels: rm_labels.labels.to_owned(),
1200
+ }),
1201
+ })
1202
+ .collect::<Result<_>>()
1203
+ }
923
1204
  }
924
1205
 
925
1206
  pub(crate) fn compile(
926
1207
  function_manager: &functions::Manager,
927
- statements: crate::parser::ast::Statements,
1208
+ logical_plans: LogicalPlans,
928
1209
  ) -> Result<interpreter::Program>
929
1210
  {
930
1211
  let mut compiler = Compiler {
@@ -932,93 +1213,64 @@ pub(crate) fn compile(
932
1213
  function_manager: function_manager.clone(),
933
1214
  temporary_variables: 0,
934
1215
  };
935
- let mut statements_err = Ok(());
936
- let program = statements
937
- .iter()
938
- .map(|stmt| {
1216
+ let program = logical_plans
1217
+ .into_iter()
1218
+ .map(|logical_plan| {
939
1219
  compiler.temporary_variables = 0;
940
- compiler.variables_manager.analyse(stmt)?;
941
- match stmt
1220
+ compiler.variables_manager.analyse(&logical_plan)?;
1221
+ match logical_plan
942
1222
  {
943
- ast::Statement::CreateGraph(create_graph) => Ok(Block::CreateGraph {
944
- name: create_graph.name.to_owned(),
945
- if_not_exists: create_graph.if_not_exists,
946
- }),
947
- ast::Statement::DropGraph(drop_graph) => Ok(Block::DropGraph {
948
- name: drop_graph.name.to_owned(),
949
- if_exists: drop_graph.if_exists,
1223
+ LogicalPlan::CreateGraph {
1224
+ name,
1225
+ if_not_exists,
1226
+ } => Ok(Block::CreateGraph {
1227
+ name,
1228
+ if_not_exists,
950
1229
  }),
951
- ast::Statement::UseGraph(use_graph) => Ok(Block::UseGraph {
952
- name: use_graph.name.to_owned(),
953
- }),
954
- ast::Statement::Create(create) => compiler.compile_create_patterns(&create.patterns),
955
- ast::Statement::Match(match_statement) => compiler.compile_match_patterns(
956
- &match_statement.patterns,
957
- &match_statement.where_expression,
958
- match_statement.optional,
959
- ),
960
- ast::Statement::Return(return_statement) =>
1230
+ LogicalPlan::DropGraph { name, if_exists } => Ok(Block::DropGraph { name, if_exists }),
1231
+ LogicalPlan::UseGraph { name } => Ok(Block::UseGraph { name }),
1232
+ LogicalPlan::Create { patterns } => compiler.compile_create_patterns(patterns),
1233
+ LogicalPlan::NodeScan { .. } => compiler.compile_scan_plan(logical_plan),
1234
+ LogicalPlan::Filter { ref source, .. } if is_scan_plan(source.as_ref()) =>
961
1235
  {
962
- let compiled_return_with = compiler.compile_return_with(
963
- return_statement.all,
964
- &return_statement.expressions,
965
- &return_statement.where_expression,
966
- &return_statement.modifiers,
967
- )?;
968
- Ok(Block::Return {
969
- variables: compiled_return_with.variables,
970
- filter: compiled_return_with.filter,
971
- modifiers: compiled_return_with.modifiers,
972
- variables_sizes: compiled_return_with.variables_sizes,
973
- })
1236
+ compiler.compile_scan_plan(logical_plan)
974
1237
  }
975
- ast::Statement::Call(call) =>
1238
+ LogicalPlan::Projection { .. }
1239
+ | LogicalPlan::Sort { .. }
1240
+ | LogicalPlan::Skip { .. }
1241
+ | LogicalPlan::Limit { .. }
1242
+ | LogicalPlan::Filter { .. } => compiler.compile_projection_plan(logical_plan),
1243
+ LogicalPlan::Call { name, arguments } =>
976
1244
  {
977
1245
  let mut instructions = Instructions::new();
978
- for e in call.arguments.iter().rev()
1246
+ for e in arguments.iter().rev()
979
1247
  {
980
1248
  compiler.compile_expression(e, &mut instructions, &mut None)?;
981
1249
  }
982
1250
  Ok(Block::Call {
983
1251
  arguments: instructions,
984
- name: call.name.to_owned(),
1252
+ name,
985
1253
  })
986
1254
  }
987
- ast::Statement::With(with) =>
988
- {
989
- let compiled_return_with = compiler.compile_return_with(
990
- with.all,
991
- &with.expressions,
992
- &with.where_expression,
993
- &with.modifiers,
994
- )?;
995
- Ok(Block::With {
996
- variables: compiled_return_with
997
- .variables
998
- .into_iter()
999
- .map(|(_, v)| v)
1000
- .collect(),
1001
- filter: compiled_return_with.filter,
1002
- modifiers: compiled_return_with.modifiers,
1003
- variables_sizes: compiled_return_with.variables_sizes,
1004
- })
1005
- }
1006
- ast::Statement::Unwind(unwind) =>
1255
+ LogicalPlan::Unwind {
1256
+ identifier,
1257
+ expression,
1258
+ } =>
1007
1259
  {
1008
1260
  let mut instructions = Instructions::new();
1009
- compiler.compile_expression(&unwind.expression, &mut instructions, &mut None)?;
1261
+ compiler.compile_expression(&expression, &mut instructions, &mut None)?;
1010
1262
  Ok(Block::Unwind {
1011
- col_id: compiler
1012
- .variables_manager
1013
- .get_variable_index(&unwind.identifier)?,
1263
+ col_id: compiler.variables_manager.get_variable_index(&identifier)?,
1014
1264
  instructions,
1015
1265
  variables_size: compiler.variables_size(),
1016
1266
  })
1017
1267
  }
1018
- ast::Statement::Delete(delete_statement) => Ok(Block::Delete {
1019
- detach: delete_statement.detach,
1020
- instructions: delete_statement
1021
- .expressions
1268
+ LogicalPlan::Delete {
1269
+ detach,
1270
+ expressions,
1271
+ } => Ok(Block::Delete {
1272
+ detach,
1273
+ instructions: expressions
1022
1274
  .iter()
1023
1275
  .map(|expr| {
1024
1276
  let mut instructions = Instructions::new();
@@ -1039,84 +1291,112 @@ pub(crate) fn compile(
1039
1291
  })
1040
1292
  .collect::<Result<_>>()?,
1041
1293
  }),
1042
- ast::Statement::Update(update_statement) => Ok(Block::Update {
1043
- updates: update_statement
1044
- .updates
1045
- .iter()
1046
- .map(|x| match x
1047
- {
1048
- ast::OneUpdate::SetProperty(update_property)
1049
- | ast::OneUpdate::AddProperty(update_property) =>
1050
- {
1051
- let mut instructions = Instructions::new();
1052
- compiler.compile_expression(
1053
- &update_property.expression,
1054
- &mut instructions,
1055
- &mut None,
1056
- )?;
1057
-
1058
- match x
1059
- {
1060
- ast::OneUpdate::SetProperty(_) => Ok(instructions::UpdateOne::SetProperty {
1061
- target: compiler
1062
- .variables_manager
1063
- .get_variable_index(&update_property.target)?,
1064
- path: update_property.path.to_owned(),
1065
- instructions,
1066
- }),
1067
- ast::OneUpdate::AddProperty(_) => Ok(instructions::UpdateOne::AddProperty {
1068
- target: compiler
1069
- .variables_manager
1070
- .get_variable_index(&update_property.target)?,
1071
- path: update_property.path.to_owned(),
1072
- instructions,
1073
- }),
1074
- _ => Err(
1075
- InternalError::Unreachable {
1076
- context: "compile/Update/SetAddProperty",
1077
- }
1078
- .into(),
1079
- ),
1080
- }
1081
- }
1082
- ast::OneUpdate::RemoveProperty(remove_property) =>
1083
- {
1084
- Ok(instructions::UpdateOne::RemoveProperty {
1085
- target: compiler
1086
- .variables_manager
1087
- .get_variable_index(&remove_property.target)?,
1088
- path: remove_property.path.to_owned(),
1089
- })
1090
- }
1091
- ast::OneUpdate::AddLabels(add_labels) => Ok(instructions::UpdateOne::AddLabels {
1092
- target: compiler
1093
- .variables_manager
1094
- .get_variable_index(&add_labels.target)?,
1095
- labels: add_labels.labels.to_owned(),
1096
- }),
1097
- ast::OneUpdate::RemoveLabels(rm_labels) =>
1098
- {
1099
- Ok(instructions::UpdateOne::RemoveLabels {
1100
- target: compiler
1101
- .variables_manager
1102
- .get_variable_index(&rm_labels.target)?,
1103
- labels: rm_labels.labels.to_owned(),
1104
- })
1105
- }
1106
- })
1107
- .collect::<Result<_>>()?,
1294
+ LogicalPlan::Update { updates } => Ok(Block::Update {
1295
+ updates: compiler.compile_updates(&updates)?,
1108
1296
  variables_size: compiler.variables_size(),
1109
1297
  }),
1298
+ LogicalPlan::VectorSearch {
1299
+ index,
1300
+ query,
1301
+ k,
1302
+ result_var,
1303
+ score_var,
1304
+ } =>
1305
+ {
1306
+ let mut query_instructions = Instructions::new();
1307
+ let ei = expression_analyser::Analyser::new(
1308
+ &compiler.variables_manager,
1309
+ &compiler.function_manager,
1310
+ )
1311
+ .analyse(&query)?;
1312
+ if ei.aggregation_result
1313
+ {
1314
+ return Err(CompileTimeError::InvalidAggregation.into());
1315
+ }
1316
+ match ei.expression_type
1317
+ {
1318
+ ExpressionType::Array | ExpressionType::Tensor | ExpressionType::Variant =>
1319
+ {}
1320
+ _ => return Err(CompileTimeError::InvalidVectorInput.into()),
1321
+ }
1322
+ compiler.compile_expression(&query, &mut query_instructions, &mut None)?;
1323
+
1324
+ // Get the column IDs for the output variables from the variables manager
1325
+ let out_node_col_id = compiler.variables_manager.get_variable_index(&result_var)?;
1326
+ let out_score_col_id = compiler
1327
+ .variables_manager
1328
+ .get_variable_index_option(&score_var)?;
1329
+
1330
+ Ok(Block::VectorSearch {
1331
+ index,
1332
+ query_instructions,
1333
+ k,
1334
+ out_node_col_id,
1335
+ out_score_col_id,
1336
+ variables_size: compiler.variables_size(),
1337
+ })
1338
+ }
1339
+ LogicalPlan::Merge {
1340
+ patterns,
1341
+ on_create,
1342
+ on_match,
1343
+ } =>
1344
+ {
1345
+ // 1. Compile the match side
1346
+ let Block::Match {
1347
+ blocks: match_blocks,
1348
+ filter: match_filter,
1349
+ ..
1350
+ } = compiler.compile_match_patterns(&patterns, &None, false)?
1351
+ else
1352
+ {
1353
+ unreachable!()
1354
+ };
1355
+
1356
+ // 2. Compile the create side
1357
+ let Block::Create {
1358
+ actions: create_actions,
1359
+ ..
1360
+ } = compiler.compile_create_patterns(patterns)?
1361
+ else
1362
+ {
1363
+ unreachable!()
1364
+ };
1365
+
1366
+ // 3. Compile ON CREATE / ON MATCH updates
1367
+ let on_create_updates = compiler.compile_updates(&on_create)?;
1368
+ let on_match_updates = compiler.compile_updates(&on_match)?;
1369
+
1370
+ Ok(Block::Merge {
1371
+ match_blocks,
1372
+ match_filter,
1373
+ create_actions,
1374
+ on_create_updates,
1375
+ on_match_updates,
1376
+ variables_size: compiler.variables_size(),
1377
+ })
1378
+ }
1379
+ LogicalPlan::CreateVectorIndex {
1380
+ name,
1381
+ label,
1382
+ property,
1383
+ dimension,
1384
+ metric,
1385
+ if_not_exists,
1386
+ } => Ok(Block::CreateVectorIndex {
1387
+ name,
1388
+ label,
1389
+ property,
1390
+ dimension,
1391
+ metric,
1392
+ if_not_exists,
1393
+ }),
1110
1394
  }
1111
1395
  })
1112
- .scan(&mut statements_err, |err, gp| {
1113
- gp.map_err(|e| **err = Err(e)).ok()
1114
- });
1115
- let program = program.collect::<interpreter::Program>();
1116
- statements_err?;
1396
+ .collect::<Result<interpreter::Program>>()?;
1117
1397
  if crate::consts::SHOW_PROGRAM
1118
1398
  {
1119
- println!("program = {:#?}", program);
1399
+ log::debug!("program = {:#?}", program);
1120
1400
  }
1121
1401
  Ok(program)
1122
1402
  }