gqlite 1.7.0 → 1.8.1

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.
@@ -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,6 +466,7 @@ 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
  },
@@ -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>),
@@ -601,6 +616,7 @@ pub struct FunctionCall
601
616
  {
602
617
  pub name: String,
603
618
  pub arguments: Vec<Expression>,
619
+ pub distinct: bool,
604
620
  }
605
621
 
606
622
  create_from_expr! {FunctionCall}
@@ -630,6 +646,10 @@ create_binary_op! {RelationalSuperiorEqual}
630
646
  create_binary_op! {RelationalIn}
631
647
  create_binary_op! {RelationalNotIn}
632
648
 
649
+ create_binary_op! {Contains}
650
+ create_binary_op! {EndsWith}
651
+ create_binary_op! {StartsWith}
652
+
633
653
  create_binary_op! {Addition}
634
654
  create_binary_op! {Subtraction}
635
655
  create_binary_op! {Multiplication}
@@ -22,17 +22,23 @@ pub(crate) enum Token
22
22
  By,
23
23
  #[token("call", ignore(case))]
24
24
  Call,
25
+ #[token("contains", ignore(case))]
26
+ Contains,
27
+ #[token("create", ignore(case))]
28
+ Create,
25
29
  #[token("desc", ignore(case))]
26
30
  #[token("descending", ignore(case))]
27
31
  Desc,
28
- #[token("create", ignore(case))]
29
- Create,
30
32
  #[token("delete", ignore(case))]
31
33
  Delete,
32
34
  #[token("detach", ignore(case))]
33
35
  Detach,
36
+ #[token("distinct", ignore(case))]
37
+ Distinct,
34
38
  #[token("drop", ignore(case))]
35
39
  Drop,
40
+ #[token("ends", ignore(case))]
41
+ Ends,
36
42
  #[token("exists", ignore(case))]
37
43
  Exists,
38
44
  #[token("for", ignore(case))]
@@ -65,6 +71,8 @@ pub(crate) enum Token
65
71
  Search,
66
72
  #[token("set", ignore(case))]
67
73
  Set,
74
+ #[token("starts", ignore(case))]
75
+ Starts,
68
76
  #[token("not", ignore(case))]
69
77
  Not,
70
78
  #[token("null", ignore(case))]
@@ -188,6 +196,7 @@ impl Token
188
196
  | Token::By
189
197
  | Token::Call
190
198
  | Token::Desc
199
+ | Token::Distinct
191
200
  | Token::Create
192
201
  | Token::Delete
193
202
  | Token::Detach
@@ -101,6 +101,17 @@ where
101
101
  assert_eq!(unwrap_nom(input.clone(), parser.parse(input)), exp);
102
102
  }
103
103
 
104
+ fn parse_string<P>(s: &str, mut parser: P, exp: impl Into<String>)
105
+ where
106
+ for<'a> P: nom::Parser<Input<'a>, Output = String, Error = Error>,
107
+ {
108
+ let exp = exp.into();
109
+ let ctx = Context::new(s);
110
+ let tokens = lexer::tokenize(s).expect("tokenization failed");
111
+ let input = Input(&tokens, &ctx);
112
+ assert_eq!(unwrap_nom(input.clone(), parser.parse(input)), exp);
113
+ }
114
+
104
115
  #[test]
105
116
  fn test_oc_parse_context_variable_identity()
106
117
  {
@@ -131,19 +142,19 @@ fn test_oc_parse_parameter_name()
131
142
  #[test]
132
143
  fn test_oc_parse_string_literal_double_quote()
133
144
  {
134
- parse_str(r#""hello world""#, string_literal, "hello world");
145
+ parse_string(r#""hello world""#, string_literal, "hello world");
135
146
  }
136
147
 
137
148
  #[test]
138
149
  fn test_oc_parse_string_literal_single_quote()
139
150
  {
140
- parse_str("'hello world'", string_literal, "hello world");
141
- parse_str("', as#?lßdj '", string_literal, ", as#?lßdj ");
151
+ parse_string("'hello world'", string_literal, "hello world");
152
+ parse_string("', as#?lßdj '", string_literal, ", as#?lßdj ");
142
153
  }
143
154
  #[test]
144
155
  fn test_oc_parse_string_literal_backtick()
145
156
  {
146
- parse_str("`hello`", string_literal, "hello");
157
+ parse_string("`hello`", string_literal, "hello");
147
158
  }
148
159
 
149
160
  #[test]
@@ -307,6 +318,7 @@ fn test_oc_parse_function_call()
307
318
  ast::Expression::Value(ast::Value { value: 1.into() }),
308
319
  ast::Expression::Value(ast::Value { value: 2.into() }),
309
320
  ],
321
+ distinct: false,
310
322
  },
311
323
  );
