Debug
This commit is contained in:
parent
b9307ce566
commit
45e26f7c12
1 changed files with 55 additions and 29 deletions
|
|
@ -16,26 +16,46 @@ def is_ignored(name: str) -> bool:
|
|||
# Garante que a comparação é feita em caixa alta para robustez
|
||||
return FILTER_SUBSTRING in str(name).upper()
|
||||
|
||||
# --- NOVA FUNÇÃO HELPER: NORMALIZAÇÃO DE CHAVES ---
|
||||
|
||||
def _normalize_keys_to_upper(data: Any) -> Any:
|
||||
"""
|
||||
Recursivamente converte todas as chaves de dicionário para UPPERCASE.
|
||||
Mantém os valores (conteúdo) originais.
|
||||
"""
|
||||
if isinstance(data, dict):
|
||||
new_dict = {}
|
||||
for k, v in data.items():
|
||||
# Converte a chave para UPPERCASE se for string
|
||||
new_k = k.upper() if isinstance(k, str) else k
|
||||
# Chama recursivamente para o valor
|
||||
new_dict[new_k] = _normalize_keys_to_upper(v)
|
||||
return new_dict
|
||||
elif isinstance(data, list):
|
||||
# Itera sobre a lista
|
||||
return [_normalize_keys_to_upper(item) for item in data]
|
||||
else:
|
||||
# Retorna o valor (string, int, etc.)
|
||||
return data
|
||||
|
||||
# --- FUNÇÃO HELPER PARA REMOÇÃO DE SOURCE_CODE ---
|
||||
|
||||
def _remove_source_code(item: Dict) -> Dict:
|
||||
"""
|
||||
Remove o campo 'SOURCE_CODE' ou 'source_code' de um item de dicionário.
|
||||
(Case-insensitive para chaves comuns de código-fonte).
|
||||
(Funciona após a normalização, pois a chave sempre será 'SOURCE_CODE').
|
||||
"""
|
||||
item_copy = item.copy()
|
||||
|
||||
# Após a normalização para UPPERCASE, só precisamos checar 'SOURCE_CODE'
|
||||
if 'SOURCE_CODE' in item_copy:
|
||||
del item_copy['SOURCE_CODE']
|
||||
|
||||
if 'source_code' in item_copy:
|
||||
del item_copy['source_code']
|
||||
|
||||
return item_copy
|
||||
|
||||
# --- FUNÇÃO HELPER PARA OBTER IDENTIFICADOR ---
|
||||
def get_element_identifier(item):
|
||||
"""Retorna o principal identificador de um elemento de schema."""
|
||||
"""Retorna o principal identificador de um elemento de schema (assume UPPERCASE)."""
|
||||
return (
|
||||
item.get('TABLE_NAME') or
|
||||
item.get('CONSTRAINT_NAME') or
|
||||
|
|
@ -45,33 +65,32 @@ def get_element_identifier(item):
|
|||
item.get('TRIGGER_NAME')
|
||||
)
|
||||
|
||||
# --- FUNÇÃO AUXILIAR PARA COMPARAÇÃO DE CAMPOS (Omitida, pois não é chamada) ---
|
||||
# --- FUNÇÕES DE COMPARAÇÃO (Mantidas mas não chamadas para o retorno) ---
|
||||
def compare_fields(standard_fields: List[Dict], client_fields: List[Dict], table_name: str) -> List[Dict]:
|
||||
pass
|
||||
|
||||
# --- FUNÇÃO PRINCIPAL DE COMPARAÇÃO DE ESTRUTURAS (Omitida, pois não é chamada) ---
|
||||
def compare_structures(standard_structure: Dict[str, Any], client_structure: Dict[str, Any]) -> Dict[str, Any]:
|
||||
pass
|
||||
|
||||
|
||||
# --- FUNÇÃO: ELEMENTOS SOMENTE NO CLIENTE ---
|
||||
# --- FUNÇÃO: ELEMENTOS SOMENTE NO CLIENTE (Agora usa chaves UPPERCASE) ---
|
||||
|
||||
def find_client_only_elements(standard_structure: Dict[str, Any], client_structure: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Identifica elementos presentes na estrutura do cliente mas ausentes na estrutura padrão.
|
||||
Filtra elementos que contenham a substring CONVERSAO.
|
||||
Assume que as estruturas de entrada já estão com as chaves em UPPERCASE.
|
||||
"""
|
||||
client_only = {}
|
||||
|
||||
# --- 1. TABLES (Lidando com a estrutura achatada do cliente) ---
|
||||
|
||||
# 1a. Normalize e Filtra Tabelas Padrão
|
||||
standard_tables_names = {t.get('TABLE_NAME') for t in standard_structure.get('tables', [])
|
||||
standard_tables_names = {t.get('TABLE_NAME') for t in standard_structure.get('TABLES', [])
|
||||
if t.get('TABLE_NAME') and not is_ignored(t.get('TABLE_NAME'))}
|
||||
|
||||
# 1b. Agrupa e Filtra Campos do Cliente por Nome de Tabela
|
||||
client_fields_by_table: Dict[str, List[Dict]] = {}
|
||||
for field_item in client_structure.get('tables', []):
|
||||
# A chave do nível superior agora é 'TABLES' (em UPPERCASE)
|
||||
for field_item in client_structure.get('TABLES', []):
|
||||
table_name = field_item.get('TABLE_NAME')
|
||||
# Filtra a tabela e o elemento, se for CONVERSAO
|
||||
if table_name and not is_ignored(table_name):
|
||||
|
|
@ -93,11 +112,12 @@ def find_client_only_elements(standard_structure: Dict[str, Any], client_structu
|
|||
})
|
||||
|
||||
if client_only_tables:
|
||||
client_only["tabelas_unicas"] = client_only_tables
|
||||
client_only["TABELAS_UNICAS"] = client_only_tables
|
||||
|
||||
# --- 2. OUTROS ELEMENTOS (PKs, FKs, etc.) ---
|
||||
|
||||
elements_to_check = ['primary_keys', 'foreign_keys', 'indexes', 'views', 'procedures', 'triggers']
|
||||
# Chaves de nível superior agora em UPPERCASE
|
||||
elements_to_check = ['PRIMARY_KEYS', 'FOREIGN_KEYS', 'INDEXES', 'VIEWS', 'PROCEDURES', 'TRIGGERS']
|
||||
|
||||
for element_key in elements_to_check:
|
||||
standard_elements = standard_structure.get(element_key, [])
|
||||
|
|
@ -108,6 +128,7 @@ def find_client_only_elements(standard_structure: Dict[str, Any], client_structu
|
|||
# Standard Set (Filtrado para IGNORED)
|
||||
standard_elements_filtered = [item for item in standard_elements
|
||||
if not is_ignored(get_element_identifier(item))]
|
||||
# O _remove_source_code é chamado após a normalização.
|
||||
standard_set = {json.dumps(_remove_source_code(item), sort_keys=True)
|
||||
for item in standard_elements_filtered}
|
||||
|
||||
|
|
@ -126,7 +147,7 @@ def find_client_only_elements(standard_structure: Dict[str, Any], client_structu
|
|||
unique_client_elements_str = client_set - standard_set
|
||||
|
||||
if unique_client_elements_str:
|
||||
client_only[element_key + "_unicos"] = [
|
||||
client_only[element_key + "_UNICOS"] = [
|
||||
client_set_normalized[json_str] for json_str in unique_client_elements_str
|
||||
]
|
||||
|
||||
|
|
@ -138,19 +159,20 @@ def find_client_only_elements(standard_structure: Dict[str, Any], client_structu
|
|||
class ShowDatabaseService:
|
||||
|
||||
def _clean_full_structure_for_output(self, structure: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Cria uma cópia limpa da estrutura, removendo 'SOURCE_CODE' em todos os elementos relevantes."""
|
||||
"""Cria uma cópia limpa da estrutura, removendo 'SOURCE_CODE' em todos os elementos relevantes.
|
||||
Assume que a estrutura já está em UPPERCASE."""
|
||||
cleaned = json.loads(json.dumps(structure))
|
||||
|
||||
keys_to_clean = ['tables', 'views', 'procedures', 'triggers', 'primary_keys', 'foreign_keys', 'indexes']
|
||||
keys_to_clean = ['TABLES', 'VIEWS', 'PROCEDURES', 'TRIGGERS', 'PRIMARY_KEYS', 'FOREIGN_KEYS', 'INDEXES']
|
||||
|
||||
for key in keys_to_clean:
|
||||
if key in cleaned and isinstance(cleaned[key], list):
|
||||
# Aplica a limpeza a cada item da lista
|
||||
cleaned[key] = [_remove_source_code(item) for item in cleaned[key]]
|
||||
|
||||
# Garante que, se houver campos (FIELDS) aninhados (no padrão), eles também sejam limpos
|
||||
if 'tables' in cleaned and isinstance(cleaned['tables'], list):
|
||||
for table in cleaned['tables']:
|
||||
# Garante que, se houver campos (FIELDS) aninhados, eles também sejam limpos
|
||||
if 'TABLES' in cleaned and isinstance(cleaned['TABLES'], list):
|
||||
for table in cleaned['TABLES']:
|
||||
if 'FIELDS' in table and isinstance(table['FIELDS'], list):
|
||||
table['FIELDS'] = [_remove_source_code(field) for field in table['FIELDS']]
|
||||
|
||||
|
|
@ -176,6 +198,10 @@ class ShowDatabaseService:
|
|||
database_data = dados_json.get("database", {})
|
||||
client_structure: Dict[str, Any] = database_data.get("structure", {})
|
||||
|
||||
# 🚨 NOVO PASSO CRUCIAL: Normaliza as chaves para UPPERCASE em ambas as estruturas
|
||||
standard_structure_data = _normalize_keys_to_upper(standard_structure_data)
|
||||
client_structure = _normalize_keys_to_upper(client_structure)
|
||||
|
||||
# Limpa ambas as estruturas de 'source_code' para o output de debug
|
||||
debug_cliente = self._clean_full_structure_for_output(client_structure)
|
||||
debug_padrao = self._clean_full_structure_for_output(standard_structure_data)
|
||||
|
|
@ -189,22 +215,22 @@ class ShowDatabaseService:
|
|||
# 1. Lista para Análise Visual (estruturas Padrão e Cliente)
|
||||
data_list_for_visual_check = [
|
||||
{
|
||||
"id": 1,
|
||||
"estrutura": "Padrão (standard_structure_json)",
|
||||
"conteudo": debug_padrao
|
||||
"ID": 1,
|
||||
"ESTRUTURA": "PADRÃO (STANDARD_STRUCTURE_JSON) - CHAVES NORMALIZADAS",
|
||||
"CONTEUDO": debug_padrao
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"estrutura": "Cliente (client_structure)",
|
||||
"conteudo": debug_cliente
|
||||
"ID": 2,
|
||||
"ESTRUTURA": "CLIENTE (CLIENT_STRUCTURE) - CHAVES NORMALIZADAS",
|
||||
"CONTEUDO": debug_cliente
|
||||
}
|
||||
]
|
||||
|
||||
# 2. Monta o retorno final com as duas seções
|
||||
return {
|
||||
"message": "Estruturas de Banco de Dados para Análise Visual e Itens Exclusivos do Cliente",
|
||||
"data": data_list_for_visual_check,
|
||||
"itens_nao_encontrados_no_padrao": elementos_unicos_cliente
|
||||
"MESSAGE": "ESTRUTURAS DE BANCO DE DADOS PARA ANÁLISE VISUAL E ITENS EXCLUSIVOS DO CLIENTE",
|
||||
"DATA": data_list_for_visual_check,
|
||||
"ITENS_NAO_ENCONTRADOS_NO_PADRAO": elementos_unicos_cliente
|
||||
}
|
||||
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue