Common commit
This commit is contained in:
@@ -2,7 +2,7 @@ import datetime
|
||||
from dataclasses import dataclass, fields
|
||||
from typing import Optional, List, get_origin
|
||||
|
||||
from DataClassJson import DataClassJson
|
||||
from .DataClassJson import DataClassJson
|
||||
from modules.shared.DatabaseAbstraction import Cursor
|
||||
|
||||
types = {bool: 'INTEGER', int: 'INTEGER', float: 'REAL', str: "TEXT",
|
||||
@@ -22,9 +22,14 @@ class DataClassDatabase(DataClassJson):
|
||||
tmp_instance = cls()
|
||||
if not table_name: table_name = tmp_instance._table_name
|
||||
|
||||
pk_type = str
|
||||
for field in fields(tmp_instance):
|
||||
if field.name == tmp_instance._key_field:
|
||||
pk_type = field.type
|
||||
|
||||
result: list[str] = list()
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS {table_name} (fk TEXT NOT NULL, pk TEXT NOT NULL, PRIMARY KEY(pk, fk));')
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS {table_name}_archive (fk TEXT NOT NULL, pk TEXT NOT NULL, save_date TEXT NOT NULL, PRIMARY KEY(pk, fk, save_date));')
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS "{table_name}" (fk INTEGER NOT NULL, pk {types.get(pk_type, 'INTEGER')} NOT NULL, PRIMARY KEY(pk, fk));')
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS "{table_name}_archive" (fk INTEGER NOT NULL, pk {types.get(pk_type, 'INTEGER')} NOT NULL, save_date TEXT NOT NULL, PRIMARY KEY(pk, fk, save_date));')
|
||||
|
||||
excluded_fields = {f.name for f in fields(DataClassDatabase)}
|
||||
all_fields = [f for f in fields(cls) if f.name not in excluded_fields and not f.name.startswith('_')]
|
||||
@@ -35,10 +40,10 @@ class DataClassDatabase(DataClassJson):
|
||||
try: result.extend(inner_type.get_create_sqls())
|
||||
except Exception as e: raise RuntimeError('invalid forwarding type') from e
|
||||
elif field.type in { list, Optional[list], Optional[List] }:
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS {table_name}_{field.name} (fk TEXT NOT NULL, data TEXT NOT NULL, PRIMARY KEY(data, fk));')
|
||||
result.append(f'CREATE TABLE IF NOT EXISTS "{table_name}_{field.name}" (fk TEXT NOT NULL, data TEXT NOT NULL, PRIMARY KEY(data, fk));')
|
||||
else:
|
||||
result.append(f'ALTER TABLE {table_name} ADD COLUMN {field.name} {types.get(field.type, 'TEXT')};')
|
||||
result.append(f'ALTER TABLE {table_name}_archive ADD COLUMN {field.name} {types.get(field.type, 'TEXT')};')
|
||||
result.append(f'ALTER TABLE "{table_name}" ADD COLUMN "{field.name}" {types.get(field.type, 'TEXT')};')
|
||||
result.append(f'ALTER TABLE "{table_name}_archive" ADD COLUMN "{field.name}" {types.get(field.type, 'TEXT')};')
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
@@ -53,7 +58,7 @@ class DataClassDatabase(DataClassJson):
|
||||
params = list()
|
||||
instance = cls()
|
||||
|
||||
sql = f'SELECT pk, fk FROM {instance._table_name}'
|
||||
sql = f'SELECT pk, fk FROM "{instance._table_name}"'
|
||||
if pk or fk: sql += ' WHERE'
|
||||
if pk:
|
||||
params.append(pk)
|
||||
@@ -77,7 +82,7 @@ class DataClassDatabase(DataClassJson):
|
||||
def _load(cls, cur: Cursor, pk, fk, depth = 5):
|
||||
if not pk and not fk: return None
|
||||
instance = cls()
|
||||
res: dict = cur.fetchone(f'SELECT * FROM {instance._table_name} WHERE pk = ? AND fk = ?', [pk, fk])
|
||||
res: dict = cur.fetchone(f'SELECT * FROM "{instance._table_name}" WHERE pk = ? AND fk = ?', [pk, fk])
|
||||
if not res: return None
|
||||
rpk = res.pop('pk')
|
||||
rfk = res.pop('fk')
|
||||
@@ -93,7 +98,7 @@ class DataClassDatabase(DataClassJson):
|
||||
elif len(items) > 0: setattr(result, field.name, items[0])
|
||||
|
||||
elif field.type in {list, List, Optional[list], Optional[List]}:
|
||||
items = cur.fetchall(f'SELECT data from {instance._table_name}_{field.name} WHERE fk=?', [rpk])
|
||||
items = cur.fetchall(f'SELECT data from "{instance._table_name}_{field.name}" WHERE fk=?', [rpk])
|
||||
if items:
|
||||
items = [row['data'] for row in items]
|
||||
else:
|
||||
@@ -117,15 +122,15 @@ class DataClassDatabase(DataClassJson):
|
||||
|
||||
if prev and not self.equals_simple(prev):
|
||||
d = str(datetime.datetime.now())
|
||||
cur.execute(f'INSERT OR IGNORE INTO {prev._table_name}_archive (fk, pk, save_date) VALUES (?, ?, ?)', [fk, pk, d])
|
||||
cur.execute(f'INSERT OR IGNORE INTO "{prev._table_name}_archive" (fk, pk, save_date) VALUES (?, ?, ?)', [fk, pk, d])
|
||||
for field in prev.serializable_fields():
|
||||
attr = getattr(prev, field.name)
|
||||
if field.name in prev._forwarding: continue
|
||||
elif field.type in {list, List, Optional[list], Optional[List]} or isinstance(attr, list): continue
|
||||
else:
|
||||
cur.execute(f'UPDATE {prev._table_name}_archive SET {field.name}=? WHERE fk=? AND pk=? AND save_date=?', [attr, fk, pk, d])
|
||||
cur.execute(f'UPDATE "{prev._table_name}_archive" SET {field.name}=? WHERE fk=? AND pk=? AND save_date=?', [attr, fk, pk, d])
|
||||
|
||||
cur.execute(f'INSERT OR IGNORE INTO {self._table_name} (fk, pk) VALUES (?, ?)', [fk, pk])
|
||||
cur.execute(f'INSERT OR IGNORE INTO "{self._table_name}" (fk, pk) VALUES (?, ?)', [fk, pk])
|
||||
|
||||
for field in self.serializable_fields():
|
||||
attr = getattr(self, field.name)
|
||||
@@ -134,13 +139,13 @@ class DataClassDatabase(DataClassJson):
|
||||
if field.name in self._forwarding:
|
||||
if not isinstance(getattr(self, field.name), list): attr = [attr]
|
||||
for val in attr:
|
||||
val.save(cur, fk=pk)
|
||||
val.autosave(cur, fk=pk)
|
||||
continue
|
||||
elif field.type in {list, List, Optional[list], Optional[List]} or isinstance(attr, list):
|
||||
for val in attr: cur.execute(f'INSERT OR IGNORE INTO {self._table_name}_{field.name} VALUES (?, ?)', [pk, val])
|
||||
for val in attr: cur.execute(f'INSERT OR IGNORE INTO "{self._table_name}_{field.name}" VALUES (?, ?)', [pk, val])
|
||||
continue
|
||||
else:
|
||||
cur.execute(f'UPDATE {self._table_name} SET {field.name}=? WHERE fk=? AND pk=?', [attr, fk, pk])
|
||||
cur.execute(f'UPDATE "{self._table_name}" SET "{field.name}"=? WHERE fk=? AND pk=?', [attr, fk, pk])
|
||||
continue
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user