[genmdesc] Fixed generator to allow instructions lengths equal to 0.
[mono.git] / mcs / class / System.Data / System.Data / XmlDataInferenceLoader.cs
index dd1c62b221084b681b61aacdc316684f79bc9064..03e2737d127a7ebf398f46a9ce9a9472cb2eddee 100644 (file)
@@ -9,32 +9,34 @@
 //\r
 // Design notes are the bottom of the source.\r
 //\r
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
 using System;\r
 using System.Collections;\r
 using System.Data;\r
+using System.Globalization;\r
 using System.IO; // for Driver\r
 using System.Text; // for Driver\r
 using System.Xml;\r
@@ -76,9 +78,7 @@ namespace System.Data
                public DataColumn SimpleContent;\r
                public DataColumn PrimaryKey;\r
                public DataColumn ReferenceKey;\r
-#if NET_2_0\r
                public int lastElementIndex = -1;\r
-#endif\r
 \r
                // Parent TableMapping\r
                public TableMapping ParentTable;\r
@@ -178,6 +178,8 @@ namespace System.Data
                        if (document.DocumentElement == null)\r
                                return;\r
 \r
+                       dataset.Locale = new CultureInfo ("en-US"); // default(!)\r
+\r
                        // If the root element is not a data table, treat \r
                        // this element as DataSet.\r
                        // Read one element. It might be DataSet element.\r
@@ -201,9 +203,22 @@ namespace System.Data
                                }\r
                        }\r
 \r
+                       int count = 0;                  \r
                        foreach (TableMapping map in tables) {\r
+                               string baseName = map.PrimaryKey != null ? map.PrimaryKey.ColumnName : map.Table.TableName + "_Id";\r
+                               \r
+                               // Make sure name of RK column is unique\r
+                               string rkName = baseName;\r
+                               if (map.ChildTables [map.Table.TableName] != null) {\r
+                                       rkName = baseName + '_' + count;\r
+                                       while (map.GetColumn (rkName) != null) {\r
+                                               count++;\r
+                                               rkName = baseName + '_' + count;\r
+                                       }\r
+                               }\r
+                               \r
                                foreach (TableMapping ct in map.ChildTables) {\r
-                                       ct.ReferenceKey = GetMappedColumn (ct, map.Table.TableName + "_Id", map.Table.Prefix, map.Table.Namespace, MappingType.Hidden);\r
+                                       ct.ReferenceKey = GetMappedColumn (ct, rkName, map.Table.Prefix, map.Table.Namespace, MappingType.Hidden, map.PrimaryKey != null ? map.PrimaryKey.DataType : typeof (int));\r
                                }\r
                        }\r
 \r
@@ -212,13 +227,17 @@ namespace System.Data
                                        continue;\r
                                if (map.PrimaryKey != null)\r
                                        map.Table.Columns.Add (map.PrimaryKey);\r
-                               foreach (DataColumn col in map.Elements)\r
+\r
+                               foreach (DataColumn col in map.Elements) \r
                                        map.Table.Columns.Add (col);\r
+\r
                                foreach (DataColumn col in map.Attributes)\r
                                        map.Table.Columns.Add (col);\r
-                               if (map.SimpleContent != null)\r
+                               \r
+                               if (map.SimpleContent != null) \r
                                        map.Table.Columns.Add (map.SimpleContent);\r
-                               if (map.ReferenceKey != null)\r
+                               \r
+                               if (map.ReferenceKey != null) \r
                                        map.Table.Columns.Add (map.ReferenceKey);\r
                                dataset.Tables.Add (map.Table);\r
                        }\r
@@ -228,7 +247,16 @@ namespace System.Data
                                DataTable pt = dataset.Tables [rs.ParentTableName];\r
                                DataTable ct = dataset.Tables [rs.ChildTableName];\r
                                DataColumn pc = pt.Columns [rs.ParentColumnName];\r
