Skip to content

Commit 170183b

Browse files
Try blocks in write stages (#417)
## Product change and motivation We allow `try {}` blocks in all write stages, viz. `insert`, `delete`, `put`, and `update`. ## Implementation
1 parent d679e07 commit 170183b

7 files changed

Lines changed: 111 additions & 60 deletions

File tree

dependencies/typedb/repositories.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ def typedb_behaviour():
1515
git_repository(
1616
name = "typedb_behaviour",
1717
remote = "https://github.com/typedb/typedb-behaviour",
18-
commit = "37e3c823be327ed023ac554a044d2996de10ac3b", # sync-marker: do not remove this comment, this is used for sync-dependencies by @typedb_behaviour
18+
commit = "27d8ada76fe0d066a6035dfdef353408232f807a", # sync-marker: do not remove this comment, this is used for sync-dependencies by @typedb_behaviour
1919
)

rust/parser/pipeline.rs

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ use super::{
1010
define::function::visit_definition_function,
1111
expression::{visit_expression, visit_expression_function},
1212
literal::{visit_integer_literal, visit_quoted_string_literal},
13-
statement::{
14-
thing::{visit_relation, visit_statement_thing},
15-
visit_statement,
16-
},
13+
statement::{thing::visit_relation, visit_statement},
1714
type_::{visit_label, visit_label_list},
1815
visit_reduce_assignment_var, visit_var, visit_var_named, visit_vars, IntoChildNodes, Node, Rule, RuleMatcher,
1916
};
@@ -23,7 +20,7 @@ use crate::{
2320
token::{Order, ReduceOperator},
2421
Spanned,
2522
},
26-
parser::{define::function::visit_function_block, statement::single::visit_statement_assignment},
23+
parser::define::function::visit_function_block,
2724
pattern::{Conjunction, Disjunction, Negation, Optional, Pattern},
2825
query::{
2926
pipeline::{
@@ -44,7 +41,6 @@ use crate::{
4441
},
4542
Pipeline,
4643
},
47-
statement::Statement,
4844
value::StringLiteral,
4945
TypeRef, TypeRefAny,
5046
};
@@ -171,39 +167,45 @@ fn visit_pattern_try(node: Node<'_>) -> Optional {
171167
fn visit_clause_insert(node: Node<'_>) -> Insert {
172168
debug_assert_eq!(node.as_rule(), Rule::clause_insert);
173169
let span = node.span();
174-
let statements = node
175-
.into_children()
176-
.skip_expected(Rule::INSERT)
177-
.map(|child| match child.as_rule() {
178-
Rule::statement_thing => visit_statement_thing(child),
179-
Rule::statement_assignment => Statement::Assignment(visit_statement_assignment(child)),
180-
_ => unreachable!(
181-
"Unrecognised statement inside insert clause: {:?}",
182-
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
183-
),
184-
})
185-
.collect();
186-
Insert::new(span, statements)
170+
let mut children = node.into_children();
171+
let patterns = visit_patterns(children.skip_expected(Rule::INSERT).consume_expected(Rule::patterns));
172+
debug_assert_eq!(children.try_consume_any(), None);
173+
Insert::new(span, patterns)
187174
}
188175

189176
fn visit_clause_put(node: Node<'_>) -> Put {
190177
debug_assert_eq!(node.as_rule(), Rule::clause_put);
191178
let span = node.span();
192-
let statement_things = node.into_children().skip_expected(Rule::PUT).map(visit_statement_thing).collect();
193-
Put::new(span, statement_things)
179+
let mut children = node.into_children();
180+
let patterns = visit_patterns(children.skip_expected(Rule::PUT).consume_expected(Rule::patterns));
181+
debug_assert_eq!(children.try_consume_any(), None);
182+
Put::new(span, patterns)
194183
}
195184

196185
fn visit_clause_update(node: Node<'_>) -> Update {
197186
debug_assert_eq!(node.as_rule(), Rule::clause_update);
198187
let span = node.span();
199-
let statement_things = node.into_children().skip_expected(Rule::UPDATE).map(visit_statement_thing).collect();
200-
Update::new(span, statement_things)
188+
let mut children = node.into_children();
189+
let patterns = visit_patterns(children.skip_expected(Rule::UPDATE).consume_expected(Rule::patterns));
190+
debug_assert_eq!(children.try_consume_any(), None);
191+
Update::new(span, patterns)
201192
}
202193

203194
fn visit_clause_delete(node: Node<'_>) -> Delete {
204195
debug_assert_eq!(node.as_rule(), Rule::clause_delete);
205196
let span = node.span();
206-
let deletables = node.into_children().skip_expected(Rule::DELETE).map(visit_statement_deletable).collect();
197+
let deletables = node
198+
.into_children()
199+
.skip_expected(Rule::DELETE)
200+
.map(|child| match child.as_rule() {
201+
Rule::statement_deletable => visit_statement_deletable(child),
202+
Rule::pattern_try_deletable => visit_pattern_try_deletable(child),
203+
_ => unreachable!(
204+
"Unrecognised statement inside delete clause: {:?}",
205+
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
206+
),
207+
})
208+
.collect();
207209
Delete::new(span, deletables)
208210
}
209211

@@ -235,6 +237,23 @@ fn visit_statement_deletable(node: Node<'_>) -> Deletable {
235237
Deletable::new(span, kind)
236238
}
237239

240+
fn visit_pattern_try_deletable(node: Node<'_>) -> Deletable {
241+
debug_assert_eq!(node.as_rule(), Rule::pattern_try_deletable);
242+
let span = node.span();
243+
let deletables = node
244+
.into_children()
245+
.skip_expected(Rule::TRY)
246+
.map(|child| match child.as_rule() {
247+
Rule::statement_deletable => visit_statement_deletable(child),
248+
_ => unreachable!(
249+
"Unrecognised statement inside delete clause: {:?}",
250+
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
251+
),
252+
})
253+
.collect();
254+
Deletable::new(span, DeletableKind::Optional { deletables })
255+
}
256+
238257
fn visit_clause_fetch(node: Node<'_>) -> Fetch {
239258
debug_assert_eq!(node.as_rule(), Rule::clause_fetch);
240259
let span = node.span();

rust/parser/typeql.pest

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ query_stage_terminal = { clause_fetch ~ SEMICOLON }
2929

3030
clause_match = { MATCH ~ patterns }
3131

32-
clause_insert = { INSERT ~ ( statement_thing ~ SEMICOLON | statement_assignment ~ SEMICOLON )+ }
33-
clause_put = { PUT ~ ( statement_thing ~ SEMICOLON )+ }
34-
clause_update = { UPDATE ~ ( statement_thing ~ SEMICOLON )+ }
32+
clause_insert = { INSERT ~ patterns }
33+
clause_put = { PUT ~ patterns }
34+
clause_update = { UPDATE ~ patterns }
3535

36-
clause_delete = { DELETE ~ ( statement_deletable ~ SEMICOLON )+ }
36+
clause_delete = { DELETE ~ ( ( statement_deletable | pattern_try_deletable ) ~ SEMICOLON )+ }
3737

3838
// STREAM OPERATORS ===========================================================
3939

@@ -123,6 +123,8 @@ statement_deletable = { HAS? ~ var ~ OF ~ var
123123
| var
124124
}
125125

126+
pattern_try_deletable = { TRY ~ CURLY_OPEN ~ ( statement_deletable ~ SEMICOLON )+ ~ CURLY_CLOSE }
127+
126128
// SINGLE STATEMENTS ===========================================================
127129

128130
statement_single = { statement_is | statement_comparison | statement_assignment | statement_in }

rust/query/pipeline/stage/delete.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,50 @@ pub enum DeletableKind {
9393
Has { attribute: Variable, owner: Variable },
9494
Links { players: Relation, relation: Variable },
9595
Concept { variable: Variable },
96+
Optional { deletables: Vec<Deletable> },
9697
}
9798

98-
impl Pretty for DeletableKind {}
99+
impl Pretty for DeletableKind {
100+
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101+
match self {
102+
Self::Optional { deletables } => {
103+
writeln!(f, "{} {{", token::Keyword::Try)?;
104+
for deletable in deletables {
105+
indent(indent_level + 1, f)?;
106+
Pretty::fmt(deletable, indent_level + 1, f)?;
107+
writeln!(f, ";")?;
108+
indent(indent_level, f)?;
109+
}
110+
f.write_char('}')?;
111+
Ok(())
112+
}
113+
_ => write!(f, "{}", self),
114+
}
115+
}
116+
}
99117

100118
impl fmt::Display for DeletableKind {
101119
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102-
match self {
103-
Self::Has { attribute, owner } => {
104-
write!(f, "{} {} {} {}", token::Keyword::Has, attribute, token::Keyword::Of, owner)
105-
}
106-
Self::Links { players, relation } => {
107-
write!(f, "{} {} {} {}", token::Keyword::Links, players, token::Keyword::Of, relation)
120+
if f.alternate() {
121+
Pretty::fmt(self, 0, f)
122+
} else {
123+
match self {
124+
Self::Has { attribute, owner } => {
125+
write!(f, "{} {} {} {}", token::Keyword::Has, attribute, token::Keyword::Of, owner)
126+
}
127+
Self::Links { players, relation } => {
128+
write!(f, "{} {} {} {}", token::Keyword::Links, players, token::Keyword::Of, relation)
129+
}
130+
Self::Concept { variable } => write!(f, "{}", variable),
131+
Self::Optional { deletables } => {
132+
write!(f, "{} {{ ", token::Keyword::Try)?;
133+
for deletable in deletables {
134+
write!(f, "{}; ", deletable)?;
135+
}
136+
f.write_char('}')?;
137+
Ok(())
138+
}
108139
}
109-
Self::Concept { variable } => write!(f, "{}", variable),
110140
}
111141
}
112142
}

rust/query/pipeline/stage/insert.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ use std::fmt::{self, Write};
88

99
use crate::{
1010
common::{token, Span, Spanned},
11+
pattern::Pattern,
1112
pretty::{indent, Pretty},
12-
statement::Statement,
1313
};
1414

1515
#[derive(Debug, Clone, Eq, PartialEq)]
1616
pub struct Insert {
1717
pub span: Option<Span>,
18-
pub statements: Vec<Statement>,
18+
pub patterns: Vec<Pattern>,
1919
}
2020

2121
impl Insert {
22-
pub(crate) fn new(span: Option<Span>, statements: Vec<Statement>) -> Self {
23-
Self { span, statements }
22+
pub(crate) fn new(span: Option<Span>, patterns: Vec<Pattern>) -> Self {
23+
Self { span, patterns }
2424
}
2525
}
2626

@@ -33,10 +33,10 @@ impl Spanned for Insert {
3333
impl Pretty for Insert {
3434
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3535
write!(f, "{}", token::Clause::Insert)?;
36-
for statement in &self.statements {
36+
for pattern in &self.patterns {
3737
writeln!(f)?;
3838
indent(indent_level, f)?;
39-
Pretty::fmt(statement, indent_level, f)?;
39+
Pretty::fmt(pattern, indent_level, f)?;
4040
f.write_char(';')?;
4141
}
4242
Ok(())
@@ -49,7 +49,7 @@ impl fmt::Display for Insert {
4949
Pretty::fmt(self, 0, f)
5050
} else {
5151
write!(f, "{}", token::Clause::Insert)?;
52-
for statement in &self.statements {
52+
for statement in &self.patterns {
5353
write!(f, " {statement};")?;
5454
}
5555
Ok(())

rust/query/pipeline/stage/put.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ use std::fmt::{self, Write};
88

99
use crate::{
1010
common::{token, Span, Spanned},
11+
pattern::Pattern,
1112
pretty::{indent, Pretty},
12-
statement::Statement,
1313
};
1414

1515
#[derive(Debug, Clone, Eq, PartialEq)]
1616
pub struct Put {
1717
pub span: Option<Span>,
18-
pub statements: Vec<Statement>,
18+
pub patterns: Vec<Pattern>,
1919
}
2020

2121
impl Put {
22-
pub(crate) fn new(span: Option<Span>, statements: Vec<Statement>) -> Self {
23-
Self { span, statements }
22+
pub(crate) fn new(span: Option<Span>, patterns: Vec<Pattern>) -> Self {
23+
Self { span, patterns }
2424
}
2525
}
2626

@@ -33,10 +33,10 @@ impl Spanned for Put {
3333
impl Pretty for Put {
3434
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3535
write!(f, "{}", token::Clause::Put)?;
36-
for statement in &self.statements {
36+
for pattern in &self.patterns {
3737
writeln!(f)?;
3838
indent(indent_level, f)?;
39-
Pretty::fmt(statement, indent_level, f)?;
39+
Pretty::fmt(pattern, indent_level, f)?;
4040
f.write_char(';')?;
4141
}
4242
Ok(())
@@ -49,8 +49,8 @@ impl fmt::Display for Put {
4949
Pretty::fmt(self, 0, f)
5050
} else {
5151
write!(f, "{}", token::Clause::Put)?;
52-
for statement in &self.statements {
53-
write!(f, " {statement};")?;
52+
for pattern in &self.patterns {
53+
write!(f, " {pattern};")?;
5454
}
5555
Ok(())
5656
}

rust/query/pipeline/stage/update.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ use std::fmt::{self, Write};
88

99
use crate::{
1010
common::{token, Span, Spanned},
11+
pattern::Pattern,
1112
pretty::{indent, Pretty},
12-
statement::Statement,
1313
};
1414

1515
#[derive(Debug, Clone, Eq, PartialEq)]
1616
pub struct Update {
1717
pub span: Option<Span>,
18-
pub statements: Vec<Statement>,
18+
pub patterns: Vec<Pattern>,
1919
}
2020

2121
impl Update {
22-
pub(crate) fn new(span: Option<Span>, statements: Vec<Statement>) -> Self {
23-
Self { span, statements }
22+
pub(crate) fn new(span: Option<Span>, patterns: Vec<Pattern>) -> Self {
23+
Self { span, patterns }
2424
}
2525
}
2626

@@ -33,10 +33,10 @@ impl Spanned for Update {
3333
impl Pretty for Update {
3434
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3535
write!(f, "{}", token::Clause::Update)?;
36-
for statement in &self.statements {
36+
for pattern in &self.patterns {
3737
writeln!(f)?;
3838
indent(indent_level, f)?;
39-
Pretty::fmt(statement, indent_level, f)?;
39+
Pretty::fmt(pattern, indent_level, f)?;
4040
f.write_char(';')?;
4141
}
4242
Ok(())
@@ -49,8 +49,8 @@ impl fmt::Display for Update {
4949
Pretty::fmt(self, 0, f)
5050
} else {
5151
write!(f, "{}", token::Clause::Update)?;
52-
for statement in &self.statements {
53-
write!(f, " {statement};")?;
52+
for pattern in &self.patterns {
53+
write!(f, " {pattern};")?;
5454
}
5555
Ok(())
5656
}

0 commit comments

Comments
 (0)