X-Git-Url: https://git.auder.net/?p=erdiag.git;a=blobdiff_plain;f=parser.js;h=6d028fd05e07e5f812a4a0238f13dbce54aa30ef;hp=f718f316aa61b3528573a54e48629a3406c8219a;hb=e570c0aab6f7b776cb8c6ce3c7d64c585deb66a0;hpb=19addd10d9f37cc081779b9ec17f2f98ee161889 diff --git a/parser.js b/parser.js index f718f31..6d028fd 100644 --- a/parser.js +++ b/parser.js @@ -89,12 +89,12 @@ class ErDiags // attributes: ArrayOf {name, [isKey], [type], [qualifiers]} parseAttributes(lines, start, end) { - let attributes = []; + let attributes = [ ]; for (let i=start; i { + let idx = this.tables[inh.parent].findIndex( item => { return item.isKey; }); + inh.children.forEach( c => { + this.tables[c].push({ + name: inh.parent + "_id", + type: this.tables[inh.parent][idx].type, + isKey: true, + qualifiers: (this.tables[inh.parent][idx].qualifiers || "") + " foreign key references " + inh.parent, + ref: inh.parent, + }); + }); + }); // Pass 2: parse associations, add foreign keys when cardinality is 0,1 or 1,1 this.associations.forEach( a => { let newTableAttrs = [ ]; + let hasZeroOne = false; a.entities.forEach( e => { if (['?','1'].includes(e.card[0])) { + hasZeroOne = true; // Foreign key apparition (for each entity in association minus current one, for each identifying attribute) a.entities.forEach( e2 => { if (e2.name == e.name) return; - e2.attributes.forEach( attr => { + this.entities[e2.name].attributes.forEach( attr => { if (attr.isKey) { this.tables[e.name].push({ isKey: e.card.length >= 2 && e.card[1] == 'R', //"weak tables" foreign keys become part of the key - name: "#" + e2.name + "_" + attr.name, + name: e2.name + "_" + attr.name, type: attr.type, - qualifiers: "foreign key references " + e2.name + " " + (e.card[0]=='1' : "not null" : ""), + qualifiers: "foreign key references " + e2.name + " " + (e.card[0]=='1' ? "not null" : ""), ref: e2.name, //easier drawMld function (fewer regexps) }); } @@ -202,18 +218,18 @@ class ErDiags else { // Add all keys in current entity - let fields = e.attributes.filter( attr => { return attr.isKey; }); + let fields = this.entities[e.name].attributes.filter( attr => { return attr.isKey; }); newTableAttrs.push({ fields: fields, entity: e.name, }); } - } - if (newTableAttrs.length > 1) + }); + if (!hasZeroOne && newTableAttrs.length > 1) { // Ok, really create a new table let newTable = { - name: a.name || newTableAttrs.map( item => { return item.entity; }).join("_"); + name: a.name || newTableAttrs.map( item => { return item.entity; }).join("_"), fields: [ ], }; newTableAttrs.forEach( item => { @@ -221,14 +237,14 @@ class ErDiags newTable.fields.push({ name: item.entity + "_" + f.name, isKey: true, - type: f.type,, - qualifiers: (f.qualifiers+" " || "") + "foreign key references " + item.entity + " not null", + type: f.type, + qualifiers: (f.qualifiers || "") + " foreign key references " + item.entity + " not null", ref: item.entity, }); }); }); // Add relationship potential own attributes - a.attributes.forEach( attr => { + (a.attributes || [ ]).forEach( attr => { newTable.fields.push({ name: attr.name, isKey: false, @@ -325,10 +341,10 @@ class ErDiags // https://www.developpez.net/forums/d1088964/general-developpement/alm/modelisation/structure-agregation-l-association-d-association/ _.shuffle(i.children).forEach( c => { if (Math.random() < 0.5) - mcdDot += '"' + c + '":name -- "' + i.parent; + mcdDot += '"' + c + '":name -- "' + i.parent + '":name [dir="forward",arrowhead="vee",'; else - mcdDot += '"' + i.parent + '":name -- "' + c; - mcdDot += '":name [dir="forward", arrowhead="vee", style="dashed"];\n'; + mcdDot += '"' + i.parent + '":name -- "' + c + '":name [dir="back",arrowtail="vee",'; + mcdDot += 'style="dashed"];\n'; }); }); // Relationships: @@ -380,7 +396,7 @@ class ErDiags }); }); mcdDot += '}'; - console.log(mcdDot); + //console.log(mcdDot); ErDiags.AjaxGet(mcdDot, graphSvg => { this.mcdGraph = graphSvg; element.innerHTML = graphSvg; @@ -399,21 +415,32 @@ class ErDiags } // Build dot graph input (assuming foreign keys not already present...) let mldDot = 'graph {\n'; + mldDot += 'rankdir="LR";\n'; mldDot += 'node [shape=plaintext];\n'; let links = ""; _.shuffle(Object.keys(this.tables)).forEach( name => { mldDot += '"' + name + '" [label=<\n'; mldDot += '\n'; - this.tables[name].fields.forEach( f => { + this.tables[name].forEach( f => { let label = (f.isKey ? '' : '') + (!!f.qualifiers && f.qualifiers.indexOf("foreign")>=0 ? '#' : '') + f.name + (f.isKey ? '' : ''); - mldDot += '\n'; + mldDot += '\n'; if (!!f.ref) { + // Need to find a key attribute in reference entity (the first...) + let keyInRef = ""; + for (let field of this.tables[f.ref]) + { + if (field.isKey) + { + keyInRef = field.name; + break; + } + } if (Math.random() < 0.5) - links += '"' + f.ref + '":__key -- "' + '"'+name+'":"'+f.name+'"\n'; + links += '"' + f.ref + '":"' + keyInRef + '" -- "' + name+'":"'+f.name + '" [dir="forward",arrowhead="dot"'; else - links += '"'+name+'":"'+f.name+'" -- "' + f.ref + '":__key\n'; + links += '"'+name+'":"'+f.name+'" -- "' + f.ref + '":"' + keyInRef + '" [dir="back",arrowtail="dot"'; + links += ']\n;'; } }); mldDot += '
' + name + '
' + label + '
' + label + '
>];\n'; @@ -440,11 +467,11 @@ class ErDiags sqlText += "CREATE TABLE " + name + " (\n"; let key = ""; this.tables[name].forEach( f => { - sqlText += f.name + " " + (f.type || "TEXT") + (" "+f.qualifiers || "") + ",\n"; + sqlText += "\t" + f.name + " " + (f.type || "TEXT") + " " + (f.qualifiers || "") + ",\n"; if (f.isKey) key += (key.length>0 ? "," : "") + f.name; }); - sqlText += "PRIMARY KEY (" + key + ")\n"; + sqlText += "\tPRIMARY KEY (" + key + ")\n"; sqlText += ");\n"; }); //console.log(sqlText);