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.
- checksums.yaml +4 -4
- data/ext/gqliterb/.cargo/config.toml +2 -0
- data/ext/gqliterb/Cargo.lock +152 -135
- data/ext/gqliterb/Cargo.toml +4 -6
- data/ext/gqliterb/src/lib.rs +8 -2
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2115 -0
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +138 -0
- data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
- data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
- data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +259 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +431 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +621 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +342 -0
- data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
- data/ext/gqliterb/vendor/gqlitedb/src/error.rs +613 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +80 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +410 -0
- data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +283 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1776 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +267 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +41 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +611 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +196 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1183 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
- data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1262 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +1026 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store.rs +439 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +470 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
- data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +609 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +610 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
- metadata +82 -2
@@ -0,0 +1,342 @@
|
|
1
|
+
use std::path::Path;
|
2
|
+
|
3
|
+
use crate::prelude::*;
|
4
|
+
use value::ValueTryIntoRef;
|
5
|
+
|
6
|
+
/// Backend
|
7
|
+
pub enum Backend
|
8
|
+
{
|
9
|
+
/// Select the first available backend.
|
10
|
+
Automatic,
|
11
|
+
/// SQLite backend.
|
12
|
+
#[cfg(feature = "sqlite")]
|
13
|
+
SQLite,
|
14
|
+
/// Redb backend.
|
15
|
+
#[cfg(feature = "redb")]
|
16
|
+
Redb,
|
17
|
+
}
|
18
|
+
|
19
|
+
/// Builder with high-level API for creating connection.
|
20
|
+
pub struct ConnectionBuilder
|
21
|
+
{
|
22
|
+
map: value::ValueMap,
|
23
|
+
}
|
24
|
+
|
25
|
+
impl ConnectionBuilder
|
26
|
+
{
|
27
|
+
/// Merge options. This might overwrite value from the builder
|
28
|
+
pub fn options(mut self, options: value::ValueMap) -> Self
|
29
|
+
{
|
30
|
+
for (k, v) in options.into_iter()
|
31
|
+
{
|
32
|
+
self.map.insert(k, v);
|
33
|
+
}
|
34
|
+
self
|
35
|
+
}
|
36
|
+
/// Set path
|
37
|
+
pub fn path<P: AsRef<Path>>(mut self, p: P) -> Self
|
38
|
+
{
|
39
|
+
self.map.insert(
|
40
|
+
"path".to_string(),
|
41
|
+
p.as_ref().to_string_lossy().as_ref().into(),
|
42
|
+
);
|
43
|
+
self
|
44
|
+
}
|
45
|
+
/// Set backend
|
46
|
+
pub fn backend(mut self, backend: Backend) -> Self
|
47
|
+
{
|
48
|
+
let key = "backend".into();
|
49
|
+
match backend
|
50
|
+
{
|
51
|
+
Backend::Automatic =>
|
52
|
+
{
|
53
|
+
self.map.insert(key, "automatic".into());
|
54
|
+
}
|
55
|
+
#[cfg(feature = "sqlite")]
|
56
|
+
Backend::SQLite =>
|
57
|
+
{
|
58
|
+
self.map.insert(key, "sqlite".into());
|
59
|
+
}
|
60
|
+
#[cfg(feature = "redb")]
|
61
|
+
Backend::Redb =>
|
62
|
+
{
|
63
|
+
self.map.insert(key, "redb".into());
|
64
|
+
}
|
65
|
+
}
|
66
|
+
self
|
67
|
+
}
|
68
|
+
/// Create the connection
|
69
|
+
pub fn create(self) -> Result<Connection>
|
70
|
+
{
|
71
|
+
Connection::create(self.map)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
trait ConnectionTrait: Sync + Send
|
76
|
+
{
|
77
|
+
fn execute_query(&self, query: String, parameters: value::ValueMap) -> Result<value::Value>;
|
78
|
+
}
|
79
|
+
|
80
|
+
struct ConnectionImpl<TStore>
|
81
|
+
where
|
82
|
+
TStore: store::Store + Sync + Send,
|
83
|
+
{
|
84
|
+
store: TStore,
|
85
|
+
function_manager: functions::Manager,
|
86
|
+
}
|
87
|
+
|
88
|
+
impl<TStore> ConnectionTrait for ConnectionImpl<TStore>
|
89
|
+
where
|
90
|
+
TStore: store::Store + Sync + Send,
|
91
|
+
{
|
92
|
+
fn execute_query(&self, query: String, parameters: value::ValueMap) -> Result<value::Value>
|
93
|
+
{
|
94
|
+
let query_txt: String = query.into();
|
95
|
+
let queries = parser::parse(query_txt.as_str())?;
|
96
|
+
let mut results = Vec::<value::Value>::default();
|
97
|
+
for query in queries
|
98
|
+
{
|
99
|
+
let program = compiler::compile(&self.function_manager, query)?;
|
100
|
+
let v = interpreter::evaluators::eval_program(&self.store, &program, ¶meters)?;
|
101
|
+
if !v.is_null()
|
102
|
+
{
|
103
|
+
results.push(v);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
match results.len()
|
107
|
+
{
|
108
|
+
0 => Ok(value::Value::Null),
|
109
|
+
1 => Ok(results.into_iter().next().unwrap()),
|
110
|
+
_ =>
|
111
|
+
{
|
112
|
+
let mut map = value::ValueMap::new();
|
113
|
+
map.insert("type".into(), "results".into());
|
114
|
+
map.insert("results".into(), results.into());
|
115
|
+
Ok(map.into())
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
impl<TStore: store::Store> ConnectionImpl<TStore>
|
122
|
+
where
|
123
|
+
TStore: store::Store + Sync + Send,
|
124
|
+
{
|
125
|
+
fn boxed(self) -> Box<Self>
|
126
|
+
{
|
127
|
+
Box::new(self)
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
/// Connection is the interface to the database, and allow to execute new queries.
|
132
|
+
/// New connection are created with [Connection::open] and queried with [Connection::execute_query].
|
133
|
+
/// As shown in the example bellow:
|
134
|
+
///
|
135
|
+
/// ```rust
|
136
|
+
/// # use gqlitedb::{Connection, Value};
|
137
|
+
/// # fn example() -> gqlitedb::Result<()> {
|
138
|
+
/// let connection = Connection::open("filename.db", gqlitedb::map!("backend" => "redb"))?;
|
139
|
+
/// let value = connection.execute_query("MATCH (a) RETURN a", Default::default())?;
|
140
|
+
/// match value
|
141
|
+
/// {
|
142
|
+
/// Value::Array(arr) =>
|
143
|
+
/// {
|
144
|
+
/// arr.iter().for_each(|row| match row
|
145
|
+
/// {
|
146
|
+
/// Value::Array(arr) =>
|
147
|
+
/// {
|
148
|
+
/// println!("{:?}", arr);
|
149
|
+
/// }
|
150
|
+
/// _ =>
|
151
|
+
/// {
|
152
|
+
/// panic!("Unexpected: {}", row);
|
153
|
+
/// }
|
154
|
+
/// });
|
155
|
+
/// },
|
156
|
+
/// _ => {
|
157
|
+
/// panic!("Query result should be an array, got {}!", value);
|
158
|
+
/// }
|
159
|
+
/// }
|
160
|
+
/// # Ok(()) }
|
161
|
+
/// ```
|
162
|
+
|
163
|
+
pub struct Connection
|
164
|
+
{
|
165
|
+
connection: Box<dyn ConnectionTrait>,
|
166
|
+
}
|
167
|
+
|
168
|
+
ccutils::assert_impl_all!(Connection: Sync, Send);
|
169
|
+
|
170
|
+
impl Connection
|
171
|
+
{
|
172
|
+
/// Create a new connection to a `GQLite` database. The `options` parameter can
|
173
|
+
/// be used to select the backend, and configure the backend.
|
174
|
+
///
|
175
|
+
/// Supported parameters:
|
176
|
+
/// - `path` a path to a file, if not present, an in-memory database is created
|
177
|
+
/// - `backend` for instance `redb` or `sqlite` (the [Self::available_backends] function contains the list of compiled backends)
|
178
|
+
///
|
179
|
+
/// If the `backend` is not specified, the `open` function will attempt to guess it
|
180
|
+
/// for existing databases. For new database, depending on availability, it will
|
181
|
+
/// create a `sqlite` database, or a `redb` database.
|
182
|
+
///
|
183
|
+
/// Example of use, this will create an in-memory database:
|
184
|
+
///
|
185
|
+
/// ```rust
|
186
|
+
/// # use gqlitedb::Connection;
|
187
|
+
/// # fn example() -> gqlitedb::Result<()> {
|
188
|
+
/// let connection = Connection::create(gqlitedb::map!("backend" => "redb"))?;
|
189
|
+
/// # Ok(()) }
|
190
|
+
/// ```
|
191
|
+
pub fn create(options: value::ValueMap) -> Result<Connection>
|
192
|
+
{
|
193
|
+
let backend = options.get("backend").map_or_else(
|
194
|
+
|| Ok("automatic".to_string()),
|
195
|
+
|x| x.try_into_ref().map(|x: &String| x.to_owned()),
|
196
|
+
)?;
|
197
|
+
match backend.as_str()
|
198
|
+
{
|
199
|
+
"automatic" =>
|
200
|
+
{
|
201
|
+
#[cfg(feature = "sqlite")]
|
202
|
+
let sq_e = {
|
203
|
+
let mut options = options.clone();
|
204
|
+
options.insert("backend".into(), "sqlite".into());
|
205
|
+
Self::create(options)
|
206
|
+
};
|
207
|
+
#[cfg(not(feature = "sqlite"))]
|
208
|
+
let sq_e = Err(error::StoreError::UnavailableBackend { backend: "sqlite" }.into());
|
209
|
+
let sq_r = match sq_e
|
210
|
+
{
|
211
|
+
Ok(sq) => Ok(sq),
|
212
|
+
Err(sq_e) =>
|
213
|
+
{
|
214
|
+
#[cfg(feature = "redb")]
|
215
|
+
let sq_r = {
|
216
|
+
let mut options = options;
|
217
|
+
options.insert("backend".into(), "redb".into());
|
218
|
+
Self::create(options)
|
219
|
+
};
|
220
|
+
#[cfg(not(feature = "redb"))]
|
221
|
+
let sq_r = Err(error::StoreError::UnavailableBackend { backend: "redb" }.into());
|
222
|
+
|
223
|
+
sq_r.map_err(|rb_e| {
|
224
|
+
StoreError::OpeningError {
|
225
|
+
errors: error::vec_to_error::<ErrorType>(&vec![sq_e, rb_e]),
|
226
|
+
}
|
227
|
+
.into()
|
228
|
+
})
|
229
|
+
}
|
230
|
+
};
|
231
|
+
sq_r
|
232
|
+
}
|
233
|
+
#[cfg(feature = "sqlite")]
|
234
|
+
"sqlite" =>
|
235
|
+
{
|
236
|
+
let store = if let Some(path) = options.get("path")
|
237
|
+
{
|
238
|
+
let path: &String = path.try_into_ref()?;
|
239
|
+
store::sqlite::Store::open(path)?
|
240
|
+
}
|
241
|
+
else
|
242
|
+
{
|
243
|
+
store::sqlite::Store::in_memory()?
|
244
|
+
};
|
245
|
+
Ok(Connection {
|
246
|
+
connection: ConnectionImpl {
|
247
|
+
store,
|
248
|
+
function_manager: functions::Manager::new(),
|
249
|
+
}
|
250
|
+
.boxed(),
|
251
|
+
})
|
252
|
+
}
|
253
|
+
#[cfg(feature = "redb")]
|
254
|
+
"redb" =>
|
255
|
+
{
|
256
|
+
let store = if let Some(path) = options.get("path")
|
257
|
+
{
|
258
|
+
let path: &String = path.try_into_ref()?;
|
259
|
+
store::redb::Store::open(path)?
|
260
|
+
}
|
261
|
+
else
|
262
|
+
{
|
263
|
+
store::redb::Store::in_memory()?
|
264
|
+
};
|
265
|
+
Ok(Connection {
|
266
|
+
connection: ConnectionImpl {
|
267
|
+
store,
|
268
|
+
function_manager: functions::Manager::new(),
|
269
|
+
}
|
270
|
+
.boxed(),
|
271
|
+
})
|
272
|
+
}
|
273
|
+
_ => Err(StoreError::UnknownBackend { backend }.into()),
|
274
|
+
}
|
275
|
+
}
|
276
|
+
/// Create a builder, with a high-level API to set the options.
|
277
|
+
/// Example of use:
|
278
|
+
/// ```
|
279
|
+
/// let connection = Connection::builder().path("path/to/file").backend(Backend::SQLite).create()?;
|
280
|
+
/// ```
|
281
|
+
pub fn builder() -> ConnectionBuilder
|
282
|
+
{
|
283
|
+
ConnectionBuilder {
|
284
|
+
map: Default::default(),
|
285
|
+
}
|
286
|
+
}
|
287
|
+
/// List of available backends
|
288
|
+
pub fn available_backends() -> Vec<String>
|
289
|
+
{
|
290
|
+
let mut backends = vec![];
|
291
|
+
#[cfg(feature = "sqlite")]
|
292
|
+
backends.push("sqlite".to_string());
|
293
|
+
#[cfg(feature = "redb")]
|
294
|
+
backends.push("redb".to_string());
|
295
|
+
backends
|
296
|
+
}
|
297
|
+
|
298
|
+
/// Open a `path` that contains a `GQLite` database. The `options` parameter can
|
299
|
+
/// be used to select the backend, and configure the backend.
|
300
|
+
///
|
301
|
+
/// Supported parameters:
|
302
|
+
/// - `backend` can be `redb` or `sqlite`
|
303
|
+
///
|
304
|
+
/// If the `backend` is not specified, the `open` function will attempt to guess it
|
305
|
+
/// for existing databases. For new database, depending on availability, it will
|
306
|
+
/// create a `sqlite` database, or a `redb` database.
|
307
|
+
///
|
308
|
+
/// Example of use:
|
309
|
+
///
|
310
|
+
/// ```rust
|
311
|
+
/// # use gqlitedb::Connection;
|
312
|
+
/// # fn example() -> gqlitedb::Result<()> {
|
313
|
+
/// let connection = Connection::open("filename.db", gqlitedb::map!("backend" => "redb"))?;
|
314
|
+
/// # Ok(()) }
|
315
|
+
/// ```
|
316
|
+
#[cfg(any(feature = "redb", feature = "sqlite"))]
|
317
|
+
#[deprecated = "Use create or builder instead."]
|
318
|
+
pub fn open<P: AsRef<std::path::Path>>(path: P, options: value::ValueMap) -> Result<Connection>
|
319
|
+
{
|
320
|
+
Self::builder().options(options).path(path).create()
|
321
|
+
}
|
322
|
+
/// Execute the `query` (using OpenCypher), given the query `parameters` (sometimes
|
323
|
+
/// also referred as binding).
|
324
|
+
///
|
325
|
+
/// Example:
|
326
|
+
///
|
327
|
+
/// ```rust
|
328
|
+
/// # use gqlitedb::{Connection, Value};
|
329
|
+
/// # fn example() -> gqlitedb::Result<()> {
|
330
|
+
/// # let connection = gqlitedb::Connection::open("filename.db", gqlitedb::map!("backend" => "redb"))?;
|
331
|
+
/// let result = connection.execute_query("MATCH (a { name: $name }) RETURN a", gqlitedb::map!("name" => "Joe"))?;
|
332
|
+
/// # Ok(()) }
|
333
|
+
/// ```
|
334
|
+
pub fn execute_query(
|
335
|
+
&self,
|
336
|
+
query: impl Into<String>,
|
337
|
+
parameters: value::ValueMap,
|
338
|
+
) -> Result<value::Value>
|
339
|
+
{
|
340
|
+
self.connection.execute_query(query.into(), parameters)
|
341
|
+
}
|
342
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
pub(crate) const SHOW_PARSE_TREE: bool = false;
|
2
|
+
pub(crate) const SHOW_AST: bool = false;
|
3
|
+
pub(crate) const SHOW_PROGRAM: bool = false;
|
4
|
+
pub(crate) const SHOW_EVALUATOR_STATE: bool = false;
|
5
|
+
|
6
|
+
pub(crate) const GQLITE_VERSION: crate::utils::Version = crate::utils::Version {
|
7
|
+
major: 1,
|
8
|
+
minor: 2,
|
9
|
+
patch: 0,
|
10
|
+
};
|