gqlite 1.2.2 → 1.3.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 +20 -0
- data/ext/gqlitedb/Cargo.toml +77 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/pokec.rs +30 -20
- data/ext/gqlitedb/gqlite_bench_data/README.MD +6 -0
- data/ext/gqlitedb/gqlite_bench_data/scripts/generate_smaller_pokec.rb +85 -0
- data/ext/gqlitedb/gqlite_bench_data/scripts/to_efficient_pokec.rb +34 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/release.toml +2 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/arithmetic.rs +1 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/stats.rs +27 -49
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators.rs +7 -7
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/capi.rs +34 -10
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/expression_analyser.rs +10 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/variables_manager.rs +36 -39
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler.rs +46 -41
- data/ext/gqlitedb/src/connection.rs +300 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/error.rs +113 -50
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/containers.rs +21 -26
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/edge.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/math.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/node.rs +2 -2
- data/ext/gqlitedb/src/functions/path.rs +75 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/scalar.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/string.rs +1 -1
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/value.rs +7 -7
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions.rs +29 -31
- data/ext/gqlitedb/src/graph.rs +11 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/evaluators.rs +178 -224
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/instructions.rs +8 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/lib.rs +9 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/ast.rs +54 -76
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/gql.pest +9 -4
- data/ext/{gqliterb/vendor/gqlitedb/src/parser/parser.rs → gqlitedb/src/parser/parser_impl.rs} +86 -34
- data/ext/gqlitedb/src/parser.rs +4 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/prelude.rs +3 -2
- data/ext/gqlitedb/src/query_result.rs +88 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/redb.rs +260 -170
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/sqlite.rs +157 -142
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store.rs +30 -23
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/evaluators.rs +41 -85
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/redb.rs +12 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/sqlite.rs +12 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store.rs +106 -114
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/ast.rs +29 -29
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/programs.rs +4 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/compare.rs +13 -20
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/contains.rs +2 -2
- data/ext/gqlitedb/src/value.rs +225 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value_table.rs +22 -18
- data/ext/gqliterb/Cargo.toml +12 -34
- data/ext/gqliterb/src/lib.rs +67 -39
- data/ext/graphcore/Cargo.toml +19 -0
- data/ext/graphcore/README.MD +4 -0
- data/ext/graphcore/release.toml +1 -0
- data/ext/graphcore/src/error.rs +28 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/graph.rs +146 -35
- data/ext/graphcore/src/lib.rs +16 -0
- data/ext/graphcore/src/prelude.rs +4 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/serialize_with.rs +2 -2
- data/ext/graphcore/src/table.rs +272 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/value/value_map.rs +44 -49
- data/ext/graphcore/src/value.rs +413 -0
- metadata +94 -83
- data/ext/gqliterb/.cargo/config.toml +0 -2
- data/ext/gqliterb/Cargo.lock +0 -1109
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +0 -2060
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +0 -132
- data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +0 -208
- data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +0 -48
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +0 -4
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +0 -559
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/askama.toml +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/mod.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_divan.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_iai.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/containers.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/count.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/consts.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/mod.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/pgql.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/compiler.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/parser.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/utils.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/call_stats.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_count_for_node.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete_by_nodes.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_select.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_update.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_create_table.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_get.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_set.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_select.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_update.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/table_exists.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/upgrade_from_1_01.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/upgrade_graph_from_1_01.sql +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8b19f14f03ff7f92bf78f132e0c26f800e2d9ce3be108557bb9d23c11e0e8d1
|
4
|
+
data.tar.gz: aad435a97e100195806af926765c90f6c57d1232c51afe771d2b89f00ffa2ea2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe9d202a5b338e34141df0240867a68b4f794067dc506d173264a66decd973029dc04f64da9f0a1f6192da8cab652e8c71e8c63a1432c4110259d971d64d3697
|
7
|
+
data.tar.gz: 6f90979086a3be82858d38b62bc23a84ab8a05266ca048541d59c87d5f43757219e88c8a2d7c158762e19533e17720f2d5b583d24d8614a6bbef9196374b6004
|
data/ext/Cargo.toml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
[workspace]
|
2
|
+
resolver = "2"
|
3
|
+
members = ["gqliterb", "gqlitedb", "graphcore"]
|
4
|
+
|
5
|
+
[workspace.package]
|
6
|
+
version = "0.6.0"
|
7
|
+
edition = "2021"
|
8
|
+
license = "MIT"
|
9
|
+
homepage = "https://gqlite.org"
|
10
|
+
repository = "https://gitlab.com/gqlite/gqlite"
|
11
|
+
|
12
|
+
[workspace.dependencies]
|
13
|
+
graphcore = { version = "0.2.0", path = "graphcore" }
|
14
|
+
gqlitedb = { version = "0.6.0", path = "gqlitedb" }
|
15
|
+
|
16
|
+
askama = { version = "0.14" }
|
17
|
+
itertools = "0.14"
|
18
|
+
serde = "1"
|
19
|
+
thiserror = "2"
|
20
|
+
uuid = { version = "1", features = ["v4"] }
|
@@ -0,0 +1,77 @@
|
|
1
|
+
[package]
|
2
|
+
name = "gqlitedb"
|
3
|
+
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."
|
4
|
+
readme = "../../README.md"
|
5
|
+
version.workspace = true
|
6
|
+
edition.workspace = true
|
7
|
+
license.workspace = true
|
8
|
+
homepage.workspace = true
|
9
|
+
repository.workspace = true
|
10
|
+
|
11
|
+
[lib]
|
12
|
+
crate-type = ["cdylib", "lib"]
|
13
|
+
|
14
|
+
[features]
|
15
|
+
default = ["redb", "capi", "sqlite"]
|
16
|
+
_backtrace = []
|
17
|
+
capi = []
|
18
|
+
redb = ["dep:redb", "dep:redb2"]
|
19
|
+
_pgql = ["dep:pgrx"]
|
20
|
+
_pg13 = ["pgrx/pg13"]
|
21
|
+
_pg14 = ["pgrx/pg14"]
|
22
|
+
_pg15 = ["pgrx/pg15"]
|
23
|
+
_pg16 = ["pgrx/pg16"]
|
24
|
+
_pg17 = ["pgrx/pg17"]
|
25
|
+
sqlite = ["dep:rusqlite", "dep:askama"]
|
26
|
+
_value_private = []
|
27
|
+
bundled = ["rusqlite/bundled"]
|
28
|
+
|
29
|
+
[dependencies]
|
30
|
+
graphcore = { workspace = true }
|
31
|
+
|
32
|
+
askama = { workspace = true, optional = true }
|
33
|
+
ccutils = { version = "0.4", features = ["alias", "pool", "sync"] }
|
34
|
+
ciborium = "0.2"
|
35
|
+
itertools = { workspace = true }
|
36
|
+
pgrx = { version = "0.16", optional = true }
|
37
|
+
pest = "2"
|
38
|
+
pest_derive = "2"
|
39
|
+
rand = "0.9"
|
40
|
+
redb = { version = "3", optional = true }
|
41
|
+
redb2 = { version = "2", optional = true, package = "redb" }
|
42
|
+
rusqlite = { package = "rusqlite", version = "0.37", optional = true, features = [
|
43
|
+
"functions",
|
44
|
+
"uuid",
|
45
|
+
] }
|
46
|
+
serde = { workspace = true }
|
47
|
+
serde_json = "1"
|
48
|
+
thiserror = { workspace = true }
|
49
|
+
uuid = { workspace = true }
|
50
|
+
|
51
|
+
[dev-dependencies]
|
52
|
+
ccutils = { version = "0.4", features = ["alias", "temporary"] }
|
53
|
+
divan = "0.1"
|
54
|
+
iai-callgrind = { version = "0.16" }
|
55
|
+
regex = "1"
|
56
|
+
|
57
|
+
# web:
|
58
|
+
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
59
|
+
# rusqlite_wasm = { package = "rusqlite", version = "0.37", optional = true, git = "https://github.com/Spxg/rusqlite.git", branch = "wasm-demo", features = [
|
60
|
+
# "functions",
|
61
|
+
# "uuid",
|
62
|
+
# ] }
|
63
|
+
uuid = { version = "1", features = ["js"] }
|
64
|
+
|
65
|
+
# [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
66
|
+
# rusqlite_main = { package = "rusqlite", version = "0.37", optional = true, features = [
|
67
|
+
# "functions",
|
68
|
+
# "uuid",
|
69
|
+
# ] }
|
70
|
+
|
71
|
+
[[bench]]
|
72
|
+
name = "pokec_divan"
|
73
|
+
harness = false
|
74
|
+
|
75
|
+
[[bench]]
|
76
|
+
name = "pokec_iai"
|
77
|
+
harness = false
|
@@ -1,7 +1,7 @@
|
|
1
1
|
use std::{collections::HashSet, fs};
|
2
2
|
|
3
3
|
use ccutils::temporary::TemporaryFile;
|
4
|
-
use gqlitedb::{
|
4
|
+
use gqlitedb::{value_map, Connection};
|
5
5
|
use rand::{seq::IndexedRandom, Rng};
|
6
6
|
use regex::Regex;
|
7
7
|
|
@@ -24,11 +24,21 @@ impl Pokec
|
|
24
24
|
{
|
25
25
|
pub(crate) fn load(backend: &str, size: PokecSize) -> Pokec
|
26
26
|
{
|
27
|
+
let backend = match backend
|
28
|
+
{
|
29
|
+
"sqlite" => gqlitedb::Backend::SQLite,
|
30
|
+
"redb" => gqlitedb::Backend::Redb,
|
31
|
+
o => panic!("Unknown backend '{}'", o),
|
32
|
+
};
|
27
33
|
let temporary_file = TemporaryFile::builder()
|
28
34
|
.should_create_file(false)
|
29
35
|
.label("gqlite_bench")
|
30
36
|
.create();
|
31
|
-
let connection = Connection::
|
37
|
+
let connection = Connection::builder()
|
38
|
+
.path(temporary_file.path())
|
39
|
+
.backend(backend)
|
40
|
+
.create()
|
41
|
+
.unwrap();
|
32
42
|
|
33
43
|
let filename = match size
|
34
44
|
{
|
@@ -39,7 +49,7 @@ impl Pokec
|
|
39
49
|
let import_query = fs::read_to_string(filename).unwrap();
|
40
50
|
|
41
51
|
connection
|
42
|
-
.
|
52
|
+
.execute_oc_query(import_query, Default::default())
|
43
53
|
.unwrap();
|
44
54
|
Self {
|
45
55
|
temporary_file,
|
@@ -71,9 +81,9 @@ impl Pokec
|
|
71
81
|
let random_id = self.ids.choose(rng).unwrap();
|
72
82
|
self
|
73
83
|
.connection
|
74
|
-
.
|
84
|
+
.execute_oc_query(
|
75
85
|
"MATCH (n:User {id: $id}) RETURN n",
|
76
|
-
|
86
|
+
value_map!("$id" => *random_id),
|
77
87
|
)
|
78
88
|
.unwrap();
|
79
89
|
}
|
@@ -84,9 +94,9 @@ impl Pokec
|
|
84
94
|
let random_id = self.ids.choose(rng).unwrap();
|
85
95
|
self
|
86
96
|
.connection
|
87
|
-
.
|
97
|
+
.execute_oc_query(
|
88
98
|
"MATCH (n:User) WHERE n.id = $id RETURN n",
|
89
|
-
|
99
|
+
value_map!("$id" => *random_id),
|
90
100
|
)
|
91
101
|
.unwrap();
|
92
102
|
}
|
@@ -97,9 +107,9 @@ impl Pokec
|
|
97
107
|
let random_id = self.ids.choose(rng).unwrap();
|
98
108
|
self
|
99
109
|
.connection
|
100
|
-
.
|
110
|
+
.execute_oc_query(
|
101
111
|
"MATCH (s:User {id: $id})-->(n:User) RETURN n.id",
|
102
|
-
|
112
|
+
value_map!("$id" => *random_id),
|
103
113
|
)
|
104
114
|
.unwrap();
|
105
115
|
}
|
@@ -110,9 +120,9 @@ impl Pokec
|
|
110
120
|
let random_id = self.ids.choose(rng).unwrap();
|
111
121
|
self
|
112
122
|
.connection
|
113
|
-
.
|
123
|
+
.execute_oc_query(
|
114
124
|
"MATCH (s:User {id: $id})-->(n:User) WHERE n.age >= 18 RETURN n.id",
|
115
|
-
|
125
|
+
value_map!("$id" => *random_id),
|
116
126
|
)
|
117
127
|
.unwrap();
|
118
128
|
}
|
@@ -123,9 +133,9 @@ impl Pokec
|
|
123
133
|
let random_id = self.ids.choose(rng).unwrap();
|
124
134
|
self
|
125
135
|
.connection
|
126
|
-
.
|
136
|
+
.execute_oc_query(
|
127
137
|
"MATCH (s:User {id: $id})-->()-->(n:User) RETURN n.id",
|
128
|
-
|
138
|
+
value_map!("$id" => *random_id),
|
129
139
|
)
|
130
140
|
.unwrap();
|
131
141
|
}
|
@@ -136,9 +146,9 @@ impl Pokec
|
|
136
146
|
let random_id = self.ids.choose(rng).unwrap();
|
137
147
|
self
|
138
148
|
.connection
|
139
|
-
.
|
149
|
+
.execute_oc_query(
|
140
150
|
"MATCH (s:User {id: $id})-->()-->(n:User) WHERE n.age >= 18 RETURN n.id",
|
141
|
-
|
151
|
+
value_map!("$id" => *random_id),
|
142
152
|
)
|
143
153
|
.unwrap();
|
144
154
|
}
|
@@ -149,9 +159,9 @@ impl Pokec
|
|
149
159
|
let random_id = self.ids.choose(rng).unwrap();
|
150
160
|
self
|
151
161
|
.connection
|
152
|
-
.
|
162
|
+
.execute_oc_query(
|
153
163
|
"MATCH (n:User {id: $id})-[e1]->(m)-[e2]->(n) RETURN e1, m, e2",
|
154
|
-
|
164
|
+
value_map!("$id" => *random_id),
|
155
165
|
)
|
156
166
|
.unwrap();
|
157
167
|
}
|
@@ -159,14 +169,14 @@ impl Pokec
|
|
159
169
|
{
|
160
170
|
self
|
161
171
|
.connection
|
162
|
-
.
|
172
|
+
.execute_oc_query("MATCH (n:User) RETURN n.age, count(*)", Default::default())
|
163
173
|
.unwrap();
|
164
174
|
}
|
165
175
|
pub(crate) fn aggregate_count_filter(&self)
|
166
176
|
{
|
167
177
|
self
|
168
178
|
.connection
|
169
|
-
.
|
179
|
+
.execute_oc_query(
|
170
180
|
"MATCH (n:User) WHERE n.age >= 18 RETURN n.age, count(*)",
|
171
181
|
Default::default(),
|
172
182
|
)
|
@@ -176,7 +186,7 @@ impl Pokec
|
|
176
186
|
{
|
177
187
|
self
|
178
188
|
.connection
|
179
|
-
.
|
189
|
+
.execute_oc_query(
|
180
190
|
"MATCH (n) RETURN min(n.age), max(n.age), avg(n.age)",
|
181
191
|
Default::default(),
|
182
192
|
)
|
@@ -0,0 +1,6 @@
|
|
1
|
+
 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)).
