gqlite 1.8.1 → 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.
- checksums.yaml +4 -4
- data/ext/Cargo.toml +8 -8
- data/ext/gqlitedb/Cargo.toml +0 -2
- data/ext/gqlitedb/src/compiler/variables_manager.rs +109 -10
- data/ext/gqlitedb/src/compiler.rs +481 -47
- data/ext/gqlitedb/src/connection.rs +12 -0
- data/ext/gqlitedb/src/consts.rs +1 -1
- data/ext/gqlitedb/src/error.rs +24 -0
- data/ext/gqlitedb/src/interpreter/evaluators.rs +91 -325
- data/ext/gqlitedb/src/interpreter/instructions.rs +72 -0
- data/ext/gqlitedb/src/interpreter/mod.rs +1 -0
- data/ext/gqlitedb/src/interpreter/path/bfs.rs +494 -0
- data/ext/gqlitedb/src/interpreter/path/dfs.rs +267 -0
- data/ext/gqlitedb/src/interpreter/path/group.rs +418 -0
- data/ext/gqlitedb/src/interpreter/path.rs +542 -0
- data/ext/gqlitedb/src/planner.rs +218 -6
- data/ext/gqlitedb/src/query_result.rs +19 -4
- data/ext/gqlitedb/src/tests/compiler.rs +2453 -1
- data/ext/gqlitedb/src/tests/connection/redb.rs +8 -0
- data/ext/gqlitedb/src/tests/connection.rs +37 -0
- data/ext/gqlitedb/src/tests/evaluators.rs +2206 -1
- data/ext/gqlitedb/src/tests/parser.rs +1225 -0
- data/ext/gqlitedb/src/tests/planner.rs +432 -2
- data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +5 -5
- data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +3 -1
- data/ext/gqlitedb/src/tests/templates/ast.rs +284 -1
- data/ext/gqlitedb/src/tests/templates/programs.rs +306 -0
- data/ext/gqliterb/Cargo.toml +0 -1
- data/ext/gqlparser/src/oc/ast.rs +52 -3
- data/ext/gqlparser/src/oc/error.rs +18 -0
- data/ext/gqlparser/src/oc/lexer.rs +146 -0
- data/ext/gqlparser/src/oc/parser/tests.rs +365 -20
- data/ext/gqlparser/src/oc/parser.rs +1196 -143
- data/ext/graphcore/src/value.rs +12 -1
- metadata +5 -2
- data/ext/gqlitedb/src/parser/gql.pest +0 -198
|
@@ -421,7 +421,7 @@ fn test_oc_parse_relational_binary_operator()
|
|
|
421
421
|
#[test]
|
|
422
422
|
fn test_oc_parse_node_pattern_simple()
|
|
423
423
|
{
|
|
424
|
-
let actual = parse("(n:Person)", node_pattern);
|
|
424
|
+
let actual = parse("(n:Person)", node_pattern::<AllowUndirected>);
|
|
425
425
|
|
|
426
426
|
let expected = ast::NodePattern {
|
|
427
427
|
variable: ast::VariableIdentifier {
|
|
@@ -431,6 +431,8 @@ fn test_oc_parse_node_pattern_simple()
|
|
|
431
431
|
.into(),
|
|
432
432
|
labels: ast::LabelExpression::String("Person".to_string()),
|
|
433
433
|
properties: None,
|
|
434
|
+
|
|
435
|
+
predicate: None,
|
|
434
436
|
};
|
|
435
437
|
compare_ast(actual, expected);
|
|
436
438
|
}
|
|
@@ -438,7 +440,7 @@ fn test_oc_parse_node_pattern_simple()
|
|
|
438
440
|
#[test]
|
|
439
441
|
fn test_oc_parse_node_pattern_parameters()
|
|
440
442
|
{
|
|
441
|
-
let node = parse("(n {id: 12, name: 'foo'})", node_pattern);
|
|
443
|
+
let node = parse("(n {id: 12, name: 'foo'})", node_pattern::<AllowUndirected>);
|
|
442
444
|
|
|
443
445
|
let expected_node = ast::NodePattern {
|
|
444
446
|
variable: ast::VariableIdentifier {
|
|
@@ -461,11 +463,16 @@ fn test_oc_parse_node_pattern_parameters()
|
|
|
461
463
|
),
|
|
462
464
|
],
|
|
463
465
|
})),
|
|
466
|
+
|
|
467
|
+
predicate: None,
|
|
464
468
|
};
|
|
465
469
|
|
|
466
470
|
compare_ast(node, expected_node);
|
|
467
471
|
|
|
468
|
-
let node = parse(
|
|
472
|
+
let node = parse(
|
|
473
|
+
r#"(n {id: "12", name: "foo"})"#,
|
|
474
|
+
node_pattern::<AllowUndirected>,
|
|
475
|
+
);
|
|
469
476
|
|
|
470
477
|
let expected_node = ast::NodePattern {
|
|
471
478
|
variable: ast::VariableIdentifier {
|
|
@@ -488,6 +495,8 @@ fn test_oc_parse_node_pattern_parameters()
|
|
|
488
495
|
),
|
|
489
496
|
],
|
|
490
497
|
})),
|
|
498
|
+
|
|
499
|
+
predicate: None,
|
|
491
500
|
};
|
|
492
501
|
|
|
493
502
|
compare_ast(node, expected_node);
|
|
@@ -509,6 +518,7 @@ fn test_oc_parse_edge_patterns()
|
|
|
509
518
|
.into(),
|
|
510
519
|
labels: ast::LabelExpression::None,
|
|
511
520
|
properties: None,
|
|
521
|
+
predicate: None,
|
|
512
522
|
},
|
|
513
523
|
variable: ast::VariableIdentifier {
|
|
514
524
|
name: "m".to_string(),
|
|
@@ -523,11 +533,13 @@ fn test_oc_parse_edge_patterns()
|
|
|
523
533
|
.into(),
|
|
524
534
|
labels: ast::LabelExpression::None,
|
|
525
535
|
properties: None,
|
|
536
|
+
predicate: None,
|
|
526
537
|
},
|
|
527
538
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
528
539
|
labels: ast::LabelExpression::None,
|
|
529
540
|
properties: None,
|
|
530
|
-
|
|
541
|
+
|
|
542
|
+
predicate: None,
|
|
531
543
|
}
|
|
532
544
|
.into(),
|
|
533
545
|
],
|
|
@@ -562,7 +574,8 @@ fn test_oc_parse_edge_recursive_patterns()
|
|
|
562
574
|
"(n)-[m*1..2]->(p)",
|
|
563
575
|
patterns::<AllowUndirected>,
|
|
564
576
|
vec![
|
|
565
|
-
ast::
|
|
577
|
+
ast::QuantifiedPathPattern {
|
|
578
|
+
variable: None,
|
|
566
579
|
source: ast::NodePattern {
|
|
567
580
|
variable: ast::VariableIdentifier {
|
|
568
581
|
name: "n".to_string(),
|
|
@@ -571,12 +584,45 @@ fn test_oc_parse_edge_recursive_patterns()
|
|
|
571
584
|
.into(),
|
|
572
585
|
labels: ast::LabelExpression::None,
|
|
573
586
|
properties: None,
|
|
587
|
+
predicate: None,
|
|
574
588
|
},
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
589
|
+
group: vec![
|
|
590
|
+
ast::EdgePattern {
|
|
591
|
+
source: ast::NodePattern {
|
|
592
|
+
variable: ast::VariableIdentifier {
|
|
593
|
+
name: "n".to_string(),
|
|
594
|
+
id: 0,
|
|
595
|
+
}
|
|
596
|
+
.into(),
|
|
597
|
+
labels: ast::LabelExpression::None,
|
|
598
|
+
properties: None,
|
|
599
|
+
predicate: None,
|
|
600
|
+
},
|
|
601
|
+
variable: ast::VariableIdentifier {
|
|
602
|
+
name: "m".to_string(),
|
|
603
|
+
id: 2,
|
|
604
|
+
}
|
|
605
|
+
.into(),
|
|
606
|
+
destination: ast::NodePattern {
|
|
607
|
+
variable: ast::VariableIdentifier {
|
|
608
|
+
name: "p".to_string(),
|
|
609
|
+
id: 1,
|
|
610
|
+
}
|
|
611
|
+
.into(),
|
|
612
|
+
labels: ast::LabelExpression::None,
|
|
613
|
+
properties: None,
|
|
614
|
+
predicate: None,
|
|
615
|
+
},
|
|
616
|
+
directivity: graphcore::EdgeDirectivity::Directed,
|
|
617
|
+
labels: ast::LabelExpression::None,
|
|
618
|
+
properties: None,
|
|
619
|
+
predicate: None,
|
|
620
|
+
}
|
|
621
|
+
.into(),
|
|
622
|
+
],
|
|
623
|
+
group_where: None,
|
|
624
|
+
path_where: None,
|
|
625
|
+
quantifier: Some(1..2),
|
|
580
626
|
destination: ast::NodePattern {
|
|
581
627
|
variable: ast::VariableIdentifier {
|
|
582
628
|
name: "p".to_string(),
|
|
@@ -585,11 +631,9 @@ fn test_oc_parse_edge_recursive_patterns()
|
|
|
585
631
|
.into(),
|
|
586
632
|
labels: ast::LabelExpression::None,
|
|
587
633
|
properties: None,
|
|
634
|
+
predicate: None,
|
|
588
635
|
},
|
|
589
|
-
|
|
590
|
-
labels: ast::LabelExpression::None,
|
|
591
|
-
properties: None,
|
|
592
|
-
recursive_range: Some(1..2),
|
|
636
|
+
selector: ast::PathSelector::All,
|
|
593
637
|
}
|
|
594
638
|
.into(),
|
|
595
639
|
],
|
|
@@ -763,7 +807,7 @@ fn test_oc_parse_string_literal()
|
|
|
763
807
|
#[test]
|
|
764
808
|
fn test_oc_parse_node_pattern_with_parameter_properties()
|
|
765
809
|
{
|
|
766
|
-
let node = parse("(n $props)", node_pattern);
|
|
810
|
+
let node = parse("(n $props)", node_pattern::<AllowUndirected>);
|
|
767
811
|
|
|
768
812
|
let expr = node.properties.expect("properties expected");
|
|
769
813
|
|
|
@@ -789,6 +833,8 @@ fn test_oc_parse_match_statement_without_where()
|
|
|
789
833
|
.into(),
|
|
790
834
|
labels: ast::LabelExpression::None,
|
|
791
835
|
properties: None,
|
|
836
|
+
|
|
837
|
+
predicate: None,
|
|
792
838
|
}
|
|
793
839
|
.into(),
|
|
794
840
|
],
|
|
@@ -815,6 +861,8 @@ fn test_oc_parse_optional_match_statement_without_where()
|
|
|
815
861
|
.into(),
|
|
816
862
|
labels: ast::LabelExpression::None,
|
|
817
863
|
properties: None,
|
|
864
|
+
|
|
865
|
+
predicate: None,
|
|
818
866
|
}
|
|
819
867
|
.into(),
|
|
820
868
|
],
|
|
@@ -838,6 +886,7 @@ fn test_oc_parse_match_statement_double_edge()
|
|
|
838
886
|
variable: None,
|
|
839
887
|
labels: ast::LabelExpression::None,
|
|
840
888
|
properties: None,
|
|
889
|
+
predicate: None,
|
|
841
890
|
},
|
|
842
891
|
destination: ast::NodePattern {
|
|
843
892
|
variable: Some(ast::VariableIdentifier {
|
|
@@ -846,12 +895,14 @@ fn test_oc_parse_match_statement_double_edge()
|
|
|
846
895
|
}),
|
|
847
896
|
labels: ast::LabelExpression::None,
|
|
848
897
|
properties: None,
|
|
898
|
+
predicate: None,
|
|
849
899
|
},
|
|
850
900
|
variable: None,
|
|
851
901
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
852
902
|
labels: ast::LabelExpression::None,
|
|
853
903
|
properties: None,
|
|
854
|
-
|
|
904
|
+
|
|
905
|
+
predicate: None,
|
|
855
906
|
}
|
|
856
907
|
.into(),
|
|
857
908
|
ast::EdgePattern {
|
|
@@ -862,17 +913,20 @@ fn test_oc_parse_match_statement_double_edge()
|
|
|
862
913
|
}),
|
|
863
914
|
labels: ast::LabelExpression::None,
|
|
864
915
|
properties: None,
|
|
916
|
+
predicate: None,
|
|
865
917
|
},
|
|
866
918
|
destination: ast::NodePattern {
|
|
867
919
|
variable: None,
|
|
868
920
|
labels: ast::LabelExpression::None,
|
|
869
921
|
properties: None,
|
|
922
|
+
predicate: None,
|
|
870
923
|
},
|
|
871
924
|
variable: None,
|
|
872
925
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
873
926
|
labels: ast::LabelExpression::None,
|
|
874
927
|
properties: None,
|
|
875
|
-
|
|
928
|
+
|
|
929
|
+
predicate: None,
|
|
876
930
|
}
|
|
877
931
|
.into(),
|
|
878
932
|
],
|
|
@@ -905,6 +959,8 @@ fn test_oc_parse_merge_basic_pattern()
|
|
|
905
959
|
}),
|
|
906
960
|
)],
|
|
907
961
|
})),
|
|
962
|
+
|
|
963
|
+
predicate: None,
|
|
908
964
|
}
|
|
909
965
|
.into(),
|
|
910
966
|
],
|
|
@@ -929,6 +985,8 @@ fn test_oc_parse_merge_with_on_create_set()
|
|
|
929
985
|
}),
|
|
930
986
|
labels: ast::LabelExpression::String("Person".to_string()),
|
|
931
987
|
properties: None,
|
|
988
|
+
|
|
989
|
+
predicate: None,
|
|
932
990
|
}
|
|
933
991
|
.into(),
|
|
934
992
|
],
|
|
@@ -960,6 +1018,8 @@ fn test_oc_parse_merge_with_on_match_set()
|
|
|
960
1018
|
}),
|
|
961
1019
|
labels: ast::LabelExpression::String("Person".to_string()),
|
|
962
1020
|
properties: None,
|
|
1021
|
+
|
|
1022
|
+
predicate: None,
|
|
963
1023
|
}
|
|
964
1024
|
.into(),
|
|
965
1025
|
],
|
|
@@ -994,6 +1054,8 @@ fn test_oc_parse_merge_with_both_on_clauses()
|
|
|
994
1054
|
}),
|
|
995
1055
|
labels: ast::LabelExpression::String("Person".to_string()),
|
|
996
1056
|
properties: None,
|
|
1057
|
+
|
|
1058
|
+
predicate: None,
|
|
997
1059
|
}
|
|
998
1060
|
.into(),
|
|
999
1061
|
],
|
|
@@ -1035,6 +1097,8 @@ fn test_oc_parse_merge_with_both_on_clauses_reversed()
|
|
|
1035
1097
|
}),
|
|
1036
1098
|
labels: ast::LabelExpression::String("Person".to_string()),
|
|
1037
1099
|
properties: None,
|
|
1100
|
+
|
|
1101
|
+
predicate: None,
|
|
1038
1102
|
}
|
|
1039
1103
|
.into(),
|
|
1040
1104
|
],
|
|
@@ -1074,6 +1138,7 @@ fn test_oc_parse_merge_with_edge_pattern()
|
|
|
1074
1138
|
}),
|
|
1075
1139
|
labels: ast::LabelExpression::None,
|
|
1076
1140
|
properties: None,
|
|
1141
|
+
predicate: None,
|
|
1077
1142
|
},
|
|
1078
1143
|
destination: ast::NodePattern {
|
|
1079
1144
|
variable: Some(ast::VariableIdentifier {
|
|
@@ -1082,12 +1147,14 @@ fn test_oc_parse_merge_with_edge_pattern()
|
|
|
1082
1147
|
}),
|
|
1083
1148
|
labels: ast::LabelExpression::None,
|
|
1084
1149
|
properties: None,
|
|
1150
|
+
predicate: None,
|
|
1085
1151
|
},
|
|
1086
1152
|
variable: None,
|
|
1087
1153
|
labels: ast::LabelExpression::String("KNOWS".to_string()),
|
|
1088
1154
|
properties: None,
|
|
1089
1155
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
1090
|
-
|
|
1156
|
+
|
|
1157
|
+
predicate: None,
|
|
1091
1158
|
}
|
|
1092
1159
|
.into(),
|
|
1093
1160
|
],
|
|
@@ -1114,6 +1181,8 @@ fn test_oc_parse_merge_statement()
|
|
|
1114
1181
|
.into(),
|
|
1115
1182
|
labels: ast::LabelExpression::None,
|
|
1116
1183
|
properties: None,
|
|
1184
|
+
|
|
1185
|
+
predicate: None,
|
|
1117
1186
|
}
|
|
1118
1187
|
.into(),
|
|
1119
1188
|
],
|
|
@@ -1128,6 +1197,8 @@ fn test_oc_parse_merge_statement()
|
|
|
1128
1197
|
variable: None,
|
|
1129
1198
|
labels: ast::LabelExpression::None,
|
|
1130
1199
|
properties: None,
|
|
1200
|
+
|
|
1201
|
+
predicate: None,
|
|
1131
1202
|
}
|
|
1132
1203
|
.into(),
|
|
1133
1204
|
],
|
|
@@ -1142,6 +1213,8 @@ fn test_oc_parse_merge_statement()
|
|
|
1142
1213
|
variable: None,
|
|
1143
1214
|
labels: ast::LabelExpression::String("A".to_string()),
|
|
1144
1215
|
properties: None,
|
|
1216
|
+
|
|
1217
|
+
predicate: None,
|
|
1145
1218
|
}
|
|
1146
1219
|
.into(),
|
|
1147
1220
|
],
|
|
@@ -1159,6 +1232,8 @@ fn test_oc_parse_merge_statement()
|
|
|
1159
1232
|
ast::LabelExpression::String("B".to_string()),
|
|
1160
1233
|
]),
|
|
1161
1234
|
properties: None,
|
|
1235
|
+
|
|
1236
|
+
predicate: None,
|
|
1162
1237
|
}
|
|
1163
1238
|
.into(),
|
|
1164
1239
|
],
|
|
@@ -1179,17 +1254,20 @@ fn test_oc_parse_create_edge_statements()
|
|
|
1179
1254
|
variable: None,
|
|
1180
1255
|
labels: ast::LabelExpression::None,
|
|
1181
1256
|
properties: None,
|
|
1257
|
+
predicate: None,
|
|
1182
1258
|
},
|
|
1183
1259
|
destination: ast::NodePattern {
|
|
1184
1260
|
variable: None,
|
|
1185
1261
|
labels: ast::LabelExpression::None,
|
|
1186
1262
|
properties: None,
|
|
1263
|
+
predicate: None,
|
|
1187
1264
|
},
|
|
1188
1265
|
variable: None,
|
|
1189
1266
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
1190
1267
|
labels: ast::LabelExpression::String("R".to_string()),
|
|
1191
1268
|
properties: None,
|
|
1192
|
-
|
|
1269
|
+
|
|
1270
|
+
predicate: None,
|
|
1193
1271
|
}
|
|
1194
1272
|
.into(),
|
|
1195
1273
|
],
|
|
@@ -1208,6 +1286,7 @@ fn test_oc_parse_create_edge_statements()
|
|
|
1208
1286
|
}),
|
|
1209
1287
|
labels: ast::LabelExpression::None,
|
|
1210
1288
|
properties: None,
|
|
1289
|
+
predicate: None,
|
|
1211
1290
|
},
|
|
1212
1291
|
destination: ast::NodePattern {
|
|
1213
1292
|
variable: Some(ast::VariableIdentifier {
|
|
@@ -1216,12 +1295,14 @@ fn test_oc_parse_create_edge_statements()
|
|
|
1216
1295
|
}),
|
|
1217
1296
|
labels: ast::LabelExpression::None,
|
|
1218
1297
|
properties: None,
|
|
1298
|
+
predicate: None,
|
|
1219
1299
|
},
|
|
1220
1300
|
variable: None,
|
|
1221
1301
|
directivity: graphcore::EdgeDirectivity::Directed,
|
|
1222
1302
|
labels: ast::LabelExpression::String("FOO".to_string()),
|
|
1223
1303
|
properties: None,
|
|
1224
|
-
|
|
1304
|
+
|
|
1305
|
+
predicate: None,
|
|
1225
1306
|
}
|
|
1226
1307
|
.into(),
|
|
1227
1308
|
],
|
|
@@ -1726,6 +1807,8 @@ fn test_oc_parse_queries_multiple_statements()
|
|
|
1726
1807
|
.into(),
|
|
1727
1808
|
labels: ast::LabelExpression::None,
|
|
1728
1809
|
properties: None,
|
|
1810
|
+
|
|
1811
|
+
predicate: None,
|
|
1729
1812
|
}
|
|
1730
1813
|
.into(),
|
|
1731
1814
|
],
|
|
@@ -1765,6 +1848,8 @@ fn test_oc_parse_queries_multiple_queries()
|
|
|
1765
1848
|
.into(),
|
|
1766
1849
|
labels: ast::LabelExpression::None,
|
|
1767
1850
|
properties: None,
|
|
1851
|
+
|
|
1852
|
+
predicate: None,
|
|
1768
1853
|
}
|
|
1769
1854
|
.into(),
|
|
1770
1855
|
],
|
|
@@ -1807,6 +1892,8 @@ fn test_oc_parse_query_union_basic()
|
|
|
1807
1892
|
.into(),
|
|
1808
1893
|
labels: ast::LabelExpression::None,
|
|
1809
1894
|
properties: None,
|
|
1895
|
+
|
|
1896
|
+
predicate: None,
|
|
1810
1897
|
}
|
|
1811
1898
|
.into(),
|
|
1812
1899
|
],
|
|
@@ -1827,6 +1914,8 @@ fn test_oc_parse_query_union_basic()
|
|
|
1827
1914
|
.into(),
|
|
1828
1915
|
labels: ast::LabelExpression::None,
|
|
1829
1916
|
properties: None,
|
|
1917
|
+
|
|
1918
|
+
predicate: None,
|
|
1830
1919
|
}
|
|
1831
1920
|
.into(),
|
|
1832
1921
|
],
|
|
@@ -1861,6 +1950,8 @@ fn test_oc_parse_query_union_all_basic()
|
|
|
1861
1950
|
.into(),
|
|
1862
1951
|
labels: ast::LabelExpression::None,
|
|
1863
1952
|
properties: None,
|
|
1953
|
+
|
|
1954
|
+
predicate: None,
|
|
1864
1955
|
}
|
|
1865
1956
|
.into(),
|
|
1866
1957
|
],
|
|
@@ -1881,6 +1972,8 @@ fn test_oc_parse_query_union_all_basic()
|
|
|
1881
1972
|
.into(),
|
|
1882
1973
|
labels: ast::LabelExpression::None,
|
|
1883
1974
|
properties: None,
|
|
1975
|
+
|
|
1976
|
+
predicate: None,
|
|
1884
1977
|
}
|
|
1885
1978
|
.into(),
|
|
1886
1979
|
],
|
|
@@ -1915,6 +2008,8 @@ fn test_oc_parse_query_chained_union_basic()
|
|
|
1915
2008
|
.into(),
|
|
1916
2009
|
labels: ast::LabelExpression::None,
|
|
1917
2010
|
properties: None,
|
|
2011
|
+
|
|
2012
|
+
predicate: None,
|
|
1918
2013
|
}
|
|
1919
2014
|
.into(),
|
|
1920
2015
|
],
|
|
@@ -1935,6 +2030,8 @@ fn test_oc_parse_query_chained_union_basic()
|
|
|
1935
2030
|
.into(),
|
|
1936
2031
|
labels: ast::LabelExpression::None,
|
|
1937
2032
|
properties: None,
|
|
2033
|
+
|
|
2034
|
+
predicate: None,
|
|
1938
2035
|
}
|
|
1939
2036
|
.into(),
|
|
1940
2037
|
],
|
|
@@ -1955,6 +2052,8 @@ fn test_oc_parse_query_chained_union_basic()
|
|
|
1955
2052
|
.into(),
|
|
1956
2053
|
labels: ast::LabelExpression::None,
|
|
1957
2054
|
properties: None,
|
|
2055
|
+
|
|
2056
|
+
predicate: None,
|
|
1958
2057
|
}
|
|
1959
2058
|
.into(),
|
|
1960
2059
|
],
|
|
@@ -1987,6 +2086,8 @@ fn test_oc_parse_query_plain()
|
|
|
1987
2086
|
.into(),
|
|
1988
2087
|
labels: ast::LabelExpression::None,
|
|
1989
2088
|
properties: None,
|
|
2089
|
+
|
|
2090
|
+
predicate: None,
|
|
1990
2091
|
}
|
|
1991
2092
|
.into(),
|
|
1992
2093
|
],
|
|
@@ -2151,6 +2252,19 @@ fn test_oc_call_internal_stats()
|
|
|
2151
2252
|
);
|
|
2152
2253
|
}
|
|
2153
2254
|
|
|
2255
|
+
#[test]
|
|
2256
|
+
fn test_oc_call_db_list_graphs()
|
|
2257
|
+
{
|
|
2258
|
+
compare_parse_to_ast(
|
|
2259
|
+
"CALL gqlite.db.list_graphs()",
|
|
2260
|
+
call_statement,
|
|
2261
|
+
ast::Call {
|
|
2262
|
+
name: "gqlite.db.list_graphs".to_string(),
|
|
2263
|
+
arguments: vec![],
|
|
2264
|
+
},
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2154
2268
|
#[test]
|
|
2155
2269
|
fn test_oc_parse_match_with_search_basic()
|
|
2156
2270
|
{
|
|
@@ -2643,3 +2757,234 @@ fn test_oc_parse_function_call_distinct_with_multiple_args()
|
|
|
2643
2757
|
},
|
|
2644
2758
|
);
|
|
2645
2759
|
}
|
|
2760
|
+
|
|
2761
|
+
// Tests for work item #569: node_pattern predicate parsing
|
|
2762
|
+
|
|
2763
|
+
#[test]
|
|
2764
|
+
fn test_oc_parse_node_pattern_with_predicate_and_label()
|
|
2765
|
+
{
|
|
2766
|
+
// Test parsing (n:Station WHERE n.name = 'X')
|
|
2767
|
+
let actual = parse(
|
|
2768
|
+
"(n:Station WHERE n.name = 'X')",
|
|
2769
|
+
node_pattern::<AllowUndirected>,
|
|
2770
|
+
);
|
|
2771
|
+
|
|
2772
|
+
// Verify predicate is present
|
|
2773
|
+
assert!(actual.predicate.is_some(), "expected predicate to be Some");
|
|
2774
|
+
|
|
2775
|
+
// Verify label is correct
|
|
2776
|
+
assert!(matches!(actual.labels, ast::LabelExpression::String(ref s) if s == "Station"));
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
#[test]
|
|
2780
|
+
fn test_oc_parse_node_pattern_with_predicate_no_label()
|
|
2781
|
+
{
|
|
2782
|
+
// Test parsing (n WHERE n.name = 'X')
|
|
2783
|
+
let actual = parse("(n WHERE n.name = 'X')", node_pattern::<AllowUndirected>);
|
|
2784
|
+
|
|
2785
|
+
// Verify predicate is present
|
|
2786
|
+
assert!(actual.predicate.is_some(), "expected predicate to be Some");
|
|
2787
|
+
|
|
2788
|
+
// Verify label is None
|
|
2789
|
+
assert!(matches!(actual.labels, ast::LabelExpression::None));
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
#[test]
|
|
2793
|
+
fn test_oc_parse_node_pattern_with_predicate_and_properties()
|
|
2794
|
+
{
|
|
2795
|
+
// Test parsing (n:Station {zone: 2} WHERE n.name STARTS WITH 'D')
|
|
2796
|
+
let actual = parse(
|
|
2797
|
+
"(n:Station {zone: 2} WHERE n.name STARTS WITH 'D')",
|
|
2798
|
+
node_pattern::<AllowUndirected>,
|
|
2799
|
+
);
|
|
2800
|
+
|
|
2801
|
+
// Verify both properties and predicate are present
|
|
2802
|
+
assert!(
|
|
2803
|
+
actual.properties.is_some(),
|
|
2804
|
+
"expected properties to be Some"
|
|
2805
|
+
);
|
|
2806
|
+
assert!(actual.predicate.is_some(), "expected predicate to be Some");
|
|
2807
|
+
|
|
2808
|
+
// Verify label is correct
|
|
2809
|
+
assert!(matches!(actual.labels, ast::LabelExpression::String(ref s) if s == "Station"));
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
#[test]
|
|
2813
|
+
fn test_oc_parse_node_pattern_without_predicate_regression()
|
|
2814
|
+
{
|
|
2815
|
+
// Regression test: ensure predicate remains None when not specified
|
|
2816
|
+
let actual = parse("(n)", node_pattern::<AllowUndirected>);
|
|
2817
|
+
|
|
2818
|
+
// Verify predicate is None
|
|
2819
|
+
assert!(actual.predicate.is_none(), "expected predicate to be None");
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
#[test]
|
|
2823
|
+
fn test_oc_parse_create_with_predicate_rejected()
|
|
2824
|
+
{
|
|
2825
|
+
// Test: CREATE patterns with WHERE predicates should be rejected
|
|
2826
|
+
// This is parsed with DisallowUndirected context (used for CREATE)
|
|
2827
|
+
parse_fail(
|
|
2828
|
+
"(n:Station WHERE n.name = 'X')",
|
|
2829
|
+
node_pattern::<DisallowUndirected>,
|
|
2830
|
+
|error_kind| *error_kind == ErrorKind::CreatingWithPredicate,
|
|
2831
|
+
);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
#[test]
|
|
2835
|
+
fn test_oc_parse_group_pattern_simple()
|
|
2836
|
+
{
|
|
2837
|
+
// Test parsing ((n)-[r:KNOWS]->(m)){1,5}(b)
|
|
2838
|
+
let actual = parse(
|
|
2839
|
+
"((n)-[r:KNOWS]->(m)){1,5}(b)",
|
|
2840
|
+
group_pattern::<AllowUndirected>,
|
|
2841
|
+
);
|
|
2842
|
+
|
|
2843
|
+
// Verify group contains exactly one pattern (the edge)
|
|
2844
|
+
assert_eq!(
|
|
2845
|
+
actual.group.len(),
|
|
2846
|
+
1,
|
|
2847
|
+
"Expected one pattern in group, got {}",
|
|
2848
|
+
actual.group.len()
|
|
2849
|
+
);
|
|
2850
|
+
|
|
2851
|
+
// Verify the group contains an Edge pattern
|
|
2852
|
+
assert!(
|
|
2853
|
+
matches!(&actual.group[0], ast::Pattern::Edge(_)),
|
|
2854
|
+
"Expected Edge pattern in group"
|
|
2855
|
+
);
|
|
2856
|
+
|
|
2857
|
+
// Verify quantifier is 1..5
|
|
2858
|
+
assert_eq!(
|
|
2859
|
+
actual.quantifier,
|
|
2860
|
+
1..5,
|
|
2861
|
+
"Expected quantifier 1..5, got {:?}",
|
|
2862
|
+
actual.quantifier
|
|
2863
|
+
);
|
|
2864
|
+
|
|
2865
|
+
// Verify destination_node is bound to variable 'b'
|
|
2866
|
+
assert!(
|
|
2867
|
+
actual.destination_node.variable.is_some(),
|
|
2868
|
+
"Expected destination_node to have a variable"
|
|
2869
|
+
);
|
|
2870
|
+
if let Some(var) = &actual.destination_node.variable
|
|
2871
|
+
{
|
|
2872
|
+
assert_eq!(
|
|
2873
|
+
var.name(),
|
|
2874
|
+
"b",
|
|
2875
|
+
"Expected destination_node variable to be 'b', got '{}'",
|
|
2876
|
+
var.name()
|
|
2877
|
+
);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
#[test]
|
|
2882
|
+
fn test_oc_parse_selector_scoped_pattern_basic()
|
|
2883
|
+
{
|
|
2884
|
+
// Test parsing selector-scoped pattern: ((n)-[r]->(m) WHERE n.x > 1)
|
|
2885
|
+
let actual = parse(
|
|
2886
|
+
"((n)-[r]->(m) WHERE n.x > 1)",
|
|
2887
|
+
selector_scoped_pattern::<AllowUndirected>,
|
|
2888
|
+
);
|
|
2889
|
+
|
|
2890
|
+
// Verify it returns a single QuantifiedPathPattern
|
|
2891
|
+
assert_eq!(
|
|
2892
|
+
actual.len(),
|
|
2893
|
+
1,
|
|
2894
|
+
"Expected one pattern, got {}",
|
|
2895
|
+
actual.len()
|
|
2896
|
+
);
|
|
2897
|
+
|
|
2898
|
+
if let ast::Pattern::QuantifiedPath(qp) = &actual[0]
|
|
2899
|
+
{
|
|
2900
|
+
// Verify quantifier is None (key difference from group pattern)
|
|
2901
|
+
assert_eq!(
|
|
2902
|
+
qp.quantifier, None,
|
|
2903
|
+
"Expected quantifier to be None for selector-scoped pattern, got {:?}",
|
|
2904
|
+
qp.quantifier
|
|
2905
|
+
);
|
|
2906
|
+
|
|
2907
|
+
// Verify group_where is set
|
|
2908
|
+
assert!(qp.group_where.is_some(), "Expected group_where to be set");
|
|
2909
|
+
|
|
2910
|
+
// Verify variable is None (not set in selector_scoped_pattern itself)
|
|
2911
|
+
assert_eq!(
|
|
2912
|
+
qp.variable, None,
|
|
2913
|
+
"Expected variable to be None before patterns() closure applies it"
|
|
2914
|
+
);
|
|
2915
|
+
|
|
2916
|
+
// Verify group contains the pattern(s)
|
|
2917
|
+
assert!(!qp.group.is_empty(), "Expected group to contain patterns");
|
|
2918
|
+
}
|
|
2919
|
+
else
|
|
2920
|
+
{
|
|
2921
|
+
panic!("Expected QuantifiedPathPattern, got {:?}", actual[0]);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
#[test]
|
|
2926
|
+
fn test_oc_parse_selector_scoped_pattern_with_variable()
|
|
2927
|
+
{
|
|
2928
|
+
// Test parsing selector-scoped pattern with variable: (p = (n)-[r]->(m))
|
|
2929
|
+
// This tests just the selector_scoped_pattern directly
|
|
2930
|
+
let actual = parse(
|
|
2931
|
+
"(p = (n)-[r]->(m))",
|
|
2932
|
+
selector_scoped_pattern::<AllowUndirected>,
|
|
2933
|
+
);
|
|
2934
|
+
|
|
2935
|
+
// Verify it returns a single QuantifiedPathPattern
|
|
2936
|
+
assert_eq!(
|
|
2937
|
+
actual.len(),
|
|
2938
|
+
1,
|
|
2939
|
+
"Expected one pattern, got {}",
|
|
2940
|
+
actual.len()
|
|
2941
|
+
);
|
|
2942
|
+
|
|
2943
|
+
if let ast::Pattern::QuantifiedPath(qp) = &actual[0]
|
|
2944
|
+
{
|
|
2945
|
+
// Verify variable is set from the p = binding inside the scoped pattern
|
|
2946
|
+
assert!(qp.variable.is_some(), "Expected variable to be set");
|
|
2947
|
+
if let Some(var) = &qp.variable
|
|
2948
|
+
{
|
|
2949
|
+
assert_eq!(
|
|
2950
|
+
var.name(),
|
|
2951
|
+
"p",
|
|
2952
|
+
"Expected variable 'p', got '{}'",
|
|
2953
|
+
var.name()
|
|
2954
|
+
);
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
// Verify quantifier is None (key difference from regular group patterns)
|
|
2958
|
+
assert_eq!(
|
|
2959
|
+
qp.quantifier, None,
|
|
2960
|
+
"Expected quantifier to be None for selector-scoped pattern"
|
|
2961
|
+
);
|
|
2962
|
+
}
|
|
2963
|
+
else
|
|
2964
|
+
{
|
|
2965
|
+
panic!("Expected QuantifiedPathPattern, got {:?}", actual[0]);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2969
|
+
#[test]
|
|
2970
|
+
fn test_oc_parse_selector_scoped_pattern_no_where()
|
|
2971
|
+
{
|
|
2972
|
+
// Test parsing selector-scoped pattern without WHERE: ((n)-[r]->(m))
|
|
2973
|
+
let actual = parse("((n)-[r]->(m))", selector_scoped_pattern::<AllowUndirected>);
|
|
2974
|
+
|
|
2975
|
+
if let ast::Pattern::QuantifiedPath(qp) = &actual[0]
|
|
2976
|
+
{
|
|
2977
|
+
// Verify quantifier is None
|
|
2978
|
+
assert_eq!(qp.quantifier, None, "Expected quantifier to be None");
|
|
2979
|
+
|
|
2980
|
+
// Verify group_where is None when no WHERE clause
|
|
2981
|
+
assert_eq!(
|
|
2982
|
+
qp.group_where, None,
|
|
2983
|
+
"Expected group_where to be None when no WHERE clause"
|
|
2984
|
+
);
|
|
2985
|
+
}
|
|
2986
|
+
else
|
|
2987
|
+
{
|
|
2988
|
+
panic!("Expected QuantifiedPathPattern, got {:?}", actual[0]);
|
|
2989
|
+
}
|
|
2990
|
+
}
|