gqlite 1.7.0 → 1.8.1
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/db-index/Cargo.toml +2 -2
- data/ext/gqlitedb/src/aggregators.rs +28 -0
- data/ext/gqlitedb/src/compiler/expression_analyser.rs +33 -0
- data/ext/gqlitedb/src/compiler/variables_manager.rs +2 -1
- data/ext/gqlitedb/src/compiler.rs +25 -1
- data/ext/gqlitedb/src/connection.rs +2 -2
- data/ext/gqlitedb/src/consts.rs +1 -1
- data/ext/gqlitedb/src/error.rs +7 -0
- data/ext/gqlitedb/src/interpreter/evaluators.rs +62 -6
- data/ext/gqlitedb/src/interpreter/instructions.rs +5 -0
- data/ext/gqlitedb/src/planner.rs +13 -0
- data/ext/gqlitedb/src/store/redb.rs +1 -1
- data/ext/gqlitedb/src/tests/compiler.rs +1 -0
- data/ext/gqlitedb/src/tests/connection/postgres.rs +22 -0
- data/ext/gqlitedb/src/tests/connection/redb.rs +16 -0
- data/ext/gqlitedb/src/tests/connection/sqlite.rs +16 -0
- data/ext/gqlitedb/src/tests/connection.rs +64 -0
- data/ext/gqlitedb/src/tests/planner.rs +1 -0
- data/ext/gqlitedb/src/tests/templates/ast.rs +10 -0
- data/ext/gqlitedb/src/tests/templates/programs.rs +12 -0
- data/ext/gqlparser/src/oc/ast.rs +20 -0
- data/ext/gqlparser/src/oc/lexer.rs +11 -2
- data/ext/gqlparser/src/oc/parser/tests.rs +370 -9
- data/ext/gqlparser/src/oc/parser.rs +116 -39
- data/ext/gqlparser/src/oc/string.rs +172 -0
- data/ext/gqlparser/src/oc.rs +1 -0
- data/ext/graphcore/src/value/value_map.rs +2 -2
- data/ext/graphcore/src/value.rs +1 -0
- metadata +2 -1
|
@@ -73,6 +73,7 @@ pub(crate) fn create_named_node() -> Program
|
|
|
73
73
|
limit: None,
|
|
74
74
|
skip: None,
|
|
75
75
|
order_by: vec![],
|
|
76
|
+
distinct: false,
|
|
76
77
|
},
|
|
77
78
|
variables_sizes: create_variable_size(2, 0),
|
|
78
79
|
},
|
|
@@ -138,6 +139,7 @@ pub(crate) fn create_named_node_double_return() -> Program
|
|
|
138
139
|
limit: None,
|
|
139
140
|
skip: None,
|
|
140
141
|
order_by: vec![],
|
|
142
|
+
distinct: false,
|
|
141
143
|
},
|
|
142
144
|
variables_sizes: create_variable_size(3, 0),
|
|
143
145
|
},
|
|
@@ -166,6 +168,7 @@ pub(crate) fn double_with_return() -> Program
|
|
|
166
168
|
limit: None,
|
|
167
169
|
skip: None,
|
|
168
170
|
order_by: vec![],
|
|
171
|
+
distinct: false,
|
|
169
172
|
},
|
|
170
173
|
variables_sizes: create_variable_size(2, 0),
|
|
171
174
|
},
|
|
@@ -187,6 +190,7 @@ pub(crate) fn double_with_return() -> Program
|
|
|
187
190
|
limit: None,
|
|
188
191
|
skip: None,
|
|
189
192
|
order_by: vec![],
|
|
193
|
+
distinct: false,
|
|
190
194
|
},
|
|
191
195
|
variables_sizes: create_variable_size(4, 0),
|
|
192
196
|
},
|
|
@@ -204,6 +208,7 @@ pub(crate) fn double_with_return() -> Program
|
|
|
204
208
|
limit: None,
|
|
205
209
|
skip: None,
|
|
206
210
|
order_by: vec![],
|
|
211
|
+
distinct: false,
|
|
207
212
|
},
|
|
208
213
|
variables_sizes: create_variable_size(2, 0),
|
|
209
214
|
},
|
|
@@ -239,6 +244,7 @@ pub(crate) fn unwind() -> Program
|
|
|
239
244
|
limit: None,
|
|
240
245
|
skip: None,
|
|
241
246
|
order_by: vec![],
|
|
247
|
+
distinct: false,
|
|
242
248
|
},
|
|
243
249
|
variables_sizes: create_variable_size(1, 0),
|
|
244
250
|
},
|
|
@@ -294,6 +300,7 @@ pub(crate) fn match_loop() -> Program
|
|
|
294
300
|
limit: None,
|
|
295
301
|
skip: None,
|
|
296
302
|
order_by: vec![],
|
|
303
|
+
distinct: false,
|
|
297
304
|
},
|
|
298
305
|
variables_sizes: create_variable_size(1, 0),
|
|
299
306
|
},
|
|
@@ -333,6 +340,7 @@ pub(crate) fn optional_match() -> Program
|
|
|
333
340
|
limit: None,
|
|
334
341
|
skip: None,
|
|
335
342
|
order_by: vec![],
|
|
343
|
+
distinct: false,
|
|
336
344
|
},
|
|
337
345
|
variables_sizes: create_variable_size(1, 0),
|
|
338
346
|
},
|
|
@@ -375,6 +383,7 @@ pub(crate) fn match_count(function_manager: &functions::Manager) -> Program
|
|
|
375
383
|
aggregator: function_manager
|
|
376
384
|
.get_aggregator::<error::CompileTimeError>("count")
|
|
377
385
|
.unwrap(),
|
|
386
|
+
distinct: false,
|
|
378
387
|
},
|
|
379
388
|
)],
|
|
380
389
|
},
|
|
@@ -384,6 +393,7 @@ pub(crate) fn match_count(function_manager: &functions::Manager) -> Program
|
|
|
384
393
|
limit: None,
|
|
385
394
|
skip: None,
|
|
386
395
|
order_by: vec![],
|
|
396
|
+
distinct: false,
|
|
387
397
|
},
|
|
388
398
|
variables_sizes: create_variable_size(2, 1),
|
|
389
399
|
},
|
|
@@ -445,6 +455,7 @@ pub(crate) fn aggregation(function_manager: &functions::Manager) -> Program
|
|
|
445
455
|
aggregator: function_manager
|
|
446
456
|
.get_aggregator::<error::CompileTimeError>("count")
|
|
447
457
|
.unwrap(),
|
|
458
|
+
distinct: false,
|
|
448
459
|
},
|
|
449
460
|
)],
|
|
450
461
|
},
|
|
@@ -455,6 +466,7 @@ pub(crate) fn aggregation(function_manager: &functions::Manager) -> Program
|
|
|
455
466
|
limit: None,
|
|
456
467
|
skip: None,
|
|
457
468
|
order_by: vec![],
|
|
469
|
+
distinct: false,
|
|
458
470
|
},
|
|
459
471
|
variables_sizes: create_variable_size(3, 1),
|
|
460
472
|
},
|
data/ext/gqlparser/src/oc/ast.rs
CHANGED
|
@@ -378,11 +378,22 @@ pub struct OrderBy
|
|
|
378
378
|
#[derive(Default, Debug)]
|
|
379
379
|
pub struct Modifiers
|
|
380
380
|
{
|
|
381
|
+
pub distinct: bool,
|
|
381
382
|
pub skip: Option<Expression>,
|
|
382
383
|
pub limit: Option<Expression>,
|
|
383
384
|
pub order_by: Option<OrderBy>,
|
|
384
385
|
}
|
|
385
386
|
|
|
387
|
+
impl Modifiers
|
|
388
|
+
{
|
|
389
|
+
/// Set the distinct field
|
|
390
|
+
pub(crate) fn set_distinct(mut self, distinct: bool) -> Self
|
|
391
|
+
{
|
|
392
|
+
self.distinct = distinct;
|
|
393
|
+
self
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
386
397
|
// Expressions
|
|
387
398
|
|
|
388
399
|
#[derive(Debug, Clone, PartialEq)]
|
|
@@ -411,6 +422,10 @@ pub enum Expression
|
|
|
411
422
|
RelationalIn(Box<RelationalIn>),
|
|
412
423
|
RelationalNotIn(Box<RelationalNotIn>),
|
|
413
424
|
|
|
425
|
+
Contains(Box<Contains>),
|
|
426
|
+
EndsWith(Box<EndsWith>),
|
|
427
|
+
StartsWith(Box<StartsWith>),
|
|
428
|
+
|
|
414
429
|
Addition(Box<Addition>),
|
|
415
430
|
Subtraction(Box<Subtraction>),
|
|
416
431
|
Multiplication(Box<Multiplication>),
|
|
@@ -601,6 +616,7 @@ pub struct FunctionCall
|
|
|
601
616
|
{
|
|
602
617
|
pub name: String,
|
|
603
618
|
pub arguments: Vec<Expression>,
|
|
619
|
+
pub distinct: bool,
|
|
604
620
|
}
|
|
605
621
|
|
|
606
622
|
create_from_expr! {FunctionCall}
|
|
@@ -630,6 +646,10 @@ create_binary_op! {RelationalSuperiorEqual}
|
|
|
630
646
|
create_binary_op! {RelationalIn}
|
|
631
647
|
create_binary_op! {RelationalNotIn}
|
|
632
648
|
|
|
649
|
+
create_binary_op! {Contains}
|
|
650
|
+
create_binary_op! {EndsWith}
|
|
651
|
+
create_binary_op! {StartsWith}
|
|
652
|
+
|
|
633
653
|
create_binary_op! {Addition}
|
|
634
654
|
create_binary_op! {Subtraction}
|
|
635
655
|
create_binary_op! {Multiplication}
|
|
@@ -22,17 +22,23 @@ pub(crate) enum Token
|
|
|
22
22
|
By,
|
|
23
23
|
#[token("call", ignore(case))]
|
|
24
24
|
Call,
|
|
25
|
+
#[token("contains", ignore(case))]
|
|
26
|
+
Contains,
|
|
27
|
+
#[token("create", ignore(case))]
|
|
28
|
+
Create,
|
|
25
29
|
#[token("desc", ignore(case))]
|
|
26
30
|
#[token("descending", ignore(case))]
|
|
27
31
|
Desc,
|
|
28
|
-
#[token("create", ignore(case))]
|
|
29
|
-
Create,
|
|
30
32
|
#[token("delete", ignore(case))]
|
|
31
33
|
Delete,
|
|
32
34
|
#[token("detach", ignore(case))]
|
|
33
35
|
Detach,
|
|
36
|
+
#[token("distinct", ignore(case))]
|
|
37
|
+
Distinct,
|
|
34
38
|
#[token("drop", ignore(case))]
|
|
35
39
|
Drop,
|
|
40
|
+
#[token("ends", ignore(case))]
|
|
41
|
+
Ends,
|
|
36
42
|
#[token("exists", ignore(case))]
|
|
37
43
|
Exists,
|
|
38
44
|
#[token("for", ignore(case))]
|
|
@@ -65,6 +71,8 @@ pub(crate) enum Token
|
|
|
65
71
|
Search,
|
|
66
72
|
#[token("set", ignore(case))]
|
|
67
73
|
Set,
|
|
74
|
+
#[token("starts", ignore(case))]
|
|
75
|
+
Starts,
|
|
68
76
|
#[token("not", ignore(case))]
|
|
69
77
|
Not,
|
|
70
78
|
#[token("null", ignore(case))]
|
|
@@ -188,6 +196,7 @@ impl Token
|
|
|
188
196
|
| Token::By
|
|
189
197
|
| Token::Call
|
|
190
198
|
| Token::Desc
|
|
199
|
+
| Token::Distinct
|
|
191
200
|
| Token::Create
|
|
192
201
|
| Token::Delete
|
|
193
202
|
| Token::Detach
|
|
@@ -101,6 +101,17 @@ where
|
|
|
101
101
|
assert_eq!(unwrap_nom(input.clone(), parser.parse(input)), exp);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
fn parse_string<P>(s: &str, mut parser: P, exp: impl Into<String>)
|
|
105
|
+
where
|
|
106
|
+
for<'a> P: nom::Parser<Input<'a>, Output = String, Error = Error>,
|
|
107
|
+
{
|
|
108
|
+
let exp = exp.into();
|
|
109
|
+
let ctx = Context::new(s);
|
|
110
|
+
let tokens = lexer::tokenize(s).expect("tokenization failed");
|
|
111
|
+
let input = Input(&tokens, &ctx);
|
|
112
|
+
assert_eq!(unwrap_nom(input.clone(), parser.parse(input)), exp);
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
#[test]
|
|
105
116
|
fn test_oc_parse_context_variable_identity()
|
|
106
117
|
{
|
|
@@ -131,19 +142,19 @@ fn test_oc_parse_parameter_name()
|
|
|
131
142
|
#[test]
|
|
132
143
|
fn test_oc_parse_string_literal_double_quote()
|
|
133
144
|
{
|
|
134
|
-
|
|
145
|
+
parse_string(r#""hello world""#, string_literal, "hello world");
|
|
135
146
|
}
|
|
136
147
|
|
|
137
148
|
#[test]
|
|
138
149
|
fn test_oc_parse_string_literal_single_quote()
|
|
139
150
|
{
|
|
140
|
-
|
|
141
|
-
|
|
151
|
+
parse_string("'hello world'", string_literal, "hello world");
|
|
152
|
+
parse_string("', as#?lßdj '", string_literal, ", as#?lßdj ");
|
|
142
153
|
}
|
|
143
154
|
#[test]
|
|
144
155
|
fn test_oc_parse_string_literal_backtick()
|
|
145
156
|
{
|
|
146
|
-
|
|
157
|
+
parse_string("`hello`", string_literal, "hello");
|
|
147
158
|
}
|
|
148
159
|
|
|
149
160
|
#[test]
|
|
@@ -307,6 +318,7 @@ fn test_oc_parse_function_call()
|
|
|
307
318
|
ast::Expression::Value(ast::Value { value: 1.into() }),
|
|
308
319
|
ast::Expression::Value(ast::Value { value: 2.into() }),
|
|
309
320
|
],
|
|
321
|
+
distinct: false,
|
|
310
322
|
},
|
|
311
323
|
);
|
|
312
324
|
}
|
|
@@ -320,6 +332,7 @@ fn test_oc_parse_function_call_all()
|
|
|
320
332
|
ast::FunctionCall {
|
|
321
333
|
name: "func".to_string(),
|
|
322
334
|
arguments: vec![ast::Expression::Value(ast::Value { value: 0.into() })],
|
|
335
|
+
distinct: false,
|
|
323
336
|
},
|
|
324
337
|
);
|
|
325
338
|
}
|
|
@@ -384,6 +397,7 @@ fn test_oc_parse_relational_binary_operator()
|
|
|
384
397
|
}
|
|
385
398
|
.into(),
|
|
386
399
|
],
|
|
400
|
+
distinct: false,
|
|
387
401
|
}
|
|
388
402
|
.into(),
|
|
389
403
|
right: ast::FunctionCall {
|
|
@@ -397,6 +411,7 @@ fn test_oc_parse_relational_binary_operator()
|
|
|
397
411
|
}
|
|
398
412
|
.into(),
|
|
399
413
|
],
|
|
414
|
+
distinct: false,
|
|
400
415
|
}
|
|
401
416
|
.into(),
|
|
402
417
|
},
|
|
@@ -1261,6 +1276,35 @@ fn test_oc_parse_return_n()
|
|
|
1261
1276
|
compare_ast(vec![stmt], vec![exppected_stmt]);
|
|
1262
1277
|
}
|
|
1263
1278
|
|
|
1279
|
+
#[test]
|
|
1280
|
+
fn test_oc_parse_return_distinct_n()
|
|
1281
|
+
{
|
|
1282
|
+
let stmt = parse("RETURN DISTINCT n", return_statement);
|
|
1283
|
+
|
|
1284
|
+
let exppected_stmt = ast::Statement::Return(ast::Return {
|
|
1285
|
+
all: false,
|
|
1286
|
+
expressions: vec![ast::NamedExpression {
|
|
1287
|
+
identifier: ast::VariableIdentifier {
|
|
1288
|
+
name: "n".to_string(),
|
|
1289
|
+
id: 0,
|
|
1290
|
+
},
|
|
1291
|
+
expression: ast::Variable {
|
|
1292
|
+
identifier: ast::VariableIdentifier {
|
|
1293
|
+
name: "n".to_string(),
|
|
1294
|
+
id: 0,
|
|
1295
|
+
},
|
|
1296
|
+
}
|
|
1297
|
+
.into(),
|
|
1298
|
+
}],
|
|
1299
|
+
where_expression: None,
|
|
1300
|
+
modifiers: ast::Modifiers {
|
|
1301
|
+
distinct: true,
|
|
1302
|
+
..Default::default()
|
|
1303
|
+
},
|
|
1304
|
+
});
|
|
1305
|
+
compare_ast(vec![stmt], vec![exppected_stmt]);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1264
1308
|
#[test]
|
|
1265
1309
|
fn test_oc_parse_return_n_m()
|
|
1266
1310
|
{
|
|
@@ -1411,9 +1455,8 @@ fn test_oc_parse_return_n_modifiers()
|
|
|
1411
1455
|
}],
|
|
1412
1456
|
where_expression: None,
|
|
1413
1457
|
modifiers: ast::Modifiers {
|
|
1414
|
-
order_by: None,
|
|
1415
1458
|
limit: Some(ast::Expression::Value(ast::Value { value: (-1).into() })),
|
|
1416
|
-
|
|
1459
|
+
..Default::default()
|
|
1417
1460
|
},
|
|
1418
1461
|
}),
|
|
1419
1462
|
);
|
|
@@ -1529,6 +1572,7 @@ fn test_oc_parse_modifiers()
|
|
|
1529
1572
|
}),
|
|
1530
1573
|
limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
|
|
1531
1574
|
skip: Some(ast::Expression::Value(ast::Value { value: 2.into() })),
|
|
1575
|
+
..Default::default()
|
|
1532
1576
|
},
|
|
1533
1577
|
);
|
|
1534
1578
|
compare_parse_to_ast(
|
|
@@ -1569,15 +1613,15 @@ fn test_oc_parse_modifiers()
|
|
|
1569
1613
|
}),
|
|
1570
1614
|
limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
|
|
1571
1615
|
skip: None,
|
|
1616
|
+
..Default::default()
|
|
1572
1617
|
},
|
|
1573
1618
|
);
|
|
1574
1619
|
compare_parse_to_ast(
|
|
1575
1620
|
"LIMIT -1",
|
|
1576
1621
|
modifiers,
|
|
1577
1622
|
ast::Modifiers {
|
|
1578
|
-
order_by: None,
|
|
1579
1623
|
limit: Some(ast::Expression::Value(ast::Value { value: (-1).into() })),
|
|
1580
|
-
|
|
1624
|
+
..Default::default()
|
|
1581
1625
|
},
|
|
1582
1626
|
);
|
|
1583
1627
|
}
|
|
@@ -1638,7 +1682,7 @@ fn test_oc_parse_with_modifiers()
|
|
|
1638
1682
|
],
|
|
1639
1683
|
}),
|
|
1640
1684
|
limit: Some(ast::Expression::Value(ast::Value { value: 4.into() })),
|
|
1641
|
-
|
|
1685
|
+
..Default::default()
|
|
1642
1686
|
},
|
|
1643
1687
|
},
|
|
1644
1688
|
);
|
|
@@ -2127,6 +2171,72 @@ fn test_oc_parse_match_with_search_basic()
|
|
|
2127
2171
|
}
|
|
2128
2172
|
}
|
|
2129
2173
|
|
|
2174
|
+
#[test]
|
|
2175
|
+
fn test_oc_parse_starts_with()
|
|
2176
|
+
{
|
|
2177
|
+
compare_parse_to_ast(
|
|
2178
|
+
"s STARTS WITH 'hello'",
|
|
2179
|
+
expression,
|
|
2180
|
+
ast::StartsWith {
|
|
2181
|
+
left: ast::Variable {
|
|
2182
|
+
identifier: ast::VariableIdentifier {
|
|
2183
|
+
name: "s".to_string(),
|
|
2184
|
+
id: 0,
|
|
2185
|
+
},
|
|
2186
|
+
}
|
|
2187
|
+
.into(),
|
|
2188
|
+
right: ast::Value {
|
|
2189
|
+
value: "hello".into(),
|
|
2190
|
+
}
|
|
2191
|
+
.into(),
|
|
2192
|
+
},
|
|
2193
|
+
);
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
#[test]
|
|
2197
|
+
fn test_oc_parse_ends_with()
|
|
2198
|
+
{
|
|
2199
|
+
compare_parse_to_ast(
|
|
2200
|
+
"s ENDS WITH 'world'",
|
|
2201
|
+
expression,
|
|
2202
|
+
ast::EndsWith {
|
|
2203
|
+
left: ast::Variable {
|
|
2204
|
+
identifier: ast::VariableIdentifier {
|
|
2205
|
+
name: "s".to_string(),
|
|
2206
|
+
id: 0,
|
|
2207
|
+
},
|
|
2208
|
+
}
|
|
2209
|
+
.into(),
|
|
2210
|
+
right: ast::Value {
|
|
2211
|
+
value: "world".into(),
|
|
2212
|
+
}
|
|
2213
|
+
.into(),
|
|
2214
|
+
},
|
|
2215
|
+
);
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
#[test]
|
|
2219
|
+
fn test_oc_parse_contains()
|
|
2220
|
+
{
|
|
2221
|
+
compare_parse_to_ast(
|
|
2222
|
+
"s CONTAINS 'test'",
|
|
2223
|
+
expression,
|
|
2224
|
+
ast::Contains {
|
|
2225
|
+
left: ast::Variable {
|
|
2226
|
+
identifier: ast::VariableIdentifier {
|
|
2227
|
+
name: "s".to_string(),
|
|
2228
|
+
id: 0,
|
|
2229
|
+
},
|
|
2230
|
+
}
|
|
2231
|
+
.into(),
|
|
2232
|
+
right: ast::Value {
|
|
2233
|
+
value: "test".into(),
|
|
2234
|
+
}
|
|
2235
|
+
.into(),
|
|
2236
|
+
},
|
|
2237
|
+
);
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2130
2240
|
#[test]
|
|
2131
2241
|
fn test_oc_parse_match_with_search_and_score()
|
|
2132
2242
|
{
|
|
@@ -2282,3 +2392,254 @@ fn test_oc_parse_create_vector_index_if_not_exists()
|
|
|
2282
2392
|
},
|
|
2283
2393
|
);
|
|
2284
2394
|
}
|
|
2395
|
+
|
|
2396
|
+
#[test]
|
|
2397
|
+
fn test_oc_parse_not_wraps_full_comparison()
|
|
2398
|
+
{
|
|
2399
|
+
compare_parse_to_ast(
|
|
2400
|
+
r#"NOT n.name = "Alice""#,
|
|
2401
|
+
expression,
|
|
2402
|
+
ast::LogicalNegation {
|
|
2403
|
+
value: ast::RelationalEqual {
|
|
2404
|
+
left: ast::MemberAccess {
|
|
2405
|
+
left: ast::Variable {
|
|
2406
|
+
identifier: ast::VariableIdentifier {
|
|
2407
|
+
name: "n".to_string(),
|
|
2408
|
+
id: 0,
|
|
2409
|
+
},
|
|
2410
|
+
}
|
|
2411
|
+
.into(),
|
|
2412
|
+
path: vec!["name".to_string()],
|
|
2413
|
+
}
|
|
2414
|
+
.into(),
|
|
2415
|
+
right: ast::Value {
|
|
2416
|
+
value: "Alice".into(),
|
|
2417
|
+
}
|
|
2418
|
+
.into(),
|
|
2419
|
+
}
|
|
2420
|
+
.into(),
|
|
2421
|
+
},
|
|
2422
|
+
);
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
#[test]
|
|
2426
|
+
fn test_oc_parse_not_and_precedence()
|
|
2427
|
+
{
|
|
2428
|
+
compare_parse_to_ast(
|
|
2429
|
+
"NOT a = 1 AND c = 2",
|
|
2430
|
+
expression,
|
|
2431
|
+
ast::LogicalAnd {
|
|
2432
|
+
left: ast::LogicalNegation {
|
|
2433
|
+
value: ast::RelationalEqual {
|
|
2434
|
+
left: ast::Variable {
|
|
2435
|
+
identifier: ast::VariableIdentifier {
|
|
2436
|
+
name: "a".to_string(),
|
|
2437
|
+
id: 0,
|
|
2438
|
+
},
|
|
2439
|
+
}
|
|
2440
|
+
.into(),
|
|
2441
|
+
right: ast::Value { value: 1i64.into() }.into(),
|
|
2442
|
+
}
|
|
2443
|
+
.into(),
|
|
2444
|
+
}
|
|
2445
|
+
.into(),
|
|
2446
|
+
right: ast::RelationalEqual {
|
|
2447
|
+
left: ast::Variable {
|
|
2448
|
+
identifier: ast::VariableIdentifier {
|
|
2449
|
+
name: "c".to_string(),
|
|
2450
|
+
id: 1,
|
|
2451
|
+
},
|
|
2452
|
+
}
|
|
2453
|
+
.into(),
|
|
2454
|
+
right: ast::Value { value: 2i64.into() }.into(),
|
|
2455
|
+
}
|
|
2456
|
+
.into(),
|
|
2457
|
+
},
|
|
2458
|
+
);
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
#[test]
|
|
2462
|
+
fn test_oc_parse_double_not()
|
|
2463
|
+
{
|
|
2464
|
+
compare_parse_to_ast(
|
|
2465
|
+
"NOT NOT a = 1",
|
|
2466
|
+
expression,
|
|
2467
|
+
ast::LogicalNegation {
|
|
2468
|
+
value: ast::LogicalNegation {
|
|
2469
|
+
value: ast::RelationalEqual {
|
|
2470
|
+
left: ast::Variable {
|
|
2471
|
+
identifier: ast::VariableIdentifier {
|
|
2472
|
+
name: "a".to_string(),
|
|
2473
|
+
id: 0,
|
|
2474
|
+
},
|
|
2475
|
+
}
|
|
2476
|
+
.into(),
|
|
2477
|
+
right: ast::Value { value: 1i64.into() }.into(),
|
|
2478
|
+
}
|
|
2479
|
+
.into(),
|
|
2480
|
+
}
|
|
2481
|
+
.into(),
|
|
2482
|
+
},
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
#[test]
|
|
2487
|
+
fn test_oc_parse_not_true_still_works()
|
|
2488
|
+
{
|
|
2489
|
+
compare_parse_to_ast(
|
|
2490
|
+
"NOT true",
|
|
2491
|
+
expression,
|
|
2492
|
+
ast::LogicalNegation {
|
|
2493
|
+
value: ast::Value { value: true.into() }.into(),
|
|
2494
|
+
},
|
|
2495
|
+
);
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
#[test]
|
|
2499
|
+
fn test_oc_parse_is_not_null_unaffected()
|
|
2500
|
+
{
|
|
2501
|
+
compare_parse_to_ast(
|
|
2502
|
+
"n.age IS NOT NULL",
|
|
2503
|
+
expression,
|
|
2504
|
+
ast::IsNotNull {
|
|
2505
|
+
value: ast::MemberAccess {
|
|
2506
|
+
left: ast::Variable {
|
|
2507
|
+
identifier: ast::VariableIdentifier {
|
|
2508
|
+
name: "n".to_string(),
|
|
2509
|
+
id: 0,
|
|
2510
|
+
},
|
|
2511
|
+
}
|
|
2512
|
+
.into(),
|
|
2513
|
+
path: vec!["age".to_string()],
|
|
2514
|
+
}
|
|
2515
|
+
.into(),
|
|
2516
|
+
},
|
|
2517
|
+
);
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
#[test]
|
|
2521
|
+
fn test_oc_parse_not_in_still_works()
|
|
2522
|
+
{
|
|
2523
|
+
compare_parse_to_ast(
|
|
2524
|
+
"x NOT IN [1, 2]",
|
|
2525
|
+
expression,
|
|
2526
|
+
ast::LogicalNegation {
|
|
2527
|
+
value: ast::RelationalIn {
|
|
2528
|
+
left: ast::Variable {
|
|
2529
|
+
identifier: ast::VariableIdentifier {
|
|
2530
|
+
name: "x".to_string(),
|
|
2531
|
+
id: 0,
|
|
2532
|
+
},
|
|
2533
|
+
}
|
|
2534
|
+
.into(),
|
|
2535
|
+
right: ast::Array {
|
|
2536
|
+
array: vec![
|
|
2537
|
+
ast::Value { value: 1i64.into() }.into(),
|
|
2538
|
+
ast::Value { value: 2i64.into() }.into(),
|
|
2539
|
+
],
|
|
2540
|
+
}
|
|
2541
|
+
.into(),
|
|
2542
|
+
}
|
|
2543
|
+
.into(),
|
|
2544
|
+
},
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
#[test]
|
|
2549
|
+
fn test_oc_parse_count_distinct()
|
|
2550
|
+
{
|
|
2551
|
+
compare_parse_to_ast(
|
|
2552
|
+
"count(DISTINCT x)",
|
|
2553
|
+
expression,
|
|
2554
|
+
ast::FunctionCall {
|
|
2555
|
+
name: "count".to_string(),
|
|
2556
|
+
arguments: vec![
|
|
2557
|
+
ast::Variable {
|
|
2558
|
+
identifier: ast::VariableIdentifier {
|
|
2559
|
+
name: "x".to_string(),
|
|
2560
|
+
id: 0,
|
|
2561
|
+
},
|
|
2562
|
+
}
|
|
2563
|
+
.into(),
|
|
2564
|
+
],
|
|
2565
|
+
distinct: true,
|
|
2566
|
+
},
|
|
2567
|
+
);
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
#[test]
|
|
2571
|
+
fn test_oc_parse_count_without_distinct_defaults_false()
|
|
2572
|
+
{
|
|
2573
|
+
compare_parse_to_ast(
|
|
2574
|
+
"count(x)",
|
|
2575
|
+
expression,
|
|
2576
|
+
ast::FunctionCall {
|
|
2577
|
+
name: "count".to_string(),
|
|
2578
|
+
arguments: vec![
|
|
2579
|
+
ast::Variable {
|
|
2580
|
+
identifier: ast::VariableIdentifier {
|
|
2581
|
+
name: "x".to_string(),
|
|
2582
|
+
id: 0,
|
|
2583
|
+
},
|
|
2584
|
+
}
|
|
2585
|
+
.into(),
|
|
2586
|
+
],
|
|
2587
|
+
distinct: false,
|
|
2588
|
+
},
|
|
2589
|
+
);
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
#[test]
|
|
2593
|
+
fn test_oc_parse_sum_distinct()
|
|
2594
|
+
{
|
|
2595
|
+
compare_parse_to_ast(
|
|
2596
|
+
"sum(DISTINCT n.age)",
|
|
2597
|
+
expression,
|
|
2598
|
+
ast::FunctionCall {
|
|
2599
|
+
name: "sum".to_string(),
|
|
2600
|
+
arguments: vec![
|
|
2601
|
+
ast::MemberAccess {
|
|
2602
|
+
left: ast::Variable {
|
|
2603
|
+
identifier: ast::VariableIdentifier {
|
|
2604
|
+
name: "n".to_string(),
|
|
2605
|
+
id: 0,
|
|
2606
|
+
},
|
|
2607
|
+
}
|
|
2608
|
+
.into(),
|
|
2609
|
+
path: vec!["age".to_string()],
|
|
2610
|
+
}
|
|
2611
|
+
.into(),
|
|
2612
|
+
],
|
|
2613
|
+
distinct: true,
|
|
2614
|
+
},
|
|
2615
|
+
);
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
#[test]
|
|
2619
|
+
fn test_oc_parse_function_call_distinct_with_multiple_args()
|
|
2620
|
+
{
|
|
2621
|
+
compare_parse_to_ast(
|
|
2622
|
+
"some_func(DISTINCT a, b)",
|
|
2623
|
+
expression,
|
|
2624
|
+
ast::FunctionCall {
|
|
2625
|
+
name: "some_func".to_string(),
|
|
2626
|
+
arguments: vec![
|
|
2627
|
+
ast::Variable {
|
|
2628
|
+
identifier: ast::VariableIdentifier {
|
|
2629
|
+
name: "a".to_string(),
|
|
2630
|
+
id: 0,
|
|
2631
|
+
},
|
|
2632
|
+
}
|
|
2633
|
+
.into(),
|
|
2634
|
+
ast::Variable {
|
|
2635
|
+
identifier: ast::VariableIdentifier {
|
|
2636
|
+
name: "b".to_string(),
|
|
2637
|
+
id: 1,
|
|
2638
|
+
},
|
|
2639
|
+
}
|
|
2640
|
+
.into(),
|
|
2641
|
+
],
|
|
2642
|
+
distinct: true,
|
|
2643
|
+
},
|
|
2644
|
+
);
|
|
2645
|
+
}
|