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
@@ -1,8 +1,8 @@
1
1
  use std::{collections::HashSet, fs};
2
2
 
3
3
  use ccutils::temporary::TemporaryFile;
4
- use gqlitedb::{value_map, Connection};
5
- use rand::{seq::IndexedRandom, Rng};
4
+ use gqlitedb::{Connection, value_map};
5
+ use rand::{Rng, seq::IndexedRandom};
6
6
  use regex::Regex;
7
7
 
8
8
  /// Marker trait to keep backend-specific resources alive for the benchmark lifetime.
@@ -244,4 +244,64 @@ impl Pokec
244
244
  )
245
245
  .unwrap();
246
246
  }
247
+ pub(crate) fn scan_limit_1(&self)
248
+ {
249
+ self
250
+ .connection
251
+ .execute_oc_query("MATCH (n:User) RETURN n LIMIT 1", Default::default())
252
+ .unwrap();
253
+ }
254
+ pub(crate) fn scan_limit_10(&self)
255
+ {
256
+ self
257
+ .connection
258
+ .execute_oc_query("MATCH (n:User) RETURN n LIMIT 10", Default::default())
259
+ .unwrap();
260
+ }
261
+ pub(crate) fn scan_limit_100(&self)
262
+ {
263
+ self
264
+ .connection
265
+ .execute_oc_query("MATCH (n:User) RETURN n LIMIT 100", Default::default())
266
+ .unwrap();
267
+ }
268
+ pub(crate) fn recursive_1_2<R>(&self, rng: &mut R)
269
+ where
270
+ R: Rng + ?Sized,
271
+ {
272
+ let random_id = self.ids.choose(rng).unwrap();
273
+ self
274
+ .connection
275
+ .execute_oc_query(
276
+ "MATCH (s:User {id: $id})-[*1..2]->(n:User) RETURN n.id",
277
+ value_map!("$id" => *random_id),
278
+ )
279
+ .unwrap();
280
+ }
281
+ pub(crate) fn recursive_1_3<R>(&self, rng: &mut R)
282
+ where
283
+ R: Rng + ?Sized,
284
+ {
285
+ let random_id = self.ids.choose(rng).unwrap();
286
+ self
287
+ .connection
288
+ .execute_oc_query(
289
+ "MATCH (s:User {id: $id})-[*1..3]->(n:User) RETURN n.id",
290
+ value_map!("$id" => *random_id),
291
+ )
292
+ .unwrap();
293
+ }
294
+ pub(crate) fn recursive_1_2_filter<R>(&self, rng: &mut R)
295
+ where
296
+ R: Rng + ?Sized,
297
+ {
298
+ let random_id = self.ids.choose(rng).unwrap();
299
+ self
300
+ .connection
301
+ .execute_oc_query(
302
+ "MATCH (s:User {id: $id})-[*1..2]->(n:User) WHERE n.age >= 18 RETURN n.id",
303
+ value_map!("$id" => *random_id),
304
+ )
305
+ .unwrap();
306
+ }
247
307
  }
@@ -1,5 +1,5 @@
1
1
  use divan::Bencher;
2
- use rand::{rngs::StdRng, SeedableRng};
2
+ use rand::{SeedableRng, rngs::StdRng};
3
3
 
4
4
  mod common;
5
5
 
@@ -8,6 +8,8 @@ use common::pokec::{Pokec, PokecSize};
8
8
  const FRIEND_OF_COUNT: u32 = 100;
9
9
  const SINGLE_VERTEX_COUNT: u32 = 100;
10
10
  const IMPORT_COUNT: u32 = 30;
11
+ const LIMIT_COUNT: u32 = 200;
12
+ const RECURSIVE_COUNT: u32 = 100;
11
13
 
12
14
  fn main()
13
15
  {
@@ -125,7 +127,6 @@ fn aggregate_count_filter(bencher: Bencher, backend: &str)
125
127
  tiny_pokec.aggregate_count_filter();
126
128
  });
127
129
  }
128
-
129
130
  #[divan::bench(args = ["postgres", "sqlite", "redb"])]
