added returning statements to inserts and updates for trigger-based mutations

This commit is contained in:
2026-08-03 18:57:08 -04:00
parent 020286d603
commit b2f9fe387c
5 changed files with 302 additions and 137 deletions

View File

@ -508,7 +508,7 @@ impl Merger {
entity_change_kind.as_deref().unwrap_or(""),
&type_name,
type_def,
&entity_fields,
&mut entity_fields,
entity_fetched.as_ref(),
)?;
@ -899,7 +899,7 @@ impl Merger {
change_kind: &str,
entity_type_name: &str,
entity_type: &crate::database::r#type::Type,
entity_fields: &serde_json::Map<String, Value>,
entity_fields: &mut serde_json::Map<String, Value>,
_entity_fetched: Option<&serde_json::Map<String, Value>>,
) -> Result<(), Error> {
if change_kind.is_empty() {
@ -907,7 +907,7 @@ impl Merger {
}
let id_str = match entity_fields.get("id").and_then(|v| v.as_str()) {
Some(id) => id,
Some(id) => id.to_string(),
None => {
return Err(Error {
code: "MISSING_ENTITY_ID".to_string(),
@ -950,7 +950,7 @@ impl Merger {
};
let mut entity_pairs = serde_json::Map::new();
for (k, v) in entity_fields {
for (k, v) in entity_fields.iter() {
if table_fields.contains(k) {
entity_pairs.insert(k.clone(), v.clone());
}
@ -984,20 +984,33 @@ impl Merger {
}
let sql = format!(
"INSERT INTO agreego.\"{}\" ({}) VALUES ({})",
"INSERT INTO agreego.\"{}\" ({}) VALUES ({}) RETURNING to_jsonb(\"{}\".*)",
table_name,
columns.join(", "),
values.join(", ")
values.join(", "),
table_name
);
if let Err(e) = self.db.execute(&sql, None) {
return Err(Error {
code: "DATABASE_SPI_ERROR".to_string(),
values: Some(IndexMap::from([("error".to_string(), e.clone())])),
details: ErrorDetails {
cause: Some(e),
..Default::default()
},
});
match self.db.query(&sql, None) {
Ok(Value::Array(rows)) => {
if let Some(Value::Object(row_map)) = rows.into_iter().next() {
for (k, v) in row_map {
if !v.is_null() {
entity_fields.insert(k, v);
}
}
}
}
Err(e) => {
return Err(Error {
code: "DATABASE_SPI_ERROR".to_string(),
values: Some(IndexMap::from([("error".to_string(), e.clone())])),
details: ErrorDetails {
cause: Some(e),
..Default::default()
},
});
}
_ => {}
}
} else if change_kind == "update" || change_kind == "delete" {
entity_pairs.remove("id");
@ -1025,20 +1038,33 @@ impl Merger {
}
let sql = format!(
"UPDATE agreego.\"{}\" SET {} WHERE id = {}",
"UPDATE agreego.\"{}\" SET {} WHERE id = {} RETURNING to_jsonb(\"{}\".*)",
table_name,
set_clauses.join(", "),
Self::quote_literal(&Value::String(id_str.to_string()))
Self::quote_literal(&Value::String(id_str.to_string())),
table_name
);
if let Err(e) = self.db.execute(&sql, None) {
return Err(Error {
code: "DATABASE_SPI_ERROR".to_string(),
values: Some(IndexMap::from([("error".to_string(), e.clone())])),
details: ErrorDetails {
cause: Some(e),
..Default::default()
},
});
match self.db.query(&sql, None) {
Ok(Value::Array(rows)) => {
if let Some(Value::Object(row_map)) = rows.into_iter().next() {
for (k, v) in row_map {
if !v.is_null() {
entity_fields.insert(k, v);
}
}
}
}
Err(e) => {
return Err(Error {
code: "DATABASE_SPI_ERROR".to_string(),
values: Some(IndexMap::from([("error".to_string(), e.clone())])),
details: ErrorDetails {
cause: Some(e),
..Default::default()
},
});
}
_ => {}
}
}
}

View File

@ -97,7 +97,14 @@ impl SqlFormatter {
self.push_line("VALUES (");
self.indent += 2;
let vals = if suffix.ends_with(")") { &suffix[..suffix.len() - 1] } else { suffix };
let (vals, returning_clause) = if let Some(ret_idx) = suffix.rfind(") RETURNING ") {
(&suffix[..ret_idx], Some(&suffix[ret_idx + 2..]))
} else if suffix.ends_with(")") {
(&suffix[..suffix.len() - 1], None)
} else {
(suffix, None)
};
let mut val_tokens = Vec::new();
let mut curr = String::new();
let mut in_str = false;
@ -146,6 +153,9 @@ impl SqlFormatter {
}
self.indent -= 2;
self.push_line(")");
if let Some(ret) = returning_clause {
self.push_line(ret);
}
} else {
self.push_line(&s);
}
@ -168,10 +178,19 @@ impl SqlFormatter {
self.indent -= 2;
if let Some(w) = where_idx {
self.push_line("WHERE");
self.indent += 2;
self.push_line(&after_set[w + 7..]);
self.indent -= 2;
let where_clause = &after_set[w + 7..];
if let Some(ret_idx) = where_clause.find(" RETURNING ") {
self.push_line("WHERE");
self.indent += 2;
self.push_line(&where_clause[..ret_idx]);
self.indent -= 2;
self.push_line(&where_clause[ret_idx + 1..]);
} else {
self.push_line("WHERE");
self.indent += 2;
self.push_line(where_clause);
self.indent -= 2;
}
}
} else {
self.push_line(&s);