Browse Source

Cria arquivo para management command

pull/3112/head
Vinícius Cantuária 5 years ago
parent
commit
108ccee8f2
  1. 97
      sapl/rules/apps.py
  2. 67
      sapl/rules/management/commands/check_ids_sequences.py

97
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")

67
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()
Loading…
Cancel
Save