|
@ -12,14 +12,13 @@ from django.contrib.auth import get_user_model |
|
|
from django.contrib.auth.models import Group |
|
|
from django.contrib.auth.models import Group |
|
|
from django.contrib.contenttypes.models import ContentType |
|
|
from django.contrib.contenttypes.models import ContentType |
|
|
from django.core.exceptions import ObjectDoesNotExist |
|
|
from django.core.exceptions import ObjectDoesNotExist |
|
|
from django.db import ProgrammingError, connections, models, transaction |
|
|
from django.db import connections, transaction |
|
|
from django.db.models import CharField, Count, Max, TextField |
|
|
from django.db.models import CharField, Count, Max, TextField |
|
|
from django.db.models.base import ModelBase |
|
|
from django.db.models.base import ModelBase |
|
|
from model_mommy import mommy |
|
|
from model_mommy import mommy |
|
|
from model_mommy.mommy import foreign_key_required, make |
|
|
from model_mommy.mommy import foreign_key_required, make |
|
|
|
|
|
|
|
|
from sapl.base.models import (Argumento, Autor, Constraint, ProblemaMigracao, |
|
|
from sapl.base.models import Autor, ProblemaMigracao, TipoAutor |
|
|
TipoAutor) |
|
|
|
|
|
from sapl.comissoes.models import Comissao, Composicao, Participacao |
|
|
from sapl.comissoes.models import Comissao, Composicao, Participacao |
|
|
from sapl.materia.models import (AcompanhamentoMateria, Proposicao, |
|
|
from sapl.materia.models import (AcompanhamentoMateria, Proposicao, |
|
|
StatusTramitacao, TipoDocumento, |
|
|
StatusTramitacao, TipoDocumento, |
|
@ -170,44 +169,6 @@ def iter_sql_records(sql, db): |
|
|
record.__dict__.update(zip(fieldnames, row)) |
|
|
record.__dict__.update(zip(fieldnames, row)) |
|
|
yield record |
|
|
yield record |
|
|
|
|
|
|
|
|
# Todos os models têm no máximo uma constraint unique together |
|
|
|
|
|
# Isso é necessário para que o método delete_constraints funcione corretamente |
|
|
|
|
|
assert all(len(model._meta.unique_together) <= 1 |
|
|
|
|
|
for app in appconfs |
|
|
|
|
|
for model in app.models.values()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_constraints(model): |
|
|
|
|
|
# pega nome da unique constraint dado o nome da tabela |
|
|
|
|
|
table = model._meta.db_table |
|
|
|
|
|
cursor = exec_sql("SELECT conname FROM pg_constraint WHERE conrelid = " |
|
|
|
|
|
"(SELECT oid FROM pg_class WHERE relname LIKE " |
|
|
|
|
|
"'%s') and contype = 'u';" % (table)) |
|
|
|
|
|
result = () |
|
|
|
|
|
result = cursor.fetchall() |
|
|
|
|
|
# se existir um resultado, unique constraint será deletado |
|
|
|
|
|
for r in result: |
|
|
|
|
|
if r[0].endswith('key'): |
|
|
|
|
|
words_list = r[0].split('_') |
|
|
|
|
|
constraint = Constraint.objects.create( |
|
|
|
|
|
nome_tabela=table, nome_constraint=r[0], |
|
|
|
|
|
nome_model=model.__name__, tipo_constraint='one_to_one') |
|
|
|
|
|
for w in words_list: |
|
|
|
|
|
Argumento.objects.create(constraint=constraint, argumento=w) |
|
|
|
|
|
else: |
|
|
|
|
|
if model._meta.unique_together: |
|
|
|
|
|
args_list = model._meta.unique_together[0] |
|
|
|
|
|
constraint = Constraint.objects.create( |
|
|
|
|
|
nome_tabela=table, nome_constraint=r[0], |
|
|
|
|
|
nome_model=model.__name__, |
|
|
|
|
|
tipo_constraint='unique_together') |
|
|
|
|
|
for a in args_list: |
|
|
|
|
|
Argumento.objects.create(constraint=constraint, |
|
|
|
|
|
argumento=a) |
|
|
|
|
|
warn('Excluindo unique constraint de nome %s' % r[0]) |
|
|
|
|
|
exec_sql("ALTER TABLE %s DROP CONSTRAINT %s;" % |
|
|
|
|
|
(table, r[0])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def problema_duplicatas(model, lista_duplicatas, argumentos): |
|
|
def problema_duplicatas(model, lista_duplicatas, argumentos): |
|
|
for obj in lista_duplicatas: |
|
|
for obj in lista_duplicatas: |
|
@ -228,62 +189,6 @@ def problema_duplicatas(model, lista_duplicatas, argumentos): |
|
|
reversion.set_comment('%s não é único.' % model.__name__) |
|
|
reversion.set_comment('%s não é único.' % model.__name__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def recria_constraints(): |
|
|
|
|
|
constraints = Constraint.objects.all() |
|
|
|
|
|
for con in constraints: |
|
|
|
|
|
if con.tipo_constraint == 'one_to_one': |
|
|
|
|
|
nome_tabela = con.nome_tabela |
|
|
|
|
|
nome_constraint = con.nome_constraint |
|
|
|
|
|
args = [a.argumento for a in con.argumento_set.all()] |
|
|
|
|
|
args_string = '' |
|
|
|
|
|
args_string = "(" + "_".join(map(str, args[2:-1])) + ")" |
|
|
|
|
|
model = ContentType.objects.filter( |
|
|
|
|
|
model=con.nome_model.lower())[0].model_class() |
|
|
|
|
|
try: |
|
|
|
|
|
exec_sql("ALTER TABLE %s ADD CONSTRAINT %s UNIQUE %s;" % |
|
|
|
|
|
(nome_tabela, nome_constraint, args_string)) |
|
|
|
|
|
except ProgrammingError: |
|
|
|
|
|
info('A constraint %s já foi recriada!' % nome_constraint) |
|
|
|
|
|
if con.tipo_constraint == 'unique_together': |
|
|
|
|
|
nome_tabela = con.nome_tabela |
|
|
|
|
|
nome_constraint = con.nome_constraint |
|
|
|
|
|
# Pegando explicitamente o primeiro valor do filter, |
|
|
|
|
|
# pois pode ser que haja mais de uma ocorrência |
|
|
|
|
|
model = ContentType.objects.filter( |
|
|
|
|
|
model=con.nome_model.lower())[0].model_class() |
|
|
|
|
|
args = [a.argumento for a in con.argumento_set.all()] |
|
|
|
|
|
for i in range(len(args)): |
|
|
|
|
|
if isinstance(model._meta.get_field(args[i]), |
|
|
|
|
|
models.ForeignKey): |
|
|
|
|
|
args[i] = args[i] + '_id' |
|
|
|
|
|
args_string = '' |
|
|
|
|
|
args_string += "(" + ', '.join(map(str, args)) + ")" |
|
|
|
|
|
|
|
|
|
|
|
distintos = model.objects.order_by(*args).distinct(*args) |
|
|
|
|
|
todos = model.objects.all() |
|
|
|
|
|
if hasattr(model, "content_type"): |
|
|
|
|
|
distintos = distintos.exclude(content_type_id=None, |
|
|
|
|
|
object_id=None) |
|
|
|
|
|
todos = todos.exclude(content_type_id=None, object_id=None) |
|
|
|
|
|
|
|
|
|
|
|
lista_duplicatas = list(set(todos).difference(set(distintos))) |
|
|
|
|
|
if lista_duplicatas: |
|
|
|
|
|
problema_duplicatas(model, lista_duplicatas, args) |
|
|
|
|
|
else: |
|
|
|
|
|
try: |
|
|
|
|
|
exec_sql("ALTER TABLE %s ADD CONSTRAINT %s UNIQUE %s;" % |
|
|
|
|
|
(nome_tabela, nome_constraint, args_string)) |
|
|
|
|
|
except ProgrammingError: |
|
|
|
|
|
info('A constraint %s já foi recriada!' % nome_constraint) |
|
|
|
|
|
except Exception as err: |
|
|
|
|
|
problema = re.findall('\(.*?\)', err.args[0]) |
|
|
|
|
|
erro('A constraint [%s] da tabela [%s] não pode ser" \ |
|
|
|
|
|
recriada' % (nome_constraint, nome_tabela)) |
|
|
|
|
|
erro('Os dados %s = %s estão duplicados. ' |
|
|
|
|
|
'Arrume antes de recriar as constraints!' % |
|
|
|
|
|
(problema[0], problema[1])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO o que é isso? #################################################### |
|
|
# TODO o que é isso? #################################################### |
|
|
def obj_desnecessario(obj): |
|
|
def obj_desnecessario(obj): |
|
|
relacoes = [ |
|
|
relacoes = [ |
|
@ -484,9 +389,6 @@ class DataMigrator: |
|
|
while self.delete_stubs(): |
|
|
while self.delete_stubs(): |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
info('Recriando constraints...') |
|
|
|
|
|
recria_constraints() |
|
|
|
|
|
|
|
|
|
|
|
def _do_migrate(self, obj): |
|
|
def _do_migrate(self, obj): |
|
|
if isinstance(obj, AppConfig): |
|
|
if isinstance(obj, AppConfig): |
|
|
models_to_migrate = (model for model in obj.models.values() |
|
|
models_to_migrate = (model for model in obj.models.values() |
|
@ -514,8 +416,6 @@ class DataMigrator: |
|
|
legacy_model = legacy_app.get_model(legacy_model_name) |
|
|
legacy_model = legacy_app.get_model(legacy_model_name) |
|
|
legacy_pk_name = legacy_model._meta.pk.name |
|
|
legacy_pk_name = legacy_model._meta.pk.name |
|
|
|
|
|
|
|
|
delete_constraints(model) |
|
|
|
|
|
|
|
|
|
|
|
# setup migration strategy for tables with or without a pk |
|
|
# setup migration strategy for tables with or without a pk |
|
|
if legacy_pk_name == 'id': |
|
|
if legacy_pk_name == 'id': |
|
|
# There is no pk in the legacy table |
|
|
# There is no pk in the legacy table |
|
|