gqlite 1.3.0 → 1.4.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +4 -3
  3. data/ext/gqlitedb/Cargo.toml +7 -4
  4. data/ext/gqlitedb/src/aggregators/arithmetic.rs +1 -0
  5. data/ext/gqlitedb/src/compiler/expression_analyser.rs +2 -0
  6. data/ext/gqlitedb/src/compiler.rs +31 -19
  7. data/ext/gqlitedb/src/connection.rs +42 -7
  8. data/ext/gqlitedb/src/error.rs +3 -0
  9. data/ext/gqlitedb/src/functions/containers.rs +1 -1
  10. data/ext/gqlitedb/src/functions/path.rs +1 -1
  11. data/ext/gqlitedb/src/functions/scalar.rs +23 -0
  12. data/ext/gqlitedb/src/functions.rs +8 -0
  13. data/ext/gqlitedb/src/interpreter/evaluators.rs +10 -10
  14. data/ext/gqlitedb/src/interpreter/instructions.rs +3 -3
  15. data/ext/gqlitedb/src/lib.rs +1 -3
  16. data/ext/gqlitedb/src/parser/ast.rs +1 -0
  17. data/ext/gqlitedb/src/parser/gql.pest +3 -1
  18. data/ext/gqlitedb/src/parser/parser_impl.rs +8 -0
  19. data/ext/gqlitedb/src/prelude.rs +3 -0
  20. data/ext/gqlitedb/src/store/{pgql.rs → pgrx.rs} +2 -0
  21. data/ext/gqlitedb/src/store/postgres.rs +0 -0
  22. data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +117 -0
  23. data/ext/gqlitedb/src/store/sqlbase/sqlqueries.rs +62 -0
  24. data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +55 -0
  25. data/ext/gqlitedb/src/store/sqlbase/sqlvalue.rs +189 -0
  26. data/ext/gqlitedb/src/store/sqlbase.rs +456 -0
  27. data/ext/gqlitedb/src/store/sqlite.rs +271 -573
  28. data/ext/gqlitedb/src/store.rs +7 -5
  29. data/ext/gqlitedb/src/tests/templates/programs.rs +10 -10
  30. data/ext/gqlitedb/src/utils.rs +25 -0
  31. data/ext/gqlitedb/src/value/compare.rs +6 -0
  32. data/ext/gqlitedb/src/value.rs +18 -2
  33. data/ext/gqlitedb/templates/sql/sqlite/edge_select.sql +18 -18
  34. data/ext/gqlitedb/templates/sql/sqlite/edge_update.sql +3 -3
  35. data/ext/gqlitedb/templates/sql/sqlite/node_select.sql +6 -6
  36. data/ext/gqlitedb/templates/sql/sqlite/node_update.sql +3 -3
  37. data/ext/gqliterb/src/lib.rs +30 -2
  38. data/ext/graphcore/Cargo.toml +3 -2
  39. data/ext/graphcore/src/error.rs +2 -0
  40. data/ext/graphcore/src/lib.rs +2 -1
  41. data/ext/graphcore/src/prelude.rs +1 -1
  42. data/ext/graphcore/src/table.rs +1 -1
  43. data/ext/graphcore/src/timestamp.rs +104 -0
  44. data/ext/graphcore/src/value.rs +106 -23
  45. metadata +10 -7
  46. data/ext/gqlitedb/gqlite_bench_data/README.MD +0 -6
  47. data/ext/gqlitedb/gqlite_bench_data/scripts/generate_smaller_pokec.rb +0 -85
  48. data/ext/gqlitedb/gqlite_bench_data/scripts/to_efficient_pokec.rb +0 -34
  49. data/ext/graphcore/release.toml +0 -1