-                               DataColumn cc = ct.Columns [rs.ChildColumnName];\r
+                               DataColumn cc = null;\r
+                               \r
+                               // If both parent and child tables have same name, it is quite\r
+                               // possible to have column names suffixed with some numbers.\r
+                               if (rs.ParentTableName == rs.ChildTableName) {\r
+                                       cc = ct.Columns [rs.ChildColumnName + "_" + count];\r
+                               }\r
+                               if (cc == null)\r
+                                       cc = ct.Columns [rs.ChildColumnName];\r
+                               \r
                                if (pt == null)\r
                                        throw new DataException ("Parent table was not found : " + rs.ParentTableName);\r
                                else if (ct == null)\r
@@ -253,14 +281,12 @@ namespace System.Data
 \r
                private void InferColumnElement (TableMapping table, XmlElement el)\r
                {\r
-                       string localName = XmlHelper.Decode (el.LocalName);
+                       string localName = XmlHelper.Decode (el.LocalName);\r
                        DataColumn col = table.GetColumn (localName);\r
                        if (col != null) {\r
                                if (col.ColumnMapping != MappingType.Element)\r
                                        throw new DataException (String.Format ("Column {0} is already mapped to {1}.", localName, col.ColumnMapping));\r
-#if NET_2_0\r
                                table.lastElementIndex = table.Elements.IndexOf (col);\r
-#endif\r
                                return;\r
                        }\r
                        if (table.ChildTables [localName] != null)\r
@@ -272,11 +298,7 @@ namespace System.Data
                        col = new DataColumn (localName, typeof (string));\r
                        col.Namespace = el.NamespaceURI;\r
                        col.Prefix = el.Prefix;\r
-#if NET_2_0\r
                        table.Elements.Insert (++table.lastElementIndex, col);\r
-#else\r
-                       table.Elements.Add (col);\r
-#endif\r
                }\r
 \r
                private void CheckExtraneousElementColumn (TableMapping parentTable, XmlElement el)\r
@@ -291,11 +313,6 @@ namespace System.Data
 \r
                private void PopulatePrimaryKey (TableMapping table)\r
                {\r
-                       if (table.PrimaryKey != null) {\r
-                               if (table.PrimaryKey.ColumnName != table.Table.TableName + "_Id")\r
-                                       throw new DataException ("There is already a primary key column.");\r
-                               return;\r
-                       }\r
                        DataColumn col = new DataColumn (table.Table.TableName + "_Id");\r
                        col.ColumnMapping = MappingType.Hidden;\r
                        col.DataType = typeof (int);\r
@@ -306,16 +323,15 @@ namespace System.Data
                        table.PrimaryKey = col;\r
                }\r
 \r
-               private void PopulateRelationStructure (string parent, string child)\r
+               private void PopulateRelationStructure (string parent, string child, string pkeyColumn)\r
                {\r
                        if (relations [parent, child] != null)\r
                                return;\r
-\r
                        RelationStructure rs = new RelationStructure ();\r
                        rs.ParentTableName = parent;\r
                        rs.ChildTableName = child;\r
-                       rs.ParentColumnName = parent + "_Id";\r
-                       rs.ChildColumnName = parent + "_Id";\r
+                       rs.ParentColumnName = pkeyColumn;\r
+                       rs.ChildColumnName = pkeyColumn;\r
                        rs.CreateConstraint = true;\r
                        rs.IsNested = true;\r
                        relations.Add (rs);\r
@@ -337,7 +353,7 @@ namespace System.Data
                        if (table.SimpleContent != null)\r
                                return;\r
 \r
-                       GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent);\r
+                       GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent, null);\r
                }\r
 \r
                private void InferTableElement (TableMapping parentTable, XmlElement el)\r
@@ -353,14 +369,12 @@ namespace System.Data
 \r
                        bool hasChildElements = false;\r
                        bool hasAttributes = false;\r
