Merge pull request #4 from ModernRelay/claude/omnigraph-multi-statement-mutations-DxWSA

Support multi-statement mutations (insert + edge in one query)
This commit is contained in:
Andrew Altshuler 2026-04-12 13:58:26 +03:00 committed by GitHub
commit af9a44e879
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 240 additions and 64 deletions

View file

@ -3335,24 +3335,30 @@ impl Omnigraph {
let ir = lower_mutation_query(&query_decl)?;
match &ir.op {
MutationOpIR::Insert {
type_name,
assignments,
} => self.execute_insert(type_name, assignments, params).await,
MutationOpIR::Update {
type_name,
assignments,
predicate,
} => {
self.execute_update(type_name, assignments, predicate, params)
.await
}
MutationOpIR::Delete {
type_name,
predicate,
} => self.execute_delete(type_name, predicate, params).await,
let mut total = MutationResult::default();
for op in &ir.ops {
let result = match op {
MutationOpIR::Insert {
type_name,
assignments,
} => self.execute_insert(type_name, assignments, params).await?,
MutationOpIR::Update {
type_name,
assignments,
predicate,
} => {
self.execute_update(type_name, assignments, predicate, params)
.await?
}
MutationOpIR::Delete {
type_name,
predicate,
} => self.execute_delete(type_name, predicate, params).await?,
};
total.affected_nodes += result.affected_nodes;
total.affected_edges += result.affected_edges;
}
Ok(total)
}
pub async fn branch_merge(&mut self, source: &str, target: &str) -> Result<MergeOutcome> {

View file

@ -644,6 +644,43 @@ async fn mutation_insert_edge() {
assert_eq!(names.value(0), "Alice");
}
#[tokio::test]
async fn mutation_multi_insert_node_and_edge() {
let dir = tempfile::tempdir().unwrap();
let mut db = init_and_load(&dir).await;
// In one atomic mutation: insert Eve + edge Eve→Alice
let result = mutate_main(
&mut db,
MUTATION_QUERIES,
"insert_person_and_friend",
&mixed_params(&[("$name", "Eve"), ("$friend", "Alice")], &[("$age", 22)]),
)
.await
.unwrap();
assert_eq!(result.affected_nodes, 1);
assert_eq!(result.affected_edges, 1);
// Verify traversal: Eve → Alice
let qr = query_main(
&mut db,
TEST_QUERIES,
"friends_of",
&params(&[("$name", "Eve")]),
)
.await
.unwrap();
assert_eq!(qr.num_rows(), 1);
let batch = qr.concat_batches().unwrap();
let names = batch
.column(0)
.as_any()
.downcast_ref::<StringArray>()
.unwrap();
assert_eq!(names.value(0), "Alice");
}
#[tokio::test]
async fn mutation_update_node() {
let dir = tempfile::tempdir().unwrap();

View file

@ -35,6 +35,11 @@ query remove_person($name: String) {
query remove_friendship($from: String) {
delete Knows where from = $from
}
query insert_person_and_friend($name: String, $age: I32, $friend: String) {
insert Person { name: $name, age: $age }
insert Knows { from: $name, to: $friend }
}
"#;
/// Init a repo and load the standard test data.