312
324
  }
@@ -320,6 +332,7 @@ fn test_oc_parse_function_call_all()
320
332
  ast::FunctionCall {
321
333
  name: "func".to_string(),
322
334
  arguments: vec![ast::Expression::Value(ast::Value { value: 0.into() })],
335
+ distinct: false,
323
336
  },
324
337
  );
325
338
  }
@@ -384,6 +397,7 @@ fn test_oc_parse_relational_binary_operator()
384
397
  }
385
398
  .into(),
386
399
  ],
400
+ distinct: false,
387
401
  }
388
402
  .into(),
389
403
  right: ast::FunctionCall {
@@ -397,6 +411,7 @@ fn test_oc_parse_relational_binary_operator()
397
411
  }
398
412
  .into(),
399
413
  ],
414
+ distinct: false,
400
415
  }
401
416
  .into(),
402
417
  },
@@ -1261,6 +1276,35 @@ fn test_oc_parse_return_n()
1261
1276
  compare_ast(vec![stmt], vec![exppected_stmt]);
1262
1277
  }
1263
1278
 
1279
+ #[test]
1280
+ fn test_oc_parse_return_distinct_n()
1281
+ {
1282
+ let stmt = parse("RETURN DISTINCT n", return_statement);
1283
+
1284
+ let exppected_stmt = ast::Statement::Return(ast::Return {
1285
+ all: false,
1286
+ expressions: vec![ast::NamedExpression {
1287
+ identifier: ast::VariableIdentifier {
1288
+ name: "n".to_string(),
1289
+ id: 0,
1290
+ },
1291
+ expression: ast::Variable {
1292
+ identifier: ast::VariableIdentifier {
1293
+ name: "n".to_string(),
1294
+ id: 0,
1295
+ },
1296
+ }
1297
+ .into(),
1298
+ }],
1299
+ where_expression: None,
1300
+ modifiers: ast::Modifiers {
1301
+ distinct: true,
1302
+ ..Default::default()
1303
+ },
1304
+ });
1305
+ compare_ast(vec![stmt], vec![exppected_stmt]);
1306
+ }
1307
+
1264
1308
  #[test]
1265
1309
  fn test_oc_parse_return_n_m()
1266
1310
  {
@@ -1411,9 +1455,8 @@ fn test_oc_parse_return_n_modifiers()
1411
1455
  }],
1412
1456
  where_expression: None,
1413
1457
  modifiers: ast::Modifiers {
1414
- order_by: None,
1415
1458
  limit: Some(ast::Expression::Value(ast::Value { value: (-1).into() })),
1416
- skip: None,
1459
+ ..Default::default()
1417
1460
  },
1418
1461
  }),
1419
1462
  );
@@ -1529,6 +1572,7 @@ fn test_oc_parse_modifiers()
1529
1572
  }),
1530
1573
  limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
1531
1574
  skip: Some(ast::Expression::Value(ast::Value { value: 2.into() })),
1575
+ ..Default::default()
1532
1576
  },
1533
1577
  );
1534
1578
  compare_parse_to_ast(
@@ -1569,15 +1613,15 @@ fn test_oc_parse_modifiers()
1569
1613
  }),
1570
1614
  limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
1571
1615
  skip: None,
1616
+ ..Default::default()
1572
1617
  },
1573
1618
  );
1574
1619
  compare_parse_to_ast(
1575
1620
  "LIMIT -1",
1576
1621
  modifiers,
1577
1622
  ast::Modifiers {
1578
- order_by: None,
1579
1623
  limit: Some(ast::Expression::Value(ast::Value { value: (-1).into() })),
1580
- skip: None,
1624
+ ..Default::default()
1581
1625
  },
1582
1626
  );
1583
1627
  }
@@ -1638,7 +1682,7 @@ fn test_oc_parse_with_modifiers()
1638
1682
  ],
1639
1683
  }),
1640
1684
  limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
1641
- skip: None,
1685
+ ..Default::default()
1642
1686
  },
1643
1687
  },
1644
1688
  );
@@ -2127,6 +2171,72 @@ fn test_oc_parse_match_with_search_basic()
2127
2171
  }
2128
2172
  }
2129
2173
 