-                       bool hasText = false;
+                       bool hasText = false;\r
                        bool isElementRepeated = false;\r
 \r
                        foreach (XmlAttribute attr in el.Attributes) {\r
                                if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
                                        || attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
                                        )\r
                                        continue;\r
                                if (ignoredNamespaces != null &&\r
@@ -368,11 +382,12 @@ namespace System.Data
                                        continue;\r
 \r
                                hasAttributes = true;\r
-                               DataColumn col = GetMappedColumn (table,\r
+                               GetMappedColumn (table,\r
                                        XmlHelper.Decode (attr.LocalName),\r
                                        attr.Prefix,\r
-                                       attr.NamespaceURI,\r
-                                       MappingType.Attribute);\r
+                                       attr.NamespaceURI,\r
+                                       MappingType.Attribute,\r
+                                       null); \r
                        }\r
 \r
                        foreach (XmlNode n in el.ChildNodes) {\r
@@ -381,9 +396,9 @@ namespace System.Data
                                case XmlNodeType.ProcessingInstruction: // ignore\r
                                        continue;\r
                                default: // text content\r
-                                       hasText = true;
-                                       if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated)
-                                               isElementRepeated = true;
+                                       hasText = true;\r
+                                       if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated)\r
+                                               isElementRepeated = true;\r
                                        break;\r
                                case XmlNodeType.Element: // child\r
                                        hasChildElements = true;\r
@@ -395,13 +410,15 @@ namespace System.Data
                                                InferColumnElement (table, cel);\r
                                                break;\r
                                        case ElementMappingType.Repeated:\r
-                                               PopulatePrimaryKey (table);\r
-                                               PopulateRelationStructure (table.Table.TableName, childLocalName);\r
+                                               if (table.PrimaryKey == null)\r
+                                                       PopulatePrimaryKey (table);\r
+                                               PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName);\r
                                                InferRepeatedElement (table, cel);\r
                                                break;\r
                                        case ElementMappingType.Complex:\r
-                                               PopulatePrimaryKey (table);\r
-                                               PopulateRelationStructure (table.Table.TableName, childLocalName);\r
+                                               if (table.PrimaryKey == null)\r
+                                                       PopulatePrimaryKey (table);\r
+                                               PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName);\r
                                                InferTableElement (table, cel);\r
                                                break;\r
                                        }\r
@@ -412,7 +429,7 @@ namespace System.Data
                        // Attributes + !Children + Text = SimpleContent\r
                        if (table.SimpleContent == null // no need to create\r
                                && !hasChildElements && hasText && (hasAttributes || isElementRepeated)) {\r
-                               GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent);\r
+                               GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent, null);\r
                        }\r
                }\r
 \r
@@ -441,7 +458,7 @@ namespace System.Data
                        return map;\r
                }\r
 \r
-               private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type)\r
+               private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type, Type optColType)\r
                {\r
                        DataColumn col = table.GetColumn (name);\r
                        // Infer schema\r
@@ -462,7 +479,7 @@ namespace System.Data
                                        break;\r
                                case MappingType.Hidden:\r
                                        // To generate parent key\r
-                                       col.DataType = typeof (int);\r
+                                       col.DataType = optColType;\r
                                        table.ReferenceKey = col;\r
                                        break;\r
                                }\r
@@ -500,9 +517,7 @@ namespace System.Data
 \r
                        foreach (XmlAttribute attr in el.Attributes) {\r
                                if (attr.NamespaceURI == XmlConstants.XmlnsNS \r
-#if NET_2_0\r
                                        || attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
                                        )\r
                                        continue;\r
                                if (ignoredNamespaces != null && ignoredNamespaces.Contains (attr.NamespaceURI))\r
@@ -543,9 +558,7 @@ namespace System.Data
                {\r
                        foreach (XmlAttribute attr in top.Attributes) {\r
                                if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
                                        || attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
                                        )\r
                                        continue;\r
                                if (ignoredNamespaces != null &&\r
@@ -570,13 +583,12 @@ namespace System.Data
                // Returns if it "might" be a column element (this method is\r
                // called per child element, thus it might still consist of\r
                // table, since it might be repeated).\r
+               /*\r
                private bool IsPossibleColumnElement (XmlElement el)\r
                {\r
                        foreach (XmlAttribute attr in el.Attributes) {\r
                                if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
                                        || attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
                                        )\r
                                        continue;\r
                                return false;\r
@@ -586,6 +598,7 @@ namespace System.Data
                                        return false;\r
                        return true;\r
                }\r
+               */\r
        }\r
 }\r
 \r