gqlite 1.5.0 → 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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +12 -6
  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 -8
  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 +20 -24
  26. data/ext/gqlitedb/src/compiler/expression_analyser.rs +28 -20
  27. data/ext/gqlitedb/src/compiler/variables_manager.rs +104 -38
  28. data/ext/gqlitedb/src/compiler.rs +506 -227
  29. data/ext/gqlitedb/src/connection.rs +151 -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 +64 -0
  33. data/ext/gqlitedb/src/functions/containers.rs +2 -46
  34. data/ext/gqlitedb/src/functions/edge.rs +1 -1
  35. data/ext/gqlitedb/src/functions/math.rs +87 -15
  36. data/ext/gqlitedb/src/functions/node.rs +1 -1
  37. data/ext/gqlitedb/src/functions/path.rs +48 -11
  38. data/ext/gqlitedb/src/functions/scalar.rs +47 -4
  39. data/ext/gqlitedb/src/functions/string.rs +123 -1
  40. data/ext/gqlitedb/src/functions/value.rs +1 -1
  41. data/ext/gqlitedb/src/functions.rs +165 -28
  42. data/ext/gqlitedb/src/graph.rs +1 -9
  43. data/ext/gqlitedb/src/interpreter/evaluators.rs +968 -130
  44. data/ext/gqlitedb/src/interpreter/instructions.rs +39 -2
  45. data/ext/gqlitedb/src/lib.rs +5 -4
  46. data/ext/gqlitedb/src/parser/gql.pest +1 -1
  47. data/ext/gqlitedb/src/planner.rs +329 -0
  48. data/ext/gqlitedb/src/prelude.rs +3 -3
  49. data/ext/gqlitedb/src/store/pgrx.rs +1 -1
  50. data/ext/gqlitedb/src/store/postgres.rs +742 -16
  51. data/ext/gqlitedb/src/store/redb/hnsw_store.rs +702 -0
  52. data/ext/gqlitedb/src/store/redb/index.rs +274 -0
  53. data/ext/gqlitedb/src/store/redb.rs +1268 -113
  54. data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +28 -0
  55. data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +103 -0
  56. data/ext/gqlitedb/src/store/sqlbase.rs +146 -16
  57. data/ext/gqlitedb/src/store/sqlite.rs +576 -14
  58. data/ext/gqlitedb/src/store/vector_extract.rs +56 -0
  59. data/ext/gqlitedb/src/store.rs +140 -29
  60. data/ext/gqlitedb/src/tests/compiler.rs +207 -10
  61. data/ext/gqlitedb/src/tests/connection/postgres.rs +38 -3
  62. data/ext/gqlitedb/src/tests/connection/redb.rs +23 -0
  63. data/ext/gqlitedb/src/tests/connection/sqlite.rs +31 -0
  64. data/ext/gqlitedb/src/tests/connection.rs +61 -1
  65. data/ext/gqlitedb/src/tests/evaluators.rs +162 -7
  66. data/ext/gqlitedb/src/tests/parser.rs +54 -23
  67. data/ext/gqlitedb/src/tests/planner.rs +511 -0
  68. data/ext/gqlitedb/src/tests/store/postgres.rs +7 -0
  69. data/ext/gqlitedb/src/tests/store/redb.rs +8 -0
  70. data/ext/gqlitedb/src/tests/store/sqlite.rs +8 -0
  71. data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +182 -0
  72. data/ext/gqlitedb/src/tests/store/vector_index/redb.rs +386 -0
  73. data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +166 -0
  74. data/ext/gqlitedb/src/tests/store/vector_index.rs +2313 -0
  75. data/ext/gqlitedb/src/tests/store.rs +78 -14
  76. data/ext/gqlitedb/src/tests/templates/ast.rs +92 -16
  77. data/ext/gqlitedb/src/tests/templates/programs.rs +14 -7
  78. data/ext/gqlitedb/src/tests.rs +15 -9
  79. data/ext/gqlitedb/src/utils.rs +6 -1
  80. data/ext/gqlitedb/src/value/compare.rs +61 -3
  81. data/ext/gqlitedb/src/value.rs +136 -7
  82. data/ext/gqlitedb/templates/sql/postgres/metadata_delete.sql +1 -0
  83. data/ext/gqlitedb/templates/sql/postgres/node_select.sql +1 -1
  84. data/ext/gqlitedb/templates/sql/sqlite/metadata_delete.sql +1 -0
  85. data/ext/gqliterb/src/lib.rs +53 -8
  86. data/ext/gqlparser/Cargo.toml +25 -0
  87. data/ext/gqlparser/README.MD +9 -0
  88. data/ext/gqlparser/benches/pokec_divan.rs +34 -0
  89. data/ext/gqlparser/src/common.rs +69 -0
  90. data/ext/gqlparser/src/gqls/ast.rs +69 -0
  91. data/ext/gqlparser/src/gqls/constraint.rs +79 -0
  92. data/ext/gqlparser/src/gqls/error.rs +22 -0
  93. data/ext/gqlparser/src/gqls/parser.rs +813 -0
  94. data/ext/gqlparser/src/gqls/prelude.rs +8 -0
  95. data/ext/gqlparser/src/gqls/properties.rs +115 -0
  96. data/ext/gqlparser/src/gqls/resolve.rs +207 -0
  97. data/ext/gqlparser/src/gqls.rs +265 -0
  98. data/ext/gqlparser/src/lib.rs +7 -0
  99. data/ext/gqlparser/src/oc/ast.rs +680 -0
  100. data/ext/gqlparser/src/oc/error.rs +172 -0
  101. data/ext/gqlparser/src/oc/lexer.rs +429 -0
  102. data/ext/gqlparser/src/oc/parser/tests.rs +2284 -0
  103. data/ext/gqlparser/src/oc/parser.rs +2005 -0
  104. data/ext/gqlparser/src/oc.rs +33 -0
  105. data/ext/gqlparser/src/prelude.rs +3 -0
  106. data/ext/graphcore/Cargo.toml +1 -0
  107. data/ext/graphcore/src/error.rs +26 -0
  108. data/ext/graphcore/src/graph.rs +177 -51
  109. data/ext/graphcore/src/lib.rs +4 -2
  110. data/ext/graphcore/src/open_cypher.rs +12 -0
  111. data/ext/graphcore/src/table.rs +50 -2
  112. data/ext/graphcore/src/timestamp.rs +127 -104
  113. data/ext/graphcore/src/value/tensor.rs +739 -0
  114. data/ext/graphcore/src/value/value_map.rs +1 -1
  115. data/ext/graphcore/src/value.rs +343 -19
  116. metadata +93 -28
  117. data/ext/gqlitedb/src/parser/ast.rs +0 -604
  118. data/ext/gqlitedb/src/parser/parser_impl.rs +0 -1213
  119. data/ext/gqlitedb/src/parser.rs +0 -4
