Parcourir la source

Add support for atomic delete-and-return operations.

Kestrel il y a 2 mois
Parent
commit
0a31604476
2 fichiers modifiés avec 61 ajouts et 0 suppressions
  1. 34 0
      microrm/src/query.rs
  2. 27 0
      microrm/tests/derive.rs

+ 34 - 0
microrm/src/query.rs

@@ -464,6 +464,40 @@ pub trait Queryable: Clone {
         txn.commit()
     }
 
+    /// Delete all entities in the current context and return them
+    fn remove(self) -> DBResult<Self::OutputContainer>
+    where
+        Self: Sized,
+    {
+        let txn = Transaction::new(self.conn())?;
+        struct DeleteTag;
+        let out = self.conn().with_prepared(
+            std::any::TypeId::of::<(Self::StaticVersion, DeleteTag)>(),
+            || {
+                format!(
+                    "DELETE FROM `{entity}` WHERE `id` = ({subquery}) RETURNING *",
+                    entity = Self::EntityOutput::entity_name(),
+                    subquery = self
+                        .build()
+                        .replace(
+                            QueryPart::Columns,
+                            format!("`{}`.`id`", Self::EntityOutput::entity_name())
+                        )
+                        .assemble()
+                )
+            },
+            |mut ctx| {
+                // starting index is 1
+                let mut index = 1;
+                self.bind(&mut ctx, &mut index);
+
+                <Self::OutputContainer>::assemble_from(self.conn(), ctx)
+            },
+        )?;
+        txn.commit()?;
+        Ok(out)
+    }
+
     // ----------------------------------------------------------------------
     // Filtering methods
     // ----------------------------------------------------------------------

+ 27 - 0
microrm/tests/derive.rs

@@ -122,6 +122,33 @@ fn delete_test() {
     assert!(db.people.by_id(id).expect("couldn't query db").is_none());
 }
 
+#[test]
+fn remove_test() {
+    let db = common::open_test_db::<PeopleDB>("derive_remove_test");
+
+    let id = db
+        .people
+        .insert(Person {
+            name: "person_name".to_string(),
+            roles: Default::default(),
+        })
+        .expect("couldn't insert test person");
+    assert!(db.people.by_id(id).expect("couldn't query db").is_some());
+
+    let removed = db
+        .people
+        .with(
+            <Person as microrm::schema::entity::Entity>::IDPart::default(),
+            &id,
+        )
+        .remove()
+        .expect("couldn't execute removal query");
+
+    assert_eq!(removed.len(), 1);
+
+    assert!(db.people.by_id(id).expect("couldn't query db").is_none());
+}
+
 #[test]
 fn update_test() {
     let db = common::open_test_db::<PeopleDB>("derive_update_test");