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,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, &parameters)?;
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
+ };