X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Data%2FSystem.Data%2FXmlDataInferenceLoader.cs;h=03e2737d127a7ebf398f46a9ce9a9472cb2eddee;hb=d105620caa9c38b33b38b85a4d2d4ec5f0b6c31e;hp=dd1c62b221084b681b61aacdc316684f79bc9064;hpb=64c394f419b4971075030ecf5d455d08b229ce6e;p=mono.git diff --git a/mcs/class/System.Data/System.Data/XmlDataInferenceLoader.cs b/mcs/class/System.Data/System.Data/XmlDataInferenceLoader.cs index dd1c62b2210..03e2737d127 100644 --- a/mcs/class/System.Data/System.Data/XmlDataInferenceLoader.cs +++ b/mcs/class/System.Data/System.Data/XmlDataInferenceLoader.cs @@ -9,32 +9,34 @@ // // Design notes are the bottom of the source. // - -// -// 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. -// + +// +// 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. +// + using System; using System.Collections; using System.Data; +using System.Globalization; using System.IO; // for Driver using System.Text; // for Driver using System.Xml; @@ -76,9 +78,7 @@ namespace System.Data public DataColumn SimpleContent; public DataColumn PrimaryKey; public DataColumn ReferenceKey; -#if NET_2_0 public int lastElementIndex = -1; -#endif // Parent TableMapping public TableMapping ParentTable; @@ -178,6 +178,8 @@ namespace System.Data if (document.DocumentElement == null) return; + dataset.Locale = new CultureInfo ("en-US"); // default(!) + // If the root element is not a data table, treat // this element as DataSet. // Read one element. It might be DataSet element. @@ -201,9 +203,22 @@ namespace System.Data } } + int count = 0; foreach (TableMapping map in tables) { + string baseName = map.PrimaryKey != null ? map.PrimaryKey.ColumnName : map.Table.TableName + "_Id"; + + // Make sure name of RK column is unique + string rkName = baseName; + if (map.ChildTables [map.Table.TableName] != null) { + rkName = baseName + '_' + count; + while (map.GetColumn (rkName) != null) { + count++; + rkName = baseName + '_' + count; + } + } + foreach (TableMapping ct in map.ChildTables) { - ct.ReferenceKey = GetMappedColumn (ct, map.Table.TableName + "_Id", map.Table.Prefix, map.Table.Namespace, MappingType.Hidden); + ct.ReferenceKey = GetMappedColumn (ct, rkName, map.Table.Prefix, map.Table.Namespace, MappingType.Hidden, map.PrimaryKey != null ? map.PrimaryKey.DataType : typeof (int)); } } @@ -212,13 +227,17 @@ namespace System.Data continue; if (map.PrimaryKey != null) map.Table.Columns.Add (map.PrimaryKey); - foreach (DataColumn col in map.Elements) + + foreach (DataColumn col in map.Elements) map.Table.Columns.Add (col); + foreach (DataColumn col in map.Attributes) map.Table.Columns.Add (col); - if (map.SimpleContent != null) + + if (map.SimpleContent != null) map.Table.Columns.Add (map.SimpleContent); - if (map.ReferenceKey != null) + + if (map.ReferenceKey != null) map.Table.Columns.Add (map.ReferenceKey); dataset.Tables.Add (map.Table); } @@ -228,7 +247,16 @@ namespace System.Data DataTable pt = dataset.Tables [rs.ParentTableName]; DataTable ct = dataset.Tables [rs.ChildTableName]; DataColumn pc = pt.Columns [rs.ParentColumnName]; - DataColumn cc = ct.Columns [rs.ChildColumnName]; + DataColumn cc = null; + + // If both parent and child tables have same name, it is quite + // possible to have column names suffixed with some numbers. + if (rs.ParentTableName == rs.ChildTableName) { + cc = ct.Columns [rs.ChildColumnName + "_" + count]; + } + if (cc == null) + cc = ct.Columns [rs.ChildColumnName]; + if (pt == null) throw new DataException ("Parent table was not found : " + rs.ParentTableName); else if (ct == null) @@ -253,14 +281,12 @@ namespace System.Data private void InferColumnElement (TableMapping table, XmlElement el) { - string localName = XmlHelper.Decode (el.LocalName); + string localName = XmlHelper.Decode (el.LocalName); DataColumn col = table.GetColumn (localName); if (col != null) { if (col.ColumnMapping != MappingType.Element) throw new DataException (String.Format ("Column {0} is already mapped to {1}.", localName, col.ColumnMapping)); -#if NET_2_0 table.lastElementIndex = table.Elements.IndexOf (col); -#endif return; } if (table.ChildTables [localName] != null) @@ -272,11 +298,7 @@ namespace System.Data col = new DataColumn (localName, typeof (string)); col.Namespace = el.NamespaceURI; col.Prefix = el.Prefix; -#if NET_2_0 table.Elements.Insert (++table.lastElementIndex, col); -#else - table.Elements.Add (col); -#endif } private void CheckExtraneousElementColumn (TableMapping parentTable, XmlElement el) @@ -291,11 +313,6 @@ namespace System.Data private void PopulatePrimaryKey (TableMapping table) { - if (table.PrimaryKey != null) { - if (table.PrimaryKey.ColumnName != table.Table.TableName + "_Id") - throw new DataException ("There is already a primary key column."); - return; - } DataColumn col = new DataColumn (table.Table.TableName + "_Id"); col.ColumnMapping = MappingType.Hidden; col.DataType = typeof (int); @@ -306,16 +323,15 @@ namespace System.Data table.PrimaryKey = col; } - private void PopulateRelationStructure (string parent, string child) + private void PopulateRelationStructure (string parent, string child, string pkeyColumn) { if (relations [parent, child] != null) return; - RelationStructure rs = new RelationStructure (); rs.ParentTableName = parent; rs.ChildTableName = child; - rs.ParentColumnName = parent + "_Id"; - rs.ChildColumnName = parent + "_Id"; + rs.ParentColumnName = pkeyColumn; + rs.ChildColumnName = pkeyColumn; rs.CreateConstraint = true; rs.IsNested = true; relations.Add (rs); @@ -337,7 +353,7 @@ namespace System.Data if (table.SimpleContent != null) return; - GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent); + GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent, null); } private void InferTableElement (TableMapping parentTable, XmlElement el) @@ -353,14 +369,12 @@ namespace System.Data bool hasChildElements = false; bool hasAttributes = false; - bool hasText = false; + bool hasText = false; bool isElementRepeated = false; foreach (XmlAttribute attr in el.Attributes) { if (attr.NamespaceURI == XmlConstants.XmlnsNS -#if NET_2_0 || attr.NamespaceURI == XmlConstants.XmlNS -#endif ) continue; if (ignoredNamespaces != null && @@ -368,11 +382,12 @@ namespace System.Data continue; hasAttributes = true; - DataColumn col = GetMappedColumn (table, + GetMappedColumn (table, XmlHelper.Decode (attr.LocalName), attr.Prefix, - attr.NamespaceURI, - MappingType.Attribute); + attr.NamespaceURI, + MappingType.Attribute, + null); } foreach (XmlNode n in el.ChildNodes) { @@ -381,9 +396,9 @@ namespace System.Data case XmlNodeType.ProcessingInstruction: // ignore continue; default: // text content - hasText = true; - if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated) - isElementRepeated = true; + hasText = true; + if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated) + isElementRepeated = true; break; case XmlNodeType.Element: // child hasChildElements = true; @@ -395,13 +410,15 @@ namespace System.Data InferColumnElement (table, cel); break; case ElementMappingType.Repeated: - PopulatePrimaryKey (table); - PopulateRelationStructure (table.Table.TableName, childLocalName); + if (table.PrimaryKey == null) + PopulatePrimaryKey (table); + PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName); InferRepeatedElement (table, cel); break; case ElementMappingType.Complex: - PopulatePrimaryKey (table); - PopulateRelationStructure (table.Table.TableName, childLocalName); + if (table.PrimaryKey == null) + PopulatePrimaryKey (table); + PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName); InferTableElement (table, cel); break; } @@ -412,7 +429,7 @@ namespace System.Data // Attributes + !Children + Text = SimpleContent if (table.SimpleContent == null // no need to create && !hasChildElements && hasText && (hasAttributes || isElementRepeated)) { - GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent); + GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent, null); } } @@ -441,7 +458,7 @@ namespace System.Data return map; } - private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type) + private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type, Type optColType) { DataColumn col = table.GetColumn (name); // Infer schema @@ -462,7 +479,7 @@ namespace System.Data break; case MappingType.Hidden: // To generate parent key - col.DataType = typeof (int); + col.DataType = optColType; table.ReferenceKey = col; break; } @@ -500,9 +517,7 @@ namespace System.Data foreach (XmlAttribute attr in el.Attributes) { if (attr.NamespaceURI == XmlConstants.XmlnsNS -#if NET_2_0 || attr.NamespaceURI == XmlConstants.XmlNS -#endif ) continue; if (ignoredNamespaces != null && ignoredNamespaces.Contains (attr.NamespaceURI)) @@ -543,9 +558,7 @@ namespace System.Data { foreach (XmlAttribute attr in top.Attributes) { if (attr.NamespaceURI == XmlConstants.XmlnsNS -#if NET_2_0 || attr.NamespaceURI == XmlConstants.XmlNS -#endif ) continue; if (ignoredNamespaces != null && @@ -570,13 +583,12 @@ namespace System.Data // Returns if it "might" be a column element (this method is // called per child element, thus it might still consist of // table, since it might be repeated). + /* private bool IsPossibleColumnElement (XmlElement el) { foreach (XmlAttribute attr in el.Attributes) { if (attr.NamespaceURI == XmlConstants.XmlnsNS -#if NET_2_0 || attr.NamespaceURI == XmlConstants.XmlNS -#endif ) continue; return false; @@ -586,6 +598,7 @@ namespace System.Data return false; return true; } + */ } }