@@ -7,6 +7,10 @@ mod redb;
7
7
  #[cfg(feature = "sqlite")]
8
8
  pub(crate) mod sqlite;
9
9
 
10
+ mod vector_index;
11
+
12
+ use graphcore::Edge;
13
+
10
14
  use crate::{
11
15
  prelude::*,
12
16
  store::{SelectNodeQuery, TransactionBoxable},
@@ -95,11 +99,13 @@ where
95
99
  // Add two nodes
96
100
  let nodes = [
97
101
  graph::Node::new(
102
+ Some("default".to_string()),
98
103
  graph::Key::default(),
99
104
  graph::labels!("hello", "world"),
100
105
  value::value_map!("key" => 42i64),
101
106
  ),
102
107
  graph::Node::new(
108
+ Some("default".to_string()),
103
109
  graph::Key::default(),
104
110
  graph::labels!("not"),
105
111
  Default::default(),
@@ -139,12 +145,58 @@ where
139
145
  assert_eq!(nodes[1], selected_nodes[0]);
140
146
  }
141
147
 
148
+ fn test_select_nodes_by_uuids<TStore>(store: TStore)
149
+ where
150
+ TStore: store::Store,
151
+ {
152
+ let nodes = [
153
+ graph::Node::new(
154
+ Some("default".to_string()),
155
+ graph::Key::default(),
156
+ graph::labels!("node", "a"),
157
+ value::value_map!("name" => "Alice", "age" => 30i64),
158
+ ),
159
+ graph::Node::new(
160
+ Some("default".to_string()),
161
+ graph::Key::default(),
162
+ graph::labels!("node", "b"),
163
+ value::value_map!("name" => "Bob", "age" => 25i64),
164
+ ),
165
+ graph::Node::new(
166
+ Some("default".to_string()),
167
+ graph::Key::default(),
168
+ graph::labels!("node", "c"),
169
+ value::value_map!("name" => "Charlie", "age" => 35i64),
170
+ ),
171
+ ];
172
+
173
+ let mut tx = store.begin_write().unwrap();
174
+ store
175
+ .create_nodes(tx.borrow_mut(), "default", nodes.iter())
176
+ .unwrap();
177
+ tx.close().unwrap();
178
+
179
+ let selected_nodes = store
180
+ .select_nodes(
181
+ store.begin_read().unwrap().borrow_mut(),
182
+ "default",
183
+ store::SelectNodeQuery::select_keys(vec![nodes[0].key(), nodes[2].key()]),
184
+ )
185
+ .unwrap();
186
+
187
+ assert_eq!(selected_nodes.len(), 2);
188
+ assert!(selected_nodes.contains(&nodes[0]));
189
+ assert!(selected_nodes.contains(&nodes[2]));
190
+ assert!(!selected_nodes.contains(&nodes[1]));
191
+ }
192
+
142
193
  fn test_update_nodes<TStore>(store: TStore)
143
194
  where
144
195
  TStore: store::Store,
145
196
  {
146
197
  // Add a node
147
198
  let node = graph::Node::new(
199
+ None,
148
200
  graph::Key::default(),
149
201
  graph::labels!("hello", "world"),
150
202
  value::value_map!("key" => 42i64),
@@ -162,6 +214,7 @@ where
162
214
 
163
215
  // Modify node
164
216
  let modified_node = graph::Node::new(
217
+ Some("default".to_string()),
165
218
  node.key(),
166
219
  graph::labels!("world"),
167
220
  value::value_map!("key" => 12i64),
@@ -204,20 +257,25 @@ where
204
257
  TStore: store::Store,
205
258
  {
206
259
  let source_node = graph::Node::new(
260
+ Some("default".to_string()),
207
261
  graph::Key::default(),
208
262
  graph::labels!("hello"),
209
263
  value::value_map!("key" => 42i64),
210
264
  );
211
265
  let destination_node = graph::Node::new(
266
+ Some("default".to_string()),
212
267
  graph::Key::default(),
213
268
  graph::labels!("world"),
214
269
  value::value_map!("key" => 12i64),
215
270
  );
216
271
  let edge = graph::SinglePath::new(
217
- graph::Key::default(),
218
272
  source_node.clone(),
219
- vec!["!".into()],
220
- value::value_map!("existence" => true),
273
+ Edge::new(
274
+ Some("default".to_string()),
275
+ Default::default(),
276
+ vec!["!".into()],
277
+ value::value_map!("existence" => true),
278
+ ),
221
279
  destination_node.clone(),
222
280
  );
223
281
 
@@ -248,7 +306,7 @@ where
248
306
  store.begin_read().unwrap().borrow_mut(),
249
307
  "default",
250
308
  store::SelectEdgeQuery::select_keys([edge.key()]),
251
- graph::EdgeDirectivity::Directed,
309
+ graphcore::EdgeDirectivity::Directed,
252
310
  )
253
311
  .unwrap();
254
312
 
@@ -266,7 +324,7 @@ where
266
324
  Default::default(),
267
325
  store::SelectNodeQuery::select_all(),
268
326
  ),
269
- graph::EdgeDirectivity::Directed,
327
+ graphcore::EdgeDirectivity::Directed,
270
328
  )
271
329
  .unwrap();
272
330
 
@@ -284,7 +342,7 @@ where
284
342
  Default::default(),
285
343
  store::SelectNodeQuery::select_labels_properties(vec![], Default::default()),
286
344
  ),
287
- graph::EdgeDirectivity::Directed,
345
+ graphcore::EdgeDirectivity::Directed,
288
346
  )
289
347
  .unwrap();
290
348
 
@@ -303,7 +361,7 @@ where
303
361
  Default::default(),
304
362
  store::SelectNodeQuery::select_keys(vec![edge.source().key()]),
305
363
  ),
