You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The DBML parser assigns endpoints based on the order fields appear in the ref statement, NOT the ref direction symbol (>, <). The relation property (* or 1) is derived from the ref direction, but endpoint order is always lexical.
Test Cases
Test schema:
Table users { id int [pk] }
Table posts { id int [pk] user_id int }
Case 1: > — FK written first, arrow points right
Ref: posts.user_id > users.id
Endpoint
tableName
fieldNames
relation
ep0
posts
[user_id]
*
ep1
users
[id]
1
Problem: Current code treats ep0 as start (FK table), ep1 as end (PK table). This is correct here.
Case 2: < — FK written second, arrow points left
Ref: users.id < posts.user_id
Endpoint
tableName
fieldNames
relation
ep0
users
[id]
1
ep1
posts
[user_id]
*
Problem: Current code treats ep0 as start (FK table). But ep0 = users (PK table) and ep1 = posts (FK table). The FK is in ep1, not ep0. The start = FK table rule is broken.
Case 3: - — No direction (1-1)
Ref: users.id - profiles.user_id
Endpoint
tableName
fieldNames
relation
ep0
users
[id]
1
ep1
profiles
[user_id]
1
Problem: Both are 1. Which one is the FK? Must determine by checking if one side's fields are all primary keys or unique indexes.
Database Ref Direction Repair Logic
flowchart TD
A["For each ref in schema.refs\nep0 = ref.endpoints[0]\nep1 = ref.endpoints[1]"]
B{"ep0.relation === '*' ?"}
C["fkEndpoint = ep0\npkEndpoint = ep1"]
D{"ep1.relation === '*' ?"}
E["fkEndpoint = ep1\npkEndpoint = ep0"]
F["1-1: Check PK/unique\nAre ALL fields in ep0\nprimary or unique?"]
G{"ep0 all PK/unique AND\nep1 NOT all PK/unique?"}
H["fkEndpoint = ep1\npkEndpoint = ep0"]
I["default:\nfkEndpoint = ep1\npkEndpoint = ep0"]
J["start = fkEndpoint\nend = pkEndpoint"]
K{"fkRelation === '*' &&\npkRelation === '1' ?"}
L["MANY_TO_ONE"]
M["ONE_TO_ONE"]
A --> B
B -->|YES| C
B -->|NO| D
D -->|YES| E
D -->|NO, both are '1'| F
F --> G
G -->|YES| H
G -->|NO| I
C --> J
E --> J
H --> J
I --> J
J --> K
K -->|YES| L
K -->|NO| M
Loading
Fix Applied
for(constrefofschema.refs){constep0=ref.endpoints[0];constep1=ref.endpoints[1];// Determine FK side by relation: "*" = FK side, "1" = referenced sideletfkEndpoint,pkEndpoint;if(ep0.relation==="*"){fkEndpoint=ep0;pkEndpoint=ep1;}elseif(ep1.relation==="*"){fkEndpoint=ep1;pkEndpoint=ep0;}else{// 1-1: check which side's fields are all PK/uniqueconsttablesMap=newMap(tables.map((t)=>[t.name,t]));constpkTable=tablesMap.get(ep0.tableName);constfkTable=tablesMap.get(ep1.tableName);if(pkTable&&fkTable){constep0FieldsAllPK=ep0.fieldNames.every((name)=>{constf=pkTable.fields.find((f)=>f.name===name);returnf&&(f.primary||f.unique);});constep1FieldsAllPK=ep1.fieldNames.every((name)=>{constf=fkTable.fields.find((f)=>f.name===name);returnf&&(f.primary||f.unique);});if(ep0FieldsAllPK&&!ep1FieldsAllPK){fkEndpoint=ep1;pkEndpoint=ep0;}else{fkEndpoint=ep1;pkEndpoint=ep0;}}else{fkEndpoint=ep1;pkEndpoint=ep0;}}conststartTableName=fkEndpoint.tableName;constendTableName=pkEndpoint.tableName;// ... rest of relationship building using fkEndpoint/pkEndpoint}
DBML Ref Endpoint Order Analysis
Behavior of @dbml/core Parser
The DBML parser assigns endpoints based on the order fields appear in the ref statement, NOT the ref direction symbol (
>,<). Therelationproperty (*or1) is derived from the ref direction, but endpoint order is always lexical.Test Cases
Test schema:
Case 1:
>— FK written first, arrow points rightProblem: Current code treats ep0 as start (FK table), ep1 as end (PK table). This is correct here.
Case 2:
<— FK written second, arrow points leftProblem: Current code treats ep0 as start (FK table). But ep0 = users (PK table) and ep1 = posts (FK table). The FK is in ep1, not ep0. The start = FK table rule is broken.
Case 3:
-— No direction (1-1)Problem: Both are
1. Which one is the FK? Must determine by checking if one side's fields are all primary keys or unique indexes.Database Ref Direction Repair Logic
flowchart TD A["For each ref in schema.refs\nep0 = ref.endpoints[0]\nep1 = ref.endpoints[1]"] B{"ep0.relation === '*' ?"} C["fkEndpoint = ep0\npkEndpoint = ep1"] D{"ep1.relation === '*' ?"} E["fkEndpoint = ep1\npkEndpoint = ep0"] F["1-1: Check PK/unique\nAre ALL fields in ep0\nprimary or unique?"] G{"ep0 all PK/unique AND\nep1 NOT all PK/unique?"} H["fkEndpoint = ep1\npkEndpoint = ep0"] I["default:\nfkEndpoint = ep1\npkEndpoint = ep0"] J["start = fkEndpoint\nend = pkEndpoint"] K{"fkRelation === '*' &&\npkRelation === '1' ?"} L["MANY_TO_ONE"] M["ONE_TO_ONE"] A --> B B -->|YES| C B -->|NO| D D -->|YES| E D -->|NO, both are '1'| F F --> G G -->|YES| H G -->|NO| I C --> J E --> J H --> J I --> J J --> K K -->|YES| L K -->|NO| MFix Applied