gqlite 1.2.0 → 1.2.3

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gqliterb/.cargo/config.toml +2 -0
  3. data/ext/gqliterb/Cargo.lock +152 -135
  4. data/ext/gqliterb/Cargo.toml +4 -6
  5. data/ext/gqliterb/src/lib.rs +8 -2
  6. data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2115 -0
  7. data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +138 -0
  8. data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
  9. data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
  10. data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
  11. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
  12. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
  13. data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
  14. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
  15. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
  16. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
  17. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
  18. data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
  19. data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +259 -0
  20. data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +431 -0
  21. data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +621 -0
  22. data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1115 -0
  23. data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +342 -0
  24. data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
  25. data/ext/gqliterb/vendor/gqlitedb/src/error.rs +613 -0
  26. data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
  27. data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
  28. data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
  29. data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
  30. data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +80 -0
  31. data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
  32. data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
  33. data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
  34. data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +410 -0
  35. data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +283 -0
  36. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1776 -0
  37. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +267 -0
  38. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
  39. data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +41 -0
  40. data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +611 -0
  41. data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +196 -0
  42. data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1183 -0
  43. data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
  44. data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
  45. data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
  46. data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
  47. data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1262 -0
  48. data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +1026 -0
  49. data/ext/gqliterb/vendor/gqlitedb/src/store.rs +439 -0
  50. data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
  51. data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
  52. data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
  53. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +46 -0
  54. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +46 -0
  55. data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +470 -0
  56. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
  57. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
  58. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
  59. data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
  60. data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
  61. data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
  62. data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
  63. data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
  64. data/ext/gqliterb/vendor/gqlitedb/src/value.rs +609 -0
  65. data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +610 -0
  66. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
  67. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
  68. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
  69. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
  70. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
  71. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
  72. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
  73. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
  74. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
  75. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
  76. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
  77. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
  78. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
  79. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
  80. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
  81. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
  82. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
  83. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
  84. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
  85. metadata +82 -2