130
131
  fn aggregate_min_max_avg(bencher: Bencher, backend: &str)
131
132
  {
@@ -135,3 +136,66 @@ fn aggregate_min_max_avg(bencher: Bencher, backend: &str)
135
136
  tiny_pokec.aggregate_min_max_avg();
136
137
  });
137
138
  }
139
+
140
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = LIMIT_COUNT)]
141
+ fn scan_limit_1(bencher: Bencher, backend: &str)
142
+ {
143
+ let pokec = load_pokec(backend);
144
+
145
+ bencher.bench_local(move || {
146
+ pokec.scan_limit_1();
147
+ });
148
+ }
149
+
150
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = LIMIT_COUNT)]
151
+ fn scan_limit_10(bencher: Bencher, backend: &str)
152
+ {
153
+ let pokec = load_pokec(backend);
154
+
155
+ bencher.bench_local(move || {
156
+ pokec.scan_limit_10();
157
+ });
158
+ }
159
+
160
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = LIMIT_COUNT)]
161
+ fn scan_limit_100(bencher: Bencher, backend: &str)
162
+ {
163
+ let pokec = load_pokec(backend);
164
+
165
+ bencher.bench_local(move || {
166
+ pokec.scan_limit_100();
167
+ });
168
+ }
169
+
170
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = RECURSIVE_COUNT)]
171
+ fn recursive_1_2(bencher: Bencher, backend: &str)
172
+ {
173
+ let pokec = load_pokec(backend).read_ids();
174
+ let mut rng = StdRng::seed_from_u64(991173);
175
+
176
+ bencher.bench_local(move || {
177
+ pokec.recursive_1_2(&mut rng);
178
+ });
179
+ }
180
+
181
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = RECURSIVE_COUNT)]
182
+ fn recursive_1_3(bencher: Bencher, backend: &str)
183
+ {
184
+ let pokec = load_pokec(backend).read_ids();
185
+ let mut rng = StdRng::seed_from_u64(991173);
186
+
187
+ bencher.bench_local(move || {
188
+ pokec.recursive_1_3(&mut rng);
189
+ });
190
+ }
191
+
192
+ #[divan::bench(args = ["postgres", "sqlite", "redb"], sample_count = RECURSIVE_COUNT)]
193
+ fn recursive_1_2_filter(bencher: Bencher, backend: &str)
194
+ {
195
+ let pokec = load_pokec(backend).read_ids();
196
+ let mut rng = StdRng::seed_from_u64(991173);
197
+
198
+ bencher.bench_local(move || {
199
+ pokec.recursive_1_2_filter(&mut rng);
200
+ });
201
+ }
@@ -1,7 +1,7 @@
1
1
  use std::hint::black_box;
2
2
 
3
3
  use iai_callgrind::{library_benchmark, library_benchmark_group, main};
4
- use rand::{rngs::StdRng, SeedableRng};
4
+ use rand::{SeedableRng, rngs::StdRng};
5
5
 
6
6
  mod common;
7
7
 
@@ -123,11 +123,68 @@ fn aggregate_min_max_avg(micro_pokec: Pokec)
123
123
  micro_pokec.aggregate_min_max_avg();
124
124
  }
125
125
 
