Bug 77377 - SQL code generator generates "circular reference" foreign keys
Summary: SQL code generator generates "circular reference" foreign keys
Status: RESOLVED FIXED
Alias: None
Product: umbrello
Classification: Applications
Component: general (show other bugs)
Version: 1.2
Platform: unspecified Linux
: NOR normal
Target Milestone: ---
Assignee: Umbrello Development Group
URL:
Keywords:
: 76877 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-03-12 13:04 UTC by Maciej J . Woloszyk
Modified: 2006-11-20 22:36 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Patch to allow tables to have self-references (1.47 KB, patch)
2006-11-20 08:29 UTC, Alexey Parshin
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Maciej J . Woloszyk 2004-03-12 13:04:24 UTC
Version:           1.2 (using KDE 3.2.0, Gentoo)
Compiler:          gcc version 3.3.2 20031218 (Gentoo Linux 3.3.2-r5, propolice-3.3-7)
OS:          Linux (i686) release 2.4.22-gentoo-r7

When you use Umbrello to design SQL scheme using agregations to simulate foreign keys constraints the code generators creates foreign key constarint in both tables instead of the "source" (role B - as I assume looking at the arrowhead of the aggregation connection - which is a bit misleading) table. Below is the simple patch - it makes code generator to check the objects of the aggregations and only create constraint in one table. In the other table generator also places the constraint, but only as an SQL comment. I'm not sure how well will it work, but at least it works for me.

M.

----------------- umbrello-sqlwriter.patch ---------------------------
--- kdesdk-3.2.0-orig/umbrello/umbrello/codegenerators/sqlwriter.cpp    2003-09-21 10:41:52.000000000 +0200
+++ kdesdk-3.2.0/umbrello/umbrello/codegenerators/sqlwriter.cpp 2004-03-12 12:15:23.000000000 +0100
@@ -89,8 +89,14 @@
        UMLAssociationList aggregations = c->getAggregations();
        if( forceSections() || !aggregations.isEmpty() ) {
                for(UMLAssociation* a = aggregations.first(); a; a = aggregations.next()) {
-                       sql << ",\n\tCONSTRAINT " << a->getName() << " FOREIGN KEY (" << a->getMultiB() <<
-                              ") REFERENCES " <<   a->getObjectA()->getName() << "(" << a->getMultiA() << ")";
+                       if( a->getObjectA()->getID()==c->getID() ) {
+                               sql << "\n-- CONSTRAINT " << a->getName() << " FOREIGN KEY (" << a->getMultiB() <<
+                                       ") REFERENCES " <<   a->getObjectA()->getName() << "(" << a->getMultiA() << ")";
+                       } else {
+                               sql << ",\n\tCONSTRAINT " << a->getName() << " FOREIGN KEY (" << a->getMultiB() <<
+                                       ") REFERENCES " <<   a->getObjectA()->getName() << "(" << a->getMultiA() << ")";
+
+                       }
                }
        }
Comment 1 Jonathan Riddell 2004-03-15 23:31:39 UTC
I've applied the patch, thanks for your contribution.
Comment 2 Jonathan Riddell 2004-03-15 23:32:50 UTC
*** Bug 76877 has been marked as a duplicate of this bug. ***
Comment 3 Sebastian Stein 2004-07-29 17:47:02 UTC
- foreign key constraint fixed
- comma adding fixed for different scopes
Comment 4 Sebastian Stein 2004-07-29 17:50:08 UTC
Ah, I added the wrong comment a minute ago. This bug was already mostly fixed. I just removed the commented foreign key constraint, because it is nonsense and makes the code easier to read.
Comment 5 Alexey Parshin 2006-11-20 08:29:16 UTC
Created attachment 18621 [details]
Patch to allow tables to have self-references

Sometimes, you need something like this:
create table t1 (
  id int primary key,
  parent int references t1(id)
);
The proposed patch allows it.
Also, Umbrello sometimes tries to create (in the export file) the empty foreign
keys with no table name and fields. These declarations come as a result of
deleting associations and not accessible through the Umbrello interface.
However, they are presented in the XMI file. This patch offers a primitive
workaround for this problem, too, by ignoring such associations during export.
Comment 6 Alexey Parshin 2006-11-20 08:30:36 UTC
Forgot to tell: Umbrello version I'm reporting about is a part of KDE 3.5.5.
Comment 7 Oliver Kellogg 2006-11-20 20:29:26 UTC
In attachment id=18621, Alexey Parshin wrote:
+ if ( a->getRoleName(Uml::B) != "" && a->getRoleName(Uml::B) != "") {

Hmm, twice the same expression? Please check.
Comment 8 Oliver Kellogg 2006-11-20 22:36:55 UTC
SVN commit 606555 by okellogg:

Apply attachment 18621 [details] by Alexey Parshin with slight modification.
Thanks Alexey for contributing.
CCBUG:77377


 M  +12 -8     sqlwriter.cpp  


--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/sqlwriter.cpp #606554:606555
@@ -86,14 +86,18 @@
     UMLAssociationList aggregations = c->getAggregations();
     if( forceSections() || !aggregations.isEmpty() ) {
         for(UMLAssociation* a = aggregations.first(); a; a = aggregations.next()) {
-            if( a->getObject(Uml::A)->getID() != c->getID() ) {
-
-                sql << m_indentation << "," << m_endl << m_indentation
-                << "CONSTRAINT " << a->getName() << " FOREIGN KEY ("
-                << a->getRoleName(Uml::B) << ") REFERENCES "
-                << a->getObject(Uml::A)->getName()
-                << " (" << a->getRoleName(Uml::A) << ")";
-            }
+            UMLObject *objA = a->getObject(Uml::A);
+            UMLObject *objB = a->getObject(Uml::B);
+            if (objA->getID() == c->getID() && objB->getID() != c->getID())
+                continue;
+            QString roleNameA = a->getRoleName(Uml::A);
+            QString roleNameB = a->getRoleName(Uml::B);
+            if (roleNameA.isEmpty() || roleNameB.isEmpty())
+                continue;
+            sql << m_indentation << "," << m_endl;
+            sql << m_indentation << "CONSTRAINT " << a->getName()
+                << " FOREIGN KEY (" << roleNameB << ") REFERENCES "
+                << objA->getName() << " (" << roleNameA << ")";
         }
     }