306
- graph::EdgeDirectivity::Directed,
364
+ graphcore::EdgeDirectivity::Directed,
307
365
  )
308
366
  .unwrap();
309
367
 
@@ -319,7 +377,7 @@ where
319
377
  Default::default(),
320
378
  store::SelectNodeQuery::select_keys(vec![edge.source().key()]),
321
379
  ),
322
- graph::EdgeDirectivity::Undirected,
380
+ graphcore::EdgeDirectivity::Undirected,
323
381
  )
324
382
  .unwrap();
325
383
 
@@ -333,20 +391,25 @@ where
333
391
  TStore: store::Store,
334
392
  {
335
393
  let source_node = graph::Node::new(
394
+ None,
336
395
  graph::Key::default(),
337
396
  graph::labels!("hello"),
338
397
  value::value_map!("key" => 42i64),
339
398
  );
340
399
  let destination_node = graph::Node::new(
400
+ None,
341
401
  graph::Key::default(),
342
402
  graph::labels!("world"),
343
403
  value::value_map!("key" => 12i64),
344
404
  );
345
405
  let edge = graph::SinglePath::new(
346
- graph::Key::default(),
347
406
  source_node.clone(),
348
- vec!["!".into()],
349
- value::value_map!("existence" => true),
407
+ graph::Edge::new(
408
+ None,
409
+ Default::default(),
410
+ vec!["!".into()],
411
+ value::value_map!("existence" => true),
412
+ ),
350
413
  destination_node.clone(),
351
414
  );
352
415
 
@@ -376,6 +439,7 @@ where
376
439
  // Modify edge
377
440
 
378
441
  let modified_edge = graph::Edge::new(
442
+ Some("default".to_string()),
379
443
  edge.key(),
380
444
  graph::labels!("?"),
381
445
  value::value_map!("existence" => false),
@@ -392,7 +456,7 @@ where
392
456
  store.begin_read().unwrap().borrow_mut(),
393
457
  "default",
394
458
  store::SelectEdgeQuery::select_all(),
395
- graph::EdgeDirectivity::Directed,
459
+ graphcore::EdgeDirectivity::Directed,
396
460
  )
397
461
  .unwrap();
398
462
 
@@ -410,7 +474,7 @@ where
410
474
  &mut tx,
411
475
  "default",
412
476
  store::SelectEdgeQuery::select_all(),
413
- graph::EdgeDirectivity::Directed,
477
+ graphcore::EdgeDirectivity::Directed,
414
478
  )
