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