[Mono-bugs] [Bug 69276][Nor] New - XSD generates wrong code for ForeignKeyConstraints in typed datasets

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Tue, 9 Nov 2004 11:00:28 -0500 (EST)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by martin.voelkle@epfl.ch.

http://bugzilla.ximian.com/show_bug.cgi?id=69276

--- shadow/69276	2004-11-09 11:00:28.000000000 -0500
+++ shadow/69276.tmp.29070	2004-11-09 11:00:28.000000000 -0500
@@ -0,0 +1,176 @@
+Bug#: 69276
+Product: Mono: Compilers
+Version: 1.0
+OS: All
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: XSD
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: martin.voelkle@epfl.ch               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: XSD generates wrong code for ForeignKeyConstraints in typed datasets
+
+Description of Problem: 
+When generating a typed dataset from a schema file which contains foreign 
+key constraints, the resulting code is wrong. 
+ 
+Steps to reproduce the problem: 
+1. Here is a simple schema with 2 relations (foreign key constraints) 
+<?xml version="1.0" standalone="yes"?> 
+<xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" 
+id="MyDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
+  <xs:element name="MyDataSet" msdata:IsDataSet="true" msdata:Locale=""> 
+    <xs:complexType> 
+      <xs:choice maxOccurs="unbounded"> 
+        <xs:element name="Playlists"> 
+          <xs:complexType> 
+            <xs:sequence> 
+              <xs:element minOccurs="0" name="name" type="xs:string" /> 
+            </xs:sequence> 
+          </xs:complexType> 
+        </xs:element> 
+        <xs:element name="PlaylistsItems"> 
+          <xs:complexType> 
+            <xs:sequence> 
+              <xs:element minOccurs="0" name="playlist" 
+type="xs:string" /> 
+              <xs:element minOccurs="0" name="position" type="xs:int" /> 
+              <xs:element minOccurs="0" name="file" type="xs:string" /> 
+            </xs:sequence> 
+          </xs:complexType> 
+        </xs:element> 
+        <xs:element name="Files"> 
+          <xs:complexType> 
+            <xs:sequence> 
+              <xs:element minOccurs="0" name="name" type="xs:string" /> 
+            </xs:sequence> 
+          </xs:complexType> 
+        </xs:element> 
+      </xs:choice> 
+    </xs:complexType> 
+    <xs:unique name="PlaylistsPkey" msdata:PrimaryKey="true"> 
+      <xs:selector xpath=".//Playlists" /> 
+      <xs:field xpath="name" /> 
+    </xs:unique> 
+    <xs:unique name="PlaylistsItemsPkey" msdata:PrimaryKey="true"> 
+      <xs:selector xpath=".//PlaylistsItems" /> 
+      <xs:field xpath="playlist" /> 
+      <xs:field xpath="position" /> 
+    </xs:unique> 
+    <xs:unique name="FilesPkey" msdata:PrimaryKey="true"> 
+      <xs:selector xpath=".//Files" /> 
+      <xs:field xpath="name" /> 
+    </xs:unique> 
+    <xs:keyref refer="PlaylistsPkey" name="Relation1"> 
+      <xs:selector xpath=".//PlaylistsItems" /> 
+      <xs:field xpath="playlist" /> 
+    </xs:keyref> 
+    <xs:keyref refer="FilesPkey" name="Relation2"> 
+      <xs:selector xpath=".//PlaylistsItems" /> 
+      <xs:field xpath="file" /> 
+    </xs:keyref> 
+  </xs:element> 
+</xs:schema> 
+ 
+2. Generate the dataset 
+xsd schema.xsd /dataset 
+ 
+3. Try to use the generated class 
+public class MyClass { 
+  public static void Main(string[] args) { 
+    MyDataSet data = new MyDataSet(); 
+  } 
+} 
+ 
+Actual Results: 
+Unhandled Exception: System.ArgumentException: Neither ParentColumns or 
+ChildColumns can't be zero length. 
+in <0x000af> System.Data.ForeignKeyConstraint:_validateColumns 
+(System.Data.DataColumn[],System.Data.DataColumn[]) 
+in <0x00014> System.Data.ForeignKeyConstraint:_foreignKeyConstraint 
+(string,System.Data.DataColumn[],System.Data.DataColumn[]) 
+in <0x00047> System.Data.ForeignKeyConstraint:.ctor 
+(string,System.Data.DataColumn[],System.Data.DataColumn[]) 
+in <0x003e1> Prometheus.Data:InitializeClass () 
+in <0x00024> Prometheus.Data:.ctor () 
+in <0x00025> Prometheus.Test:Main (string[]) 
+ 
+Expected Results: 
+No error 
+ 
+How often does this happen?  
+Always 
+ 
+Additional Information: 
+By looking at the generated file, the problem is here (for Relation1): 
+fkc = new System.Data.ForeignKeyConstraint("Relation1", new 
+System.Data.DataColumn[] { 
+  this.__tablePlaylistsItems.Columns["playlist"], 
+  this.__tablePlaylistsItems.Columns["name"]}, new 
+System.Data.DataColumn[0]); 
+ 
+and should be  
+fkc = new System.Data.ForeignKeyConstraint("Relation1", new 
+System.Data.DataColumn[] { 
+  this.__tablePlaylistsItems.Columns["name"], new System.Data.DataColumn[] 
+{ 
+  this.__tablePlaylistsItems.Columns["playlist"]}); 
+ 
+Looking in mono's source code, I found the error. Here is the patch: 
+--- class/System.Data/System.Data/CustomDataClassGenerator.old.cs       
+2004-11-09 15:39:48.000000000 +0100 
++++ class/System.Data/System.Data/CustomDataClassGenerator.cs   2004-11-09 
+15:41:00.000000000 +0100 
+@@ -759,12 +759,12 @@ namespace System.Data 
+                private void CreateForeignKeyStatements (CodeMemberMethod 
+m,ForeignKeyConstraint fkc, string tableField) 
+                { 
+                        ArrayList pcols = new ArrayList (); 
+-                       foreach (DataColumn col in fkc.Columns) 
++                       foreach (DataColumn col in fkc.RelatedColumns) 
+                                pcols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
+ 
+                        ArrayList ccols = new ArrayList (); 
+-                       foreach (DataColumn col in fkc.RelatedColumns) 
+-                               pcols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
++                       foreach (DataColumn col in fkc.Columns) 
++                               ccols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
+ 
+                        m.Statements.Add (Let (Local ("fkc"), New ( 
+                                typeof (ForeignKeyConstraint), 
+--- class/System.Data/System.Data/CustomDataClassGenerator.old.cs       
+2004-11-09 15:39:48.000000000 +0100 
++++ class/System.Data/System.Data/CustomDataClassGenerator.cs   2004-11-09 
+15:41:00.000000000 +0100 
+@@ -759,12 +759,12 @@ namespace System.Data 
+                private void CreateForeignKeyStatements (CodeMemberMethod 
+m,ForeignKeyConstraint fkc, string tableField) 
+                { 
+                        ArrayList pcols = new ArrayList (); 
+-                       foreach (DataColumn col in fkc.Columns) 
++                       foreach (DataColumn col in fkc.RelatedColumns) 
+                                pcols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
+ 
+                        ArrayList ccols = new ArrayList (); 
+-                       foreach (DataColumn col in fkc.RelatedColumns) 
+-                               pcols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
++                       foreach (DataColumn col in fkc.Columns) 
++                               ccols.Add (IndexerRef (PropRef (FieldRef 
+(tableField), "Columns"), Const (col.ColumnName))); 
+ 
+                        m.Statements.Add (Let (Local ("fkc"), New ( 
+                                typeof (ForeignKeyConstraint), 
+ 
+Yes, the only problem is not only that all the columns were added to the 
+same ArrayList, but also that the parent columns are the related ones.