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
|
@@ -313,7 +313,7 @@ fn parameter_name(input: Input<'_>) -> OCPResult<Input<'_>, &str>
|
|
|
313
313
|
}
|
|
314
314
|
// Literals
|
|
315
315
|
|
|
316
|
-
fn string_literal(input: Input<'_>) -> OCPResult<Input<'_>,
|
|
316
|
+
fn string_literal(input: Input<'_>) -> OCPResult<Input<'_>, String>
|
|
317
317
|
{
|
|
318
318
|
match input.0
|
|
319
319
|
{
|
|
@@ -327,7 +327,10 @@ fn string_literal(input: Input<'_>) -> OCPResult<Input<'_>, &str>
|
|
|
327
327
|
{
|
|
328
328
|
let lit = input.1.extract_text(span);
|
|
329
329
|
|
|
330
|
-
Ok((
|
|
330
|
+
Ok((
|
|
331
|
+
Input(rest, input.1),
|
|
332
|
+
super::string::unescape_cypher(&lit[1..lit.len() - 1]),
|
|
333
|
+
))
|
|
331
334
|
}
|
|
332
335
|
_ => Err(nom::Err::Error(Error::new(
|
|
333
336
|
ErrorKind::ExpectedTokens(vec![Token::String].into()),
|
|
@@ -440,11 +443,21 @@ fn function_call(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
440
443
|
to_string(ident),
|
|
441
444
|
delimited(
|
|
442
445
|
token(Token::StartParenthesis),
|
|
443
|
-
|
|
446
|
+
pair(
|
|
447
|
+
map(opt(token(Token::Distinct)), |d| d.is_some()),
|
|
448
|
+
separated_list0(token(Token::Comma), expression),
|
|
449
|
+
),
|
|
444
450
|
token(Token::EndParenthesis),
|
|
445
451
|
),
|
|
446
452
|
),
|
|
447
|
-
|(name, arguments)|
|
|
453
|
+
|(name, (distinct, arguments))| {
|
|
454
|
+
ast::FunctionCall {
|
|
455
|
+
name,
|
|
456
|
+
arguments,
|
|
457
|
+
distinct,
|
|
458
|
+
}
|
|
459
|
+
.into()
|
|
460
|
+
},
|
|
448
461
|
)
|
|
449
462
|
.parse(input)
|
|
450
463
|
}
|
|
@@ -483,9 +496,9 @@ fn primary(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
483
496
|
.into()
|
|
484
497
|
}),
|
|
485
498
|
// String
|
|
486
|
-
map(string_literal, |s
|
|
499
|
+
map(string_literal, |s| {
|
|
487
500
|
ast::Value {
|
|
488
|
-
value: graphcore::Value::String(s
|
|
501
|
+
value: graphcore::Value::String(s),
|
|
489
502
|
}
|
|
490
503
|
.into()
|
|
491
504
|
}),
|
|
@@ -522,7 +535,7 @@ fn member_access(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
522
535
|
primary,
|
|
523
536
|
many0(preceded(
|
|
524
537
|
token(Token::Dot),
|
|
525
|
-
|
|
538
|
+
alt((to_string(ident), string_literal)),
|
|
526
539
|
)),
|
|
527
540
|
),
|
|
528
541
|
|(left, path)| {
|
|
@@ -617,6 +630,7 @@ fn label_check(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
617
630
|
.into()
|
|
618
631
|
}))
|
|
619
632
|
.collect(),
|
|
633
|
+
distinct: false,
|
|
620
634
|
}
|
|
621
635
|
.into()
|
|
622
636
|
}
|
|
@@ -625,6 +639,57 @@ fn label_check(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
625
639
|
.parse(input)
|
|
626
640
|
}
|
|
627
641
|
|
|
642
|
+
#[derive(Clone, Copy)]
|
|
643
|
+
enum StringOp
|
|
644
|
+
{
|
|
645
|
+
StartsWith,
|
|
646
|
+
EndsWith,
|
|
647
|
+
Contains,
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
fn string_operators(input: Input) -> OCPResult<Input, ast::Expression>
|
|
651
|
+
{
|
|
652
|
+
map(
|
|
653
|
+
(
|
|
654
|
+
label_check,
|
|
655
|
+
opt(
|
|
656
|
+
alt((
|
|
657
|
+
value(
|
|
658
|
+
StringOp::StartsWith,
|
|
659
|
+
(token(Token::Starts), token(Token::With)),
|
|
660
|
+
),
|
|
661
|
+
value(StringOp::EndsWith, (token(Token::Ends), token(Token::With))),
|
|
662
|
+
value(StringOp::Contains, token(Token::Contains)),
|
|
663
|
+
))
|
|
664
|
+
.and(label_check),
|
|
665
|
+
),
|
|
666
|
+
),
|
|
667
|
+
|(lhs, op)| match op
|
|
668
|
+
{
|
|
669
|
+
None => lhs,
|
|
670
|
+
Some(op) => match op.0
|
|
671
|
+
{
|
|
672
|
+
StringOp::StartsWith => ast::StartsWith {
|
|
673
|
+
left: lhs,
|
|
674
|
+
right: op.1,
|
|
675
|
+
}
|
|
676
|
+
.into(),
|
|
677
|
+
StringOp::EndsWith => ast::EndsWith {
|
|
678
|
+
left: lhs,
|
|
679
|
+
right: op.1,
|
|
680
|
+
}
|
|
681
|
+
.into(),
|
|
682
|
+
StringOp::Contains => ast::Contains {
|
|
683
|
+
left: lhs,
|
|
684
|
+
right: op.1,
|
|
685
|
+
}
|
|
686
|
+
.into(),
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
)
|
|
690
|
+
.parse(input)
|
|
691
|
+
}
|
|
692
|
+
|
|
628
693
|
fn unary(input: Input) -> OCPResult<Input, ast::Expression>
|
|
629
694
|
{
|
|
630
695
|
alt((
|
|
@@ -671,9 +736,6 @@ fn unary(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
671
736
|
)
|
|
672
737
|
},
|
|
673
738
|
),
|
|
674
|
-
map(preceded(token(Token::Not), unary), |e| {
|
|
675
|
-
ast::LogicalNegation { value: e }.into()
|
|
676
|
-
}),
|
|
677
739
|
map(preceded(token(Token::Minus), unary), |e| match e
|
|
678
740
|
{
|
|
679
741
|
ast::Expression::Value(ast::Value {
|
|
@@ -691,7 +753,7 @@ fn unary(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
691
753
|
_ => ast::Negation { value: e }.into(),
|
|
692
754
|
}),
|
|
693
755
|
preceded(token(Token::Plus), unary),
|
|
694
|
-
|
|
756
|
+
string_operators,
|
|
695
757
|
))
|
|
696
758
|
.parse(input)
|
|
697
759
|
}
|
|
@@ -811,17 +873,42 @@ fn relational(input: Input) -> OCPResult<Input, ast::Expression>
|
|
|
811
873
|
}
|
|
812
874
|
else
|
|
813
875
|
{
|
|
876
|
+
// Check for NOT IN pattern
|
|
877
|
+
if let Ok((after_not, _)) = token(Token::Not).parse(input.clone())
|
|
878
|
+
&& let Ok((after_in, _)) = token(Token::In).parse(after_not)
|
|
879
|
+
{
|
|
880
|
+
let (final_input, right) = is_not_null(after_in)?;
|
|
881
|
+
let in_expr = ast::RelationalIn { left, right }.into();
|
|
882
|
+
let negated = ast::LogicalNegation { value: in_expr }.into();
|
|
883
|
+
return Ok((final_input, negated));
|
|
884
|
+
}
|
|
814
885
|
Ok((input, left))
|
|
815
886
|
}
|
|
816
887
|
}
|
|
817
888
|
|
|
889
|
+
fn not_expression(input: Input) -> OCPResult<Input, ast::Expression>
|
|
890
|
+
{
|
|
891
|
+
map(
|
|
892
|
+
pair(many0(token(Token::Not)), relational),
|
|
893
|
+
|(nots, expr)| {
|
|
894
|
+
nots
|
|
895
|
+
.into_iter()
|
|
896
|
+
.fold(expr, |e, _| ast::LogicalNegation { value: e }.into())
|
|
897
|
+
},
|
|
898
|
+
)
|
|
899
|
+
.parse(input)
|
|
900
|
+
}
|
|
901
|
+
|
|
818
902
|
fn logical_and(input: Input) -> OCPResult<Input, ast::Expression>
|
|
819
903
|
{
|
|
820
|
-
map(
|
|
821
|
-
|
|
822
|
-
v
|
|
823
|
-
|
|
824
|
-
|
|
904
|
+
map(
|
|
905
|
+
separated_list1(token(Token::And), not_expression),
|
|
906
|
+
|mut v| {
|
|
907
|
+
let first = v.remove(0);
|
|
908
|
+
v.into_iter()
|
|
909
|
+
.fold(first, |l, r| ast::LogicalAnd { left: l, right: r }.into())
|
|
910
|
+
},
|
|
911
|
+
)
|
|
825
912
|
.parse(input)
|
|
826
913
|
}
|
|
827
914
|
|
|
@@ -907,7 +994,7 @@ fn labels(input: Input) -> OCPResult<Input, ast::LabelExpression>
|
|
|
907
994
|
fn map_pair(input: Input) -> OCPResult<Input, (String, ast::Expression)>
|
|
908
995
|
{
|
|
909
996
|
separated_pair(
|
|
910
|
-
|
|
997
|
+
alt((to_string(ident), string_literal)),
|
|
911
998
|
token(Token::Colon),
|
|
912
999
|
expression,
|
|
913
1000
|
)
|
|
@@ -1656,15 +1743,16 @@ fn return_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1656
1743
|
map(
|
|
1657
1744
|
(
|
|
1658
1745
|
token(Token::Return),
|
|
1746
|
+
opt(token(Token::Distinct)),
|
|
1659
1747
|
with_return_expression,
|
|
1660
1748
|
modifiers,
|
|
1661
1749
|
opt(preceded(token(Token::Where), expression)),
|
|
1662
1750
|
),
|
|
1663
|
-
|(_, (all, expressions), modifiers, where_expression)| {
|
|
1751
|
+
|(_, distinct, (all, expressions), modifiers, where_expression)| {
|
|
1664
1752
|
ast::Return {
|
|
1665
1753
|
all,
|
|
1666
1754
|
expressions,
|
|
1667
|
-
modifiers,
|
|
1755
|
+
modifiers: modifiers.set_distinct(distinct.is_some()),
|
|
1668
1756
|
where_expression,
|
|
1669
1757
|
}
|
|
1670
1758
|
.into()
|
|
@@ -1678,15 +1766,16 @@ fn with_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1678
1766
|
map(
|
|
1679
1767
|
(
|
|
1680
1768
|
token(Token::With),
|
|
1769
|
+
opt(token(Token::Distinct)),
|
|
1681
1770
|
with_return_expression,
|
|
1682
1771
|
modifiers,
|
|
1683
1772
|
opt(preceded(token(Token::Where), expression)),
|
|
1684
1773
|
),
|
|
1685
|
-
|(_, (all, expressions), modifiers, where_expression)| {
|
|
1774
|
+
|(_, distinct, (all, expressions), modifiers, where_expression)| {
|
|
1686
1775
|
ast::With {
|
|
1687
1776
|
all,
|
|
1688
1777
|
expressions,
|
|
1689
|
-
modifiers,
|
|
1778
|
+
modifiers: modifiers.set_distinct(distinct.is_some()),
|
|
1690
1779
|
where_expression,
|
|
1691
1780
|
}
|
|
1692
1781
|
.into()
|
|
@@ -1747,7 +1836,7 @@ fn parse_set_actions(input: Input) -> OCPResult<Input, Vec<ast::OneUpdate>>
|
|
|
1747
1836
|
)),
|
|
1748
1837
|
many0(preceded(
|
|
1749
1838
|
token(Token::Dot),
|
|
1750
|
-
|
|
1839
|
+
alt((to_string(ident), string_literal)),
|
|
1751
1840
|
)),
|
|
1752
1841
|
token(Token::Equal),
|
|
1753
1842
|
expression,
|
|
@@ -1772,7 +1861,7 @@ fn parse_set_actions(input: Input) -> OCPResult<Input, Vec<ast::OneUpdate>>
|
|
|
1772
1861
|
)),
|
|
1773
1862
|
many0(preceded(
|
|
1774
1863
|
token(Token::Dot),
|
|
1775
|
-
|
|
1864
|
+
alt((to_string(ident), string_literal)),
|
|
1776
1865
|
)),
|
|
1777
1866
|
token(Token::PlusEqual),
|
|
1778
1867
|
expression,
|
|
@@ -1824,7 +1913,7 @@ fn remove_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1824
1913
|
ident,
|
|
1825
1914
|
many1(preceded(
|
|
1826
1915
|
token(Token::Dot),
|
|
1827
|
-
|
|
1916
|
+
alt((to_string(ident), string_literal)),
|
|
1828
1917
|
)),
|
|
1829
1918
|
),
|
|
1830
1919
|
|(ident, path)| {
|
|
@@ -1884,13 +1973,7 @@ fn call_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1884
1973
|
fn use_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
1885
1974
|
{
|
|
1886
1975
|
map(
|
|
1887
|
-
(
|
|
1888
|
-
token(Token::Use),
|
|
1889
|
-
alt((
|
|
1890
|
-
map(string_literal, |s| s.to_string()),
|
|
1891
|
-
map(ident, |s| s.to_string()),
|
|
1892
|
-
)),
|
|
1893
|
-
),
|
|
1976
|
+
(token(Token::Use), alt((string_literal, to_string(ident)))),
|
|
1894
1977
|
|(_, name)| ast::UseGraph { name }.into(),
|
|
1895
1978
|
)
|
|
1896
1979
|
.parse(input)
|
|
@@ -1903,10 +1986,7 @@ fn create_graph_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1903
1986
|
token(Token::Create),
|
|
1904
1987
|
token(Token::Graph),
|
|
1905
1988
|
opt((token(Token::If), token(Token::Not), token(Token::Exists))),
|
|
1906
|
-
alt((
|
|
1907
|
-
map(string_literal, |s| s.to_string()),
|
|
1908
|
-
map(ident, |s| s.to_string()),
|
|
1909
|
-
)),
|
|
1989
|
+
alt((string_literal, to_string(ident))),
|
|
1910
1990
|
),
|
|
1911
1991
|
|(_, _, if_not_exists, name)| {
|
|
1912
1992
|
ast::CreateGraph {
|
|
@@ -1926,10 +2006,7 @@ fn drop_graph_statement(input: Input) -> OCPResult<Input, ast::Statement>
|
|
|
1926
2006
|
token(Token::Drop),
|
|
1927
2007
|
token(Token::Graph),
|
|
1928
2008
|
opt((token(Token::If), token(Token::Exists))),
|
|
1929
|
-
alt((
|
|
1930
|
-
map(string_literal, |s| s.to_string()),
|
|
1931
|
-
map(ident, |s| s.to_string()),
|
|
1932
|
-
)),
|
|
2009
|
+
alt((string_literal, to_string(ident))),
|
|
1933
2010
|
),
|
|
1934
2011
|
|(_, _, if_exists, name)| {
|
|
1935
2012
|
ast::DropGraph {
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
use logos::Logos;
|
|
2
|
+
|
|
3
|
+
#[derive(Logos, Debug, PartialEq)]
|
|
4
|
+
enum CypherEscapeToken<'a>
|
|
5
|
+
{
|
|
6
|
+
#[regex(r#"[^\\]+"#, |lex| lex.slice())]
|
|
7
|
+
Text(&'a str),
|
|
8
|
+
|
|
9
|
+
#[token(r"\t")]
|
|
10
|
+
Tab,
|
|
11
|
+
|
|
12
|
+
#[token(r"\b")]
|
|
13
|
+
Backspace,
|
|
14
|
+
|
|
15
|
+
#[token(r"\n")]
|
|
16
|
+
Newline,
|
|
17
|
+
|
|
18
|
+
#[token(r"\r")]
|
|
19
|
+
CarriageReturn,
|
|
20
|
+
|
|
21
|
+
#[token(r"\f")]
|
|
22
|
+
FormFeed,
|
|
23
|
+
|
|
24
|
+
#[token(r"\'")]
|
|
25
|
+
SingleQuote,
|
|
26
|
+
|
|
27
|
+
#[token(r#"\""#)]
|
|
28
|
+
DoubleQuote,
|
|
29
|
+
|
|
30
|
+
#[token(r"\\")]
|
|
31
|
+
Backslash,
|
|
32
|
+
|
|
33
|
+
#[regex(r"\\u[0-9a-fA-F]{4}", |lex| lex.slice())]
|
|
34
|
+
Unicode16(&'a str),
|
|
35
|
+
|
|
36
|
+
#[regex(r"\\U[0-9a-fA-F]{8}", |lex| lex.slice())]
|
|
37
|
+
Unicode32(&'a str),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub(crate) fn unescape_cypher(input: &str) -> String
|
|
41
|
+
{
|
|
42
|
+
let mut output = String::with_capacity(input.len());
|
|
43
|
+
|
|
44
|
+
for token in CypherEscapeToken::lexer(input)
|
|
45
|
+
{
|
|
46
|
+
match token.expect("invalid Cypher escape")
|
|
47
|
+
{
|
|
48
|
+
CypherEscapeToken::Text(s) => output.push_str(s),
|
|
49
|
+
CypherEscapeToken::Tab => output.push('\t'),
|
|
50
|
+
CypherEscapeToken::Backspace => output.push('\u{0008}'),
|
|
51
|
+
CypherEscapeToken::Newline => output.push('\n'),
|
|
52
|
+
CypherEscapeToken::CarriageReturn => output.push('\r'),
|
|
53
|
+
CypherEscapeToken::FormFeed => output.push('\u{000C}'),
|
|
54
|
+
CypherEscapeToken::SingleQuote => output.push('\''),
|
|
55
|
+
CypherEscapeToken::DoubleQuote => output.push('"'),
|
|
56
|
+
CypherEscapeToken::Backslash => output.push('\\'),
|
|
57
|
+
|
|
58
|
+
CypherEscapeToken::Unicode16(s) =>
|
|
59
|
+
{
|
|
60
|
+
let value = u16::from_str_radix(&s[2..], 16).expect("invalid UTF-16 escape");
|
|
61
|
+
|
|
62
|
+
let ch = char::from_u32(value as u32).expect("invalid Unicode scalar");
|
|
63
|
+
|
|
64
|
+
output.push(ch);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
CypherEscapeToken::Unicode32(s) =>
|
|
68
|
+
{
|
|
69
|
+
let value = u32::from_str_radix(&s[2..], 16).expect("invalid UTF-32 escape");
|
|
70
|
+
|
|
71
|
+
output.push(char::from_u32(value).expect("invalid Unicode scalar"));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
output
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[cfg(test)]
|
|
80
|
+
mod tests
|
|
81
|
+
{
|
|
82
|
+
use super::unescape_cypher;
|
|
83
|
+
|
|
84
|
+
#[test]
|
|
85
|
+
fn plain_text()
|
|
86
|
+
{
|
|
87
|
+
assert_eq!(unescape_cypher("hello world"), "hello world");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[test]
|
|
91
|
+
fn tab()
|
|
92
|
+
{
|
|
93
|
+
assert_eq!(unescape_cypher(r"foo\tbar"), "foo\tbar");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#[test]
|
|
97
|
+
fn backspace()
|
|
98
|
+
{
|
|
99
|
+
assert_eq!(unescape_cypher(r"foo\bbar"), "foo\u{0008}bar");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#[test]
|
|
103
|
+
fn newline()
|
|
104
|
+
{
|
|
105
|
+
assert_eq!(unescape_cypher(r"foo\nbar"), "foo\nbar");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#[test]
|
|
109
|
+
fn carriage_return()
|
|
110
|
+
{
|
|
111
|
+
assert_eq!(unescape_cypher(r"foo\rbar"), "foo\rbar");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
fn form_feed()
|
|
116
|
+
{
|
|
117
|
+
assert_eq!(unescape_cypher(r"foo\fbar"), "foo\u{000C}bar");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#[test]
|
|
121
|
+
fn quotes()
|
|
122
|
+
{
|
|
123
|
+
assert_eq!(unescape_cypher(r#"\'hello\""#), "'hello\"");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[test]
|
|
127
|
+
fn backslash()
|
|
128
|
+
{
|
|
129
|
+
assert_eq!(unescape_cypher(r"foo\\bar"), r"foo\bar");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#[test]
|
|
133
|
+
fn unicode_16()
|
|
134
|
+
{
|
|
135
|
+
assert_eq!(unescape_cypher(r"\u0041"), "A");
|
|
136
|
+
|
|
137
|
+
assert_eq!(unescape_cypher(r"\u03BB"), "λ");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#[test]
|
|
141
|
+
fn unicode_32()
|
|
142
|
+
{
|
|
143
|
+
assert_eq!(unescape_cypher(r"\U0001F600"), "😀");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
#[test]
|
|
147
|
+
fn mixed_sequences()
|
|
148
|
+
{
|
|
149
|
+
assert_eq!(
|
|
150
|
+
unescape_cypher(r"Hello\nWorld\t\u0021\U0001F600"),
|
|
151
|
+
"Hello\nWorld\t!😀"
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#[test]
|
|
156
|
+
fn multiple_text_chunks()
|
|
157
|
+
{
|
|
158
|
+
assert_eq!(unescape_cypher(r"abc\n123\txyz"), "abc\n123\txyz");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#[test]
|
|
162
|
+
fn empty_string()
|
|
163
|
+
{
|
|
164
|
+
assert_eq!(unescape_cypher(""), "");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
#[test]
|
|
168
|
+
fn only_escape_sequences()
|
|
169
|
+
{
|
|
170
|
+
assert_eq!(unescape_cypher("\n\t\r"), "\n\t\r");
|
|
171
|
+
}
|
|
172
|
+
}
|
data/ext/gqlparser/src/oc.rs
CHANGED
|
@@ -7,7 +7,7 @@ use std::{
|
|
|
7
7
|
|
|
8
8
|
use crate::{Value, prelude::*};
|
|
9
9
|
|
|
10
|
-
type ValueMapInner = std::collections::
|
|
10
|
+
type ValueMapInner = std::collections::BTreeMap<String, Value>;
|
|
11
11
|
|
|
12
12
|
/// A map of values.
|
|
13
13
|
#[derive(Debug, PartialEq, Default, Clone, Deserialize, Serialize)]
|
|
@@ -249,7 +249,7 @@ impl FromIterator<(String, Value)> for ValueMap
|
|
|
249
249
|
/// all but one of the corresponding values will be dropped.
|
|
250
250
|
fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> ValueMap
|
|
251
251
|
{
|
|
252
|
-
let mut map = ValueMapInner::
|
|
252
|
+
let mut map = ValueMapInner::new();
|
|
253
253
|
map.extend(iter);
|
|
254
254
|
ValueMap(map)
|
|
255
255
|
}
|
data/ext/graphcore/src/value.rs
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gqlite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyrille Berger
|
|
@@ -233,6 +233,7 @@ files:
|
|
|
233
233
|
- ext/gqlparser/src/oc/lexer.rs
|
|
234
234
|
- ext/gqlparser/src/oc/parser.rs
|
|
235
235
|
- ext/gqlparser/src/oc/parser/tests.rs
|
|
236
|
+
- ext/gqlparser/src/oc/string.rs
|
|
236
237
|
- ext/gqlparser/src/prelude.rs
|
|
237
238
|
- ext/graphcore/Cargo.toml
|
|
238
239
|
- ext/graphcore/README.MD
|