gqlite 1.1.0 → 1.2.2

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gqliterb/.cargo/config.toml +2 -0
  3. data/ext/gqliterb/Cargo.lock +1109 -0
  4. data/ext/gqliterb/Cargo.toml +43 -0
  5. data/ext/gqliterb/extconf.rb +4 -0
  6. data/ext/gqliterb/src/lib.rs +260 -0
  7. data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2060 -0
  8. data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +132 -0
  9. data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
  10. data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
  11. data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
  12. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
  13. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
  14. data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
  15. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
  16. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
  17. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
  18. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
  19. data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
  20. data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +236 -0
  21. data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +427 -0
  22. data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +620 -0
  23. data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1106 -0
  24. data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +208 -0
  25. data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
  26. data/ext/gqliterb/vendor/gqlitedb/src/error.rs +621 -0
  27. data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
  28. data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
  29. data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
  30. data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
  31. data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +48 -0
  32. data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
  33. data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
  34. data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
  35. data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +412 -0
  36. data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +268 -0
  37. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1788 -0
  38. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +262 -0
  39. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
  40. data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +42 -0
  41. data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +625 -0
  42. data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +191 -0
  43. data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1153 -0
  44. data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
  45. data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
  46. data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
  47. data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
  48. data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1250 -0
  49. data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +994 -0
  50. data/ext/gqliterb/vendor/gqlitedb/src/store.rs +432 -0
  51. data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
  52. data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
  53. data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
  54. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +39 -0
  55. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +39 -0
  56. data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +462 -0
  57. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
  58. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
  59. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
  60. data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
  61. data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
  62. data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
  63. data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
  64. data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
  65. data/ext/gqliterb/vendor/gqlitedb/src/value.rs +559 -0
  66. data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +616 -0
  67. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
  68. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
  69. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
  70. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
  71. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
  72. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
  73. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
  74. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
  75. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
  76. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
  77. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
  78. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
  79. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
  80. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
  81. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
  82. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
  83. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
  84. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
  85. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
  86. data/lib/gqlite.rb +1 -75
  87. metadata +118 -25
  88. data/ext/gqlite/extconf.rb +0 -21
  89. data/ext/gqlite/gqlite-amalgamate.cpp +0 -9599
  90. data/ext/gqlite/gqlite-c.h +0 -95
  91. data/ext/gqlite/gqlite.h +0 -141
