from collections.abc import Iterable from typing import TypedDict from folkugat_web.dal.sql import Connection, get_connection from folkugat_web.model import temes as model PropertyRowTuple = tuple[int, int, str, str] class PropertyRowDict(TypedDict): id: int | None tema_id: int field: str value: str def property_to_row(property: model.Property) -> PropertyRowDict: return { "id": property.id, "tema_id": property.tema_id, "field": property.field.value, "value": property.value, } def row_to_property(row: PropertyRowTuple) -> model.Property: return model.Property( id=row[0], tema_id=row[1], field=model.PropertyField(row[2]), value=row[3], ) class QueryData(TypedDict, total=False): id: int tema_id: int def _filter_clause( property_id: int | None, tema_id: int | None, ) -> tuple[str, QueryData]: filter_clauses: list[str] = [] filter_data: QueryData = {} if property_id is not None: filter_clauses.append("id = :id") filter_data["id"] = property_id if tema_id is not None: filter_clauses.append("tema_id = :tema_id") filter_data["tema_id"] = tema_id filter_clause = " AND ".join(filter_clauses) return filter_clause, filter_data def get_properties(property_id: int | None = None, tema_id: int | None = None, con: Connection | None = None) -> Iterable[model.Property]: filter_clause, data = _filter_clause(property_id=property_id, tema_id=tema_id) if filter_clause: filter_clause = f"WHERE {filter_clause}" query = f""" SELECT id, tema_id, field, value FROM tema_properties {filter_clause} """ with get_connection(con) as con: cur = con.cursor() _ = cur.execute(query, data) return map(row_to_property, cur.fetchall()) def insert_property(property: model.Property, con: Connection | None = None) -> model.Property: data = property_to_row(property) query = f""" INSERT INTO tema_properties (id, tema_id, field, value) VALUES (:id, :tema_id, :field, :value) RETURNING * """ with get_connection(con) as con: cur = con.cursor() _ = cur.execute(query, data) row: PropertyRowTuple = cur.fetchone() return row_to_property(row) def create_property(tema_id: int, field: model.PropertyField | None = None, con: Connection | None = None) -> model.Property: new_property = model.Property( id=None, tema_id=tema_id, field=field or model.PropertyField.AUTOR, value="", ) return insert_property(new_property, con=con) def update_property(property: model.Property, con: Connection | None = None): data = property_to_row(property) query = """ UPDATE tema_properties SET tema_id = :tema_id, field = :field, value = :value WHERE id = :id """ with get_connection(con) as con: cur = con.cursor() _ = cur.execute(query, data) def delete_property(property_id: int, tema_id: int | None = None, con: Connection | None = None): filter_clause, data = _filter_clause(property_id=property_id, tema_id=tema_id) if filter_clause: filter_clause = f"WHERE {filter_clause}" query = f""" DELETE FROM tema_properties {filter_clause} """ with get_connection(con) as con: cur = con.cursor() _ = cur.execute(query, data)