126
+ #[library_benchmark(setup = load_pokec)]
127
+ #[bench::postgres("postgres")]
128
+ #[bench::redb("redb")]
129
+ #[bench::sqlite("sqlite")]
130
+ fn scan_limit_1(micro_pokec: Pokec)
131
+ {
132
+ micro_pokec.scan_limit_1();
133
+ }
134
+
135
+ #[library_benchmark(setup = load_pokec)]
136
+ #[bench::postgres("postgres")]
137
+ #[bench::redb("redb")]
138
+ #[bench::sqlite("sqlite")]
139
+ fn scan_limit_10(micro_pokec: Pokec)
140
+ {
141
+ micro_pokec.scan_limit_10();
142
+ }
143
+
144
+ #[library_benchmark(setup = load_pokec)]
145
+ #[bench::postgres("postgres")]
146
+ #[bench::redb("redb")]
147
+ #[bench::sqlite("sqlite")]
148
+ fn scan_limit_100(micro_pokec: Pokec)
149
+ {
150
+ micro_pokec.scan_limit_100();
151
+ }
152
+
153
+ #[library_benchmark(setup = load_with_ids)]
154
+ #[bench::postgres("postgres")]
155
+ #[bench::redb("redb")]
156
+ #[bench::sqlite("sqlite")]
157
+ fn recursive_1_2(micro_pokec: Pokec)
158
+ {
159
+ let mut rng = StdRng::seed_from_u64(991173);
160
+ micro_pokec.recursive_1_2(&mut rng);
161
+ }
162
+
163
+ #[library_benchmark(setup = load_with_ids)]
164
+ #[bench::postgres("postgres")]
165
+ #[bench::redb("redb")]
166
+ #[bench::sqlite("sqlite")]
167
+ fn recursive_1_3(micro_pokec: Pokec)
168
+ {
169
+ let mut rng = StdRng::seed_from_u64(991173);
170
+ micro_pokec.recursive_1_3(&mut rng);
171
+ }
172
+
173
+ #[library_benchmark(setup = load_with_ids)]
174
+ #[bench::postgres("postgres")]
175
+ #[bench::redb("redb")]
176
+ #[bench::sqlite("sqlite")]
177
+ fn recursive_1_2_filter(micro_pokec: Pokec)
178
+ {
179
+ let mut rng = StdRng::seed_from_u64(991173);
180
+ micro_pokec.recursive_1_2_filter(&mut rng);
181
+ }
182
+
126
183
  library_benchmark_group!(
127
184
  name = bench_micro_pokec_group;
128
- benchmarks = import_micro_pokec, single_vertex, single_vertex_where, friend_of, friend_of_filter, friend_of_friend_of, friend_of_friend_of_filter, reciprocal_friends, aggregate_count, aggregate_count_filter, aggregate_min_max_avg
185
+ benchmarks = recursive_1_2, import_micro_pokec, single_vertex, single_vertex_where, friend_of, friend_of_filter, friend_of_friend_of, friend_of_friend_of_filter, reciprocal_friends, aggregate_count, aggregate_count_filter, aggregate_min_max_avg, scan_limit_1, scan_limit_10, scan_limit_100, recursive_1_3, recursive_1_2_filter
129
186
  );
130
187
 
131
188
  main!(
132
- setup = common::get_bench_data();
189
+ setup = common::get_bench_data();
133
190
  library_benchmark_groups = bench_micro_pokec_group);
