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ção | Derivada de | Colunas extras |
|---|---|---|
pessoa_habilidade | habilidade | nivel |
pessoa_idioma_nivel | pessoa_idioma | nivel_leitura, nivel_fala |
pessoa_hobby | hobby | desde_quando |
pessoa_grupo_social | membro_grupo_social | papel |
pessoa_evento | participacao_evento_social | papel |
pessoa_doenca_familiar | predisposicao_genetica | grau_risco (normalizado em [0,1]) |
pessoa_pet | pet | tipo_vinculo |
pessoa_veiculo | veiculo | tipo_posse |
pessoa_imovel | imovel | tipo_posse |
pessoa_eleicao | comparecimento_eleitoral | participou |
pessoa_viagem_companheiro | companhia_viagem | papel |
pessoa_empresa_socio | contrato_trabalho com tipo_contrato = "PJ" | percentual_participacao |
pessoa_religiao_historico | conversao_religiosa | data_inicio, data_fim |
pessoa_documento_historico | pessoa_documento | data_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
| Tabela | Conteúdo |
|---|---|
versao_registro | uma linha de exemplo versionando o primeiro registro de pessoa |
log_alteracao | exemplo de alteração de estado_civil (campo antigo → novo) |
auditoria | registra a chamada generate_all(n=…, seed=…), usuário personadb_orchestrator, tabela ALL |
regra_geracao | uma linha por posição do pipeline (parametro = "pipeline_order") |
fonte_dado | uma linha por tabela do dataset, com metodo_geracao = "deterministic_pcg64_generator" |
validacao_consistencia | resultado dos validadores (violações ou cinco linhas nenhuma_violacao) |
exportacao_dataset | formato, número de tabelas e destino = "sha256:<digest>" |
semente_aleatoria | preenchida 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).