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,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 @@
|
|
1
|
+
DELETE FROM gqlite_{{ graph_name }}_edges WHERE hex(edge_key) IN ('{{ keys | join("', '") }}')
|