@@ -8,6 +8,7 @@ use std::{
8
8
  mod value_map;
9
9
 
10
10
  pub(crate) use crate::prelude::*;
11
+ use crate::TimeStamp;
11
12
 
12
13
  pub use value_map::ValueMap;
13
14
 
@@ -33,6 +34,8 @@ pub enum Value
33
34
  Float(f64),
34
35
  /// String value.
35
36
  String(String),
37
+ /// Timestamp value
38
+ TimeStamp(timestamp::TimeStamp),
36
39
  /// Array of values.
37
40
  Array(Vec<Value>),
38
41
  /// Unordered map of values.
@@ -97,6 +100,7 @@ impl Hash for Value
97
100
  bits.hash(state);
98
101
  }
99
102
  Value::String(s) => s.hash(state),
103
+ Value::TimeStamp(ts) => ts.hash(state),
100
104
  Value::Array(a) => a.hash(state),
101
105
  Value::Map(m) => m.hash(state),
102
106
  Value::Node(n) => n.hash(state),
@@ -118,6 +122,7 @@ impl Add for Value
118
122
  | Value::Node(..)
119
123
  | Value::Edge(..)
120
124
  | Value::Map(..)
125
+ | Value::TimeStamp(..)
121
126
  | Value::Path(..) => Err(Error::InvalidBinaryOperands),
122
127
  Value::Null => Ok(Value::Null),
123
128
  Self::Array(lhs) => match rhs
@@ -171,6 +176,7 @@ macro_rules! impl_mdsr {
171
176
  Value::Boolean(..)
172
177
  | Value::Key(..)
173
178
  | Value::String(..)
179
+ | Value::TimeStamp(..)
174
180
  | Value::Node(..)
175
181
  | Value::Edge(..)
176
182
  | Value::Array(..)
@@ -212,6 +218,7 @@ impl Value
212
218
  Value::Boolean(..)
213
219
  | Value::Key(..)
214
220
  | Value::String(..)
221
+ | Value::TimeStamp(..)
215
222
  | Value::Node(..)
216
223
  | Value::Edge(..)
217
224
  | Value::Array(..)
@@ -255,6 +262,7 @@ impl Neg for Value
255
262
  | Value::String(..)
256
263
  | Value::Node(..)
257
264
  | Value::Edge(..)
265
+ | Value::TimeStamp(..)
258
266
  | Value::Array(..)
259
267
  | Value::Map(..)
260
268
  | Value::Path(..) => Err(Error::InvalidNegationOperands),
@@ -274,6 +282,7 @@ impl std::fmt::Display for Value
274
282
  Value::Integer(i) => write!(f, "{}", i),
275
283
  Value::Float(fl) => write!(f, "{}", fl),
276
284
  Value::String(s) => write!(f, "{}", s),
285
+ Value::TimeStamp(t) => write!(f, "{}", t),
277
286
  Value::Array(v) => write!(f, "[{}]", v.iter().map(|x| x.to_string()).join(", ")),
278
287
  Value::Map(o) => write!(f, "{}", o),
279
288
  Value::Node(n) => write!(f, "{}", n),
@@ -298,7 +307,42 @@ impl ValueTryIntoRef<Value> for Value
298
307
  }
299
308
  }
300
309
 