2174
+ #[test]
2175
+ fn test_oc_parse_starts_with()
2176
+ {
2177
+ compare_parse_to_ast(
2178
+ "s STARTS WITH 'hello'",
2179
+ expression,
2180
+ ast::StartsWith {
2181
+ left: ast::Variable {
2182
+ identifier: ast::VariableIdentifier {
2183
+ name: "s".to_string(),
2184
+ id: 0,
2185
+ },
2186
+ }
2187
+ .into(),
2188
+ right: ast::Value {
2189
+ value: "hello".into(),
2190
+ }
2191
+ .into(),
2192
+ },
2193
+ );
2194
+ }
2195
+
2196
+ #[test]
2197
+ fn test_oc_parse_ends_with()
2198
+ {
2199
+ compare_parse_to_ast(
2200
+ "s ENDS WITH 'world'",
2201
+ expression,
2202
+ ast::EndsWith {
2203
+ left: ast::Variable {
2204
+ identifier: ast::VariableIdentifier {
2205
+ name: "s".to_string(),
2206
+ id: 0,
2207
+ },
2208
+ }
2209
+ .into(),
2210
+ right: ast::Value {
2211
+ value: "world".into(),
2212
+ }
2213
+ .into(),
2214
+ },
2215
+ );
2216
+ }
2217
+
2218
+ #[test]
2219
+ fn test_oc_parse_contains()
2220
+ {
2221
+ compare_parse_to_ast(
2222
+ "s CONTAINS 'test'",
2223
+ expression,
2224
+ ast::Contains {
2225
+ left: ast::Variable {
2226
+ identifier: ast::VariableIdentifier {
2227
+ name: "s".to_string(),
2228
+ id: 0,
2229
+ },
2230
+ }
2231
+ .into(),
2232
+ right: ast::Value {
2233
+ value: "test".into(),
2234
+ }
2235
+ .into(),
2236
+ },
2237
+ );
2238
+ }
2239
+
2130
2240
  #[test]
2131
2241
  fn test_oc_parse_match_with_search_and_score()
2132
2242
  {
@@ -2282,3 +2392,254 @@ fn test_oc_parse_create_vector_index_if_not_exists()
2282
2392
  },
2283
2393
  );
2284
2394
  }
