Skip to content

Commit 9a18464

Browse files
Add optional write documentation (#1013)
## Goal We add documentation for `try {}` in write stages (`insert`, `put`, `update`, `delete`). ## Implementation
1 parent 45facca commit 9a18464

File tree

3 files changed

+140
-13
lines changed

3 files changed

+140
-13
lines changed

core-concepts/modules/ROOT/pages/typeql/invalid-patterns.adoc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,40 @@ match
224224
----
225225

226226
====
227+
228+
=== Nested optional blocks in write stages
229+
230+
A `try` block in a write stage is executed as a unit. When all variables referenced in the `try` block are bound, the write instructions are executed. While this could allow for arbitrary nesting of
231+
`try` blocks where the bound variables are checked at every level, for simplicity's sake nesting `try` blocks is not permitted.
232+
233+
[,typeql]
234+
----
235+
#!test[write, fail_at=runtime]
236+
match
237+
$person isa person;
238+
try {
239+
$edu isa education, links (institute: $institute, attendee: $person);
240+
try { $emp isa employment, links (employer: $company, employee: $person); }; # allowed in match
241+
};
242+
delete
243+
try {
244+
$edu;
245+
try { $emp; }; # not allowed!
246+
};
247+
----
248+
249+
Use instead:
250+
251+
[,typeql]
252+
----
253+
#!test[write, rollback]
254+
match
255+
$person isa person;
256+
try {
257+
$edu isa education, links (institute: $institute, attendee: $person);
258+
try { $emp isa employment, links (employer: $company, employee: $person); };
259+
};
260+
delete
261+
try { $edu; };
262+
try { $emp; };
263+
----

core-concepts/modules/ROOT/pages/typeql/query-variables-patterns.adoc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,42 @@ Finished. Total rows: 3
356356
Optional variables *are* bound by the optional block and not internal to it.
357357
====
358358

359+
==== Optional writes
360+
A `try` block in a write stage such as `insert` allows for conditional writes in a larger pipeline.
361+
362+
[,typeql]
363+
----
364+
#!test[write, rollback]
365+
match
366+
$p isa person, has name $p-name;
367+
try {
368+
$e isa employment, links (employer: $c, employee: $p);
369+
$c has name "Shut Shop";
370+
};
371+
delete try { $e; };
372+
# pipeline continues with $p, $p-name, and $c still available
373+
----
374+
375+
Optional patterns in write stages execute only if all the variables referenced in them are bound to a value.
376+
That means that in this example, if either `$p` or `$c` is not bound, the insert stage does nothing.
377+
If they are both bound, however, then a new employment relation is inserted.
378+
379+
[,typeql]
380+
----
381+
#!test[write, rollback]
382+
match
383+
try { $p isa person, has name $p-name; };
384+
try { $c isa company, has name "Shut Shop"; };
385+
insert
386+
try { $_ isa employment, links (employer: $c, employee: $p); };
387+
----
388+
389+
[NOTE]
390+
====
391+
Note that `try` blocks may not be nested (`try { try { ... }; };`) in write stages.
392+
The inner `try` block can usually either be flattened into the outer block or placed at the top level in the write stage.
393+
====
394+
359395
== Notes on variables
360396
=== Variables in an answer
361397
Notice that a variable that is "bound" in a conjunction is guaranteed to be bound

typeql-reference/modules/ROOT/pages/patterns/optionals.adoc

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,11 @@ match
3434
$_ isa marriage, links (spouse: $person, spouse: $spouse);
3535
};
3636
----
37-
Here, `$spouse` will be bound to the spouse if `$person` is in a `marriage`.
38-
Else, `$spouse` will be bound to `None`
37+
Here, `$spouse` is bound to the spouse if `$person` is in a `marriage`.
38+
Else, `$spouse` is bound to `None`
3939
40-
=== insert & delete
41-
[NOTE]
42-
====
43-
Coming soon!
44-
====
45-
Optional patterns in insert or delete stages will execute only if ALL the variables present in them are bound.
40+
=== insert, update, & delete
41+
Optional patterns in insert, update, or delete stages execute only if ALL the variables present in them are bound.
4642
// Re-enable the tests when we do implement it
4743
[,typeql]
4844
----
@@ -56,18 +52,76 @@ insert
5652
$policy links (covered: $person);
5753
try { $policy links (covered: $spouse); };
5854
----
59-
If `$person` is in a marriage, the match stage will bind `$spouse`
60-
and the insert stage will add them to the policy.
55+
If `$person` is in a marriage, the match stage binds `$spouse` and the insert stage adds them to the policy.
56+
57+
=== put
58+
Because a put stage only inserts data if no existing data matches the body of the put, the patterns in a `try` block of a put stage only attempt to insert data if the mandatory patterns (i.e. those
59+
outside `try` blocks) fail to produce a match. When inserting data, put behaves identically to an insert stage in that a `try` block only executes if all referenced variables are bound.
60+
61+
[,typeql]
62+
----
63+
#!test[write, rollback]
64+
match
65+
$person isa person;
66+
$spouse isa person;
67+
try {
68+
$policy isa policy, links (covered: $person);
69+
};
70+
put
71+
$_ isa marriage, links (spouse: $person, spouse: $spouse);
72+
try {
73+
$policy links (covered: $spouse);
74+
};
75+
----
76+
77+
In this example, if the marriage relation already exists, the put stage does not attempt to add `$spouse` to the optionally bound `$policy`.
78+
79+
If this behavior is not desirable, the `try` block should be put in a separate insert stage instead.
80+
81+
[,typeql]
82+
----
83+
#!test[write, rollback]
84+
match
85+
$person isa person;
86+
$spouse isa person;
87+
try {
88+
$policy isa policy, links (covered: $person);
89+
not { $policy links (covered: $spouse); };
90+
};
91+
put
92+
$_ isa marriage, links (spouse: $person, spouse: $spouse);
93+
insert
94+
try {
95+
$policy links (covered: $spouse);
96+
};
97+
----
98+
99+
In this pipeline, the `marriage` relation is created if it does not already exist, and `$spouse` is always inserted as a roleplayer in `$policy` provided it is bound.
61100
62101
[NOTE]
63102
====
64-
Optional patterns are banned in `put` stages.
103+
In particular, a put stage with only `try` blocks never inserts any data!
104+
[,typeql]
105+
----
106+
#!test[write, rollback]
107+
match
108+
$_ isa marriage, links (spouse: $person, spouse: $spouse);
109+
try {
110+
$policy isa policy, links (covered: $person);
111+
};
112+
put
113+
try {
114+
$policy links (covered: $spouse);
115+
};
116+
----
117+
118+
In this example the `$policy` is bound only if `$person` plays a role in it, but if it doesn't also link `$spouse`, that link is not inserted.
65119
====
66120

67121
== Behavior in match clauses
68122
=== Single origin
69123
In the stage that it first occurs, An optional variable may only occur in a single try-block.
70-
[,typeql]
124+
71125
----
72126
#!test[read, fail_at=runtime]
73127
match
@@ -82,7 +136,7 @@ match
82136

83137
=== Optional variables in subsequent stages
84138
An optional variable can be used in subsequent stages.
85-
An unbound optional variable will cause the pattern to fail.
139+
An unbound optional variable causes the pattern to fail.
86140

87141
The following is a valid way to express the intent of the example above:
88142
[,typeql]

0 commit comments

Comments
 (0)