Bug 138139

Summary: Incorrect export to SQL
Product: [Applications] umbrello Reporter: Alexey Parshin <alexeyp>
Component: generalAssignee: Umbrello Development Group <umbrello-devel>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Gentoo Packages   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: Patch to fix sql export

Description Alexey Parshin 2006-11-30 10:53:32 UTC
Version:            (using KDE KDE 3.5.5)
Installed from:    Gentoo Packages
Compiler:          gcc 4.1.1 
OS:                Linux

The SQL export is incorrect as soon as the diagram is over about 50 objects, and associations between objects were dropped and recreated.
The following problems are detected:

1) Export to SQL ignores associations when a field of the table refers to another field of the same table.

2) With the large diagram (over 70..90) objects, some associations are repeated during the export multiple times (as CONSTRAINT .. FOREIGN KEY)

3) The generated CREATE TABLE statement contains CONSTRAINTS. That requires to execute output .sql files in certain order.

4) .XMI file contains hundreds of bogus connections. Some edit+save operations cause file size to double. I've given name to all the connections, yet hundreds of connections with name="" exist in the file. I didn't find any workaround for this yet.

I have a patch that fixes 1)..3). I'll try to attach it here if I find how.
Comment 1 Alexey Parshin 2006-11-30 10:54:30 UTC
Created attachment 18732 [details]
Patch to fix sql export
Comment 2 Oliver Kellogg 2006-11-30 18:56:43 UTC
> Patch to fix sql export 
 
The attachment contains the diff for sqlwriter.cpp but
apparently you have added a new member, constraintMap.
Please check - did you also modify sqlwriter.h (or some
other file?)

Comment 3 Oliver Kellogg 2006-11-30 19:00:06 UTC
Sorry, forget about Comment #2. All is fine and I will apply instantly.
Comment 4 Oliver Kellogg 2006-11-30 19:50:14 UTC
SVN commit 609424 by okellogg:

Apply attachment 18732 [details] from Alexey Parshin with slight modification.
writeClass(): Add an auxiliary variable, constraintMap, to avoid excessive
 code for duplicated associations. (Those duplicated associations should
 not be there in the first place though.)
writeAttributes(): Generate code for implementation-level attributes.
BUG:138139


 M  +1 -0      ChangeLog  
 M  +24 -11    umbrello/codegenerators/sqlwriter.cpp  


--- branches/KDE/3.5/kdesdk/umbrello/ChangeLog #609423:609424
@@ -11,6 +11,7 @@
   http://www.geeksoc.org/~jr/umbrello/uml-devel/9863.html
 * Bugs/wishes from http://bugs.kde.org:
 * Artifacts of a component diagram are wrongly placed in Deployment View folder (137564)
+* Incorrect export to SQL (138139)
 
 Version 1.5.52
 
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/sqlwriter.cpp #609423:609424
@@ -83,6 +83,9 @@
     if (isClass)
         writeAttributes(c, sql);
 
+    sql << m_endl << ");" << m_endl;
+
+    QMap<UMLAssociation*,UMLAssociation*> constraintMap; // so we don't repeat constraint
     UMLAssociationList aggregations = c->getAggregations();
     if( forceSections() || !aggregations.isEmpty() ) {
         for(UMLAssociation* a = aggregations.first(); a; a = aggregations.next()) {
@@ -90,18 +93,20 @@
             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 << ")";
+	    constraintMap[a] = a;
         }
     }
+    
+    QMap<UMLAssociation*,UMLAssociation*>::Iterator itor = constraintMap.begin();
+    for (;itor != constraintMap.end();itor++) {
+	UMLAssociation* a = itor.data();
+	sql << "ALTER TABLE "<< classname
+            << " ADD CONSTRAINT " << a->getName() << " FOREIGN KEY ("
+            << a->getRoleName(Uml::B) << ") REFERENCES "
+            << a->getObject(Uml::A)->getName()
+            << " (" << a->getRoleName(Uml::A) << ");" << m_endl;
+    }
 
-    sql << m_endl << ");" << m_endl;
 
     file.close();
     emit codeGenerated(c, true);
@@ -109,10 +114,11 @@
 
 
 void SQLWriter::writeAttributes(UMLClassifier *c, QTextStream &sql) {
-    UMLAttributeList atpub, atprot, atpriv;
+    UMLAttributeList atpub, atprot, atpriv, atimp;
     atpub.setAutoDelete(false);
     atprot.setAutoDelete(false);
     atpriv.setAutoDelete(false);
+    atimp.setAutoDelete(false);
 
     //sort attributes by scope and see if they have a default value
     UMLAttributeList atl = c->getAttributeList();
@@ -127,7 +133,8 @@
           case Uml::Visibility::Private:
             atpriv.append(at);
             break;
-          default:
+          case Uml::Visibility::Implementation:
+            atimp.append(at);
             break;
         }
     }
@@ -155,6 +162,12 @@
         first = false;
     }
 
+    if (atimp.count() > 0)
+    {
+        printAttributes(sql, atimp, first);
+        first = false;
+    }
+
     return;
 }