2395
+
2396
+ #[test]
2397
+ fn test_oc_parse_not_wraps_full_comparison()
2398
+ {
2399
+ compare_parse_to_ast(
2400
+ r#"NOT n.name = "Alice""#,
2401
+ expression,
2402
+ ast::LogicalNegation {
2403
+ value: ast::RelationalEqual {
2404
+ left: ast::MemberAccess {
2405
+ left: ast::Variable {
2406
+ identifier: ast::VariableIdentifier {
2407
+ name: "n".to_string(),
2408
+ id: 0,
2409
+ },
2410
+ }
2411
+ .into(),
2412
+ path: vec!["name".to_string()],
2413
+ }
2414
+ .into(),
2415
+ right: ast::Value {
2416
+ value: "Alice".into(),
2417
+ }
2418
+ .into(),
2419
+ }
2420
+ .into(),
2421
+ },
2422
+ );
2423
+ }
2424
+
2425
+ #[test]
2426
+ fn test_oc_parse_not_and_precedence()
2427
+ {
2428
+ compare_parse_to_ast(
2429
+ "NOT a = 1 AND c = 2",
2430
+ expression,
2431
+ ast::LogicalAnd {
2432
+ left: ast::LogicalNegation {
2433
+ value: ast::RelationalEqual {
2434
+ left: ast::Variable {
2435
+ identifier: ast::VariableIdentifier {
2436
+ name: "a".to_string(),
2437
+ id: 0,
2438
+ },
2439
+ }
2440
+ .into(),
2441
+ right: ast::Value { value: 1i64.into() }.into(),
2442
+ }
2443
+ .into(),
2444
+ }
2445
+ .into(),
2446
+ right: ast::RelationalEqual {
2447
+ left: ast::Variable {
2448
+ identifier: ast::VariableIdentifier {
2449
+ name: "c".to_string(),
2450
+ id: 1,
2451
+ },
2452
+ }
2453
+ .into(),
2454
+ right: ast::Value { value: 2i64.into() }.into(),
2455
+ }
2456
+ .into(),
2457
+ },
2458
+ );
2459
+ }
2460
+
2461
+ #[test]
2462
+ fn test_oc_parse_double_not()
2463
+ {
2464
+ compare_parse_to_ast(
2465
+ "NOT NOT a = 1",
2466
+ expression,
2467
+ ast::LogicalNegation {
2468
+ value: ast::LogicalNegation {
2469
+ value: ast::RelationalEqual {
2470
+ left: ast::Variable {
2471
+ identifier: ast::VariableIdentifier {
2472
+ name: "a".to_string(),
2473
+ id: 0,
2474
+ },
2475
+ }
2476
+ .into(),
2477
+ right: ast::Value { value: 1i64.into() }.into(),
2478
+ }
2479
+ .into(),
2480
+ }
2481
+ .into(),
2482
+ },
2483
+ );
2484
+ }
2485
+
2486
+ #[test]
2487
+ fn test_oc_parse_not_true_still_works()
2488
+ {
2489
+ compare_parse_to_ast(
2490
+ "NOT true",
2491
+ expression,
2492
+ ast::LogicalNegation {
2493
+ value: ast::Value { value: true.into() }.into(),
2494
+ },
2495
+ );
2496
+ }
2497
+
2498
+ #[test]
2499
+ fn test_oc_parse_is_not_null_unaffected()
2500
+ {
2501
+ compare_parse_to_ast(
2502
+ "n.age IS NOT NULL",
2503
+ expression,
2504
+ ast::IsNotNull {
2505
+ value: ast::MemberAccess {
2506
+ left: ast::Variable {
2507
+ identifier: ast::VariableIdentifier {
2508
+ name: "n".to_string(),
2509
+ id: 0,
2510
+ },
2511
+ }
2512
+ .into(),
2513
+ path: vec!["age".to_string()],
2514
+ }
2515
+ .into(),
2516
+ },
2517
+ );
2518
+ }
2519
+
2520
+ #[test]
2521
+ fn test_oc_parse_not_in_still_works()
2522
+ {
2523
+ compare_parse_to_ast(
2524
+ "x NOT IN [1, 2]",
2525
+ expression,
2526
+ ast::LogicalNegation {
2527
+ value: ast::RelationalIn {
2528
+ left: ast::Variable {
2529
+ identifier: ast::VariableIdentifier {
2530
+ name: "x".to_string(),
2531
+ id: 0,
2532
+ },
2533
+ }
2534
+ .into(),
2535
+ right: ast::Array {
2536
+ array: vec![
2537
+ ast::Value { value: 1i64.into() }.into(),
2538
+ ast::Value { value: 2i64.into() }.into(),
2539
+ ],
2540
+ }
2541
+ .into(),
2542
+ }
2543
+ .into(),
2544
+ },
2545
+ );
2546
+ }
2547
+
2548
+ #[test]
2549
+ fn test_oc_parse_count_distinct()
2550
+ {
2551
+ compare_parse_to_ast(
2552
+ "count(DISTINCT x)",
2553
+ expression,
2554
+ ast::FunctionCall {
2555
+ name: "count".to_string(),
2556
+ arguments: vec![
2557
+ ast::Variable {
2558
+ identifier: ast::VariableIdentifier {
2559
+ name: "x".to_string(),
2560
+ id: 0,
2561
+ },
2562
+ }
2563
+ .into(),
2564
+ ],
2565
+ distinct: true,
2566
+ },
2567
+ );
2568
+ }
2569
+
2570
+ #[test]
2571
+ fn test_oc_parse_count_without_distinct_defaults_false()
2572
+ {
2573
+ compare_parse_to_ast(
2574
+ "count(x)",
2575
+ expression,
2576
+ ast::FunctionCall {
2577
+ name: "count".to_string(),
2578
+ arguments: vec![
2579
+ ast::Variable {
2580
+ identifier: ast::VariableIdentifier {
2581
+ name: "x".to_string(),
2582
+ id: 0,
2583
+ },
2584
+ }
2585
+ .into(),
2586
+ ],
2587
+ distinct: false,
2588
+ },
2589
+ );
2590
+ }
2591
+
2592
+ #[test]
2593
+ fn test_oc_parse_sum_distinct()
2594
+ {
2595
+ compare_parse_to_ast(
2596
+ "sum(DISTINCT n.age)",
2597
+ expression,
2598
+ ast::FunctionCall {
2599
+ name: "sum".to_string(),
2600
+ arguments: vec![
2601
+ ast::MemberAccess {
2602
+ left: ast::Variable {
2603
+ identifier: ast::VariableIdentifier {
2604
+ name: "n".to_string(),
2605
+ id: 0,
2606
+ },
2607
+ }
2608
+ .into(),
2609
+ path: vec!["age".to_string()],
2610
+ }
2611
+ .into(),
2612
+ ],
2613
+ distinct: true,
2614
+ },
2615
+ );
2616
+ }
2617
+
2618
+ #[test]
2619
+ fn test_oc_parse_function_call_distinct_with_multiple_args()
2620
+ {
2621
+ compare_parse_to_ast(
2622
+ "some_func(DISTINCT a, b)",
2623
+ expression,
2624
+ ast::FunctionCall {
2625
+ name: "some_func".to_string(),
2626
+ arguments: vec![
2627
+ ast::Variable {
2628
+ identifier: ast::VariableIdentifier {
2629
+ name: "a".to_string(),
2630
+ id: 0,
2631
+ },
2632
+ }
2633
+ .into(),
2634
+ ast::Variable {
2635
+ identifier: ast::VariableIdentifier {
2636
+ name: "b".to_string(),
2637
+ id: 1,
2638
+ },
2639
+ }
2640
+ .into(),
2641
+ ],
2642
+ distinct: true,
2643
+ },
2644
+ );
2645
+ }