Source code for ewoksutils.logging_utils.sqlite3
import sqlite3
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Sequence
from .. import sqlite3_utils
from .connection import ConnectionHandler
Sqlite3RecordType = List[Any]
[docs]
class Sqlite3Handler(ConnectionHandler):
def __init__(
self,
uri: str,
table: str,
field_types: Dict,
timeout: float = 10,
disconnect_on_error: bool = False,
):
"""
:param uri: for example "file:/path/to/test.db" or "file:///path/to/test.db".
:param table: name of the database table in which records are inserted
(the table is created when missing).
:param field_types: mapping from record attribute names (table columns)
to python types.
:param timeout: native sqlite3 busy timeout: the maximum time to wait
for database locks to be released by other connections.
A record is dropped when the timeout is reached.
:param disconnect_on_error: disconnect when emitting a record failed.
"""
super().__init__(disconnect_on_error=disconnect_on_error)
self._uri = uri
self._timeout = timeout
self._field_sql_types = sqlite3_utils.python_to_sql_types(field_types)
self._ensure_table_query = sqlite3_utils.ensure_table_query(
table, self._field_sql_types
)
self._insert_row_query = sqlite3_utils.insert_query(
table, len(self._field_sql_types)
)
self._connection = None
self._connection_context = None
def _connect(self) -> None:
ctx = sqlite3_utils.connect(
self._uri, timeout=self._timeout, uri=True, check_same_thread=False
)
try:
conn = ctx.__enter__()
self._sql_query(self._ensure_table_query, conn=conn)
except BaseException:
ctx.__exit__(None, None, None)
self._connection = None
self._connection_context = None
raise
self._connection = conn
self._connection_context = ctx
def _disconnect(self) -> None:
self._connection_context.__exit__(None, None, None)
self._connection = None
self._connection_context = None
def _connected(self) -> bool:
return self._connection is not None
def _send_serialized_record(self, values: Optional[Sqlite3RecordType]):
if values:
self._sql_query(self._insert_row_query, values)
def _serialize_record(self, record) -> Optional[Sqlite3RecordType]:
lst = list()
for field, sql_type in self._field_sql_types.items():
value = getattr(record, field, None)
lst.append(sqlite3_utils.serialize(value, sql_type))
return lst
def _sql_query(
self,
sql: str,
parameters: Sequence = tuple(),
conn: Optional[sqlite3.Connection] = None,
) -> None:
if conn is None:
conn = self._connection
try:
conn.execute(sql, parameters)
conn.commit()
except BaseException:
# Do not leave the failed query pending in an open transaction.
try:
conn.rollback()
except sqlite3.OperationalError:
pass
raise