415
479
  .unwrap();
416
480
  tx.close().unwrap();
@@ -421,7 +485,7 @@ where
421
485
  store.begin_read().unwrap().borrow_mut(),
422
486
  "default",
423
487
  store::SelectEdgeQuery::select_all(),
424
- graph::EdgeDirectivity::Directed,
488
+ graphcore::EdgeDirectivity::Directed,
425
489
  )
426
490
  .unwrap();
427
491
 
@@ -1,4 +1,4 @@
1
- use crate::{graph::EdgeDirectivity, parser::ast::*};
1
+ use gqlparser::oc::ast::*;
2
2
 
3
3
  fn return_statement(var_id: VariableIdentifier) -> Statement
4
4
  {
@@ -20,14 +20,16 @@ fn return_statement(var_id: VariableIdentifier) -> Statement
20
20
 
21
21
  pub(crate) fn simple_create_node() -> Statements
22
22
  {
23
- vec![Create {
24
- patterns: vec![Pattern::Node(NodePattern {
25
- variable: None,
26
- labels: LabelExpression::None,
27
- properties: None,
28
- })],
29
- }
30
- .into()]
23
+ vec![
24
+ Create {
25
+ patterns: vec![Pattern::Node(NodePattern {
26
+ variable: None,
27
+ labels: LabelExpression::None,
28
+ properties: None,
29
+ })],
30
+ }
31
+ .into(),
32
+ ]
31
33
  }
32
34
 
33
35
  /// AST for `CREATE (n {name: 'foo'}) RETURN n.name AS p`
@@ -234,10 +236,12 @@ pub(crate) fn match_loop() -> Statements
234
236
  },
235
237
  labels: LabelExpression::None,
236
238
  properties: None,
237
- directivity: EdgeDirectivity::Directed,
239
+ directivity: graphcore::EdgeDirectivity::Directed,
240
+ recursive_range: None,
238
241
  })],
239
242
  where_expression: None,
240
243
  optional: false,
244
+ search: None,
241
245
  }
242
246
  .into(),
243
247
  return_statement(var_ids.create_variable_from_name("n")),
@@ -257,6 +261,7 @@ pub(crate) fn optional_match() -> Statements
257
261
  })],
258
262
  where_expression: None,
259
263
  optional: true,
264
+ search: None,
260
265
  }
261
266
  .into(),
