From b8af38fdc3c2f56ffbf4f0be715742152a3f37c8 Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Fri, 2 Feb 2018 19:43:38 +0100 Subject: [PATCH] Fix bugs, MLD graphs now seem well generated --- README.md | 2 +- example.html | 7 ++++ example.svg | 96 ------------------------------------------------- example_MCD.svg | 86 ++++++++++++++++++++++++++++++++++++++++++++ example_MLD.svg | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ parser.js | 54 +++++++++++++++++++--------- 6 files changed, 228 insertions(+), 113 deletions(-) delete mode 100644 example.svg create mode 100644 example_MCD.svg create mode 100644 example_MLD.svg diff --git a/README.md b/README.md index b39f8a7..2f543b9 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ To indicate an inheritance relation, proceed as follow Animal Cat Fish Planet Mars Venus -Finally, blocks must be separated by new lines. For a usage example, see example.html (it should render as seen in example.svg) +Finally, blocks must be separated by new lines. For a usage example, see example.html (it should render as seen in example\_\*.svg) Note that the "drawMcd" method can take a second argument, which indicates the type of graph. * "bubble" draws the standard graph, as seen [here](https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model#/media/File:ER_Diagram_MMORPG.png) for example diff --git a/example.html b/example.html index d5a27ac..24d8953 100644 --- a/example.html +++ b/example.html @@ -1,6 +1,12 @@ +

MCD graph:

+ +

MLD graph:

+

SQL instructions:

+
+ diff --git a/example.svg b/example.svg deleted file mode 100644 index bf81b87..0000000 --- a/example.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - -%3 - - - -Musician - -Musician - -id - -name - -band - -role - - - - -Play - -Play - - - -Musician:name--Play - -1,n - - - -Instrument - -Instrument - -name - -family - - - - -Instrument:name--Play - -0,n - - - -Piano - -Piano - -type - - - - -Piano:name--Instrument:name - - - - - -Guitar - -Guitar - -type - - - - -Guitar:name--Instrument:name - - - - - -Play_event - -event - - - -Play_event--Play - - - - diff --git a/example_MCD.svg b/example_MCD.svg new file mode 100644 index 0000000..4d6c1a1 --- /dev/null +++ b/example_MCD.svg @@ -0,0 +1,86 @@ + + + + + + +%3 + + + +Musician + +Musician + +id + +name + +band + +role + + + + +Play + +<Play> +event + + + +Musician:name--Play + +1,n + + + +Instrument + +Instrument + +name + +family + + + + +Guitar + +Guitar + +type + + + + +Instrument:name--Guitar:name + + + + + +Instrument:name--Play + +0,n + + + +Piano + +Piano + +type + + + + +Piano:name--Instrument:name + + + + + diff --git a/example_MLD.svg b/example_MLD.svg new file mode 100644 index 0000000..4f03c96 --- /dev/null +++ b/example_MLD.svg @@ -0,0 +1,96 @@ + + + + + + +%3 + + + +Instrument + +Instrument + +name + +family + + + + +Guitar + +Guitar + +type + +#Instrument_id + + + + +Instrument:name--Guitar:Instrument_id + + + + + +Piano + +Piano + +type + +#Instrument_id + + + + +Instrument:name--Piano:Instrument_id + + + + + +Musician + +Musician + +id + +name + +band + +role + + + + +Play + +Play + +#Musician_id + +#Instrument_name + +event + + + + +Play:Instrument_name--Instrument:name + + + + + +Play:Musician_id--Musician:id + + + + + diff --git a/parser.js b/parser.js index db70f7f..41eff93 100644 --- a/parser.js +++ b/parser.js @@ -9,9 +9,6 @@ class ErDiags this.tables = { }; this.mcdParsing(description); this.mldParsing(); - - console.log(this.tables); - // Cache SVG graphs returned by server (in addition to server cache = good perfs) this.mcdGraph = ""; this.mldGraph = ""; @@ -178,6 +175,20 @@ class ErDiags }); this.tables[name] = newTable; }); + // Add foreign keys information for children (inheritance). TODO: allow several levels + // NOTE: modelisation assume each child has its own table, refering parent (other options exist) + this.inheritances.forEach( inh => { + 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 = [ ]; @@ -193,7 +204,7 @@ class ErDiags { 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" : ""), ref: e2.name, //easier drawMld function (fewer regexps) @@ -225,7 +236,7 @@ class ErDiags name: item.entity + "_" + f.name, isKey: true, type: f.type, - qualifiers: (f.qualifiers+" " || "") + "foreign key references " + item.entity + " not null", + qualifiers: (f.qualifiers || "") + " foreign key references " + item.entity + " not null", ref: item.entity, }); }); @@ -328,10 +339,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: @@ -383,7 +394,7 @@ class ErDiags }); }); mcdDot += '}'; - console.log(mcdDot); + //console.log(mcdDot); ErDiags.AjaxGet(mcdDot, graphSvg => { this.mcdGraph = graphSvg; element.innerHTML = graphSvg; @@ -402,6 +413,7 @@ 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 => { @@ -409,21 +421,31 @@ class ErDiags mldDot += '' + name + '\n'; this.tables[name].forEach( f => { let label = (f.isKey ? '' : '') + (!!f.qualifiers && f.qualifiers.indexOf("foreign")>=0 ? '#' : '') + f.name + (f.isKey ? '' : ''); - mldDot += '' + label + '\n'; + mldDot += '' + label + '\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 += '>];\n'; }); mldDot += links + '\n'; mldDot += '}\n'; - console.log(mldDot); + //console.log(mldDot); ErDiags.AjaxGet(mldDot, graphSvg => { this.mldGraph = graphSvg; element.innerHTML = graphSvg; @@ -443,11 +465,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); -- 2.44.0