Source code for sqldbclient.dialects.postgresql.sql_view_materializer.sql_view_materializer

import logging
from dataclasses import fields

from sqldbclient.sql_executor import SqlExecutor
from sqldbclient.dialects.postgresql.sql_view_factory.view import View
from sqldbclient.dialects.postgresql.sql_view_factory.sql_view_factory import SqlViewFactory
from sqldbclient.dialects.postgresql.sql_view_materializer.sql_view_materializer_utils import SqlViewMaterializerUtils

logger = logging.getLogger(__name__)


[docs]class SqlViewMaterializer: """Class that is used to materialize in database changes that were made to corresponding View object. """ def __init__(self, view: View, sql_executor: SqlExecutor): self.sql_executor = sql_executor self.view = view self.existing_view = SqlViewFactory(self.view.name, self.view.schema, self.sql_executor).create() def _recreate(self): with self.sql_executor: # from children to parents dependant_objects_reversed = self.existing_view.dependant_objects[::-1] for obj in dependant_objects_reversed: SqlViewMaterializerUtils(obj, self.sql_executor).drop() SqlViewMaterializerUtils(self.existing_view, self.sql_executor).drop() # from parents to children SqlViewMaterializerUtils(self.view, self.sql_executor).restore() for obj in self.view.dependant_objects: SqlViewMaterializerUtils(obj, self.sql_executor).restore() # from parents to children SqlViewMaterializerUtils(self.view, self.sql_executor).refresh() for obj in self.view.dependant_objects: SqlViewMaterializerUtils(obj, self.sql_executor).refresh() # from parents to children SqlViewMaterializerUtils(self.view, self.sql_executor).create_indexes() for obj in self.view.dependant_objects: SqlViewMaterializerUtils(obj, self.sql_executor).create_indexes() self.sql_executor.commit() logger.info(f'View {self} recreated') def _parse_field(self, field): existing_value = getattr(self.existing_view, field.name) new_value = getattr(self.view, field.name) if existing_value == new_value: return logger.info(f'Found different value for field: {field.name}') if field.name in ['schema', 'name', 'full_name']: raise Exception('Unexpected error') if field.name in ['dependant_objects', 'dependant_objects_number', 'indexes', 'indexes_number']: logger.warning(f'{field.name} cannot be changed') return if field.name in ('table_description', 'col_descriptions'): raise NotImplementedError() if field.name == 'privileges': SqlViewMaterializerUtils(self.view, self.sql_executor).set_privileges() elif field.name == 'owner': SqlViewMaterializerUtils(self.view, self.sql_executor).set_owner() elif field.name in ['definition', 'view_type']: logger.warning(f'To change {field.name} view {self.view.full_name} will be fully recreated') self._recreate() logger.info(f'Field {field.name} set to {new_value}')
[docs] def materialize(self) -> None: """Materializes in database changes that were made to corresponding View object. """ if self.view == self.existing_view: logger.warning("View already exists, nothing done") return if fields(self.view) != fields(self.existing_view): raise ValueError(f'View {self.view} invalid') for field in fields(self.view): self._parse_field(field)