262
267
  return_statement(var_ids.create_variable_from_name("a")),
@@ -276,6 +281,7 @@ pub(crate) fn match_count() -> Statements
276
281
  })],
277
282
  where_expression: None,
278
283
  optional: false,
284
+ search: None,
279
285
  }
280
286
  .into(),
281
287
  Return {
@@ -312,6 +318,7 @@ pub(crate) fn aggregation() -> Statements
312
318
  })],
313
319
  where_expression: None,
314
320
  optional: false,
321
+ search: None,
315
322
  }
316
323
  .into(),
317
324
  Return {
@@ -332,14 +339,16 @@ pub(crate) fn aggregation() -> Statements
332
339
  identifier: var_ids.create_variable_from_name("count(n.num)"),
333
340
  expression: FunctionCall {
334
341
  name: "count".into(),
335
- arguments: vec![MemberAccess {
336
- left: Variable {
337
- identifier: var_ids.create_variable_from_name("n"),
342
+ arguments: vec![
343
+ MemberAccess {
344
+ left: Variable {
345
+ identifier: var_ids.create_variable_from_name("n"),
346
+ }
347
+ .into(),
348
+ path: vec!["num".into()],
338
349
  }
339
350
  .into(),
340
- path: vec!["num".into()],
341
- }
342
- .into()],
351
+ ],
343
352
  }
344
353
  .into(),
345
354
  },
@@ -354,3 +363,70 @@ pub(crate) fn aggregation() -> Statements
354
363
  .into(),
355
364
  ]
356
365
  }
366
+
367
+ /// AST for `CREATE VECTOR INDEX idx ON :Doc (embedding) OPTIONS { dimension: 3, metric: "cosine" }`
368
+ pub(crate) fn create_vector_index(name: &str) -> Statements
369
+ {
370
+ vec![
371
+ CreateVectorIndex {
372
+ name: name.to_string(),
373
+ label: "Doc".to_string(),
374
+ property: "embedding".to_string(),
375
+ dimension: Some(3),
376
+ metric: Some(Metric::Cosine),
377
+ if_not_exists: false,
378
+ }
379
+ .into(),
380
+ ]
381
+ }
382
+
383
+ /// AST for `MATCH (n:Doc) SEARCH n IN (VECTOR INDEX idx FOR [0.1, 0.2, 0.3] LIMIT 2) RETURN n.title`
384
+ pub(crate) fn match_with_vector_search(index_name: &str) -> Statements
385
+ {
386
+ let var_ids = VariableIdentifiers::default();
387
+ let n = var_ids.create_variable_from_name("n");
388
+ vec![
389
+ Match {
390
+ patterns: vec![Pattern::Node(NodePattern {
391
+ variable: Some(n.clone()),
392
+ labels: LabelExpression::String("Doc".to_string()),
393
+ properties: None,
394
+ })],
395
+ where_expression: None,
396
+ optional: false,
397
+ search: Some(Search {
398
+ variable: n.clone(),
399
+ index: index_name.to_string(),
400
+ query: Array {
401
+ array: vec![
402
+ Value { value: 0.1.into() }.into(),
403
+ Value { value: 0.2.into() }.into(),
404
+ Value { value: 0.3.into() }.into(),
405
+ ],
406
+ }
407
+ .into(),
408
+ limit: 2,
409
+ score_alias: None,
410
+ }),
411
+ }
412
+ .into(),
413
+ Return {
414
+ all: false,
415
+ expressions: vec![NamedExpression {
416
+ identifier: var_ids.create_variable_from_name("p"),
417
+ expression: MemberAccess {
418
+ left: Variable { identifier: n }.into(),
419
+ path: vec!["title".into()],
420
+ }
421
+ .into(),
422
+ }],
423
+ modifiers: Modifiers {
424
+ skip: None,
425
+ limit: None,
426
+ order_by: None,
427
+ },
428
+ where_expression: None,
429
+ }
430
+ .into(),
431
+ ]
432
+ }
@@ -1,8 +1,8 @@
1
+ use graphcore::EdgeDirectivity;
2
+
1
3
  use crate::{
2
- error, functions,
3
- graph::EdgeDirectivity,
4
- interpreter::{instructions::*, Program},
5
- ValueMap,
4
+ ValueMap, error, functions,
5
+ interpreter::{Program, instructions::*},
6
6
  };
7
7
 
8
8
  fn create_variable_size(persistent_variables: usize, temporary_variables: usize) -> VariablesSizes
