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.
- checksums.yaml +4 -4
- data/ext/Cargo.toml +12 -6
- data/ext/db-index/Cargo.toml +29 -0
- data/ext/db-index/src/hnsw/error.rs +66 -0
- data/ext/db-index/src/hnsw/graph_store.rs +272 -0
- data/ext/db-index/src/hnsw/id.rs +36 -0
- data/ext/db-index/src/hnsw/implementation.rs +1517 -0
- data/ext/db-index/src/hnsw/kernels.rs +1228 -0
- data/ext/db-index/src/hnsw/metric.rs +244 -0
- data/ext/db-index/src/hnsw/scalar.rs +72 -0
- data/ext/db-index/src/hnsw/simple_store.rs +140 -0
- data/ext/db-index/src/hnsw/store.rs +472 -0
- data/ext/db-index/src/hnsw/vector.rs +105 -0
- data/ext/db-index/src/hnsw/vectors.rs +568 -0
- data/ext/db-index/src/hnsw.rs +42 -0
- data/ext/db-index/src/lib.rs +3 -0
- data/ext/gqlitedb/Cargo.toml +19 -8
- data/ext/gqlitedb/benches/common/pokec.rs +62 -2
- data/ext/gqlitedb/benches/pokec_divan.rs +66 -2
- data/ext/gqlitedb/benches/pokec_iai.rs +60 -3
- data/ext/gqlitedb/release.toml +2 -2
- data/ext/gqlitedb/src/aggregators/arithmetic.rs +3 -1
- data/ext/gqlitedb/src/aggregators/containers.rs +1 -1
- data/ext/gqlitedb/src/aggregators/stats.rs +21 -12
- data/ext/gqlitedb/src/capi.rs +20 -24
- data/ext/gqlitedb/src/compiler/expression_analyser.rs +28 -20
- data/ext/gqlitedb/src/compiler/variables_manager.rs +104 -38
- data/ext/gqlitedb/src/compiler.rs +506 -227
- data/ext/gqlitedb/src/connection.rs +151 -11
- data/ext/gqlitedb/src/consts.rs +1 -2
- data/ext/gqlitedb/src/error.rs +123 -61
- data/ext/gqlitedb/src/functions/common.rs +64 -0
- data/ext/gqlitedb/src/functions/containers.rs +2 -46
- data/ext/gqlitedb/src/functions/edge.rs +1 -1
- data/ext/gqlitedb/src/functions/math.rs +87 -15
- data/ext/gqlitedb/src/functions/node.rs +1 -1
- data/ext/gqlitedb/src/functions/path.rs +48 -11
- data/ext/gqlitedb/src/functions/scalar.rs +47 -4
- data/ext/gqlitedb/src/functions/string.rs +123 -1
- data/ext/gqlitedb/src/functions/value.rs +1 -1
- data/ext/gqlitedb/src/functions.rs +165 -28
- data/ext/gqlitedb/src/graph.rs +1 -9
- data/ext/gqlitedb/src/interpreter/evaluators.rs +968 -130
- data/ext/gqlitedb/src/interpreter/instructions.rs +39 -2
- data/ext/gqlitedb/src/lib.rs +5 -4
- data/ext/gqlitedb/src/parser/gql.pest +1 -1
- data/ext/gqlitedb/src/planner.rs +329 -0
- data/ext/gqlitedb/src/prelude.rs +3 -3
- data/ext/gqlitedb/src/store/pgrx.rs +1 -1
- data/ext/gqlitedb/src/store/postgres.rs +742 -16
- data/ext/gqlitedb/src/store/redb/hnsw_store.rs +702 -0
- data/ext/gqlitedb/src/store/redb/index.rs +274 -0
- data/ext/gqlitedb/src/store/redb.rs +1268 -113
- data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +28 -0
- data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +103 -0
- data/ext/gqlitedb/src/store/sqlbase.rs +146 -16
- data/ext/gqlitedb/src/store/sqlite.rs +576 -14
- data/ext/gqlitedb/src/store/vector_extract.rs +56 -0
- data/ext/gqlitedb/src/store.rs +140 -29
- data/ext/gqlitedb/src/tests/compiler.rs +207 -10
- data/ext/gqlitedb/src/tests/connection/postgres.rs +38 -3
- data/ext/gqlitedb/src/tests/connection/redb.rs +23 -0
- data/ext/gqlitedb/src/tests/connection/sqlite.rs +31 -0
- data/ext/gqlitedb/src/tests/connection.rs +61 -1
- data/ext/gqlitedb/src/tests/evaluators.rs +162 -7
- data/ext/gqlitedb/src/tests/parser.rs +54 -23
- data/ext/gqlitedb/src/tests/planner.rs +511 -0
- data/ext/gqlitedb/src/tests/store/postgres.rs +7 -0
- data/ext/gqlitedb/src/tests/store/redb.rs +8 -0
- data/ext/gqlitedb/src/tests/store/sqlite.rs +8 -0
- data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +182 -0
- data/ext/gqlitedb/src/tests/store/vector_index/redb.rs +386 -0
- data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +166 -0
- data/ext/gqlitedb/src/tests/store/vector_index.rs +2313 -0
- data/ext/gqlitedb/src/tests/store.rs +78 -14
- data/ext/gqlitedb/src/tests/templates/ast.rs +92 -16
- data/ext/gqlitedb/src/tests/templates/programs.rs +14 -7
- data/ext/gqlitedb/src/tests.rs +15 -9
- data/ext/gqlitedb/src/utils.rs +6 -1
- data/ext/gqlitedb/src/value/compare.rs +61 -3
- data/ext/gqlitedb/src/value.rs +136 -7
- data/ext/gqlitedb/templates/sql/postgres/metadata_delete.sql +1 -0
- data/ext/gqlitedb/templates/sql/postgres/node_select.sql +1 -1
- data/ext/gqlitedb/templates/sql/sqlite/metadata_delete.sql +1 -0
- data/ext/gqliterb/src/lib.rs +53 -8
- data/ext/gqlparser/Cargo.toml +25 -0
- data/ext/gqlparser/README.MD +9 -0
- data/ext/gqlparser/benches/pokec_divan.rs +34 -0
- data/ext/gqlparser/src/common.rs +69 -0
- data/ext/gqlparser/src/gqls/ast.rs +69 -0
- data/ext/gqlparser/src/gqls/constraint.rs +79 -0
- data/ext/gqlparser/src/gqls/error.rs +22 -0
- data/ext/gqlparser/src/gqls/parser.rs +813 -0
- data/ext/gqlparser/src/gqls/prelude.rs +8 -0
- data/ext/gqlparser/src/gqls/properties.rs +115 -0
- data/ext/gqlparser/src/gqls/resolve.rs +207 -0
- data/ext/gqlparser/src/gqls.rs +265 -0
- data/ext/gqlparser/src/lib.rs +7 -0
- data/ext/gqlparser/src/oc/ast.rs +680 -0
- data/ext/gqlparser/src/oc/error.rs +172 -0
- data/ext/gqlparser/src/oc/lexer.rs +429 -0
- data/ext/gqlparser/src/oc/parser/tests.rs +2284 -0
- data/ext/gqlparser/src/oc/parser.rs +2005 -0
- data/ext/gqlparser/src/oc.rs +33 -0
- data/ext/gqlparser/src/prelude.rs +3 -0
- data/ext/graphcore/Cargo.toml +1 -0
- data/ext/graphcore/src/error.rs +26 -0
- data/ext/graphcore/src/graph.rs +177 -51
- data/ext/graphcore/src/lib.rs +4 -2
- data/ext/graphcore/src/open_cypher.rs +12 -0
- data/ext/graphcore/src/table.rs +50 -2
- data/ext/graphcore/src/timestamp.rs +127 -104
- data/ext/graphcore/src/value/tensor.rs +739 -0
- data/ext/graphcore/src/value/value_map.rs +1 -1
- data/ext/graphcore/src/value.rs +343 -19
- metadata +93 -28
- data/ext/gqlitedb/src/parser/ast.rs +0 -604
- data/ext/gqlitedb/src/parser/parser_impl.rs +0 -1213
- 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::{
|
|
5
|
-
use rand::{seq::IndexedRandom
|
|
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
|
|
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
|
|
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);
|
data/ext/gqlitedb/release.toml
CHANGED
|
@@ -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 = "...{{
|
|
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/
|
|
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
|
|
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
|
{
|
|
@@ -26,17 +26,17 @@ impl AggregatorState for AvgState
|
|
|
26
26
|
{
|
|
27
27
|
fn next(&mut self, value: value::Value) -> crate::Result<()>
|
|
28
28
|
{
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
self.value = value;
|
|
32
|
-
}
|
|
33
|
-
else
|
|
29
|
+
match value
|
|
34
30
|
{
|
|
35
|
-
|
|
31
|
+
value::Value::Null => Ok(()),
|
|
32
|
+
value::Value::Integer(i) =>
|
|
36
33
|
{
|
|
37
|
-
value
|
|
38
|
-
{
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
{
|
data/ext/gqlitedb/src/capi.rs
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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::{
|
|
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
|
-
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
158
|
-
self.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
|
-
|
|
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,
|
|
187
|
+
fn new(expression_type: ExpressionType, runtime_constant: bool, aggregation_result: bool)
|
|
188
|
+
-> Self
|
|
181
189
|
{
|
|
182
190
|
Self {
|
|
183
191
|
expression_type,
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
},
|