Files
aiodatalite/datalite/mass_actions.py
2020-08-23 01:49:15 +03:00

68 lines
2.4 KiB
Python

"""
This module includes functions to insert multiple records
to a bound database at one time, with one time open and closing
of the database file.
"""
from typing import TypeVar, Union, List, Tuple
from dataclasses import asdict
from .constraints import ConstraintFailedError
from .commons import _convert_sql_format
import sqlite3 as sql
T = TypeVar('T')
class MisformedCollectionError(Exception):
pass
def is_homogeneous(objects: Union[List[T], Tuple[T]]) -> bool:
"""
Check if all of the members a Tuple or a List
is of the same type.
:param objects: Tuple or list to check.
:return: If all of the members of the same type.
"""
class_ = objects[0].__class__
return all([isinstance(obj, class_) for obj in objects])
def create_many_entries(objects: Union[List[T], Tuple[T]], protect_memory: bool = True) -> None:
"""
Insert many records corresponding to objects
in a tuple or a list.
:param protect_memory: If False, memory protections are turned off,
makes it faster.
:param objects: A tuple or a list of objects decorated
with datalite.
:return: None.
"""
if not objects or not is_homogeneous(objects):
raise MisformedCollectionError("Tuple or List is empty or homogeneous.")
sql_queries = []
first_index: int = 0
table_name = objects[0].__class__.__name__.lower()
for obj in objects:
kv_pairs = asdict(obj).items()
sql_queries.append(f"INSERT INTO {table_name}(" +
f"{', '.join(item[0] for item in kv_pairs)})" +
f" VALUES ({', '.join(_convert_sql_format(item[1]) for item in kv_pairs)});")
with sql.connect(getattr(objects[0], "db_path")) as con:
cur: sql.Cursor = con.cursor()
try:
if not protect_memory:
cur.execute("PRAGMA synchronous = OFF")
cur.execute("PRAGMA journal_mode = MEMORY")
cur.execute(f"SELECT obj_id FROM {table_name} ORDER BY obj_id DESC LIMIT 1")
index_tuple = cur.fetchone()
if index_tuple:
first_index = index_tuple[0]
cur.executescript("BEGIN TRANSACTION;\n" + '\n'.join(sql_queries) + '\nEND TRANSACTION;')
except sql.IntegrityError:
raise ConstraintFailedError
con.commit()
for i, obj in enumerate(objects):
setattr(obj, "obj_id", first_index + i)