@@ -1,7 +1,7 @@
1
1
  pre-release-replacements = [
2
2
  { file = "../../CHANGELOG.md", search = "Unreleased", replace = "{{version}}" },
3
- { file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/1", replace = "...{{tag_name}}", exactly = 1 },
3
+ { file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/1", replace = "...gqlitedb-v{{version}}", exactly = 1 },
4
4
  { file = "../../CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" },
5
5
  { file = "../../CHANGELOG.md", search = "<!-- next-header -->", replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate", exactly = 1 },
6
- { file = "../../CHANGELOG.md", search = "<!-- next-url -->", replace = "<!-- next-url -->\n[Unreleased]: https://gitlab.com/gqlite/gqlite/compare/{{tag_name}}...dev/1", exactly = 1 },
6
+ { file = "../../CHANGELOG.md", search = "<!-- next-url -->", replace = "<!-- next-url -->\n[Unreleased]: https://gitlab.com/auksys/gqlite/compare/gqlitedb-v{{version}}...dev/1", exactly = 1 },
7
7
  ]
@@ -2,7 +2,7 @@ use std::fmt::Debug;
2
2
 
3
3
  use super::AggregatorState;
4
4
 
5
- use crate::{error::RunTimeError, value::Value, Result};
5
+ use crate::{Result, error::RunTimeError, value::Value};
6
6
 
7
7
  trait Op
8
8
  {
@@ -45,9 +45,11 @@ where
45
45
  | Value::Node(..)
46
46
  | Value::Edge(..)
47
47
  | Value::Array(..)
48
+ | Value::Tensor(..)
48
49
  | Value::String(..)
49
50
  | Value::TimeStamp(..)
50
51
  | Value::Map(..)
52
+ | Value::SinglePath(..)
51
53
  | Value::Path(..) => Err(RunTimeError::InvalidBinaryOperands)?,
52
54
  Value::Null =>
53
55
  {
@@ -1,6 +1,6 @@
1
1
  use super::AggregatorState;
2
2
 
3
- use crate::{value::Value, Result};
3
+ use crate::{Result, value::Value};
4
4
 
5
5
  #[derive(Debug)]
6
6
  struct CollectState
@@ -26,17 +26,17 @@ impl AggregatorState for AvgState
26
26
  {
27
27
  fn next(&mut self, value: value::Value) -> crate::Result<()>
28
28
  {
29
- if self.value.is_null()
30
- {
31
- self.value = value;
32
- }
33
- else
29
+ match value
34
30
  {
35
- match value
31
+ value::Value::Null => Ok(()),
32
+ value::Value::Integer(i) =>
36
33
  {
37
- value::Value::Null =>
38
- {}
39
- value::Value::Integer(i) =>
34
+ if self.value.is_null()
35
+ {
36
+ self.value = value::Value::Integer(i);
37
+ self.count = 1;
38
+ }
39
+ else
40
40
  {
41
41
  self.count += 1;
42
42
  match self.value
@@ -46,7 +46,16 @@ impl AggregatorState for AvgState
46
46
  _ => Err(InternalError::InvalidAggregationState)?,
47
47
  }
48
48
  }
49
- value::Value::Float(f) =>
49
+ Ok(())
50
+ }
51
+ value::Value::Float(f) =>
52
+ {
53
+ if self.value.is_null()
54
+ {
55
+ self.value = value::Value::Float(f);
56
+ self.count = 1;
57
+ }
58
+ else
50
59
  {
51
60
  self.count += 1;
52
61
  match self.value
@@ -56,10 +65,10 @@ impl AggregatorState for AvgState
56
65
  _ => Err(InternalError::InvalidAggregationState)?,
57
66
  }
58
67
  }
59
- _ => Err(RunTimeError::InvalidArgumentType)?,
68
+ Ok(())
60
69
  }
70
+ _ => Err(RunTimeError::InvalidArgumentType)?,
61
71
  }
62
- Ok(())
63
72
  }
64
73
  fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
65
74
  {
@@ -41,7 +41,7 @@ fn check_error(context: *mut GqliteApiContextT)
41
41
  {
42
42
  let context = unsafe { Box::from_raw(context) };
43
43
  let stri = context.string.to_str().unwrap();
44
- println!("Error message '{stri:?}' was not cleared from context!");
44
+ log::error!("Error message '{stri:?}' was not cleared from context!");
45
45
  let _ = Box::into_raw(context);
46
46
  }
47
47
  }
@@ -65,7 +65,7 @@ pub struct GqliteValueT
65
65
  value: crate::value::Value,
66
66
  }
67
67
 
68
- #[no_mangle]
68
+ #[unsafe(no_mangle)]
69
69
  pub extern "C" fn gqlite_api_context_create() -> *mut GqliteApiContextT
70
70
  {
71
71
  Box::into_raw(Box::new(GqliteApiContextT {
@@ -74,7 +74,7 @@ pub extern "C" fn gqlite_api_context_create() -> *mut GqliteApiContextT
74
74
  }))
75
75
  }
76
76
 
77
- #[no_mangle]
77
+ #[unsafe(no_mangle)]
78
78
  pub extern "C" fn gqlite_api_context_destroy(context: *mut GqliteApiContextT)
79
79
  {
80
80
  unsafe {
@@ -82,7 +82,7 @@ pub extern "C" fn gqlite_api_context_destroy(context: *mut GqliteApiContextT)
82
82
  }
83
83
  }
84
84
 
85
- #[no_mangle]
85
+ #[unsafe(no_mangle)]
86
86
  pub extern "C" fn gqlite_api_context_get_message(
87
87
  context: *mut GqliteApiContextT,
88
88
  ) -> *const std::ffi::c_char
@@ -90,13 +90,13 @@ pub extern "C" fn gqlite_api_context_get_message(
90
90
  unsafe { (*context).string.as_ptr() }
91
91
  }
92
92
 
93
- #[no_mangle]
93
+ #[unsafe(no_mangle)]
94
94
  pub extern "C" fn gqlite_api_context_has_error(context: *mut GqliteApiContextT) -> bool
95
95
  {
96
96
  unsafe { (*context).has_error }
97
97
  }
98
98
 
99
- #[no_mangle]
99
+ #[unsafe(no_mangle)]
100
100
  pub extern "C" fn gqlite_api_context_clear_error(context: *mut GqliteApiContextT)
101
101
  {
102
102
  let mut context = unsafe { Box::from_raw(context) };
@@ -104,7 +104,7 @@ pub extern "C" fn gqlite_api_context_clear_error(context: *mut GqliteApiContextT
104
104
  let _ = Box::into_raw(context);
105
105
  }
106
106
 
107
- #[no_mangle]
107
+ #[unsafe(no_mangle)]
108
108
  pub extern "C" fn gqlite_connection_create_from_file(
109
109
  context: *mut GqliteApiContextT,
110
110
  filename: *const std::ffi::c_char,
@@ -116,22 +116,20 @@ pub extern "C" fn gqlite_connection_create_from_file(
116
116
  let path = unsafe { std::ffi::CStr::from_ptr(filename) };
117
117
 
118
118
  if let Ok(path) = handle_error(context, path.to_str())
119
- {
120
- if let Ok(c) = handle_error(
119
+ && let Ok(c) = handle_error(
121
120
  context,
122
121
  crate::Connection::builder()
123
122
  .options(options.into_map())
124
123
  .path(path)
125
124
  .create(),
126
125
  )
127
- {
128
- return Box::into_raw(Box::new(GqliteConnectionT { connection: c }));
129
- }
126
+ {
127
+ return Box::into_raw(Box::new(GqliteConnectionT { connection: c }));
130
128
  }
131
129
  std::ptr::null::<GqliteConnectionT>() as *mut GqliteConnectionT
132
130
  }
133
131
 
134
- #[no_mangle]
132
+ #[unsafe(no_mangle)]
135
133
  pub extern "C" fn gqlite_connection_create(
136
134
  context: *mut GqliteApiContextT,
137
135
  options: *mut GqliteValueT,
@@ -147,7 +145,7 @@ pub extern "C" fn gqlite_connection_create(
147
145
  std::ptr::null::<GqliteConnectionT>() as *mut GqliteConnectionT
148
146
  }
149
147
 
150
- #[no_mangle]
148
+ #[unsafe(no_mangle)]
151
149
  pub extern "C" fn gqlite_connection_destroy(
152
150
  _context: *mut GqliteApiContextT,
153
151
  connection: *mut GqliteConnectionT,
@@ -158,7 +156,7 @@ pub extern "C" fn gqlite_connection_destroy(
158
156
  }
159
157
  }
160
158
 
161
- #[no_mangle]
159
+ #[unsafe(no_mangle)]
162
160
  pub extern "C" fn gqlite_connection_query(
163
161
  context: *mut GqliteApiContextT,
164
162
  connection: *mut GqliteConnectionT,
@@ -185,7 +183,7 @@ pub extern "C" fn gqlite_connection_query(
185
183
  std::ptr::null::<GqliteValueT>() as *mut GqliteValueT
186
184
  }
187
185
 
188
- #[no_mangle]
186
+ #[unsafe(no_mangle)]
189
187
  pub extern "C" fn gqlite_value_create(context: *mut GqliteApiContextT) -> *mut GqliteValueT
190
188
  {
191
189
  check_error(context);
@@ -194,7 +192,7 @@ pub extern "C" fn gqlite_value_create(context: *mut GqliteApiContextT) -> *mut G
194
192
  }))
195
193
  }
196
194
 
197
- #[no_mangle]
195
+ #[unsafe(no_mangle)]
198
196
  pub extern "C" fn gqlite_value_destroy(context: *mut GqliteApiContextT, value: *mut GqliteValueT)
199
197
  {
200
198
  check_error(context);
@@ -203,7 +201,7 @@ pub extern "C" fn gqlite_value_destroy(context: *mut GqliteApiContextT, value: *
203
201
  }
204
202
  }
205
203
 
206
- #[no_mangle]
204
+ #[unsafe(no_mangle)]
207
205
  pub extern "C" fn gqlite_value_to_json(
208
206
  context: *mut GqliteApiContextT,
209
207
  value: *mut GqliteValueT,
@@ -227,7 +225,7 @@ pub extern "C" fn gqlite_value_to_json(
227
225
  std::ptr::null()
228
226
  }
229
227
 
230
- #[no_mangle]
228
+ #[unsafe(no_mangle)]
231
229
  pub extern "C" fn gqlite_value_from_json(
232
230
  context: *mut GqliteApiContextT,
233
231
  json: *const std::ffi::c_char,
@@ -237,16 +235,14 @@ pub extern "C" fn gqlite_value_from_json(
237
235
 
238
236
  let json = unsafe { std::ffi::CStr::from_ptr(json) };
239
237
  if let Ok(json) = handle_error(context, json.to_str())
238
+ && let Ok(v) = handle_error(context, serde_json::from_str::<crate::value::Value>(json))
240
239
  {
241
- if let Ok(v) = handle_error(context, serde_json::from_str::<crate::value::Value>(json))
242
- {
243
- return Box::into_raw(Box::new(GqliteValueT { value: v }));
244
- }
240
+ return Box::into_raw(Box::new(GqliteValueT { value: v }));
245
241
  }
246
242
  std::ptr::null::<GqliteValueT>() as *mut GqliteValueT
247
243
  }
248
244
 
249
- #[no_mangle]
245
+ #[unsafe(no_mangle)]
250
246
  pub extern "C" fn gqlite_value_is_valid(
251
247
  context: *mut GqliteApiContextT,
252
248
  value: *mut GqliteValueT,
@@ -1,4 +1,6 @@
1
- use crate::{compiler::variables_manager::VariablesManager, parser::ast, prelude::*};
1
+ use gqlparser::oc::ast;
2
+
3
+ use crate::{compiler::variables_manager::VariablesManager, prelude::*};
2
4
 
3
5
  // __ __ _ _ _ _____
4
6
  // \ \ / /_ _ _ __(_) __ _| |__ | | __|_ _| _ _ __ ___
@@ -23,6 +25,8 @@ pub(crate) enum ExpressionType
23
25
  String,
24
26
  TimeStamp,
25
27
  Variant,
28
+ #[expect(dead_code)]
29
+ Tensor,
26
30
  }
27
31
 
28
32
  // _ _ _ _
@@ -34,7 +38,7 @@ pub(crate) enum ExpressionType
34
38
 
35
39
  mod validators
36
40
  {
37
- use crate::{error, Result};
41
+ use crate::{Result, error};
38
42
 
39
43
  use super::{ExpressionInfo, ExpressionType};
40
44
 
@@ -136,15 +140,15 @@ where
136
140
  }
137
141
  }
138
142
 
139
- impl<VT> ExpressionAnalyser for (&ast::Expression, VT)
140
- where
141
- VT: Fn(ExpressionInfo) -> Result<ExpressionInfo>,
142
- {
143
- fn analyse<'b>(self, analyser: &Analyser<'b>) -> Result<Vec<ExpressionInfo>>
144
- {
145
- Ok(vec![self.1(analyser.analyse(self.0)?)?])
146
- }
147
- }
143
+ // impl<VT> ExpressionAnalyser for (&ast::Expression, VT)
144
+ // where
145
+ // VT: Fn(ExpressionInfo) -> Result<ExpressionInfo>,
146
+ // {
147
+ // fn analyse<'b>(self, analyser: &Analyser<'b>) -> Result<Vec<ExpressionInfo>>
148
+ // {
149
+ // Ok(vec![self.1(analyser.analyse(self.0)?)?])
150
+ // }
151
+ // }
148
152
 
149
153
  impl<'a, VT0, VT1> ExpressionAnalyser for ((&'a ast::Expression, &'a ast::Expression), (VT0, VT1))
150
154
  where
@@ -154,8 +158,8 @@ where
154
158
  fn analyse<'b>(self, analyser: &Analyser<'b>) -> Result<Vec<ExpressionInfo>>
155
159
  {
156
160
  Ok(vec![
157
- self.1 .0(analyser.analyse(self.0 .0)?)?,
158
- self.1 .1(analyser.analyse(self.0 .1)?)?,
161
+ self.1.0(analyser.analyse(self.0.0)?)?,
162
+ self.1.1(analyser.analyse(self.0.1)?)?,
159
163
  ])
160
164
  }
161
165
  }
@@ -171,17 +175,21 @@ where
171
175
  pub(crate) struct ExpressionInfo
172
176
  {
173
177
  pub(crate) expression_type: ExpressionType,
174
- pub(crate) constant: bool,
178
+ /// runtime constant indicates a constant that can be evaluated during compilation, but
179
+ /// that might not always be deterministic. For instance, `toInteger(rand()*9)` is such
180
+ /// a contant.
181
+ pub(crate) runtime_constant: bool,
175
182
  pub(crate) aggregation_result: bool,
176
183
  }
177
184
 
178
185
  impl ExpressionInfo
179
186
  {
180
- fn new(expression_type: ExpressionType, constant: bool, aggregation_result: bool) -> Self
187
+ fn new(expression_type: ExpressionType, runtime_constant: bool, aggregation_result: bool)
188
+ -> Self
181
189
  {
182
190
  Self {
183
191
  expression_type,
184
- constant,
192
+ runtime_constant,
185
193
  aggregation_result,
186
194
  }
187
195
  }
@@ -190,7 +198,7 @@ impl ExpressionInfo
190
198
  let dependents = dependents.into();
191
199
  Self {
192
200
  expression_type,
193
- constant: dependents.iter().all(|x| x.constant),
201
+ runtime_constant: dependents.iter().all(|x| x.runtime_constant),
194
202
  aggregation_result: dependents.into_iter().any(|x| x.aggregation_result),
195
203
  }
196
204
  }
@@ -254,8 +262,7 @@ impl<'b> Analyser<'b>
254
262
  &call.name,
255
263
  arguments.iter().map(|x| x.expression_type).collect(),
256
264
  )?,
257
- self.functions_manager.is_deterministic(&call.name)?
258
- && arguments.iter().all(|x| x.constant),
265
+ arguments.iter().all(|x| x.runtime_constant),
259
266
  self.functions_manager.is_aggregate(&call.name)?,
260
267
  ))
261
268
  }
@@ -410,6 +417,7 @@ impl<'b> Analyser<'b>
410
417
  match val.value
411
418
  {
412
419
  value::Value::Array(_) => ExpressionType::Array,
420
+ value::Value::Tensor(_) => ExpressionType::Array,
413
421
  value::Value::Key(_) => ExpressionType::Key,
414
422
  value::Value::Boolean(_) => ExpressionType::Boolean,
415
423
  value::Value::Edge(_) => ExpressionType::Edge,
@@ -418,7 +426,7 @@ impl<'b> Analyser<'b>
418
426
  value::Value::Integer(_) => ExpressionType::Integer,
419
427
  value::Value::Null => ExpressionType::Null,
420
428
  value::Value::Map(_) => ExpressionType::Map,
421
- value::Value::Path(_) => ExpressionType::Path,
429
+ value::Value::SinglePath(_) | value::Value::Path(_) => ExpressionType::Path,
422
430
  value::Value::String(_) => ExpressionType::String,
423
431
  value::Value::TimeStamp(_) => ExpressionType::TimeStamp,
424
432
  },