about summary refs log tree commit diff
path: root/gn3/db/case_attributes.py
diff options
context:
space:
mode:
authorMunyoki Kilyungi2025-07-01 15:10:03 +0300
committerBonfaceKilz2025-07-07 07:58:31 +0300
commit495219adf83af8ba576de613735b9bd954e4cc9d (patch)
treefdf438075110f4e5142021283a9119a50fb92932 /gn3/db/case_attributes.py
parent0d144bd464c493dc53be38fe5129bfbdfa1a3b29 (diff)
downloadgenenetwork3-495219adf83af8ba576de613735b9bd954e4cc9d.tar.gz
Add function for adding a change.
Signed-off-by: Munyoki Kilyungi <me@bonfacemunyoki.com>
Diffstat (limited to 'gn3/db/case_attributes.py')
-rw-r--r--gn3/db/case_attributes.py99
1 files changed, 98 insertions, 1 deletions
diff --git a/gn3/db/case_attributes.py b/gn3/db/case_attributes.py
index 4bdb654..0c3d115 100644
--- a/gn3/db/case_attributes.py
+++ b/gn3/db/case_attributes.py
@@ -123,7 +123,7 @@ def update_case_attribute(cursor, directory: Path,
                     review_ids = pickle.loads(reviews)
                 if approvals := txn.get(b"approved"):
                     approved_ids = pickle.loads(approvals)
-                review_ids.remove(change_id)
+                review_ids.discard(change_id)
                 approved_ids.add(change_id)
                 txn.put(b"review", pickle.dumps(review_ids))
                 txn.put(b"approved", pickle.dumps(approved_ids))
@@ -186,3 +186,100 @@ def get_changes(cursor, inbredset_id: int, directory: Path) -> dict:
         "approvals": approvals,
         "rejections": rejections
     }
+
+
+def apply_change(cursor, change_type: EditStatus, change_id: int, directory: Path) -> bool:
+    review_ids, approved_ids, rejected_ids = set(), set(), set()
+    env = lmdb.open(directory, map_size=8_000_000)  # 1 MB
+    with env.begin(write=True) as txn:
+        if reviews := txn.get(b"review"):
+            review_ids = pickle.loads(reviews)
+        if change_id not in review_ids:
+            return False
+        match change_type:
+            case EditStatus.rejected:
+                cursor.execute(
+                    "UPDATE caseattributes_audit "
+                    "SET status = %s "
+                    "WHERE id = %s",
+                    (str(change_type), change_id))
+                review_ids.discard(change_id)
+                rejected_ids.add(change_id)
+                txn.put(b"review", pickle.dumps(review_ids))
+                txn.put(b"rejected", pickle.dumps(rejected_ids))
+                return True
+            case EditStatus.approved:
+                cursor.execute(
+                    "SELECT json_diff_data "
+                    "FROM caseattributes_audit WHERE "
+                    "id = %s",
+                    (change_id,)
+                )
+                json_diff_data, _ = cursor.fetchone()
+                json_diff_data = json.loads(json_diff_data)
+                inbredset_id = json_diff_data.get("inbredset_id")
+                modifications = json_diff_data.get(
+                    "Modifications", {}).get("Current", {})
+                strains = tuple(modifications.keys())
+                case_attrs = set()
+                for data in modifications.values():
+                    case_attrs.update(data.keys())
+
+                # Bulk fetch strain ids
+                strain_id_map = {}
+                if strains:
+                    cursor.execute(
+                        "SELECT Name, Id FROM Strain WHERE Name IN "
+                        f"({', '.join(['%s'] * len(strains))})",
+                        strains
+                    )
+                    for name, strain_id in cursor.fetchall():
+                        strain_id_map[name] = strain_id
+
+                # Bulk fetch case attr ids
+                caseattr_id_map = {}
+                if case_attrs:
+                    cursor.execute(
+                        "SELECT Name, CaseAttributeId FROM CaseAttribute "
+                        "WHERE InbredSetId = %s AND Name IN "
+                        f"({', '.join(['%s'] * len(case_attrs))})",
+                        (inbredset_id, *case_attrs)
+                    )
+                    for name, caseattr_id in cursor.fetchall():
+                        caseattr_id_map[name] = caseattr_id
+
+                # Bulk insert data
+                insert_data = []
+                for strain, data in modifications.items():
+                    strain_id = strain_id_map.get(strain)
+                    for case_attr, value in data.items():
+                        insert_data.append({
+                            "inbredset_id": inbredset_id,
+                            "strain_id": strain_id,
+                            "caseattr_id": caseattr_id_map.get(case_attr),
+                            "value": value,
+                        })
+                if insert_data:
+                    cursor.executemany(
+                        "INSERT INTO CaseAttributeXRefNew "
+                        "(InbredSetId, StrainId, CaseAttributeId, Value) "
+                        "VALUES (%(inbredset_id)s, %(strain_id)s, %(caseattr_id)s, %(value)s) "
+                        "ON DUPLICATE KEY UPDATE Value = VALUES(Value)",
+                        insert_data
+                    )
+
+                # Update LMDB and audit table
+                cursor.execute(
+                    "UPDATE caseattributes_audit "
+                    "SET status = %s "
+                    "WHERE id = %s",
+                    (str(change_type), change_id))
+                if approvals := txn.get(b"approved"):
+                    approved_ids = pickle.loads(approvals)
+                review_ids.discard(change_id)
+                approved_ids.add(change_id)
+                txn.put(b"review", pickle.dumps(review_ids))
+                txn.put(b"approvals", pickle.dumps(approved_ids))
+                return True
+            case _:
+                raise ValueError