@@ -0,0 +1,616 @@
1
+ use std::{fmt::Debug, mem};
2
+
3
+ use crate::prelude::*;
4
+
5
+ pub(crate) type ColId = usize;
6
+
7
+ pub(crate) trait RowInterface: Debug
8
+ {
9
+ fn get(&self, index: usize) -> Result<&value::Value>;
10
+ fn get_owned(&self, index: usize) -> Result<value::Value>
11
+ {
12
+ Ok(self.get(index)?.to_owned())
13
+ }
14
+ fn len(&self) -> usize;
15
+ }
16
+
17
+ pub(crate) trait MutableRowInterface: RowInterface
18
+ {
19
+ /// Set the value.
20
+ fn set(&mut self, index: usize, value: value::Value) -> Result<()>;
21
+ /// Set the value, if it is not set.
22
+ fn set_if_unset(&mut self, index: usize, value: value::Value) -> Result<()>;
23
+ }
24
+
25
+ #[derive(Debug, Default, Clone, Hash, PartialEq)]
26
+ pub(crate) struct Row
27
+ {
28
+ values: Vec<value::Value>,
29
+ }
30
+
31
+ impl Row
32
+ {
33
+ /// Creates a new Row from an initial vector and a total size.
34
+ /// If `extra_size` > initial.len(), it will fill with default values.
35
+ pub(crate) fn new(mut values: Vec<value::Value>, extra_size: usize) -> Self
36
+ {
37
+ values.resize(extra_size + values.len(), Default::default());
38
+ Row { values }
39
+ }
40
+ pub(crate) fn len(&self) -> usize
41
+ {
42
+ self.values.len()
43
+ }
44
+ /// Take the value at the given index, and replace it in the current row with an invalid value.
45
+ pub(crate) fn take(&mut self, index: usize) -> Result<value::Value>
46
+ {
47
+ if index < self.values.len()
48
+ {
49
+ Ok(mem::replace(&mut self.values[index], value::Value::Null))
50
+ }
51
+ else
52
+ {
53
+ Err(
54
+ InternalError::InvalidIndex {
55
+ index: index,
56
+ length: self.values.len(),
57
+ }
58
+ .into(),
59
+ )
60
+ }
61
+ }
62
+ /// Extend the row to the targeted size
63
+ pub(crate) fn extended(self, target_size: usize) -> Result<Self>
64
+ {
65
+ let values_len = self.values.len();
66
+ if target_size < values_len
67
+ {
68
+ Err(
69
+ error::InternalError::InvalidRowLength {
70
+ got: target_size,
71
+ expected: values_len,
72
+ }
73
+ .into(),
74
+ )
75
+ }
76
+ else
77
+ {
78
+ Ok(self.extended_by(target_size - values_len))
79
+ }
80
+ }
81
+ pub(crate) fn extended_by(self, extension: usize) -> Self
82
+ {
83
+ Self::new(self.values, extension)
84
+ }
85
+ }
86
+
87
+ // Implement the RowInterface trait for Row
88
+ impl RowInterface for Row
89
+ {
90
+ fn get(&self, index: usize) -> Result<&value::Value>
91
+ {
92
+ self.values.get(index).ok_or_else(|| {
93
+ InternalError::InvalidIndex {
94
+ index,
95
+ length: self.values.len(),
96
+ }
97
+ .into()
98
+ })
99
+ }
100
+ fn len(&self) -> usize
101
+ {
102
+ self.values.len()
103
+ }
104
+ }
105
+
106
+ impl MutableRowInterface for Row
107
+ {
108
+ fn set(&mut self, index: usize, value: value::Value) -> Result<()>
109
+ {
110
+ let values_length = self.values.len();
111
+ let elem = self
112
+ .values
113
+ .get_mut(index)
114
+ .ok_or_else(|| InternalError::InvalidIndex {
115
+ index,
116
+ length: values_length,
117
+ })?;
118
+ *elem = value;
119
+ Ok(())
120
+ }
121
+ fn set_if_unset(&mut self, index: usize, value: value::Value) -> Result<()>
122
+ {
123
+ let values_length = self.values.len();
124
+ let elem = self
125
+ .values
126
+ .get_mut(index)
127
+ .ok_or_else(|| InternalError::InvalidIndex {
128
+ index,
129
+ length: values_length,
130
+ })?;
131
+ if elem.is_null()
132
+ {
133
+ *elem = value;
134
+ }
135
+ Ok(())
136
+ }
137
+ }
138
+
139
+ impl Into<value::Value> for Row
140
+ {
141
+ fn into(self) -> value::Value
142
+ {
143
+ value::Value::Array(self.values)
144
+ }
145
+ }
146
+
147
+ impl FromIterator<value::Value> for Row
148
+ {
149
+ fn from_iter<I: IntoIterator<Item = value::Value>>(iter: I) -> Self
150
+ {
151
+ Row::new(iter.into_iter().collect(), 0)
152
+ }
153
+ }
154
+
155
+ pub(crate) trait Header
156
+ {
157
+ fn columns(&self) -> usize;
158
+ fn titles(&self) -> Option<Vec<String>>;
159
+ }
160
+
161
+ impl Header for usize
162
+ {
163
+ fn columns(&self) -> usize
164
+ {
165
+ *self
166
+ }
167
+ fn titles(&self) -> Option<Vec<String>>
168
+ {
169
+ None
170
+ }
171
+ }
172
+
173
+ impl Header for Vec<String>
174
+ {
175
+ fn columns(&self) -> usize
176
+ {
177
+ self.len()
178
+ }
179
+ fn titles(&self) -> Option<Vec<String>>
180
+ {
181
+ Some(self.clone())
182
+ }
183
+ }
184
+
185
+ #[derive(Debug)]
186
+ pub(crate) struct ValueTable<HeaderType>
187
+ where
188
+ HeaderType: Header,
189
+ {
190
+ header: HeaderType,
191
+ row_count: usize,
192
+ data: Vec<value::Value>,
193
+ }
194
+
195
+ impl<HeaderType> ValueTable<HeaderType>
196
+ where
197
+ HeaderType: Header,
198
+ {
199
+ pub(crate) fn new(header: HeaderType) -> Self
200
+ {
201
+ Self {
202
+ header,
203
+ row_count: 0,
204
+ data: Default::default(),
205
+ }
206
+ }
207
+ /// Add the full row to the table, return an error if the size of the row doesn't match the column.
208
+ pub(crate) fn add_full_row(&mut self, mut row: Row) -> Result<()>
209
+ {
210
+ if row.len() != self.header.columns()
211
+ {
212
+ Err(
213
+ error::InternalError::InvalidNumberColumns {
214
+ actual: row.len(),
215
+ expected: self.header.columns(),
216
+ }
217
+ .into(),
218
+ )
219
+ }
220
+ else
221
+ {
222
+ self.row_count += 1;
223
+ self.data.append(&mut row.values);
224
+ Ok(())
225
+ }
226
+ }
227
+ /// Add the row to the table, if the row is larger, the row is truncated, if the row is smaller, an error is returned.
228
+ pub(crate) fn add_truncated_row(&mut self, row: Row) -> Result<()>
229
+ {
230
+ if row.len() < self.header.columns()
231
+ {
232
+ Err(
233
+ error::InternalError::InvalidNumberColumns {
234
+ actual: row.len(),
235
+ expected: self.header.columns(),
236
+ }
237
+ .into(),
238
+ )
239
+ }
240
+ else
241
+ {
242
+ self.row_count += 1;
243
+ self
244
+ .data
245
+ .extend(row.values.into_iter().take(self.header.columns()));
246
+ Ok(())
247
+ }
248
+ }
249
+
250
+ pub fn add_truncated_rows(&mut self, rows: Vec<Row>) -> Result<()>
251
+ {
252
+ for row in rows.into_iter()
253
+ {
254
+ self.add_truncated_row(row)?;
255
+ }
256
+ Ok(())
257
+ }
258
+
259
+ pub fn row_count(&self) -> usize
260
+ {
261
+ self.row_count
262
+ }
263
+
264
+ /// Create a RowView into a specific row
265
+ pub fn row_view(&self, row_index: usize) -> Option<RowView<'_>>
266
+ {
267
+ if self.header.columns() == 0 && row_index >= self.row_count
268
+ {
269
+ return None;
270
+ }
271
+ let columns = self.header.columns();
272
+ let start = row_index.checked_mul(columns)?;
273
+ let end = start + columns;
274
+ if end <= self.data.len()
275
+ {
276
+ Some(RowView {
277
+ row: &self.data[start..end],
278
+ })
279
+ }
280
+ else
281
+ {
282
+ None
283
+ }
284
+ }
285
+ /// Create an iterator over the rows in the table
286
+ pub(crate) fn row_iter(&self) -> RowIter<'_>
287
+ {
288
+ RowIter {
289
+ data: &self.data,
290
+ columns: self.header.columns(),
291
+ index: 0,
292
+ row_count: self.row_count,
293
+ }
294
+ }
295
+ /// Transform into an iterator over the rows in the table
296
+ pub(crate) fn into_row_iter(self) -> IntoRowIter
297
+ {
298
+ IntoRowIter {
299
+ data: self.data.into_iter(),
300
+ columns: self.header.columns(),
301
+ row_count: self.row_count,
302
+ index: 0,
303
+ }
304
+ }
305
+ pub(crate) fn first_row(&self) -> Option<RowView>
306
+ {
307
+ self.row_view(0)
308
+ }
309
+ pub(crate) fn remove_first_rows(&mut self, n: usize)
310
+ {
311
+ let n = n * self.header.columns();
312
+ if n < self.data.len()
313
+ {
314
+ self.data.drain(0..n);
315
+ }
316
+ else
317
+ {
318
+ self.data.clear();
319
+ }
320
+ }
321
+ pub(crate) fn truncate(&mut self, n: usize)
322
+ {
323
+ let n = n * self.header.columns();
324
+ self.data.truncate(n);
325
+ }
326
+ }
327
+
328
+ /// A view into a single row of the ValueTable
329
+ #[derive(Debug)]
330
+ pub(crate) struct RowView<'a>
331
+ {
332
+ row: &'a [value::Value], // length = columns.len()
333
+ }
334
+
335
+ impl<'a> RowView<'a>
336
+ {
337
+ /// Create an owned Row by cloning the values in this row view
338
+ pub fn to_row(&self) -> Row
339
+ {
340
+ Row {
341
+ values: self.row.to_vec(),
342
+ }
343
+ }
344
+ /// Create an owned Row by cloning the values in this row view, and extend it to the given size
345
+ pub fn to_extended_row(&self, length: usize) -> Result<Row>
346
+ {
347
+ Row {
348
+ values: self.row.to_vec(),
349
+ }
350
+ .extended(length)
351
+ }
352
+ }
353
+
354
+ impl<'a> RowInterface for RowView<'a>
355
+ {
356
+ fn get(&self, index: usize) -> Result<&value::Value>
357
+ {
358
+ self.row.get(index).ok_or_else(|| {
359
+ InternalError::InvalidIndex {
360
+ index,
361
+ length: self.row.len(),
362
+ }
363
+ .into()
364
+ })
365
+ }
366
+ fn len(&self) -> usize
367
+ {
368
+ self.row.len()
369
+ }
370
+ }
371
+
372
+ /// Iterator over the row of the value table that yields RowViews
373
+ pub(crate) struct RowIter<'a>
374
+ {
375
+ data: &'a Vec<value::Value>,
376
+ columns: usize,
377
+ index: usize,
378
+ row_count: usize,
379
+ }
380
+
381
+ impl<'a> Iterator for RowIter<'a>
382
+ {
383
+ type Item = RowView<'a>;
384
+
385
+ fn next(&mut self) -> Option<Self::Item>
386
+ {
387
+ if self.columns == 0
388
+ {
389
+ if self.index < self.row_count
390
+ {
391
+ self.index += 1;
392
+ Some(RowView {
393
+ row: &self.data[0..0],
394
+ })
395
+ }
396
+ else
397
+ {
398
+ None
399
+ }
400
+ }
401
+ else
402
+ {
403
+ let start = self.index * self.columns;
404
+ let end = start + self.columns;
405
+
406
+ if self.columns == 0 || end > self.data.len()
407
+ {
408
+ return None;
409
+ }
410
+
411
+ let rv = RowView {
412
+ row: &self.data[start..end],
413
+ };
414
+
415
+ self.index += 1;
416
+
417
+ Some(rv)
418
+ }
419
+ }
420
+ }
421
+
422
+ pub(crate) struct IntoRowIter
423
+ {
424
+ data: std::vec::IntoIter<value::Value>,
425
+ columns: usize,
426
+ /// index used to output empty rows, when columns is 0
427
+ index: usize,
428
+ row_count: usize,
429
+ }
430
+
431
+ impl Iterator for IntoRowIter
432
+ {
433
+ type Item = Row;
434
+
435
+ fn next(&mut self) -> Option<Self::Item>
436
+ {
437
+ if self.columns == 0
438
+ {
439
+ if self.index < self.row_count
440
+ {
441
+ self.index += 1;
442
+ Some(Row::default())
443
+ }
444
+ else
445
+ {
446
+ None
447
+ }
448
+ }
449
+ else
450
+ {
451
+ let v: Vec<_> = self.data.by_ref().take(self.columns).collect();
452
+ if v.len() == 0
453
+ {
454
+ None
455
+ }
456
+ else
457
+ {
458
+ Some(Row::new(v, 0))
459
+ }
460
+ }
461
+ }
462
+ }
463
+
464
+ fn from_row_iterator<T>(iter: impl IntoIterator<Item = T>) -> Result<ValueTable<usize>>
465
+ where
466
+ T: TryInto<Row>,
467
+ crate::prelude::ErrorType: From<<T as TryInto<Row>>::Error>,
468
+ {
469
+ let mut data = Vec::new();
470
+ let mut header = None;
471
+ let mut row_count = 0;
472
+
473
+ let iter = iter.into_iter();
474
+ let (size_hint, _) = iter.size_hint();
475
+
476
+ for row in iter
477
+ {
478
+ let row = row.try_into()?;
479
+ row_count += 1;
480
+ match header
481
+ {
482
+ Some(header) =>
483
+ {
484
+ if header != row.len()
485
+ {
486
+ return Err(
487
+ InternalError::InvalidRowLength {
488
+ got: row.len(),
489
+ expected: header,
490
+ }
491
+ .into(),
492
+ );
493
+ }
494
+ }
495
+ None =>
496
+ {
497
+ header = Some(row.len());
498
+ data.reserve(row.len() * size_hint);
499
+ }
500
+ }
501
+
502
+ data.extend(row.values);
503
+ }
504
+
505
+ let header = header.unwrap_or_default();
506
+ Ok(ValueTable {
507
+ header,
508
+ data,
509
+ row_count,
510
+ })
511
+ }
512
+
513
+ impl FromIterator<Row> for Result<ValueTable<usize>>
514
+ {
515
+ fn from_iter<I: IntoIterator<Item = Row>>(iter: I) -> Self
516
+ {
517
+ from_row_iterator(iter)
518
+ }
519
+ }
520
+
521
+ pub(crate) struct RowResult(pub Result<Row>);
522
+
523
+ impl TryInto<Row> for RowResult
524
+ {
525
+ type Error = ErrorType;
526
+ fn try_into(self) -> Result<Row>
527
+ {
528
+ self.0
529
+ }
530
+ }
531
+
532
+ impl FromIterator<RowResult> for Result<ValueTable<usize>>
533
+ {
534
+ fn from_iter<I: IntoIterator<Item = RowResult>>(iter: I) -> Self
535
+ {
536
+ from_row_iterator(iter)
537
+ }
538
+ }
539
+
540
+ impl TryFrom<Vec<Row>> for ValueTable<usize>
541
+ {
542
+ type Error = crate::prelude::ErrorType;
543
+ fn try_from(value: Vec<Row>) -> Result<Self>
544
+ {
545
+ value.into_iter().collect()
546
+ }
547
+ }
548
+
549
+ #[cfg(test)]
550
+ mod tests
551
+ {
552
+ use super::*;
553
+ #[test]
554
+ fn test_table_0_column()
555
+ {
556
+ let mut table = ValueTable::new(0);
557
+
558
+ // Test emptiness
559
+ assert_eq!(table.row_count(), 0);
560
+ let mut it = table.row_iter();
561
+ assert!(it.next().is_none());
562
+ assert!(table.row_view(0).is_none());
563
+
564
+ // Add a row
565
+ table.add_full_row(Default::default()).unwrap();
566
+ assert_eq!(table.row_count(), 1);
567
+ let mut it = table.row_iter();
568
+ let first_row = it.next().unwrap();
569
+ assert_eq!(first_row.len(), 0);
570
+ assert!(it.next().is_none());
571
+ assert!(table.row_view(0).is_some());
572
+ assert!(table.row_view(1).is_none());
573
+ }
574
+ #[test]
575
+ fn test_table_1_column()
576
+ {
577
+ let mut table = ValueTable::new(1);
578
+
579
+ // Test emptiness
580
+ assert_eq!(table.row_count(), 0);
581
+ let mut it = table.row_iter();
582
+ assert!(it.next().is_none());
583
+ assert!(table.row_view(0).is_none());
584
+
585
+ // Add a row
586
+ table.add_full_row(Row::new(vec![1.into()], 0)).unwrap();
587
+ assert_eq!(table.row_count(), 1);
588
+ let mut it = table.row_iter();
589
+ let first_row = it.next().unwrap();
590
+ assert_eq!(first_row.len(), 1);
591
+ assert_eq!(*first_row.get(0).unwrap(), (1 as i64).into());
592
+ assert!(it.next().is_none());
593
+ let first_row = table.row_view(0).unwrap();
594
+ assert_eq!(first_row.len(), 1);
595
+ assert_eq!(*first_row.get(0).unwrap(), (1 as i64).into());
596
+ assert!(table.row_view(1).is_none());
597
+ }
598
+ #[test]
599
+ fn test_row()
600
+ {
601
+ let row = Row::new(vec!["a".into(), 1.0.into()], 1);
602
+ assert_eq!(row.len(), 3);
603
+ assert_eq!(*row.get(0).unwrap(), "a".into());
604
+ assert_eq!(*row.get(1).unwrap(), 1.0.into());
605
+ assert!(row.get(2).unwrap().is_null());
606
+ assert!(row.get(3).is_err());
607
+
608
+ let row = row.extended(4).unwrap();
609
+ assert_eq!(row.len(), 4);
610
+ assert_eq!(*row.get(0).unwrap(), "a".into());
611
+ assert_eq!(*row.get(1).unwrap(), 1.0.into());
612
+ assert!(row.get(2).unwrap().is_null());
613
+ assert!(row.get(3).unwrap().is_null());
614
+ assert!(row.get(4).is_err());
615
+ }
616
+ }
@@ -0,0 +1,22 @@
1
+ WITH
2
+ node_labels AS (
3
+ SELECT DISTINCT value AS label
4
+ FROM gqlite_{{ graph_name }}_nodes, json_each(gqlite_{{ graph_name }}_nodes.labels)
5
+ ),
6
+ node_properties AS (
7
+ SELECT 1
8
+ FROM gqlite_{{ graph_name }}_nodes, json_each(gqlite_{{ graph_name }}_nodes.properties)
9
+ WHERE json_each.value IS NOT NULL
10
+ ),
11
+ edge_properties AS (
12
+ SELECT 1
13
+ FROM gqlite_{{ graph_name }}_edges, json_each(gqlite_{{ graph_name }}_edges.properties)
14
+ WHERE json_each.value IS NOT NULL
15
+ )
16
+
17
+ SELECT
18
+ (SELECT COUNT(*) FROM gqlite_{{ graph_name }}_nodes) AS node_count,
19
+ (SELECT COUNT(*) FROM gqlite_{{ graph_name }}_edges) AS edge_count,
20
+ (SELECT COUNT(*) FROM node_labels) AS unique_node_label_count,
21
+ (SELECT COUNT(*) FROM node_properties)
22
+ + (SELECT COUNT(*) FROM edge_properties) AS total_property_count;
@@ -0,0 +1,3 @@
1
+ SELECT COUNT(*) FROM gqlite_{{ graph_name }}_edges AS e
2
+ JOIN gqlite_{{ graph_name }}_nodes AS n ON n.id = e.left OR n.id = e.right
3
+ WHERE hex(n.node_key) in ('{{ keys | join("', '") }}')
@@ -0,0 +1,6 @@
1
+ INSERT INTO gqlite_{{ graph_name }}_edges (edge_key, labels, properties, left, right)
2
+ VALUES (
3
+ ?1, ?2, ?3,
4
+ (SELECT id FROM gqlite_{{ graph_name }}_nodes WHERE node_key = ?4),
5
+ (SELECT id FROM gqlite_{{ graph_name }}_nodes WHERE node_key = ?5)
6
+ );
@@ -0,0 +1 @@
1
+ DELETE FROM gqlite_{{ graph_name }}_edges WHERE hex(edge_key) IN ('{{ keys | join("', '") }}')
@@ -0,0 +1,2 @@
1
+ WITH source_delete AS NOT MATERIALIZED (SELECT id FROM gqlite_{{ graph_name }}_nodes WHERE hex(node_key) in ('{{ keys | join("', '") }}'))
2
+ DELETE FROM gqlite_{{ graph_name }}_edges WHERE left IN source_delete OR right IN source_delete