@@ -0,0 +1,138 @@
1
+ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
2
+ #
3
+ # When uploading crates to the registry Cargo will automatically
4
+ # "normalize" Cargo.toml files for maximal compatibility
5
+ # with all versions of Cargo and also rewrite `path` dependencies
6
+ # to registry (e.g., crates.io) dependencies.
7
+ #
8
+ # If you are reading this file be aware that the original Cargo.toml
9
+ # will likely look very different (and much more reasonable).
10
+ # See Cargo.toml.orig for the original contents.
11
+
12
+ [package]
13
+ edition = "2021"
14
+ name = "gqlitedb"
15
+ version = "0.5.3"
16
+ build = false
17
+ autolib = false
18
+ autobins = false
19
+ autoexamples = false
20
+ autotests = false
21
+ autobenches = false
22
+ description = "GQLite is a Rust-language library, with a C interface, that implements a small, fast, self-contained, high-reliability, full-featured, Graph Query database engine."
23
+ homepage = "https://gqlite.org"
24
+ readme = "README.md"
25
+ license = "MIT"
26
+ repository = "https://gitlab.com/gqlite/gqlite"
27
+
28
+ [features]
29
+ _backtrace = []
30
+ _pg13 = ["pgrx/pg13"]
31
+ _pg14 = ["pgrx/pg14"]
32
+ _pg15 = ["pgrx/pg15"]
33
+ _pg16 = ["pgrx/pg16"]
34
+ _pg17 = ["pgrx/pg17"]
35
+ _pgql = ["dep:pgrx"]
36
+ _value_private = []
37
+ capi = []
38
+ default = [
39
+ "redb",
40
+ "capi",
41
+ "sqlite",
42
+ ]
43
+ redb = ["dep:redb"]
44
+ sqlite = [
45
+ "dep:rusqlite",
46
+ "dep:askama",
47
+ ]
48
+
49
+ [lib]
50
+ name = "gqlitedb"
51
+ crate-type = [
52
+ "cdylib",
53
+ "lib",
54
+ ]
55
+ path = "src/lib.rs"
56
+
57
+ [[bench]]
58
+ name = "pokec_divan"
59
+ path = "benches/pokec_divan.rs"
60
+ harness = false
61
+
62
+ [[bench]]
63
+ name = "pokec_iai"
64
+ path = "benches/pokec_iai.rs"
65
+ harness = false
66
+
67
+ [dependencies.askama]
68
+ version = "0.14"
69
+ optional = true
70
+
71
+ [dependencies.ccutils]
72
+ version = "0.3"
73
+ features = [
74
+ "sync",
75
+ "pool",
76
+ ]
77
+
78
+ [dependencies.ciborium]
79
+ version = "0.2"
80
+
81
+ [dependencies.itertools]
82
+ version = "0.14"
83
+
84
+ [dependencies.pest]
85
+ version = "2"
86
+
87
+ [dependencies.pest_derive]
88
+ version = "2"
89
+
90
+ [dependencies.pgrx]
91
+ version = "0.15"
92
+ optional = true
93
+
94
+ [dependencies.rand]
95
+ version = "0.9"
96
+
97
+ [dependencies.redb]
98
+ version = "2"
99
+ optional = true
100
+
101
+ [dependencies.rusqlite]
102
+ version = "0.37"
103
+ features = [
104
+ "functions",
105
+ "uuid",
106
+ ]
107
+ optional = true
108
+ package = "rusqlite"
109
+
110
+ [dependencies.serde]
111
+ version = "1"
112
+
113
+ [dependencies.serde_json]
114
+ version = "1"
115
+
116
+ [dependencies.thiserror]
117
+ version = "2"
118
+
119
+ [dependencies.uuid]
120
+ version = "1"
121
+ features = ["v4"]
122
+
123
+ [dev-dependencies.ccutils]
124
+ version = "0.3"
125
+ features = ["temporary"]
126
+
127
+ [dev-dependencies.divan]
128
+ version = "0.1"
129
+
130
+ [dev-dependencies.iai-callgrind]
131
+ version = "0.16"
132
+
133
+ [dev-dependencies.regex]
134
+ version = "1"
135
+
136
+ [target.'cfg(target_arch = "wasm32")'.dependencies.uuid]
137
+ version = "1"
138
+ features = ["js"]
@@ -0,0 +1,3 @@
1
+ [[escaper]]
2
+ path = ""
3
+ extensions = ["sql"]
@@ -0,0 +1,25 @@
1
+ pub(crate) mod pokec;
2
+
3
+ pub(crate) fn get_bench_data()
4
+ {
5
+ if std::fs::exists("gqlite_bench_data").unwrap()
6
+ {
7
+ std::process::Command::new("git")
8
+ .arg("pull")
9
+ .spawn()
10
+ .unwrap()
11
+ .wait()
12
+ .unwrap();
13
+ }
14
+ else
15
+ {
16
+ std::process::Command::new("git")
17
+ .arg("clone")
18
+ .arg("https://gitlab.com/auksys/data/gqlite_bench.git")
19
+ .arg("gqlite_bench_data")
20
+ .spawn()
21
+ .unwrap()
22
+ .wait()
23
+ .unwrap();
24
+ }
25
+ }
@@ -0,0 +1,185 @@
1
+ use std::{collections::HashSet, fs};
2
+
3
+ use ccutils::temporary::TemporaryFile;
4
+ use gqlitedb::{map, Connection};
5
+ use rand::{seq::IndexedRandom, Rng};
6
+ use regex::Regex;
7
+
8
+ pub(crate) struct Pokec
9
+ {
10
+ #[allow(dead_code)]
11
+ temporary_file: TemporaryFile,
12
+ connection: Connection,
13
+ ids: Vec<i64>,
14
+ }
15
+
16
+ #[allow(dead_code)]
17
+ pub(crate) enum PokecSize
18
+ {
19
+ Micro,
20
+ Tiny,
21
+ }
22
+
23
+ impl Pokec
24
+ {
25
+ pub(crate) fn load(backend: &str, size: PokecSize) -> Pokec
26
+ {
27
+ let temporary_file = TemporaryFile::builder()
28
+ .should_create_file(false)
29
+ .label("gqlite_bench")
30
+ .create();
31
+ let connection = Connection::open(temporary_file.path(), map!("backend" => backend)).unwrap();
32
+
33
+ let filename = match size
34
+ {
35
+ PokecSize::Micro => "gqlite_bench_data/pokec_micro_import.cypher",
36
+ PokecSize::Tiny => "gqlite_bench_data/pokec_tiny_import.cypher",
37
+ };
38
+
39
+ let import_query = fs::read_to_string(filename).unwrap();
40
+
41
+ connection
42
+ .execute_query(import_query, Default::default())
43
+ .unwrap();
44
+ Self {
45
+ temporary_file,
46
+ connection,
47
+ ids: Default::default(),
48
+ }
49
+ }
50
+ pub(crate) fn read_ids(mut self) -> Self
51
+ {
52
+ let re = Regex::new(r"id:\s*(\d+)").unwrap();
53
+ let mut ids = HashSet::new();
54
+ let content = fs::read_to_string("gqlite_bench_data/pokec_tiny_import.cypher")
55
+ .expect("Failed to read the file");
56
+ for cap in re.captures_iter(&content)
57
+ {
58
+ if let Some(id_match) = cap.get(1)
59
+ {
60
+ let id = id_match.as_str().parse::<i64>().unwrap();
61
+ ids.insert(id);
62
+ }
63
+ }
64
+ self.ids = ids.into_iter().collect();
65
+ self
66
+ }
67
+ pub(crate) fn single_vertex<R>(&self, rng: &mut R)
68
+ where
69
+ R: Rng + ?Sized,
70
+ {
71
+ let random_id = self.ids.choose(rng).unwrap();
72
+ self
73
+ .connection
74
+ .execute_query(
75
+ "MATCH (n:User {id: $id}) RETURN n",
76
+ map!("$id" => *random_id),
77
+ )
78
+ .unwrap();
79
+ }
80
+ pub(crate) fn single_vertex_where<R>(&self, rng: &mut R)
81
+ where
82
+ R: Rng + ?Sized,
83
+ {
84
+ let random_id = self.ids.choose(rng).unwrap();
85
+ self
86
+ .connection
87
+ .execute_query(
88
+ "MATCH (n:User) WHERE n.id = $id RETURN n",
89
+ map!("$id" => *random_id),
90
+ )
91
+ .unwrap();
92
+ }
93
+ pub(crate) fn friend_of<R>(&self, rng: &mut R)
94
+ where
95
+ R: Rng + ?Sized,
96
+ {
97
+ let random_id = self.ids.choose(rng).unwrap();
98
+ self
99
+ .connection
100
+ .execute_query(
101
+ "MATCH (s:User {id: $id})-->(n:User) RETURN n.id",
102
+ map!("$id" => *random_id),
103
+ )
104
+ .unwrap();
105
+ }
106
+ pub(crate) fn friend_of_filter<R>(&self, rng: &mut R)
107
+ where
108
+ R: Rng + ?Sized,
109
+ {
110
+ let random_id = self.ids.choose(rng).unwrap();
111
+ self
112
+ .connection
113
+ .execute_query(
114
+ "MATCH (s:User {id: $id})-->(n:User) WHERE n.age >= 18 RETURN n.id",
115
+ map!("$id" => *random_id),
116
+ )
117
+ .unwrap();
118
+ }
119
+ pub(crate) fn friend_of_friend_of<R>(&self, rng: &mut R)
120
+ where
121
+ R: Rng + ?Sized,
122
+ {
123
+ let random_id = self.ids.choose(rng).unwrap();
124
+ self
125
+ .connection
126
+ .execute_query(
127
+ "MATCH (s:User {id: $id})-->()-->(n:User) RETURN n.id",
128
+ map!("$id" => *random_id),
129
+ )
130
+ .unwrap();
131
+ }
132
+ pub(crate) fn friend_of_friend_of_filter<R>(&self, rng: &mut R)
133
+ where
134
+ R: Rng + ?Sized,
135
+ {
136
+ let random_id = self.ids.choose(rng).unwrap();
137
+ self
138
+ .connection
139
+ .execute_query(
140
+ "MATCH (s:User {id: $id})-->()-->(n:User) WHERE n.age >= 18 RETURN n.id",
141
+ map!("$id" => *random_id),
142
+ )
143
+ .unwrap();
144
+ }
145
+ pub(crate) fn reciprocal_friends<R>(&self, rng: &mut R)
146
+ where
147
+ R: Rng + ?Sized,
148
+ {
149
+ let random_id = self.ids.choose(rng).unwrap();
150
+ self
151
+ .connection
152
+ .execute_query(
153
+ "MATCH (n:User {id: $id})-[e1]->(m)-[e2]->(n) RETURN e1, m, e2",
154
+ map!("$id" => *random_id),
155
+ )
156
+ .unwrap();
157
+ }
158
+ pub(crate) fn aggregate_count(&self)
159
+ {
160
+ self
161
+ .connection
162
+ .execute_query("MATCH (n:User) RETURN n.age, count(*)", Default::default())
163
+ .unwrap();
164
+ }
165
+ pub(crate) fn aggregate_count_filter(&self)
166
+ {
167
+ self
168
+ .connection
169
+ .execute_query(
170
+ "MATCH (n:User) WHERE n.age >= 18 RETURN n.age, count(*)",
171
+ Default::default(),
172
+ )
173
+ .unwrap();
174
+ }
175
+ pub(crate) fn aggregate_min_max_avg(&self)
176
+ {
177
+ self
178
+ .connection
179
+ .execute_query(
180
+ "MATCH (n) RETURN min(n.age), max(n.age), avg(n.age)",
181
+ Default::default(),
182
+ )
183
+ .unwrap();
184
+ }
185
+ }
@@ -0,0 +1,137 @@
1
+ use divan::Bencher;
2
+ use rand::{rngs::StdRng, SeedableRng};
3
+
4
+ mod common;
5
+
6
+ use common::pokec::{Pokec, PokecSize};
7
+
8
+ const FRIEND_OF_COUNT: u32 = 100;
9
+ const SINGLE_VERTEX_COUNT: u32 = 100;
10
+ const IMPORT_COUNT: u32 = 30;
11
+
12
+ fn main()
13
+ {
14
+ common::get_bench_data();
15
+
16
+ // Run registered benchmarks.
17
+ divan::main();
18
+ }
19
+
20
+ fn load_pokec(backend: &str) -> Pokec
21
+ {
22
+ Pokec::load(backend, PokecSize::Tiny)
23
+ }
24
+
25
+ // Import the tiny `pokec` dataset.
26
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = IMPORT_COUNT)]
27
+ fn import_tiny_pokec(backend: &str)
28
+ {
29
+ let _ = load_pokec(backend);
30
+ }
31
+
32
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = SINGLE_VERTEX_COUNT)]
33
+ fn single_vertex(bencher: Bencher, backend: &str)
34
+ {
35
+ let tiny_pokec = load_pokec(backend).read_ids();
36
+ let mut rng = StdRng::seed_from_u64(991173);
37
+
38
+ bencher.bench_local(move || {
39
+ tiny_pokec.single_vertex(&mut rng);
40
+ });
41
+ }
42
+
43
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = SINGLE_VERTEX_COUNT)]
44
+ fn single_vertex_where(bencher: Bencher, backend: &str)
45
+ {
46
+ let tiny_pokec = load_pokec(backend).read_ids();
47
+ let mut rng = StdRng::seed_from_u64(991173);
48
+
49
+ bencher.bench_local(move || {
50
+ tiny_pokec.single_vertex_where(&mut rng);
51
+ });
52
+ }
53
+
54
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
55
+ fn friend_of(bencher: Bencher, backend: &str)
56
+ {
57
+ let tiny_pokec = load_pokec(backend).read_ids();
58
+ let mut rng = StdRng::seed_from_u64(991173);
59
+
60
+ bencher.bench_local(move || {
61
+ tiny_pokec.friend_of(&mut rng);
62
+ });
63
+ }
64
+
65
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
66
+ fn friend_of_filter(bencher: Bencher, backend: &str)
67
+ {
68
+ let tiny_pokec = load_pokec(backend).read_ids();
69
+ let mut rng = StdRng::seed_from_u64(991173);
70
+
71
+ bencher.bench_local(move || {
72
+ tiny_pokec.friend_of_filter(&mut rng);
73
+ });
74
+ }
75
+
76
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
77
+ fn friend_of_friend_of(bencher: Bencher, backend: &str)
78
+ {
79
+ let tiny_pokec = load_pokec(backend).read_ids();
80
+ let mut rng = StdRng::seed_from_u64(991173);
81
+
82
+ bencher.bench_local(move || {
83
+ tiny_pokec.friend_of_friend_of(&mut rng);
84
+ });
85
+ }
86
+
87
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
88
+ fn friend_of_friend_of_filter(bencher: Bencher, backend: &str)
89
+ {
90
+ let tiny_pokec = load_pokec(backend).read_ids();
91
+ let mut rng = StdRng::seed_from_u64(991173);
92
+
93
+ bencher.bench_local(move || {
94
+ tiny_pokec.friend_of_friend_of_filter(&mut rng);
95
+ });
96
+ }
97
+
98
+ #[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
99
+ fn reciprocal_friends(bencher: Bencher, backend: &str)
100
+ {
101
+ let tiny_pokec = load_pokec(backend).read_ids();
102
+ let mut rng = StdRng::seed_from_u64(991173);
103
+
104
+ bencher.bench_local(move || {
105
+ tiny_pokec.reciprocal_friends(&mut rng);
106
+ });
107
+ }
108
+
109
+ #[divan::bench(args = ["sqlite", "redb"])]
110
+ fn aggregate_count(bencher: Bencher, backend: &str)
111
+ {
112
+ let tiny_pokec = load_pokec(backend);
113
+
114
+ bencher.bench_local(move || {
115
+ tiny_pokec.aggregate_count();
116
+ });
117
+ }
118
+
119
+ #[divan::bench(args = ["sqlite", "redb"])]
120
+ fn aggregate_count_filter(bencher: Bencher, backend: &str)
121
+ {
122
+ let tiny_pokec = load_pokec(backend);
123
+
124
+ bencher.bench_local(move || {
125
+ tiny_pokec.aggregate_count_filter();
126
+ });
127
+ }
128
+
129
+ #[divan::bench(args = ["sqlite", "redb"])]
130
+ fn aggregate_min_max_avg(bencher: Bencher, backend: &str)
131
+ {
132
+ let tiny_pokec = load_pokec(backend);
133
+
134
+ bencher.bench_local(move || {
135
+ tiny_pokec.aggregate_min_max_avg();
136
+ });
137
+ }
@@ -0,0 +1,122 @@
1
+ use std::hint::black_box;
2
+
3
+ use iai_callgrind::{library_benchmark, library_benchmark_group, main};
4
+ use rand::{rngs::StdRng, SeedableRng};
5
+
6
+ mod common;
7
+
8
+ use common::pokec::{Pokec, PokecSize};
9
+
10
+ fn load_pokec(backend: &str) -> Pokec
11
+ {
12
+ Pokec::load(backend, PokecSize::Micro)
13
+ }
14
+
15
+ fn load_with_ids(backend: &str) -> Pokec
16
+ {
17
+ load_pokec(backend).read_ids()
18
+ }
19
+
20
+ #[library_benchmark]
21
+ #[bench::redb("redb")]
22
+ #[bench::sqlite("sqlite")]
23
+ fn import_micro_pokec(backend: &str)
24
+ {
25
+ black_box(load_pokec(backend));
26
+ }
27
+
28
+ #[library_benchmark(setup = load_with_ids)]
29
+ #[bench::redb("redb")]
30
+ #[bench::sqlite("sqlite")]
31
+ fn single_vertex(micro_pokec: Pokec)
32
+ {
33
+ let mut rng = StdRng::seed_from_u64(991173);
34
+ micro_pokec.single_vertex(&mut rng);
35
+ }
36
+
37
+ #[library_benchmark(setup = load_with_ids)]
38
+ #[bench::redb("redb")]
39
+ #[bench::sqlite("sqlite")]
40
+ fn single_vertex_where(micro_pokec: Pokec)
41
+ {
42
+ let mut rng = StdRng::seed_from_u64(991173);
43
+ micro_pokec.single_vertex_where(&mut rng);
44
+ }
45
+
46
+ #[library_benchmark(setup = load_with_ids)]
47
+ #[bench::redb("redb")]
48
+ #[bench::sqlite("sqlite")]
49
+ fn friend_of(micro_pokec: Pokec)
50
+ {
51
+ let mut rng = StdRng::seed_from_u64(991173);
52
+ micro_pokec.friend_of(&mut rng);
53
+ }
54
+
55
+ #[library_benchmark(setup = load_with_ids)]
56
+ #[bench::redb("redb")]
57
+ #[bench::sqlite("sqlite")]
58
+ fn friend_of_filter(micro_pokec: Pokec)
59
+ {
60
+ let mut rng = StdRng::seed_from_u64(991173);
61
+ micro_pokec.friend_of_filter(&mut rng);
62
+ }
63
+
64
+ #[library_benchmark(setup = load_with_ids)]
65
+ #[bench::redb("redb")]
66
+ #[bench::sqlite("sqlite")]
67
+ fn friend_of_friend_of(micro_pokec: Pokec)
68
+ {
69
+ let mut rng = StdRng::seed_from_u64(991173);
70
+ micro_pokec.friend_of_friend_of(&mut rng);
71
+ }
72
+
73
+ #[library_benchmark(setup = load_with_ids)]
74
+ #[bench::redb("redb")]
75
+ #[bench::sqlite("sqlite")]
76
+ fn friend_of_friend_of_filter(micro_pokec: Pokec)
77
+ {
78
+ let mut rng = StdRng::seed_from_u64(991173);
79
+ micro_pokec.friend_of_friend_of_filter(&mut rng);
80
+ }
81
+
82
+ #[library_benchmark(setup = load_with_ids)]
83
+ #[bench::redb("redb")]
84
+ #[bench::sqlite("sqlite")]
85
+ fn reciprocal_friends(micro_pokec: Pokec)
86
+ {
87
+ let mut rng = StdRng::seed_from_u64(991173);
88
+ micro_pokec.reciprocal_friends(&mut rng);
89
+ }
90
+
91
+ #[library_benchmark(setup = load_pokec)]
92
+ #[bench::redb("redb")]
93
+ #[bench::sqlite("sqlite")]
94
+ fn aggregate_count(micro_pokec: Pokec)
95
+ {
96
+ micro_pokec.aggregate_count();
97
+ }
98
+
99
+ #[library_benchmark(setup = load_pokec)]
100
+ #[bench::redb("redb")]
101
+ #[bench::sqlite("sqlite")]
102
+ fn aggregate_count_filter(micro_pokec: Pokec)
103
+ {
104
+ micro_pokec.aggregate_count_filter();
105
+ }
106
+
107
+ #[library_benchmark(setup = load_pokec)]
108
+ #[bench::redb("redb")]
109
+ #[bench::sqlite("sqlite")]
110
+ fn aggregate_min_max_avg(micro_pokec: Pokec)
111
+ {
112
+ micro_pokec.aggregate_min_max_avg();
113
+ }
114
+
115
+ library_benchmark_group!(
116
+ name = bench_micro_pokec_group;
117
+ 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
118
+ );
119
+
120
+ main!(
121
+ setup = common::get_bench_data();
122
+ library_benchmark_groups = bench_micro_pokec_group);
@@ -0,0 +1,7 @@
1
+ pre-release-replacements = [
2
+ { file = "../../CHANGELOG.md", search = "Unreleased", replace = "{{version}}" },
3
+ { file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/1", replace = "...{{tag_name}}", exactly = 1 },
4
+ { file = "../../CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" },
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 },
7
+ ]
@@ -0,0 +1,96 @@
1
+ use std::fmt::Debug;
2
+
3
+ use super::AggregatorState;
4
+
5
+ use crate::{error::RunTimeError, value::Value, Result};
6
+
7
+ trait Op
8
+ {
9
+ fn op_i64(a: i64, b: i64) -> i64;
10
+ fn op_f64(a: f64, b: f64) -> f64;
11
+ }
12
+
13
+ #[derive(Debug)]
14
+ struct OpState<T>
15
+ where
16
+ T: Op + Debug,
17
+ {
18
+ value: Value,
19
+ _marker: std::marker::PhantomData<T>,
20
+ }
21
+
22
+ impl<T> OpState<T>
23
+ where
24
+ T: Op + Debug,
25
+ {
26
+ fn new() -> Result<Self>
27
+ {
28
+ Ok(Self {
29
+ value: Value::Null,
30
+ _marker: Default::default(),
31
+ })
32
+ }
33
+ }
34
+
35
+ impl<T> AggregatorState for OpState<T>
36
+ where
37
+ T: Op + Debug,
38
+ {
39
+ fn next(&mut self, value: Value) -> crate::Result<()>
40
+ {
41
+ match self.value
42
+ {
43
+ Value::Boolean(..)
44
+ | Value::Node(..)
45
+ | Value::Edge(..)
46
+ | Value::Array(..)
47
+ | Value::String(..)
48
+ | Value::Map(..)
49
+ | Value::Path(..) => Err(RunTimeError::InvalidBinaryOperands)?,
50
+ Value::Null =>
51
+ {
52
+ self.value = value;
53
+ }
54
+ Value::Float(state) => match value
55
+ {
56
+ Value::Null =>
57
+ {}
58
+ Value::Float(new_value) => self.value = T::op_f64(state, new_value).into(),
59
+ Value::Integer(new_value) => self.value = T::op_f64(state, new_value as f64).into(),
60
+ _ => Err(RunTimeError::InvalidBinaryOperands)?,
61
+ },
62
+ Value::Integer(state) => match value
63
+ {
64
+ Value::Null =>
65
+ {}
66
+ Value::Float(new_value) => self.value = T::op_f64(state as f64, new_value).into(),
67
+ Value::Integer(new_value) => self.value = T::op_i64(state, new_value).into(),
68
+ _ => Err(RunTimeError::InvalidBinaryOperands)?,
69
+ },
70
+ }
71
+ Ok(())
72
+ }
73
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
74
+ {
75
+ Ok(self.value)
76
+ }
77
+ }
78
+
79
+ #[derive(Debug)]
80
+ struct SumOp;
81
+
82
+ impl Op for SumOp
83
+ {
84
+ fn op_f64(a: f64, b: f64) -> f64
85
+ {
86
+ a + b
87
+ }
88
+ fn op_i64(a: i64, b: i64) -> i64
89
+ {
90
+ a + b
91
+ }
92
+ }
93
+
94
+ type SumState = OpState<SumOp>;
95
+
96
+ super::declare_aggregator!(sum, Sum, SumState, () -> i64);