|
@@ -0,0 +1,85 @@
|
|
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
|
@@ -0,0 +1,34 @@
|
|
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,7 +1,7 @@
|
|
1
1
|
pre-release-replacements = [
|
2
2
|
{ file = "../../CHANGELOG.md", search = "Unreleased", replace = "{{version}}" },
|
3
|
-
{ file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/
|
3
|
+
{ file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/1", replace = "...{{tag_name}}", 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/
|
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
7
|
]
|
@@ -2,16 +2,12 @@ use std::fmt::Debug;
|
|
2
2
|
|
3
3
|
use super::AggregatorState;
|
4
4
|
|
5
|
-
use crate::
|
6
|
-
error::{InternalError, RunTimeError},
|
7
|
-
value::Value,
|
8
|
-
Result,
|
9
|
-
};
|
5
|
+
use crate::prelude::*;
|
10
6
|
|
11
7
|
#[derive(Debug)]
|
12
8
|
struct AvgState
|
13
9
|
{
|
14
|
-
value: Value,
|
10
|
+
value: value::Value,
|
15
11
|
count: usize,
|
16
12
|
}
|
17
13
|
|
@@ -20,7 +16,7 @@ impl AvgState
|
|
20
16
|
fn new() -> Result<Self>
|
21
17
|
{
|
22
18
|
Ok(Self {
|
23
|
-
value: Value::Null,
|
19
|
+
value: value::Value::Null,
|
24
20
|
count: 0,
|
25
21
|
})
|
26
22
|
}
|
@@ -28,7 +24,7 @@ impl AvgState
|
|
28
24
|
|
29
25
|
impl AggregatorState for AvgState
|
30
26
|
{
|
31
|
-
fn next(&mut self, value: Value) -> crate::Result<()>
|
27
|
+
fn next(&mut self, value: value::Value) -> crate::Result<()>
|
32
28
|
{
|
33
29
|
if self.value.is_null()
|
34
30
|
{
|
@@ -38,25 +34,25 @@ impl AggregatorState for AvgState
|
|
38
34
|
{
|
39
35
|
match value
|
40
36
|
{
|
41
|
-
Value::Null =>
|
37
|
+
value::Value::Null =>
|
42
38
|
{}
|
43
|
-
Value::Integer(i) =>
|
39
|
+
value::Value::Integer(i) =>
|
44
40
|
{
|
45
41
|
self.count += 1;
|
46
42
|
match self.value
|
47
43
|
{
|
48
|
-
Value::Integer(vi) => self.value = (vi + i).into(),
|
49
|
-
Value::Float(vf) => self.value = (vf + i as f64).into(),
|
44
|
+
value::Value::Integer(vi) => self.value = (vi + i).into(),
|
45
|
+
value::Value::Float(vf) => self.value = (vf + i as f64).into(),
|
50
46
|
_ => Err(InternalError::InvalidAggregationState)?,
|
51
47
|
}
|
52
48
|
}
|
53
|
-
Value::Float(f) =>
|
49
|
+
value::Value::Float(f) =>
|
54
50
|
{
|
55
51
|
self.count += 1;
|
56
52
|
match self.value
|
57
53
|
{
|
58
|
-
Value::Integer(vi) => self.value = (vi as f64 + f).into(),
|
59
|
-
Value::Float(vf) => self.value = (vf + f).into(),
|
54
|
+
value::Value::Integer(vi) => self.value = (vi as f64 + f).into(),
|
55
|
+
value::Value::Float(vf) => self.value = (vf + f).into(),
|
60
56
|
_ => Err(InternalError::InvalidAggregationState)?,
|
61
57
|
}
|
62
58
|
}
|
@@ -69,50 +65,41 @@ impl AggregatorState for AvgState
|
|
69
65
|
{
|
70
66
|
match self.value
|
71
67
|
{
|
72
|
-
Value::Null => Ok(Value::Null),
|
73
|
-
Value::Integer(vi) => Ok((vi / self.count as i64).into()),
|
74
|
-
Value::Float(vf) => Ok((vf / self.count as f64).into()),
|
68
|
+
value::Value::Null => Ok(value::Value::Null),
|
69
|
+
value::Value::Integer(vi) => Ok((vi / self.count as i64).into()),
|
70
|
+
value::Value::Float(vf) => Ok((vf / self.count as f64).into()),
|
75
71
|
_ => Err(InternalError::InvalidAggregationState)?,
|
76
72
|
}
|
77
73
|
}
|
78
74
|
}
|
79
75
|
|
80
|
-
super::declare_aggregator!(avg, Avg, AvgState, () -> Value);
|
76
|
+
super::declare_aggregator!(avg, Avg, AvgState, () -> value::Value);
|
81
77
|
|
82
78
|
#[derive(Debug)]
|
83
79
|
struct MinState
|
84
80
|
{
|
85
|
-
value: Value,
|
81
|
+
value: value::Value,
|
86
82
|
}
|
87
83
|
|
88
84
|
impl MinState
|
89
85
|
{
|
90
86
|
fn new() -> Result<Self>
|
91
87
|
{
|
92
|
-
Ok(Self {
|
88
|
+
Ok(Self {
|
89
|
+
value: value::Value::Null,
|
90
|
+
})
|
93
91
|
}
|
94
92
|
}
|
95
93
|
|
96
94
|
impl AggregatorState for MinState
|
97
95
|
{
|
98
|
-
fn next(&mut self, value: Value) -> crate::Result<()>
|
96
|
+
fn next(&mut self, value: value::Value) -> crate::Result<()>
|
99
97
|
{
|
100
98
|
if self.value.is_null()
|
99
|
+
|| (!value.is_null() && value.orderability(&self.value) == std::cmp::Ordering::Less)
|
101
100
|
{
|
102
101
|
self.value = value;
|
103
102
|
}
|
104
|
-
else if !value.is_null()
|
105
|
-
{
|
106
|
-
match value.orderability(&self.value)
|
107
|
-
{
|
108
|
-
std::cmp::Ordering::Less =>
|
109
|
-
{
|
110
|
-
self.value = value;
|
111
|
-
}
|
112
|
-
_ =>
|
113
|
-
{}
|
114
|
-
}
|
115
|
-
}
|
116
103
|
Ok(())
|
117
104
|
}
|
118
105
|
fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
|
@@ -126,37 +113,28 @@ super::declare_aggregator!(min, Min, MinState, () -> i64);
|
|
126
113
|
#[derive(Debug)]
|
127
114
|
struct MaxState
|
128
115
|
{
|
129
|
-
value: Value,
|
116
|
+
value: value::Value,
|
130
117
|
}
|
131
118
|
|
132
119
|
impl MaxState
|
133
120
|
{
|
134
121
|
fn new() -> Result<Self>
|
135
122
|
{
|
136
|
-
Ok(Self {
|
123
|
+
Ok(Self {
|
124
|
+
value: value::Value::Null,
|
125
|
+
})
|
137
126
|
}
|
138
127
|
}
|
139
128
|
|
140
129
|
impl AggregatorState for MaxState
|
141
130
|
{
|
142
|
-
fn next(&mut self, value: Value) -> crate::Result<()>
|
131
|
+
fn next(&mut self, value: value::Value) -> crate::Result<()>
|
143
132
|
{
|
144
133
|
if self.value.is_null()
|
134
|
+
|| (!value.is_null() && value.orderability(&self.value) == std::cmp::Ordering::Greater)
|
145
135
|
{
|
146
136
|
self.value = value;
|
147
137
|
}
|
148
|
-
else if !value.is_null()
|
149
|
-
{
|
150
|
-
match value.orderability(&self.value)
|
151
|
-
{
|
152
|
-
std::cmp::Ordering::Greater =>
|
153
|
-
{
|
154
|
-
self.value = value;
|
155
|
-
}
|
156
|
-
_ =>
|
157
|
-
{}
|
158
|
-
}
|
159
|
-
}
|
160
138
|
Ok(())
|
161
139
|
}
|
162
140
|
fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
|
@@ -28,7 +28,7 @@ macro_rules! declare_aggregator {
|
|
28
28
|
pub(super) struct $type_name {}
|
29
29
|
impl $type_name
|
30
30
|
{
|
31
|
-
pub(crate) fn
|
31
|
+
pub(crate) fn create() -> (String, crate::aggregators::Aggregator)
|
32
32
|
{
|
33
33
|
(
|
34
34
|
stringify!($function_name).to_string(),
|
@@ -63,12 +63,12 @@ pub(crate) use declare_aggregator;
|
|
63
63
|
pub(crate) fn init_aggregators() -> std::collections::HashMap<String, Aggregator>
|
64
64
|
{
|
65
65
|
[
|
66
|
-
count::Count::
|
67
|
-
arithmetic::Sum::
|
68
|
-
containers::Collect::
|
69
|
-
stats::Avg::
|
70
|
-
stats::Min::
|
71
|
-
stats::Max::
|
66
|
+
count::Count::create(),
|
67
|
+
arithmetic::Sum::create(),
|
68
|
+
containers::Collect::create(),
|
69
|
+
stats::Avg::create(),
|
70
|
+
stats::Min::create(),
|
71
|
+
stats::Max::create(),
|
72
72
|
]
|
73
73
|
.into()
|
74
74
|
}
|