From 108ccee8f26e66d8fdfc3686277203e6dbd1a59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Cantu=C3=A1ria?= Date: Wed, 30 Sep 2020 08:55:35 -0300 Subject: [PATCH] Cria arquivo para management command --- sapl/rules/apps.py | 97 +------------------ .../commands/check_ids_sequences.py | 67 +++++++++++++ 2 files changed, 71 insertions(+), 93 deletions(-) create mode 100644 sapl/rules/management/commands/check_ids_sequences.py diff --git a/sapl/rules/apps.py b/sapl/rules/apps.py index f41b39ade..18ad112a6 100644 --- a/sapl/rules/apps.py +++ b/sapl/rules/apps.py @@ -6,7 +6,7 @@ from django.apps import apps from django.contrib.auth import get_user_model from django.contrib.auth.management import _get_all_permissions from django.core import exceptions -from django.db import models, router, connection +from django.db import models, router from django.db.utils import DEFAULT_DB_ALIAS from django.utils.translation import ugettext_lazy as _ import reversion @@ -16,8 +16,6 @@ from sapl.rules import (SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_COMISSOES, SAPL_GROUP_PAINEL, SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO) -logger = logging.getLogger(__name__) - class AppConfig(django.apps.AppConfig): name = 'sapl.rules' @@ -237,99 +235,12 @@ def cria_usuarios_padrao(): rules.cria_usuarios_padrao() -def fn_check_sequence_for_model(model): - SP_NAME = fn_check_sequence_for_model.__name__ - - with connection.cursor() as c: - try: - c.callproc( - SP_NAME, [ - model._meta.db_table - ]) - except Exception as e: - if('function {}(unknown)' - ' does not exist'.format(SP_NAME) not in str(e)): - # Se ocorreu um erro e não é por inexistência da SP - logger.error( - "Falha na execução da Store Procedure " - "para a tabela {}. {}".format( - model._meta.db_table, str(e))) - else: - # se a execução da SP falhou por ela não existir - try: - # cria a SP - c.execute( - """ - CREATE OR REPLACE FUNCTION {}(IN table_name character varying) RETURNS integer AS - $$ - DECLARE - max_id integer := 0; - BEGIN - EXECUTE format('SELECT setval(pg_get_serial_sequence(''%s'',''id''), coalesce(max(id), 1), max(id) IS NOT null) FROM %s', table_name, table_name ) INTO max_id; - if max_id is null then - EXECUTE format('DROP SEQUENCE IF EXISTS %s_id_seq cascade', table_name); - EXECUTE format('CREATE SEQUENCE %s_id_seq start 1 OWNED BY %s.id', table_name, table_name); - EXECUTE format('ALTER TABLE %s ALTER COLUMN id SET DEFAULT nextval(''%s_id_seq''::regclass)', table_name, table_name); - EXECUTE format('SELECT setval(pg_get_serial_sequence(''%s'',''id''), coalesce(max(id), 1), max(id) IS NOT null) FROM %s', table_name, table_name ) INTO max_id; - end if; - return max_id; - END; - $$ LANGUAGE plpgsql; - """.format(SP_NAME) - ) - except Exception as e: - # se falhou na criação - logger.error( - "Falha na criação da Store Procedure {} " - "para o tabela {}. {}".format( - SP_NAME, - model._meta.db_table, - str(e))) - try: - # tenta executá-la após criação. - c.callproc( - SP_NAME, [ - model._meta.db_table - ]) - except Exception as e: - # se falhou na execução - logger.error( - "Falha na execução da Store Procedure {} " - "para o tabela {}. {}".format( - SP_NAME, - model._meta.db_table, - str(e))) - - finally: - c.close() - - -def check_ids_sequences(app_config, verbosity=2, interactive=True, - using=DEFAULT_DB_ALIAS, **kwargs): - - models = app_config.models - - for k, model in models.items(): - if model._meta.managed and model._meta.has_auto_field: - fn_check_sequence_for_model(model) - - def revision_pre_delete_signal(sender, **kwargs): with reversion.create_revision(): kwargs['instance'].save() reversion.set_comment("Deletado pelo sinal.") -models.signals.pre_delete.connect( - receiver=revision_pre_delete_signal, - dispatch_uid="pre_delete_signal") - -models.signals.post_migrate.connect( - receiver=update_groups) - -models.signals.post_migrate.connect( - receiver=check_ids_sequences) - -models.signals.post_migrate.connect( - receiver=create_proxy_permissions, - dispatch_uid="django.contrib.auth.management.create_permissions") +models.signals.post_migrate.connect(receiver=update_groups) +models.signals.post_migrate.connect(receiver=create_proxy_permissions, dispatch_uid="django.contrib.auth.management.create_permissions") +models.signals.pre_delete.connect(receiver=revision_pre_delete_signal, dispatch_uid="pre_delete_signal") diff --git a/sapl/rules/management/commands/check_ids_sequences.py b/sapl/rules/management/commands/check_ids_sequences.py new file mode 100644 index 000000000..92b47f9bc --- /dev/null +++ b/sapl/rules/management/commands/check_ids_sequences.py @@ -0,0 +1,67 @@ +import logging + +from django.apps import apps +from django.core.management.base import BaseCommand +from django.db import connection +from django.db.utils import DEFAULT_DB_ALIAS + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Check ids sequences and update them' + + def handle(self, *args, **kwargs): + models = apps.get_models() + + for model in models: + if model._meta.managed and model._meta.auto_field: + fn_check_sequence_for_model(model) + + +def fn_check_sequence_for_model(model): + SP_NAME = fn_check_sequence_for_model.__name__ + + with connection.cursor() as c: + try: + c.callproc(SP_NAME, [model._meta.db_table]) + except Exception as e: + if f"function {SP_NAME}(unknown) does not exist" not in str(e): + # Se ocorreu um erro e não é por inexistência da SP + logger.error(f"Falha na execução da Store Procedure para a tabela {model._meta.db_table}. {str(e)}") + else: + # se a execução da SP falhou por ela não existir + try: + # cria a SP + c.execute( + f""" + CREATE OR REPLACE FUNCTION {SP_NAME}(IN table_name character varying) RETURNS integer AS + $$ + DECLARE + max_id integer := 0; + BEGIN + EXECUTE format('SELECT setval(pg_get_serial_sequence(''%s'',''id''), coalesce(max(id), 1), max(id) IS NOT null) FROM %s', table_name, table_name ) INTO max_id; + if max_id is null then + EXECUTE format('DROP SEQUENCE IF EXISTS %s_id_seq cascade', table_name); + EXECUTE format('CREATE SEQUENCE %s_id_seq start 1 OWNED BY %s.id', table_name, table_name); + EXECUTE format('ALTER TABLE %s ALTER COLUMN id SET DEFAULT nextval(''%s_id_seq''::regclass)', table_name, table_name); + EXECUTE format('SELECT setval(pg_get_serial_sequence(''%s'',''id''), coalesce(max(id), 1), max(id) IS NOT null) FROM %s', table_name, table_name ) INTO max_id; + end if; + return max_id; + END; + $$ LANGUAGE plpgsql; + """ + ) + except Exception as e: + # se falhou na criação + logger.error(f"Falha na criação da Store Procedure {SP_NAME} para o tabela {model._meta.db_table}. {str(e)}") + logger.error(f"Falha na criação da Store Procedure {SP_NAME} para o tabela {model._meta.db_table}. {str(e)}") + try: + # tenta executá-la após criação. + c.callproc(SP_NAME, [model._meta.db_table]) + except Exception as e: + # se falhou na execução + logger.error(f"Falha na execução da Store Procedure {SP_NAME} para o tabela {model._meta.db_table}. {str(e)}") + + finally: + c.close()