feat(er): allow multiple constraints on attributes

little changes in grammar to get a list of constraints (PK, FK or UK), so little changes in renderer to handle this list
This commit is contained in:
Tom PERRILLAT-COLLOMB
2023-01-24 21:20:11 +01:00
parent 549483d19b
commit 26e9b1790b
4 changed files with 44 additions and 4 deletions

View File

@@ -71,6 +71,20 @@
</pre>
<hr />
<pre class="mermaid">
erDiagram
"HOSPITAL" {
int id PK
int doctor_id PK,FK
string address UK
string name
string phone_number
string fax_number
}
</pre
>
<hr />
<script src="./mermaid.js"></script>
<script type="module">
mermaid.initialize({

View File

@@ -59,7 +59,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
// Check to see if any of the attributes has a key or a comment
attributes.forEach((item) => {
if (item.attributeKeyType !== undefined) {
if (item.attributeKeyTypeList !== undefined && item.attributeKeyTypeList.length > 0) {
hasKeyType = true;
}
@@ -112,6 +112,9 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
nodeHeight = Math.max(typeBBox.height, nameBBox.height);
if (hasKeyType) {
const keyTypeNodeText =
item.attributeKeyTypeList !== undefined ? item.attributeKeyTypeList.join(',') : '';
const keyTypeNode = groupNode
.append('text')
.classed('er entityLabel', true)
@@ -122,7 +125,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
.style('text-anchor', 'left')
.style('font-family', getConfig().fontFamily)
.style('font-size', attrFontSize + 'px')
.text(item.attributeKeyType || '');
.text(keyTypeNodeText);
attributeNode.kn = keyTypeNode;
const keyTypeBBox = keyTypeNode.node().getBBox();

View File

@@ -28,6 +28,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
\"[^"]*\" return 'WORD';
"erDiagram" return 'ER_DIAGRAM';
"{" { this.begin("block"); return 'BLOCK_START'; }
<block>"," return 'COMMA';
<block>\s+ /* skip whitespace in block */
<block>\b((?:PK)|(?:FK)|(?:UK))\b return 'ATTRIBUTE_KEY'
<block>(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD';
@@ -131,11 +132,12 @@ attributes
attribute
: attributeType attributeName { $$ = { attributeType: $1, attributeName: $2 }; }
| attributeType attributeName attributeKeyType { $$ = { attributeType: $1, attributeName: $2, attributeKeyType: $3 }; }
| attributeType attributeName attributeKeyTypeList { $$ = { attributeType: $1, attributeName: $2, attributeKeyTypeList: $3 }; }
| attributeType attributeName attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeComment: $3 }; }
| attributeType attributeName attributeKeyType attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeKeyType: $3, attributeComment: $4 }; }
| attributeType attributeName attributeKeyTypeList attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeKeyTypeList: $3, attributeComment: $4 }; }
;
attributeType
: ATTRIBUTE_WORD { $$=$1; }
;
@@ -144,6 +146,11 @@ attributeName
: ATTRIBUTE_WORD { $$=$1; }
;
attributeKeyTypeList
: attributeKeyType { $$ = [$1]; }
| attributeKeyTypeList COMMA attributeKeyType { $1.push($3); $$ = $1; }
;
attributeKeyType
: ATTRIBUTE_KEY { $$=$1; }
;

View File

@@ -190,6 +190,22 @@ describe('when parsing ER diagram it...', function () {
expect(entities[entity].attributes.length).toBe(4);
});
it('should allow an entity with attributes that have many constraints and comments', function () {
const entity = 'BOOK';
const attribute1 = 'int customer_number PK,FK "comment"';
const attribute2 = 'datetime customer_status_start_datetime PK,UK';
const attribute3 = 'string customer_name';
erDiagram.parser.parse(
`erDiagram\n${entity} {\n${attribute1} \n\n${attribute2}\n${attribute3}\n}`
);
const entities = erDb.getEntities();
expect(entities[entity].attributes[0].attributeKeyTypeList).toEqual(['PK', 'FK']);
expect(entities[entity].attributes[0].attributeComment).toBe('comment');
expect(entities[entity].attributes[1].attributeKeyTypeList).toEqual(['PK', 'UK']);
expect(entities[entity].attributes[2].attributeKeyTypeList).toBeUndefined();
});
it('should allow an entity with attribute that has a generic type', function () {
const entity = 'BOOK';
const attribute1 = 'type~T~ type';