|
|
|
|
# vim: fileencoding=utf-8
|
|
|
|
|
#
|
|
|
|
|
from ..template_engine import ParametersContainer
|
|
|
|
|
from .base_format import Format, FormatError
|
|
|
|
|
from sqlite3 import connect, Connection, OperationalError, IntegrityError
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SqliteFormat(Format):
|
|
|
|
|
FORMAT = 'sqlite'
|
|
|
|
|
EXECUTABLE = True
|
|
|
|
|
FORMAT_PARAMETERS = {'execsql'}
|
|
|
|
|
|
|
|
|
|
def __init__(self, template_text: str,
|
|
|
|
|
template_path: str,
|
|
|
|
|
parameters: ParametersContainer = ParametersContainer(),
|
|
|
|
|
**kwargs):
|
|
|
|
|
self._template_text = template_text
|
|
|
|
|
if parameters.execsql:
|
|
|
|
|
self._mode = parameters.execsql
|
|
|
|
|
else:
|
|
|
|
|
self._mode = "rollback"
|
|
|
|
|
|
|
|
|
|
self._executor = self.__getattribute__(f"_execute_{self._mode}")
|
|
|
|
|
|
|
|
|
|
# Измененные файлы.
|
|
|
|
|
self.changed_files = dict()
|
|
|
|
|
|
|
|
|
|
# Предупреждения.
|
|
|
|
|
self._warnings: list = []
|
|
|
|
|
|
|
|
|
|
def execute_format(self, target_path: str,
|
|
|
|
|
chroot_path: str = '/') -> dict:
|
|
|
|
|
'''Метод для запуска работы формата.'''
|
|
|
|
|
if os.path.exists(target_path) and os.path.isdir(target_path):
|
|
|
|
|
raise FormatError(f"directory on target path: {target_path}")
|
|
|
|
|
status = "N"
|
|
|
|
|
if os.path.exists(target_path):
|
|
|
|
|
status = "M"
|
|
|
|
|
|
|
|
|
|
connection = connect(target_path)
|
|
|
|
|
self._executor(connection, self._template_text)
|
|
|
|
|
connection.close()
|
|
|
|
|
|
|
|
|
|
self.changed_files[target_path] = status
|
|
|
|
|
return self.changed_files
|
|
|
|
|
|
|
|
|
|
def _execute_continue(self, connection: Connection, template_text: str):
|
|
|
|
|
"""Метод для выполнения sql-команд при значения параметра
|
|
|
|
|
execsql = continue. В этом случае после обнаружения ошибки в скрипте
|
|
|
|
|
выполнение команд будет продолжено."""
|
|
|
|
|
cursor = connection.cursor()
|
|
|
|
|
commands = template_text.split(";\n")
|
|
|
|
|
for command in commands:
|
|
|
|
|
try:
|
|
|
|
|
cursor.execute(command.strip())
|
|
|
|
|
connection.commit()
|
|
|
|
|
except (OperationalError, IntegrityError) as error:
|
|
|
|
|
self._warnings.append(str(error))
|
|
|
|
|
|
|
|
|
|
def _execute_rollback(self, connection: Connection, template_text: str):
|
|
|
|
|
"""Метод для выполнения sql-команд при значения параметра
|
|
|
|
|
execsql = rollback. В этом случае после обнаружения ошибки в скрипте
|
|
|
|
|
результат выполнения команд будет сброшен."""
|
|
|
|
|
commands = template_text.split(";\n")
|
|
|
|
|
cursor = connection.cursor()
|
|
|
|
|
cursor.execute("BEGIN TRANSACTION;")
|
|
|
|
|
try:
|
|
|
|
|
for command in commands:
|
|
|
|
|
cursor.execute(command)
|
|
|
|
|
connection.commit()
|
|
|
|
|
except (OperationalError, IntegrityError) as error:
|
|
|
|
|
self._warnings.append(str(error))
|
|
|
|
|
connection.rollback()
|
|
|
|
|
|
|
|
|
|
def _execute_stop(self, connection: Connection, template_text: str):
|
|
|
|
|
"""Метод для выполнения sql-команд при значения параметра
|
|
|
|
|
execsql = stop. В этом случае после обнаружения ошибки в скрипте
|
|
|
|
|
выполнение команд будет остановлено."""
|
|
|
|
|
cursor = connection.cursor()
|
|
|
|
|
try:
|
|
|
|
|
cursor.executescript(template_text)
|
|
|
|
|
except (OperationalError, IntegrityError) as error:
|
|
|
|
|
self._warnings.append(str(error))
|
|
|
|
|
finally:
|
|
|
|
|
connection.commit()
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def warnings(self):
|
|
|
|
|
return self._warnings
|