home · contact · privacy
Refactor updates of relations tables.
[plomtask] / plomtask / todos.py
index cfac5b536e91514f02d938fc760818d3d7278129..348dbddcbb96338ba1f1e10da50e094e36b92f63 100644 (file)
@@ -1,5 +1,7 @@
 """Actionables."""
 from __future__ import annotations
+from typing import Any
+from sqlite3 import Row
 from plomtask.db import DatabaseConnection, BaseModel
 from plomtask.processes import Process
 from plomtask.conditions import Condition
@@ -31,24 +33,29 @@ class Todo(BaseModel):
             self.fulfills = process.fulfills[:]
             self.undoes = process.undoes[:]
 
+    @classmethod
+    def from_table_row(cls, db_conn: DatabaseConnection,
+                       row: Row | list[Any]) -> Todo:
+        """Make from DB row, write to DB cache."""
+        if row[1] == 0:
+            raise NotFoundException('calling Todo of '
+                                    'unsaved Process')
+        row_as_list = list(row)
+        row_as_list[1] = Process.by_id(db_conn, row[1])
+        todo = super().from_table_row(db_conn, row_as_list)
+        assert isinstance(todo, Todo)
+        return todo
+
     @classmethod
     def by_id(cls, db_conn: DatabaseConnection, id_: int | None) -> Todo:
         """Get Todo of .id_=id_ and children (from DB cache if possible)."""
-        if id_ in db_conn.cached_todos.keys():
-            todo = db_conn.cached_todos[id_]
+        if id_:
+            todo, from_cache = super()._by_id(db_conn, id_)
         else:
-            todo = None
-            for row in db_conn.exec('SELECT * FROM todos WHERE id = ?',
-                                    (id_,)):
-                row = list(row)
-                if row[1] == 0:
-                    raise NotFoundException('calling Todo of '
-                                            'unsaved Process')
-                row[1] = Process.by_id(db_conn, row[1])
-                todo = cls.from_table_row(db_conn, row)
-                break
-            if todo is None:
-                raise NotFoundException(f'Todo of ID not found: {id_}')
+            todo, from_cache = None, False
+        if todo is None:
+            raise NotFoundException(f'Todo of ID not found: {id_}')
+        if not from_cache:
             for row in db_conn.exec('SELECT child FROM todo_children '
                                     'WHERE parent = ?', (id_,)):
                 todo.children += [cls.by_id(db_conn, row[0])]
@@ -174,29 +181,11 @@ class Todo(BaseModel):
         self.save_core(db_conn)
         assert isinstance(self.id_, int)
         db_conn.cached_todos[self.id_] = self
-        db_conn.exec('DELETE FROM todo_children WHERE parent = ?',
-                     (self.id_,))
-        for child in self.children:
-            db_conn.exec('INSERT INTO todo_children VALUES (?, ?)',
-                         (self.id_, child.id_))
-        db_conn.exec('DELETE FROM todo_fulfills WHERE todo = ?', (self.id_,))
-        for condition in self.fulfills:
-            if condition.id_ is None:
-                raise NotFoundException('Fulfilled Condition of Todo '
-                                        'without ID (not saved?)')
-            db_conn.exec('INSERT INTO todo_fulfills VALUES (?, ?)',
-                         (self.id_, condition.id_))
-        db_conn.exec('DELETE FROM todo_undoes WHERE todo = ?', (self.id_,))
-        for condition in self.undoes:
-            if condition.id_ is None:
-                raise NotFoundException('Undone Condition of Todo '
-                                        'without ID (not saved?)')
-            db_conn.exec('INSERT INTO todo_undoes VALUES (?, ?)',
-                         (self.id_, condition.id_))
-        db_conn.exec('DELETE FROM todo_conditions WHERE todo = ?', (self.id_,))
-        for condition in self.conditions:
-            if condition.id_ is None:
-                raise NotFoundException('Condition of Todo '
-                                        'without ID (not saved?)')
-            db_conn.exec('INSERT INTO todo_conditions VALUES (?, ?)',
-                         (self.id_, condition.id_))
+        db_conn.rewrite_relations('todo_children', 'parent', self.id_,
+                                  [[c.id_] for c in self.children])
+        db_conn.rewrite_relations('todo_conditions', 'todo', self.id_,
+                                  [[c.id_] for c in self.conditions])
+        db_conn.rewrite_relations('todo_fulfills', 'todo', self.id_,
+                                  [[c.id_] for c in self.fulfills])
+        db_conn.rewrite_relations('todo_undoes', 'todo', self.id_,
+                                  [[c.id_] for c in self.undoes])