Pular para o conteúdo principal

Junções e metadados

Três domínios não têm gerador próprio: eles são derivados pelo orquestrador scripts/generate.py depois que todos os geradores rodam.

Domínio 25 — tabelas de junção N:N​

_build_junction_tables(dataset, today) percorre as tabelas já geradas e materializa 14 relações muitos-para-muitos, deduplicando pares com conjuntos auxiliares.

Tabela de junçãoDerivada deColunas extras
pessoa_habilidadehabilidadenivel
pessoa_idioma_nivelpessoa_idiomanivel_leitura, nivel_fala
pessoa_hobbyhobbydesde_quando
pessoa_grupo_socialmembro_grupo_socialpapel
pessoa_eventoparticipacao_evento_socialpapel
pessoa_doenca_familiarpredisposicao_geneticagrau_risco (normalizado em [0,1])
pessoa_petpettipo_vinculo
pessoa_veiculoveiculotipo_posse
pessoa_imovelimoveltipo_posse
pessoa_eleicaocomparecimento_eleitoralparticipou
pessoa_viagem_companheirocompanhia_viagempapel
pessoa_empresa_sociocontrato_trabalho com tipo_contrato = "PJ"percentual_participacao
pessoa_religiao_historicoconversao_religiosadata_inicio, data_fim
pessoa_documento_historicopessoa_documentodata_emissao, data_expiracao

A tabela pessoa_processo também é N:N, mas é produzida diretamente por gen_11_juridico.

:::note Fallback de religião Numa execução completa, se nenhuma conversão religiosa foi sorteada, o orquestrador insere uma linha mínima em pessoa_religiao_historico (primeira pessoa, primeira crença, início na data de nascimento) para que a tabela não fique vazia. O fallback depende de crenca e pessoa já estarem no dataset: numa execução parcial (--domains sem 18_religiao) a tabela pode ficar vazia. :::

for v in dataset.get("veiculo", []):
prop_id = v.get("proprietario_pessoa_id") or v.get("pessoa_id_proprietario") or v.get("pessoa_id")
if prop_id and v.get("id"):
junc["pessoa_veiculo"].append({"pessoa_id": prop_id, "veiculo_id": v["id"],
"tipo_posse": "proprietario"})

O padrão a or b or c acomoda variações de nomenclatura entre geradores — um detalhe pragmático que vale conhecer ao criar novas tabelas.

Domínio 24 — metadados, auditoria e proveniência​

TabelaConteúdo
versao_registrouma linha de exemplo versionando o primeiro registro de pessoa
log_alteracaoexemplo de alteração de estado_civil (campo antigo → novo)
auditoriaregistra a chamada generate_all(n=…, seed=…), usuário personadb_orchestrator, tabela ALL
regra_geracaouma linha por posição do pipeline (parametro = "pipeline_order")
fonte_dadouma linha por tabela do dataset, com metodo_geracao = "deterministic_pcg64_generator"
validacao_consistenciaresultado dos validadores (violações ou cinco linhas nenhuma_violacao)
exportacao_datasetformato, número de tabelas e destino = "sha256:<digest>"
semente_aleatoriapreenchida no banco pelo gatilho de 99_functions.sql ao inserir em pessoa

O digest é calculado sobre o mapa ordenado de contagens por tabela:

digest = hashlib.sha256(
json.dumps({k: len(v) for k, v in sorted(dataset.items())}, sort_keys=True).encode("utf-8")
).hexdigest()[:32]

Ou seja: o digest é uma impressão digital das contagens de linhas por tabela, não do conteúdo. Duas execuções com os mesmos parâmetros (semente, número de personas, data-âncora e domínios) produzem o mesmo digest, e ele muda quando alguma tabela passa a ter mais ou menos linhas — mas não detecta mudanças nos valores das linhas. Para regressão de conteúdo, compare os datasets (ou o JSON exportado) diretamente.

Domínio 26 — versão do schema​

schema_version recebe uma linha fixa (1.0.0, "PersonaDB schema inicial (25 domínios + controle)"), útil para validar que o dataset e o DDL aplicado estão na mesma geração.

Reproduzindo fora do orquestrador​

from datetime import date
from persona_db.scripts.generate import _build_junction_tables, generate_all

dataset = generate_all(n=50, seed=7)
juncoes = _build_junction_tables(dataset, date(2026, 1, 1))
print({k: len(v) for k, v in juncoes.items()})

A função tem prefixo _ por ser detalhe de implementação: a interface pública é generate_all, que já a chama quando o filtro --domains inclui 25_juncoes (ou quando não há filtro).