301
- macro_rules! impl_to_value {
310
+ impl<T> From<Option<T>> for Value
311
+ where
312
+ Value: From<T>,
313
+ {
314
+ fn from(value: Option<T>) -> Self
315
+ {
316
+ match value
317
+ {
318
+ Some(value) => value.into(),
319
+ None => Value::Null,
320
+ }
321
+ }
322
+ }
323
+
324
+ macro_rules! impl_from_value {
325
+ ($type:ty, $vn:tt, try) => {
326
+ impl_from_value!($type, $vn);
327
+ impl TryFrom<Value> for $type
328
+ {
329
+ type Error = Error;
330
+ fn try_from(value: Value) -> Result<$type, Self::Error>
331
+ {
332
+ match value
333
+ {
334
+ Value::$vn(v) => Ok(v),
335
+ _ => Err(
336
+ Error::InvalidValueCast {
337
+ value: Box::new(value),
338
+ typename: stringify!($type),
339
+ }
340
+ .into(),
341
+ ),
342
+ }
343
+ }
344
+ }
345
+ };
302
346
  ($type:ty, $vn:tt) => {
303
347
  impl From<$type> for Value
304
348
  {
@@ -315,25 +359,38 @@ macro_rules! impl_to_value {
315
359
  Value::Array(v.into_iter().map(|v| v.into()).collect())
316
360
  }
317
361
  }
318
- impl TryInto<$type> for Value
362
+ impl TryFrom<&Value> for $type
319
363
  {
320
364
  type Error = Error;
321
- fn try_into(self) -> Result<$type, Self::Error>
365
+ fn try_from(value: &Value) -> Result<$type, Self::Error>
322
366
  {
323
- match self
367
+ <$type>::try_from(value.to_owned())
368
+ }
369
+ }
370
+ impl TryFrom<Value> for Option<$type>
371
+ {
372
+ type Error = Error;
373
+ fn try_from(value: Value) -> Result<Self>
374
+ {
375
+ match value
324
376
  {
325
- Value::$vn(v) => Ok(v),
326
- _ => Err(
327
- Error::InvalidValueCast {
328
- value: Box::new(self),
329
- typename: stringify!($type),
330
- }
331
- .into(),
332
- ),
377
+ Value::Null => Ok(None),
378
+ _ =>
379
+ {
380
+ let t: $type = value.try_into()?;
381
+ Ok(Some(t))
382
+ }
333
383
  }
334
384
  }
335
385
  }
336
-
386
+ impl TryFrom<&Value> for Option<$type>
387
+ {
388
+ type Error = Error;
389
+ fn try_from(value: &Value) -> Result<Option<$type>, Self::Error>
390
+ {
391
+ <Option<$type>>::try_from(value.to_owned())
392
+ }
393
+ }
337
394
  impl ValueTryIntoRef<$type> for Value
338
395
  {
339
396
  fn try_into_ref(&self) -> Result<&$type, Error>
@@ -354,16 +411,42 @@ macro_rules! impl_to_value {
354
411
  };
355
412
  }
356
413
 
357
- impl_to_value!(graph::Key, Key);
358
- impl_to_value!(bool, Boolean);
359
- impl_to_value!(i64, Integer);
360
- impl_to_value!(f64, Float);
361
- impl_to_value!(String, String);
362
- impl_to_value!(graph::Node, Node);
363
- impl_to_value!(graph::Edge, Edge);
364
- impl_to_value!(graph::SinglePath, Path);
365
- impl_to_value!(Vec<Value>, Array);
366
- impl_to_value!(ValueMap, Map);
414
+ impl_from_value!(graph::Key, Key, try);
415
+ impl_from_value!(bool, Boolean, try);
416
+ impl_from_value!(i64, Integer, try);
417
+ impl_from_value!(f64, Float, try);
418
+ impl_from_value!(String, String, try);
419
+ impl_from_value!(TimeStamp, TimeStamp);
420
+ impl_from_value!(graph::Node, Node, try);
421
+ impl_from_value!(graph::Edge, Edge, try);
422
+ impl_from_value!(graph::SinglePath, Path, try);
423
+ impl_from_value!(Vec<Value>, Array, try);
424
+ impl_from_value!(ValueMap, Map, try);
425
+
426
+ impl TryFrom<Value> for TimeStamp
427
+ {
428
+ type Error = Error;
429
+ fn try_from(value: Value) -> Result<TimeStamp, Self::Error>
430
+ {
431
+ match value
432
+ {
433
+ Value::String(s) => Ok(TimeStamp::parse(&s)?),
434
+ Value::TimeStamp(v) => Ok(v),
435
+ _ => Err(Error::InvalidValueCast {
436
+ value: Box::new(value),
437
+ typename: stringify!($type),
438
+ }),
439
+ }
440
+ }
441
+ }
442
+
443
+ impl From<()> for Value
444
+ {
445
+ fn from(_: ()) -> Self
446
+ {
447
+ Self::Null
448
+ }
449
+ }
367
450
 
368
451
  impl From<&str> for Value
369
452
  {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gqlite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyrille Berger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-01 00:00:00.000000000 Z
11
+ date: 2025-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys
@@ -69,9 +69,6 @@ files:
69
69
  - ext/gqlitedb/benches/common/pokec.rs
70
70
  - ext/gqlitedb/benches/pokec_divan.rs
71
71
  - ext/gqlitedb/benches/pokec_iai.rs
72
- - ext/gqlitedb/gqlite_bench_data/README.MD
73
- - ext/gqlitedb/gqlite_bench_data/scripts/generate_smaller_pokec.rb
74
- - ext/gqlitedb/gqlite_bench_data/scripts/to_efficient_pokec.rb
75
72
  - ext/gqlitedb/release.toml
76
73
  - ext/gqlitedb/src/aggregators.rs
77
74
  - ext/gqlitedb/src/aggregators/arithmetic.rs
@@ -106,8 +103,14 @@ files:
106
103
  - ext/gqlitedb/src/prelude.rs
107
104
  - ext/gqlitedb/src/query_result.rs
108
105
  - ext/gqlitedb/src/store.rs
109
- - ext/gqlitedb/src/store/pgql.rs
106
+ - ext/gqlitedb/src/store/pgrx.rs
107
+ - ext/gqlitedb/src/store/postgres.rs
110
108
  - ext/gqlitedb/src/store/redb.rs
109
+ - ext/gqlitedb/src/store/sqlbase.rs
110
+ - ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs
111
+ - ext/gqlitedb/src/store/sqlbase/sqlqueries.rs
112
+ - ext/gqlitedb/src/store/sqlbase/sqlstore.rs
113
+ - ext/gqlitedb/src/store/sqlbase/sqlvalue.rs
111
114
  - ext/gqlitedb/src/store/sqlite.rs
112
115
  - ext/gqlitedb/src/tests.rs
113
116
  - ext/gqlitedb/src/tests/compiler.rs
@@ -148,13 +151,13 @@ files:
148
151
  - ext/gqliterb/src/lib.rs
149
152
  - ext/graphcore/Cargo.toml
150
153
  - ext/graphcore/README.MD
151
- - ext/graphcore/release.toml
152
154
  - ext/graphcore/src/error.rs
153
155
  - ext/graphcore/src/graph.rs
154
156
  - ext/graphcore/src/lib.rs
155
157
  - ext/graphcore/src/prelude.rs
156
158
  - ext/graphcore/src/serialize_with.rs
157
159
  - ext/graphcore/src/table.rs
160
+ - ext/graphcore/src/timestamp.rs
158
161
  - ext/graphcore/src/value.rs
159
162
  - ext/graphcore/src/value/value_map.rs
160
163
  - lib/gqlite.rb
@@ -1,6 +0,0 @@
1
- ![GQLite logo](logo.png) GQLite Benchnark Data
2
- ==============================================
3
-
4
- This repository includes data used to benchmark GQLite.
5
-
6
- * `pokec_tiny_nodes.cypher` is a subset of the [pokec mini](https://github.com/memgraph/memgraph/tree/master/tests/mgbench#pokec) dataset ([original](https://snap.stanford.edu/data/soc-Pokec.html)).
@@ -1,85 +0,0 @@
1
- # Script that reduces the pokec dataset, to reduce it to a subset of users.
2
- # It also reduce the initial set of queries into a single one.
3
- #
4
- # Use as:
5
- # ```bash
6
- # ruby reduce_pokec.rb size input.cypher > output.cypher
7
- # ```
8
-
9
- require 'set'
10
-
11
- size = ARGV[0] or abort("Usage: ruby #{$0} micro/tiny input.cypher")
12
- input_file = ARGV[1] or abort("Usage: ruby #{$0} micro/tiny input.cypher")
13
-
14
- if size == "tiny"
15
- initial = 5
16
- increments = 2
17
- elsif size == "micro"
18
- initial = 1
19
- increments = 1
20
- else
21
- abort("Unknown size '#{size}', should be 'tiny' or 'micro'")
22
- end
23
-
24
- user_lines = {}
25
- all_edges = []
26
- edges_by_user = Hash.new { |h, k| h[k] = [] }
27
- selected_edges = []
28
- seen_edges = Set.new
29
- selected_users = Set.new
30
-
31
- def edge_key(id1, id2)
32
- [id1, id2].sort.join('-')
33
- end
34
-
35
- File.foreach(input_file) do |line|
36
- if line =~ /CREATE\s+\(:User\s*(\{.*id:\s*(\d+)[^}]*\})\)/i
37
- user_lines[$2.to_i] = $1
38
-
39
- elsif line =~ /MATCH\s+\(n:User\s*\{id:\s*(\d+)\}\),\s*\(m:User\s*\{id:\s*(\d+)\}\).*CREATE.*Friend/i
40
- id1, id2 = $1.to_i, $2.to_i
41
- edge = { line: line, ids: [id1, id2] }
42
- all_edges << edge
43
- edges_by_user[id1] << edge
44
- edges_by_user[id2] << edge
45
- end
46
- end
47
-
48
- # Step 1: Select initial edges
49
- initial_edges = all_edges.take(initial)
50
- initial_edges.each do |edge|
51
- k = edge_key(*edge[:ids])
52
- next if seen_edges.include?(k)
53
-
54
- seen_edges << k
55
- selected_edges << edge
56
- selected_users.merge(edge[:ids])
57
- end
58
-
59
- # Step 2: Find all other edges connected to selected users
60
- for i in 0...increments
61
- for uid in selected_users.clone()
62
- edges_by_user[uid].each do |edge|
63
- k = edge_key(*edge[:ids])
64
- next if seen_edges.include?(k)
65
-
66
- seen_edges << k
67
- selected_edges << edge
68
-
69
- # Add any new user ID to the queue
70
- selected_users.merge(edge[:ids])
71
- end
72
- end
73
- end
74
-
75
- puts "CREATE"
76
- # Output user CREATEs
77
- selected_users.each do |id|
78
- puts " (user_#{id}:User #{user_lines[id]})," if user_lines.key?(id)
79
- end
80
-
81
- # Output edges
82
- selected_edges.each do |edge|
83
- ids = edge[:ids]
84
- puts " (user_#{ids[0]})-[:Friend]->(user_#{ids[1]}),"
85
- end
@@ -1,34 +0,0 @@
1
- # Script that transform the pokec dataset into a more efficient query.
2
- #
3
- # Use as:
4
- # ```bash
5
- # ruby to_efficient_pokec.rb input.cypher > output.cypher
6
- # ```
7
-
8
- require 'set'
9
-
10
- input_file = ARGV[0] or abort("Usage: ruby #{$0} input.cypher")
11
-
12
- user_lines = []
13
- edge_lines = []
14
-
15
- File.foreach(input_file) do |line|
16
- if line =~ /CREATE\s+\(:User\s*(\{.*id:\s*(\d+)[^}]*\})\)/i
17
- user_lines.append({ id: $2.to_i, data: $1})
18
-
19
- elsif line =~ /MATCH\s+\(n:User\s*\{id:\s*(\d+)\}\),\s*\(m:User\s*\{id:\s*(\d+)\}\).*CREATE.*Friend/i
20
- id1, id2 = $1.to_i, $2.to_i
21
- edge_lines.append({ id1: id1, id2: id2 })
22
- end
23
- end
24
-
25
- puts "CREATE"
26
- # Output user CREATEs
27
- user_lines.each do |user|
28
- puts " (user_#{user[:id]}:User #{user[:data]}),"
29
- end
30
-
31
- # Output edges
32
- edge_lines.each do |edge|
33
- puts " (user_#{edge[:id1]})-[:Friend]->(user_#{edge[:id2]}),"
34
- end
@@ -1 +0,0 @@
1
- tag = false