@@ -25,7 +25,7 @@ pub(crate) fn simple_create() -> Program
25
25
  labels: Default::default(),
26
26
  },
27
27
  ],
28
- variables: vec![None],
28
+ variables: vec![CreateActionVariable::default()],
29
29
  }],
30
30
  variables_size: create_variable_size(0, 0),
31
31
  }]
@@ -47,7 +47,10 @@ pub(crate) fn create_named_node() -> Program
47
47
  labels: Default::default(),
48
48
  },
49
49
  ],
50
- variables: vec![Some(0)],
50
+ variables: vec![CreateActionVariable {
51
+ element: Some(0),
52
+ path: None,
53
+ }],
51
54
  }],
52
55
  variables_size: create_variable_size(1, 0),
53
56
  },
@@ -94,7 +97,10 @@ pub(crate) fn create_named_node_double_return() -> Program
94
97
  labels: Default::default(),
95
98
  },
96
99
  ],
97
- variables: vec![Some(0)],
100
+ variables: vec![CreateActionVariable {
101
+ element: Some(0),
102
+ path: None,
103
+ }],
98
104
  }],
99
105
  variables_size: create_variable_size(1, 0),
100
106
  },
@@ -265,6 +271,7 @@ pub(crate) fn match_loop() -> Program
265
271
  path_variable: None,
266
272
  filter: vec![],
267
273
  directivity: EdgeDirectivity::Directed,
274
+ recursive_range: None,
268
275
  }],
269
276
  filter: vec![],
270
277
  optional: false,
@@ -2,14 +2,15 @@ mod compiler;
2
2
  mod connection;
3
3
  mod evaluators;
4
4
  mod parser;
5
+ mod planner;
5
6
  mod store;
6
7
  mod templates;
7
8
 
8
9
  #[cfg(all(feature = "postgres", not(windows)))]
9
10
  pub(crate) mod postgres
10
11
  {
12
+ use postgres::{Client, NoTls};
11
13
  use std::{
12
- net::TcpStream,
13
14
  process::Command,
14
15
  thread::sleep,
15
16
  time::{Duration, Instant},
@@ -31,20 +32,25 @@ pub(crate) mod postgres
31
32
 
32
33
  const MAX_WAIT: Duration = Duration::from_secs(30);
33
34
  const INTERVAL: Duration = Duration::from_secs(1);
34
- const CONNECT_TIMEOUT: Duration = Duration::from_secs(1);
35
35
 
36
36
  let deadline = Instant::now() + MAX_WAIT;
37
37
 
38
38
  while Instant::now() < deadline
39
39
  {
40
- if TcpStream::connect_timeout(
41
- &format!("127.0.0.1:{}", db.db_port()).parse().unwrap(),
42
- CONNECT_TIMEOUT,
43
- )
44
- .is_ok()
40
+ match Client::connect(&db.connection_string(), NoTls)
45
41
  {
46
- println!("Port {} is open!", db.db_port());
47
- break;
42
+ Ok(mut client) =>
43
+ {
44
+ if client.simple_query("SELECT 1").is_ok()
45
+ {
46
+ log::info!("Postgres is ready!");
47
+ break;
48
+ }
49
+ }
50
+ Err(err) =>
51
+ {
52
+ log::debug!("Postgres not ready yet: {}", err);
53
+ }
48
54
  }
49
55
  sleep(INTERVAL);
50
56
  }
@@ -2,9 +2,10 @@ use std::fmt::{Debug, Display};
2
2
 
3
3
  use serde::{Deserialize, Serialize};
4
4
 
5
+ #[cfg(feature = "sqlite")]
5
6
  use crate::prelude::*;
6
7
 
7
- #[derive(Serialize, Deserialize)]
8
+ #[derive(Serialize, Deserialize, PartialEq, Eq)]
8
9
  pub struct Version
9
10
  {
10
11
  pub major: u16,
@@ -29,6 +30,7 @@ impl Display for Version
29
30
  }
30
31
  }
31
32
 
33
+ #[cfg(feature = "sqlite")]
32
34
  pub(crate) fn hex(key: impl Into<graph::Key>) -> String
33
35
  {
34
36
  format!("{:032X}", key.into().uuid())
@@ -37,7 +39,10 @@ pub(crate) fn hex(key: impl Into<graph::Key>) -> String
37
39
  #[cfg(test)]
38
40
  mod tests
39
41
  {
42
+ #[cfg(feature = "sqlite")]
40
43
  use crate::prelude::*;
44
+
45
+ #[cfg(feature = "sqlite")]
41
46
  #[test]
42
47
  fn test_hex()
43
48
  {
@@ -73,6 +73,11 @@ fn compare_node(lhs: &graph::Node, rhs: &graph::Node) -> Ordering
73
73
  lhs.key().uuid().cmp(&rhs.key().uuid()).into()
74
74
  }
75
75
 
76
+ fn compare_edge(lhs: &graph::Edge, rhs: &graph::Edge) -> Ordering
77
+ {
78
+ lhs.key().uuid().cmp(&rhs.key().uuid()).into()
79
+ }
80
+
76
81
  pub(crate) fn compare(lhs: &value::Value, rhs: &value::Value) -> Ordering
77
82
  {
78
83
  use value::Value;
@@ -117,6 +122,33 @@ pub(crate) fn compare(lhs: &value::Value, rhs: &value::Value) -> Ordering
117
122
  Value::Null => Ordering::ComparedNull,
118
123
  _ => Ordering::Null,
119
124
  },
125
+ Value::Tensor(al) => match rhs
126
+ {
127
+ value::Value::Tensor(ar) => match (al.dtype() as u8).cmp(&(ar.dtype() as u8))
128
+ {
129
+ cmp::Ordering::Less => Ordering::Less,
130
+ cmp::Ordering::Greater => Ordering::Greater,
131
+ cmp::Ordering::Equal => match al.shape().cmp(ar.shape())
132
+ {
133
+ cmp::Ordering::Less => Ordering::Less,
134
+ cmp::Ordering::Greater => Ordering::Greater,
135
+ cmp::Ordering::Equal => al.as_bytes().cmp(ar.as_bytes()).into(),
136
+ },
137
+ },
138
+ value::Value::Array(_) =>
139
+ {
140
+ let left_arr = value::Value::Array(
141
+ al.to_f32_vec()
142
+ .into_iter()
143
+ .map(|f| value::Value::Float(f as f64))
144
+ .collect(),
145
+ );
146
+ compare(&left_arr, rhs)
147
+ }
148
+ value::Value::Null => Ordering::ComparedNull,
149
+ _ => Ordering::Null,
150
+ },
151
+
120
152
  Value::Array(al) => match rhs
121
153
  {
122
154
  Value::Array(ar) =>
@@ -183,12 +215,12 @@ pub(crate) fn compare(lhs: &value::Value, rhs: &value::Value) -> Ordering
183
215
  },
184
216
  Value::Edge(lhs) => match rhs
185
217
  {
186
- Value::Edge(rhs) => lhs.key().uuid().cmp(&rhs.key().uuid()).into(),
218
+ Value::Edge(rhs) => compare_edge(lhs, rhs),
187
219
  _ => Ordering::Null,
188
220
  },
189
- Value::Path(lhs) => match rhs
221
+ Value::SinglePath(lhs) => match rhs
190
222
  {
191
- Value::Path(rhs) =>
223
+ Value::SinglePath(rhs) =>
192
224
  {
193
225
  let labels_cmp = lhs.labels().cmp(rhs.labels());
194
226
  match labels_cmp
@@ -207,5 +239,31 @@ pub(crate) fn compare(lhs: &value::Value, rhs: &value::Value) -> Ordering
207
239
  }
208
240
  _ => Ordering::Null,
209
241
  },
242
+ Value::Path(lhs) => match rhs
243
+ {
244
+ Value::Path(rhs) => match compare_node(lhs.source(), rhs.source())
245
+ {
246
+ Ordering::Equal =>
247
+ {
248
+ for ((lhs_edge, lhs_destination), (rhs_edge, rhs_destination)) in
249
+ lhs.elements().iter().zip(rhs.elements().iter())
250
+ {
251
+ match compare_edge(lhs_edge, rhs_edge)
252
+ {
253
+ Ordering::Equal => match compare_node(lhs_destination, rhs_destination)
254
+ {
255
+ Ordering::Equal =>
256
+ {}
257
+ o => return o,
258
+ },
259
+ o => return o,
260
+ }
261
+ }
262
+ Ordering::Equal
263
+ }
264
+ o => o,
265
+ },
266
+ _ => Ordering::Null,
267
+ },
210
268
  }
211
269
  }