fix: handle bidirectional relationships in DBML export (#924)

This commit is contained in:
Guy Ben-Aharon
2025-09-17 18:13:48 +03:00
committed by GitHub
parent bc82f9d6a8
commit 9991077978
4 changed files with 178 additions and 7 deletions

View File

@@ -0,0 +1,129 @@
Enum "cbhpm_entradas_tipo" {
"grupo"
"subgrupo"
"procedimento"
}
Enum "cid_entradas_tipo" {
"capitulo"
"agrupamento"
"categoria"
"subcategoria"
}
Enum "digital_signature_provider" {
"soluti"
"valid"
}
Enum "impresso_posicao" {
"start"
"center"
"end"
}
Enum "otp_provider" {
"clinic"
"soluti_bird_id"
}
Enum "tipo_cobranca" {
"valor"
"porte"
}
Enum "tipo_contato_movel" {
"celular"
"telefone_residencial"
"telefone_comercial"
}
Enum "tipo_contrato" {
"trial"
"common"
}
Enum "tipo_endereco" {
"residencial"
"comercial"
"cobranca"
}
Enum "tipo_espectro_autista" {
"leve"
"moderado"
"severo"
}
Enum "tipo_estado_civil" {
"nao_infomado"
"solteiro"
"casado"
"divorciado"
"viuvo"
}
Enum "tipo_etnia" {
"nao_infomado"
"branca"
"preta"
"parda"
"amarela"
"indigena"
}
Enum "tipo_excecao" {
"bloqueio"
"compromisso"
}
Enum "tipo_metodo_reajuste" {
"percentual"
"valor"
}
Enum "tipo_pessoa" {
"fisica"
"juridica"
}
Enum "tipo_procedimento" {
"consulta"
"exame_laboratorial"
"exame_imagem"
"procedimento_clinico"
"procedimento_cirurgico"
"terapia"
"outros"
}
Enum "tipo_relacionamento" {
"pai"
"mae"
"conjuge"
"filho_a"
"tutor_legal"
"contato_emergencia"
"outro"
}
Enum "tipo_sexo" {
"nao_infomado"
"masculino"
"feminino"
"intersexo"
}
Enum "tipo_status_agendamento" {
"em espera"
"faltou"
"ok"
}
Table "public"."organizacao_cfg_impressos" {
"id_organizacao" integer [pk, not null, ref: < "public"."organizacao"."id"]
}
Table "public"."organizacao" {
"id" integer [pk, not null]
}

File diff suppressed because one or more lines are too long

View File

@@ -14,14 +14,36 @@ const testCase = (caseNumber: string) => {
// Generate DBML from the diagram
const result = generateDBMLFromDiagram(diagram);
const generatedDBML = result.standardDbml;
// Read the expected DBML file
const dbmlPath = path.join(__dirname, 'cases', `${caseNumber}.dbml`);
const expectedDBML = fs.readFileSync(dbmlPath, 'utf-8');
// Check for both regular and inline DBML files
const regularDbmlPath = path.join(__dirname, 'cases', `${caseNumber}.dbml`);
const inlineDbmlPath = path.join(
__dirname,
'cases',
`${caseNumber}.inline.dbml`
);
// Compare the generated DBML with the expected DBML
expect(generatedDBML).toBe(expectedDBML);
const hasRegularDbml = fs.existsSync(regularDbmlPath);
const hasInlineDbml = fs.existsSync(inlineDbmlPath);
// Test regular DBML if file exists
if (hasRegularDbml) {
const expectedRegularDBML = fs.readFileSync(regularDbmlPath, 'utf-8');
expect(result.standardDbml).toBe(expectedRegularDBML);
}
// Test inline DBML if file exists
if (hasInlineDbml) {
const expectedInlineDBML = fs.readFileSync(inlineDbmlPath, 'utf-8');
expect(result.inlineDbml).toBe(expectedInlineDBML);
}
// Ensure at least one DBML file exists
if (!hasRegularDbml && !hasInlineDbml) {
throw new Error(
`No DBML file found for test case ${caseNumber}. Expected either ${caseNumber}.dbml or ${caseNumber}.inline.dbml`
);
}
};
describe('DBML Export cases', () => {
@@ -40,4 +62,8 @@ describe('DBML Export cases', () => {
it('should handle case 4 diagram', { timeout: 30000 }, async () => {
testCase('4');
});
it('should handle case 5 diagram', { timeout: 30000 }, async () => {
testCase('5');
});
});

View File

@@ -506,15 +506,30 @@ const deduplicateRelationships = (diagram: Diagram): Diagram => {
if (!diagram.relationships) return diagram;
const seenRelationships = new Set<string>();
const seenBidirectional = new Set<string>();
const uniqueRelationships = diagram.relationships.filter((rel) => {
// Create a unique key based on the relationship endpoints
const relationshipKey = `${rel.sourceTableId}-${rel.sourceFieldId}->${rel.targetTableId}-${rel.targetFieldId}`;
// Create a normalized key that's the same for both directions
const normalizedKey = [
`${rel.sourceTableId}-${rel.sourceFieldId}`,
`${rel.targetTableId}-${rel.targetFieldId}`,
]
.sort()
.join('<->');
if (seenRelationships.has(relationshipKey)) {
return false; // Skip duplicate
return false; // Skip exact duplicate
}
if (seenBidirectional.has(normalizedKey)) {
// This is a bidirectional relationship, skip the second one
return false;
}
seenRelationships.add(relationshipKey);
seenBidirectional.add(normalizedKey);
return true; // Keep unique relationship
});