2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System.Data.Linq / src / DbLinq / Vendor / Implementation / SchemaLoader.Name.cs
1 #region MIT license\r
2 // \r
3 // MIT license\r
4 //\r
5 // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne\r
6 // \r
7 // Permission is hereby granted, free of charge, to any person obtaining a copy\r
8 // of this software and associated documentation files (the "Software"), to deal\r
9 // in the Software without restriction, including without limitation the rights\r
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
11 // copies of the Software, and to permit persons to whom the Software is\r
12 // furnished to do so, subject to the following conditions:\r
13 // \r
14 // The above copyright notice and this permission notice shall be included in\r
15 // all copies or substantial portions of the Software.\r
16 // \r
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
23 // THE SOFTWARE.\r
24 // \r
25 #endregion\r
26 \r
27 using System;\r
28 using System.Collections.Generic;\r
29 using System.Linq;\r
30 using DbLinq.Schema;\r
31 using DbLinq.Schema.Dbml;\r
32 \r
33 namespace DbLinq.Vendor.Implementation\r
34 {\r
35     partial class SchemaLoader\r
36     {\r
37         /// <summary>\r
38         /// Checks all names in DBML schema, \r
39         /// and enquotes the ones where a casing problem could occur\r
40         /// </summary>\r
41         /// <param name="schema"></param>\r
42         public virtual void CheckNamesSafety(Database schema)\r
43         {\r
44             schema.Name = Vendor.SqlProvider.GetSafeName(schema.Name);\r
45             foreach (var table in schema.Table)\r
46             {\r
47                 table.Name = Vendor.SqlProvider.GetSafeName(table.Name);\r
48                 foreach (var column in table.Type.Columns)\r
49                 {\r
50                     column.Name = Vendor.SqlProvider.GetSafeName(column.Name);\r
51                 }\r
52                 foreach (var association in table.Type.Associations)\r
53                 {\r
54                     association.Name = Vendor.SqlProvider.GetSafeName(association.Name);\r
55                 }\r
56             }\r
57             foreach (var storedProcedure in schema.Functions)\r
58             {\r
59                 storedProcedure.Name = Vendor.SqlProvider.GetSafeName(storedProcedure.Name);\r
60             }\r
61         }\r
62 \r
63         /// <summary>\r
64         /// Gets the primary keys.\r
65         /// </summary>\r
66         /// <param name="table">The table.</param>\r
67         /// <returns></returns>\r
68         protected static List<string> GetPrimaryKeys(Table table)\r
69         {\r
70             return (from c in table.Type.Columns where c.IsPrimaryKey select c.Name).ToList();\r
71         }\r
72 \r
73         /// <summary>\r
74         /// Checks for problematic names on columns\r
75         /// We currently have 1 case, where column is equal to table name\r
76         /// </summary>\r
77         /// <param name="schema"></param>\r
78         protected virtual void CheckColumnsName(Database schema)\r
79         {\r
80             foreach (var table in schema.Tables)\r
81             {\r
82                 foreach (var column in table.Type.Columns)\r
83                 {\r
84                     // THE case\r
85                     if (column.Member == table.Type.Name)\r
86                     {\r
87                         // now, we try to append 1, then 2, etc.\r
88                         var appendValue = 0;\r
89                         for (; ; )\r
90                         {\r
91                             var newColumnMember = column.Member + ++appendValue;\r
92                             if (!table.Type.Columns.Any(c => c.Member == newColumnMember))\r
93                             {\r
94                                 column.Member = newColumnMember;\r
95                             }\r
96                         }\r
97                     }\r
98                 }\r
99             }\r
100         }\r
101 \r
102         /// <summary>\r
103         /// Checks for name conflicts, given lambdas to correct on conflicts\r
104         /// </summary>\r
105         /// <param name="schema"></param>\r
106         /// <param name="tableNamedAssociationRenamer"></param>\r
107         /// <param name="columnNamedAssociationRenamer"></param>\r
108         protected virtual void CheckConstraintsName(Database schema,\r
109                                       Func<Association, string> tableNamedAssociationRenamer,\r
110                                       Func<Association, string> columnNamedAssociationRenamer)\r
111         {\r
112             foreach (var table in schema.Tables)\r
113             {\r
114                 foreach (var association in table.Type.Associations)\r
115                 {\r
116                     var localAssociation = association;\r
117                     if (association.Member == table.Type.Name)\r
118                         association.Member = tableNamedAssociationRenamer(association);\r
119                     else if ((from column in table.Type.Columns where column.Member == localAssociation.Member select column).FirstOrDefault() != null)\r
120                     {\r
121                         association.Member = columnNamedAssociationRenamer(association);\r
122                     }\r
123                 }\r
124             }\r
125         }\r
126 \r
127         /// <summary>\r
128         /// Checks for name conflicts\r
129         /// </summary>\r
130         /// <param name="schema"></param>\r
131         protected virtual void CheckConstraintsName(Database schema)\r
132         {\r
133             CheckConstraintsName(schema,\r
134                        association => association.ThisKey.Replace(',', '_') + association.Member,\r
135                        association => association.Member + association.Type);\r
136         }\r
137 \r
138         /// <summary>\r
139         /// Generates storage fields, given a formatting method\r
140         /// </summary>\r
141         /// <param name="schema"></param>\r
142         /// <param name="storageGenerator"></param>\r
143         protected virtual void GenerateStorageAndMemberFields(Database schema, Func<string, string> storageGenerator)\r
144         {\r
145             foreach (var table in schema.Tables)\r
146             {\r
147                 foreach (var column in table.Type.Columns)\r
148                 {\r
149                     column.Storage = storageGenerator(column.Member);\r
150                 }\r
151 \r
152                 Dictionary<string, int> storageFields = new Dictionary<string,int>();\r
153                 Dictionary<string, int> memberFields = new Dictionary<string,int>();\r
154                 foreach (var association in table.Type.Associations)\r
155                 {\r
156                     association.Storage = storageGenerator(association.Member);\r
157 \r
158                     //Associations may contain the same foreign key more than once - add a number suffix to duplicates\r
159                     int storageSuffix = 0;\r
160                     if ( storageFields.TryGetValue(association.Storage, out storageSuffix) )\r
161                         association.Storage += storageSuffix;\r
162                     storageFields[association.Storage] = storageSuffix + 1;\r
163 \r
164                     int memberSuffix = 0;\r
165                     if ( memberFields.TryGetValue(association.Member, out memberSuffix) )\r
166                         association.Member += memberSuffix;\r
167                     memberFields[association.Member] = memberSuffix + 1;\r
168                 }\r
169             }\r
170         }\r
171 \r
172         /// <summary>\r
173         /// Generates all storage fields\r
174         /// </summary>\r
175         /// <param name="schema"></param>\r
176         protected virtual void GenerateStorageAndMemberFields(Database schema)\r
177         {\r
178             GenerateStorageAndMemberFields(schema, delegate(string name)\r
179                                               {\r
180                                                   //jgm 2008June: pre-pended underscore to have same storage format as MS\r
181                                                   // TODO: add an option for this behavior\r
182                                                   var storage = "_" + NameFormatter.Format(name, Case.camelCase);\r
183                                                   if (storage == name)\r
184                                                       storage = "_" + storage;\r
185                                                   return storage;\r
186                                               });\r
187         }\r
188     }\r
189 }\r