Datei: NDODLL/SchemaTransitionGenerator.cs
Last Commit (2a2e7ba)
1 | // |
2 | // Copyright (c) 2002-2016 Mirko Matytschak |
3 | // (www.netdataobjects.de) |
4 | // |
5 | // Author: Mirko Matytschak |
6 | // |
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
8 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation |
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the |
10 | // Software, and to permit persons to whom the Software is furnished to do so, subject to the following |
11 | // conditions: |
12 | |
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions |
14 | // of the Software. |
15 | // |
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | // DEALINGS IN THE SOFTWARE. |
21 | |
22 | |
23 | using System; |
24 | using System.Text; |
25 | using System.IO; |
26 | using System.Collections.Generic; |
27 | using System.Data; |
28 | using System.Linq; |
29 | using System.Xml.Linq; |
30 | using NDO.Mapping; |
31 | using NDO; |
32 | using NDOInterfaces; |
33 | using System.Globalization; |
34 | |
35 | namespace NDO |
36 | { |
37 | ····/// <summary> |
38 | ····/// Zusammenfassung für GenericDiffGenerator. |
39 | ····/// </summary> |
40 | ····internal class SchemaTransitionGenerator |
41 | ····{ |
42 | ········IProvider provider; |
43 | ········ISqlGenerator concreteGenerator; |
44 | ········//MessageAdapter messages; |
45 | ········NDO.Mapping.NDOMapping mappings; |
46 | ········public SchemaTransitionGenerator(ISqlGenerator concreteGenerator, NDO.Mapping.NDOMapping mappings) |
47 | ········{ |
48 | ············provider = NDOProviderFactory.Instance[concreteGenerator.ProviderName]; |
49 | ············this.concreteGenerator = concreteGenerator; |
50 | ············this.mappings = mappings; |
51 | ········} |
52 | |
53 | ········public string Generate(XElement transElement) |
54 | ········{ |
55 | ············StringBuilder sb = new StringBuilder(); |
56 | ············foreach(XElement actionElement in transElement.Elements()) |
57 | ············{ |
58 | ················if (actionElement.Name == "DropTable") |
59 | ················{ |
60 | ····················sb.Append( DropTable( actionElement ) ); |
61 | ················} |
62 | ················else if (actionElement.Name=="CreateTable") |
63 | ················{ |
64 | ····················sb.Append( CreateTable( actionElement ) ); |
65 | ················} |
66 | ················else if (actionElement.Name=="AlterTable") |
67 | ················{ |
68 | ····················sb.Append( ChangeTable( actionElement ) ); |
69 | ················} |
70 | |
71 | ············} |
72 | ············return sb.ToString(); |
73 | ········} |
74 | |
75 | ········string ChangeTable(XElement actionElement) |
76 | ········{ |
77 | ············List<XElement> addedColumns = actionElement.Elements("AddColumn").ToList(); |
78 | ············List<XElement> removedColumns = actionElement.Elements("DropColumn").ToList(); |
79 | ············List<XElement> changedColumns = actionElement.Elements("AlterColumn").ToList(); |
80 | |
81 | ············if (addedColumns.Count == 0 && removedColumns.Count == 0 && changedColumns.Count == 0) |
82 | ················return String.Empty; |
83 | |
84 | ············StringBuilder sb = new StringBuilder(); |
85 | |
86 | ············string rawTableName = actionElement.Attribute( "name" ).Value; |
87 | ············string tableName = this.provider.GetQualifiedTableName(rawTableName); |
88 | ············string alterString = "ALTER TABLE " + tableName + ' '; |
89 | |
90 | ············foreach(XElement columnElement in addedColumns) |
91 | ············{ |
92 | ················sb.Append(alterString); |
93 | ················sb.Append(concreteGenerator.AddColumn()); |
94 | ················sb.Append(' '); |
95 | ················sb.Append(CreateColumn(columnElement, GetClassForTable(rawTableName, this.mappings), this.provider, false)); |
96 | ················sb.Append(";\n"); |
97 | ············} |
98 | |
99 | ············foreach(XElement columnElement in removedColumns) |
100 | ············{ |
101 | ················sb.Append(alterString); |
102 | ················sb.Append( concreteGenerator.RemoveColumn( provider.GetQuotedName( columnElement.Attribute( "name" ).Value ) ) ); |
103 | ················sb.Append(";\n"); |
104 | ············} |
105 | |
106 | ············foreach(XElement columnElement in changedColumns) |
107 | ············{ |
108 | ················sb.Append(alterString); |
109 | ················sb.Append(concreteGenerator.AlterColumnType()); |
110 | ················sb.Append(' '); |
111 | ················sb.Append(CreateColumn(columnElement, GetClassForTable(rawTableName, this.mappings), this.provider, false)); |
112 | ················sb.Append(";\n"); |
113 | ············} |
114 | |
115 | ············return sb.ToString(); |
116 | ········} |
117 | |
118 | ········string RenameColumn(string tableName, string oldColumn, string newColumn, string typeString) |
119 | ········{ |
120 | ············string s = concreteGenerator.RenameColumn(tableName, oldColumn, newColumn, typeString); |
121 | ············ |
122 | ············if (s != string.Empty) |
123 | ············return s; |
124 | ········ |
125 | ············string alterString = "ALTER TABLE " + tableName + ' '; |
126 | |
127 | ············StringBuilder sb = new StringBuilder(alterString); |
128 | ············sb.Append(concreteGenerator.AddColumn()); |
129 | ············sb.Append(' '); |
130 | ············sb.Append(newColumn); |
131 | ············sb.Append(' '); |
132 | ············sb.Append(typeString); |
133 | ············sb.Append(";\n"); |
134 | |
135 | ············sb.Append("UPDATE "); |
136 | ············sb.Append(tableName); |
137 | ············sb.Append(" SET ");············ |
138 | ············sb.Append(newColumn); |
139 | ············sb.Append(" = "); |
140 | ············sb.Append(oldColumn); |
141 | ············sb.Append(";\n"); |
142 | |
143 | ············sb.Append(alterString); |
144 | ············sb.Append(concreteGenerator.RemoveColumn(oldColumn)); |
145 | ············sb.Append(';'); |
146 | ············return sb.ToString(); |
147 | ········} |
148 | |
149 | ········protected string DropTable(XElement actionElement) |
150 | ········{ |
151 | ············string tableName = this.provider .GetQualifiedTableName( actionElement.Attribute( "name" ).Value ); |
152 | ············return concreteGenerator.DropTable( tableName ); |
153 | ········} |
154 | |
155 | ········protected string CreateTable(XElement actionElement) |
156 | ········{ |
157 | ············StringBuilder sb = new StringBuilder(); |
158 | ············IProvider provider = NDOProviderFactory.Instance[concreteGenerator.ProviderName]; |
159 | ············if (provider == null) |
160 | ················throw new Exception("Can't find NDO provider '" + concreteGenerator.ProviderName + "'."); |
161 | |
162 | ············string dtTableName = actionElement.Attribute( "name" ).Value; |
163 | |
164 | ············string tableName = this.provider.GetQualifiedTableName( dtTableName ); |
165 | |
166 | ············Class cl = FindClass(dtTableName, mappings); |
167 | |
168 | ············if (cl != null) |
169 | ············{ |
170 | ················Connection conn = mappings.FindConnection(cl); |
171 | ················if (conn != null) |
172 | ····················concreteGenerator.ConnectToDatabase(conn.Name); |
173 | ············} |
174 | |
175 | ············sb.Append(concreteGenerator.BeginnTable(tableName)); |
176 | ············sb.Append('\n'); |
177 | |
178 | ············List<XElement> columnElements = actionElement.Elements( "CreateColumn" ).ToList(); |
179 | |
180 | ············int vorletzterIndex = columnElements.Count - 1; |
181 | ············List<XElement> primaryKeyColumns = columnElements.Where( e => |
182 | ············{ |
183 | ················XAttribute attr; |
184 | ················return (attr = e.Attribute( "isPrimary" )) != null && String.Compare( attr.Value, "true", true ) == 0; |
185 | ············} ).ToList(); |
186 | |
187 | ············bool hasPrimaryKeyColumns = primaryKeyColumns.Count > 0; |
188 | |
189 | ············for (int i = 0; i < columnElements.Count; i++) |
190 | ············{ |
191 | ················XElement columnElement = columnElements[i]; |
192 | ················string columnName = columnElement.Attribute("name").Value; |
193 | |
194 | ················bool isPrimary = primaryKeyColumns.Any( e => e.Attribute( "name" ).Value == columnName ); |
195 | |
196 | ················sb.Append(CreateColumn(columnElement, cl, provider, isPrimary)); |
197 | ················if (i < vorletzterIndex) |
198 | ················{ |
199 | ····················sb.Append(","); |
200 | ····················sb.Append('\n'); |
201 | ················} |
202 | ············} |
203 | |
204 | ············if(concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InTable |
205 | ················&& hasPrimaryKeyColumns) |
206 | ············{ |
207 | ················sb.Append(","); |
208 | ················sb.Append('\n'); |
209 | ············} |
210 | |
211 | ············if (hasPrimaryKeyColumns && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InTable) |
212 | ············{ |
213 | ················sb.Append(CreatePrimaryKeyConstraint(primaryKeyColumns, dtTableName, provider)); |
214 | ············} |
215 | ············else |
216 | ············{ |
217 | ················sb.Append('\n'); |
218 | ············} |
219 | ············sb.Append(concreteGenerator.EndTable(tableName)); |
220 | ············sb.Append('\n'); |
221 | |
222 | ············//············CreateIndex(primaryKeyColumns, sb, dt, provider); |
223 | |
224 | ············if (hasPrimaryKeyColumns && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.AfterTable) |
225 | ············{ |
226 | ················sb.Append(CreatePrimaryKeyConstraint(primaryKeyColumns, dtTableName, provider)); |
227 | ············} |
228 | |
229 | ············sb.Append('\n'); |
230 | |
231 | ············return sb.ToString(); |
232 | ········} |
233 | |
234 | ········protected NDO.Mapping.Class FindClass(string tableName, NDOMapping mappings) |
235 | ········{ |
236 | ············Class result = null; |
237 | ············foreach(Class cl in mappings.Classes) |
238 | ············{ |
239 | ················if (cl.TableName == tableName) |
240 | ················{ |
241 | ····················result = cl; |
242 | ····················break; |
243 | ················} |
244 | ············} |
245 | ············return result; |
246 | ········} |
247 | |
248 | ········static bool IsNumeric( Type type ) |
249 | ········{ |
250 | ············switch (Type.GetTypeCode( type )) |
251 | ············{ |
252 | ················case TypeCode.Byte: |
253 | ················case TypeCode.SByte: |
254 | ················case TypeCode.UInt16: |
255 | ················case TypeCode.UInt32: |
256 | ················case TypeCode.UInt64: |
257 | ················case TypeCode.Int16: |
258 | ················case TypeCode.Int32: |
259 | ················case TypeCode.Int64: |
260 | ················case TypeCode.Decimal: |
261 | ················case TypeCode.Double: |
262 | ················case TypeCode.Single: |
263 | ····················return true; |
264 | ················case TypeCode.Object: |
265 | ····················if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof( Nullable<> )) |
266 | ····················{ |
267 | ························return IsNumeric(Nullable.GetUnderlyingType( type )); |
268 | ····················} |
269 | ····················return false; |
270 | ················default: |
271 | ····················return false; |
272 | ············} |
273 | ········} |
274 | |
275 | ········protected string CreateColumn(XElement columnElement, Class cl, IProvider provider, bool isPrimary) |
276 | ········{ |
277 | ············string rawName = columnElement.Attribute( "name" ).Value; |
278 | ············Type dcDataType = Type.GetType( columnElement.Attribute( "type" ).Value ); |
279 | ············string name = provider.GetQuotedName(rawName); |
280 | ············string columnType = columnElement.Attribute( "dbtype" )?.Value; |
281 | ············if (columnType == String.Empty)··// Make sure the column type will be infered, if it is an empty string |
282 | ················columnType = null; |
283 | ············string width = columnElement.Attribute("size") == null ? null : columnElement.Attribute("size").Value; |
284 | ············string precision = null; |
285 | ············bool autoIncrement = false; |
286 | ············StringBuilder sb = new StringBuilder(); |
287 | ············bool allowNull = true; |
288 | ············string defaultValue = columnElement.Attribute( "default" )?.Value; |
289 | |
290 | ············if (cl != null) |
291 | ············{ |
292 | ················Field field = FindField(rawName, cl); |
293 | |
294 | ················if (null != field) |
295 | ················{ |
296 | ····················if ( !String.IsNullOrEmpty(columnType) && null != field.Column.DbType) |
297 | ························columnType = field.Column.DbType; |
298 | ····················if (0 != field.Column.Size && !field.Column.IgnoreColumnSizeInDDL) |
299 | ····················{ |
300 | ························int dl = field.Column.Size; |
301 | ························if (dl == -1) |
302 | ····························width = "max"; |
303 | ························else |
304 | ····························width = dl.ToString(); |
305 | ····················} |
306 | ····················if (0 != field.Column.Precision && !field.Column.IgnoreColumnSizeInDDL) |
307 | ························precision = field.Column.Precision.ToString(); |
308 | ····················allowNull = field.Column.AllowDbNull; |
309 | ················} |
310 | ················else if (cl.TimeStampColumn == rawName) |
311 | ················{ |
312 | ····················if (!provider.SupportsNativeGuidType) |
313 | ························width = "36"; |
314 | ················} |
315 | ················else if (isPrimary && columnElement.Attribute( "autoIncrement" ) != null && String.Compare(columnElement.Attribute( "autoIncrement" ).Value, "true", true) == 0) |
316 | ················{ |
317 | ····················autoIncrement = true; |
318 | ················} |
319 | ············} |
320 | ············if (null == columnType) |
321 | ············{ |
322 | ················try |
323 | ················{ |
324 | ····················columnType = concreteGenerator.DbTypeFromType(dcDataType); |
325 | ················} |
326 | ················catch |
327 | ················{ |
328 | ····················System.Diagnostics.Debug.Write(""); |
329 | ················} |
330 | ············} |
331 | |
332 | ············if (null == width) |
333 | ············{ |
334 | ················int dl = provider.GetDefaultLength(dcDataType); |
335 | ················if (dl != 0) |
336 | ················{ |
337 | ····················if (dl == -1) |
338 | ························width = "max"; |
339 | ····················else |
340 | ························width = dl.ToString(); |
341 | ················} |
342 | ············} |
343 | ············ |
344 | ············// Because there is no GetDefaultPrecision in the provider... |
345 | ············// We assume the field to represent currency data |
346 | ············if (precision == null && dcDataType == typeof(decimal)) |
347 | ············{ |
348 | ················precision = "2"; |
349 | ············} |
350 | |
351 | ············if (columnType != null) |
352 | ············{ |
353 | ················if (!concreteGenerator.LengthAllowed(columnType)) |
354 | ····················width = null; |
355 | ············} |
356 | ············else |
357 | ············{ |
358 | ················if (!concreteGenerator.LengthAllowed(dcDataType)) |
359 | ····················width = null; |
360 | ············} |
361 | |
362 | |
363 | ············if (autoIncrement && concreteGenerator.HasSpecialAutoIncrementColumnFormat) |
364 | sb. Append( concreteGenerator. AutoIncrementColumn( name, dcDataType, columnType, width) ) ; |
365 | ············else if(isPrimary && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InColumn) |
366 | ················sb.Append(concreteGenerator.PrimaryKeyColumn(name, dcDataType, columnType, width)); |
367 | ············else if (width != null && precision != null) |
368 | ················sb.Append(name + " " + columnType + "(" + width + "," + precision + ")"); |
369 | ············else if (width != null) |
370 | ················sb.Append(name + " " + columnType + "(" + width + ")");············ |
371 | ············else |
372 | ················sb.Append(name + " " + columnType); |
373 | |
374 | ············sb.Append(" "); |
375 | |
376 | ············if (defaultValue != null) |
377 | ············{ |
378 | ················sb.Append( "DEFAULT " ); |
379 | ················if (IsNumeric( dcDataType )) |
380 | ····················sb.Append( defaultValue); |
381 | ················else |
382 | ················{ |
383 | ····················sb.Append( '\'' ); |
384 | ····················sb.Append( defaultValue.Replace( "'", "''" ) ); |
385 | ····················sb.Append( '\'' ); |
386 | ················} |
387 | ················sb.Append( ' ' ); |
388 | ············} |
389 | |
390 | ············sb.Append( concreteGenerator.NullExpression( allowNull && columnElement.Attribute( "allowNull" ) != null && String.Compare( columnElement.Attribute( "allowNull" ).Value, "true", true ) == 0 ) ); |
391 | ············return sb.ToString(); |
392 | ········} |
393 | |
394 | ········protected string CreatePrimaryKeyConstraint(List<XElement> primaryKeyColumns, string tableName, IProvider provider) |
395 | ········{ |
396 | ············if (primaryKeyColumns.Count == 0) |
397 | ················return string.Empty; |
398 | ············string[] strArr = tableName.Split('.'); |
399 | ············string constraintName = provider.GetQuotedName("PK_" + strArr[strArr.Length - 1]); |
400 | ············DataColumn[] pkColumns = (from pk in primaryKeyColumns select new DataColumn( pk.Attribute( "name" ).Value )).ToArray(); |
401 | ············return concreteGenerator.CreatePrimaryKeyConstraint(pkColumns, constraintName, provider.GetQualifiedTableName(tableName)) + '\n'; |
402 | ········} |
403 | |
404 | ········protected Field FindField (string columnName, Class cl) |
405 | ········{ |
406 | ············Field result = null; |
407 | ············foreach (Field field in cl.Fields) |
408 | ············{ |
409 | ················if (field.Column.Name == columnName) |
410 | ················{ |
411 | ····················result = field; |
412 | ····················break; |
413 | ················} |
414 | ············} |
415 | ············return result; |
416 | ········} |
417 | |
418 | ········protected Class GetClassForTable(string tableName, NDOMapping mapping) |
419 | ········{ |
420 | ············foreach(Class cl in mapping.Classes) |
421 | ················if (cl.TableName == tableName) |
422 | ····················return cl; |
423 | ············return null; |
424 | ········} |
425 | ····} |
426 | } |
427 |
New Commit (1e68dc7)
1 | // |
2 | // Copyright (c) 2002-2016 Mirko Matytschak |
3 | // (www.netdataobjects.de) |
4 | // |
5 | // Author: Mirko Matytschak |
6 | // |
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
8 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation |
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the |
10 | // Software, and to permit persons to whom the Software is furnished to do so, subject to the following |
11 | // conditions: |
12 | |
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions |
14 | // of the Software. |
15 | // |
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | // DEALINGS IN THE SOFTWARE. |
21 | |
22 | |
23 | using System; |
24 | using System.Text; |
25 | using System.IO; |
26 | using System.Collections.Generic; |
27 | using System.Data; |
28 | using System.Linq; |
29 | using System.Xml.Linq; |
30 | using NDO.Mapping; |
31 | using NDO; |
32 | using NDOInterfaces; |
33 | using System.Globalization; |
34 | |
35 | namespace NDO |
36 | { |
37 | ····/// <summary> |
38 | ····/// Zusammenfassung für GenericDiffGenerator. |
39 | ····/// </summary> |
40 | ····internal class SchemaTransitionGenerator |
41 | ····{ |
42 | ········IProvider provider; |
43 | ········ISqlGenerator concreteGenerator; |
44 | ········//MessageAdapter messages; |
45 | ········NDO.Mapping.NDOMapping mappings; |
46 | ········public SchemaTransitionGenerator(ISqlGenerator concreteGenerator, NDO.Mapping.NDOMapping mappings) |
47 | ········{ |
48 | ············provider = NDOProviderFactory.Instance[concreteGenerator.ProviderName]; |
49 | ············this.concreteGenerator = concreteGenerator; |
50 | ············this.mappings = mappings; |
51 | ········} |
52 | |
53 | ········public string Generate(XElement transElement) |
54 | ········{ |
55 | ············StringBuilder sb = new StringBuilder(); |
56 | ············foreach(XElement actionElement in transElement.Elements()) |
57 | ············{ |
58 | ················if (actionElement.Name == "DropTable") |
59 | ················{ |
60 | ····················sb.Append( DropTable( actionElement ) ); |
61 | ················} |
62 | ················else if (actionElement.Name=="CreateTable") |
63 | ················{ |
64 | ····················sb.Append( CreateTable( actionElement ) ); |
65 | ················} |
66 | ················else if (actionElement.Name=="AlterTable") |
67 | ················{ |
68 | ····················sb.Append( ChangeTable( actionElement ) ); |
69 | ················} |
70 | |
71 | ············} |
72 | ············return sb.ToString(); |
73 | ········} |
74 | |
75 | ········string ChangeTable(XElement actionElement) |
76 | ········{ |
77 | ············List<XElement> addedColumns = actionElement.Elements("AddColumn").ToList(); |
78 | ············List<XElement> removedColumns = actionElement.Elements("DropColumn").ToList(); |
79 | ············List<XElement> changedColumns = actionElement.Elements("AlterColumn").ToList(); |
80 | |
81 | ············if (addedColumns.Count == 0 && removedColumns.Count == 0 && changedColumns.Count == 0) |
82 | ················return String.Empty; |
83 | |
84 | ············StringBuilder sb = new StringBuilder(); |
85 | |
86 | ············string rawTableName = actionElement.Attribute( "name" ).Value; |
87 | ············string tableName = this.provider.GetQualifiedTableName(rawTableName); |
88 | ············string alterString = "ALTER TABLE " + tableName + ' '; |
89 | |
90 | ············foreach(XElement columnElement in addedColumns) |
91 | ············{ |
92 | ················sb.Append(alterString); |
93 | ················sb.Append(concreteGenerator.AddColumn()); |
94 | ················sb.Append(' '); |
95 | ················sb.Append(CreateColumn(columnElement, GetClassForTable(rawTableName, this.mappings), this.provider, false)); |
96 | ················sb.Append(";\n"); |
97 | ············} |
98 | |
99 | ············foreach(XElement columnElement in removedColumns) |
100 | ············{ |
101 | ················sb.Append(alterString); |
102 | ················sb.Append( concreteGenerator.RemoveColumn( provider.GetQuotedName( columnElement.Attribute( "name" ).Value ) ) ); |
103 | ················sb.Append(";\n"); |
104 | ············} |
105 | |
106 | ············foreach(XElement columnElement in changedColumns) |
107 | ············{ |
108 | ················sb.Append(alterString); |
109 | ················sb.Append(concreteGenerator.AlterColumnType()); |
110 | ················sb.Append(' '); |
111 | ················sb.Append(CreateColumn(columnElement, GetClassForTable(rawTableName, this.mappings), this.provider, false)); |
112 | ················sb.Append(";\n"); |
113 | ············} |
114 | |
115 | ············return sb.ToString(); |
116 | ········} |
117 | |
118 | ········string RenameColumn(string tableName, string oldColumn, string newColumn, string typeString) |
119 | ········{ |
120 | ············string s = concreteGenerator.RenameColumn(tableName, oldColumn, newColumn, typeString); |
121 | ············ |
122 | ············if (s != string.Empty) |
123 | ············return s; |
124 | ········ |
125 | ············string alterString = "ALTER TABLE " + tableName + ' '; |
126 | |
127 | ············StringBuilder sb = new StringBuilder(alterString); |
128 | ············sb.Append(concreteGenerator.AddColumn()); |
129 | ············sb.Append(' '); |
130 | ············sb.Append(newColumn); |
131 | ············sb.Append(' '); |
132 | ············sb.Append(typeString); |
133 | ············sb.Append(";\n"); |
134 | |
135 | ············sb.Append("UPDATE "); |
136 | ············sb.Append(tableName); |
137 | ············sb.Append(" SET ");············ |
138 | ············sb.Append(newColumn); |
139 | ············sb.Append(" = "); |
140 | ············sb.Append(oldColumn); |
141 | ············sb.Append(";\n"); |
142 | |
143 | ············sb.Append(alterString); |
144 | ············sb.Append(concreteGenerator.RemoveColumn(oldColumn)); |
145 | ············sb.Append(';'); |
146 | ············return sb.ToString(); |
147 | ········} |
148 | |
149 | ········protected string DropTable(XElement actionElement) |
150 | ········{ |
151 | ············string tableName = this.provider .GetQualifiedTableName( actionElement.Attribute( "name" ).Value ); |
152 | ············return concreteGenerator.DropTable( tableName ); |
153 | ········} |
154 | |
155 | ········protected string CreateTable(XElement actionElement) |
156 | ········{ |
157 | ············StringBuilder sb = new StringBuilder(); |
158 | ············IProvider provider = NDOProviderFactory.Instance[concreteGenerator.ProviderName]; |
159 | ············if (provider == null) |
160 | ················throw new Exception("Can't find NDO provider '" + concreteGenerator.ProviderName + "'."); |
161 | |
162 | ············string dtTableName = actionElement.Attribute( "name" ).Value; |
163 | |
164 | ············string tableName = this.provider.GetQualifiedTableName( dtTableName ); |
165 | |
166 | ············Class cl = FindClass(dtTableName, mappings); |
167 | |
168 | ············if (cl != null) |
169 | ············{ |
170 | ················Connection conn = mappings.FindConnection(cl); |
171 | ················if (conn != null) |
172 | ····················concreteGenerator.ConnectToDatabase(conn.Name); |
173 | ············} |
174 | |
175 | ············sb.Append(concreteGenerator.BeginnTable(tableName)); |
176 | ············sb.Append('\n'); |
177 | |
178 | ············List<XElement> columnElements = actionElement.Elements( "CreateColumn" ).ToList(); |
179 | |
180 | ············int vorletzterIndex = columnElements.Count - 1; |
181 | ············List<XElement> primaryKeyColumns = columnElements.Where( e => |
182 | ············{ |
183 | ················XAttribute attr; |
184 | ················return (attr = e.Attribute( "isPrimary" )) != null && String.Compare( attr.Value, "true", true ) == 0; |
185 | ············} ).ToList(); |
186 | |
187 | ············bool hasPrimaryKeyColumns = primaryKeyColumns.Count > 0; |
188 | |
189 | ············for (int i = 0; i < columnElements.Count; i++) |
190 | ············{ |
191 | ················XElement columnElement = columnElements[i]; |
192 | ················string columnName = columnElement.Attribute("name").Value; |
193 | |
194 | ················bool isPrimary = primaryKeyColumns.Any( e => e.Attribute( "name" ).Value == columnName ); |
195 | |
196 | ················sb.Append(CreateColumn(columnElement, cl, provider, isPrimary)); |
197 | ················if (i < vorletzterIndex) |
198 | ················{ |
199 | ····················sb.Append(","); |
200 | ····················sb.Append('\n'); |
201 | ················} |
202 | ············} |
203 | |
204 | ············if(concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InTable |
205 | ················&& hasPrimaryKeyColumns) |
206 | ············{ |
207 | ················sb.Append(","); |
208 | ················sb.Append('\n'); |
209 | ············} |
210 | |
211 | ············if (hasPrimaryKeyColumns && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InTable) |
212 | ············{ |
213 | ················sb.Append(CreatePrimaryKeyConstraint(primaryKeyColumns, dtTableName, provider)); |
214 | ············} |
215 | ············else |
216 | ············{ |
217 | ················sb.Append('\n'); |
218 | ············} |
219 | ············sb.Append(concreteGenerator.EndTable(tableName)); |
220 | ············sb.Append('\n'); |
221 | |
222 | ············//············CreateIndex(primaryKeyColumns, sb, dt, provider); |
223 | |
224 | ············if (hasPrimaryKeyColumns && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.AfterTable) |
225 | ············{ |
226 | ················sb.Append(CreatePrimaryKeyConstraint(primaryKeyColumns, dtTableName, provider)); |
227 | ············} |
228 | |
229 | ············sb.Append('\n'); |
230 | |
231 | ············return sb.ToString(); |
232 | ········} |
233 | |
234 | ········protected NDO.Mapping.Class FindClass(string tableName, NDOMapping mappings) |
235 | ········{ |
236 | ············Class result = null; |
237 | ············foreach(Class cl in mappings.Classes) |
238 | ············{ |
239 | ················if (cl.TableName == tableName) |
240 | ················{ |
241 | ····················result = cl; |
242 | ····················break; |
243 | ················} |
244 | ············} |
245 | ············return result; |
246 | ········} |
247 | |
248 | ········static bool IsNumeric( Type type ) |
249 | ········{ |
250 | ············switch (Type.GetTypeCode( type )) |
251 | ············{ |
252 | ················case TypeCode.Byte: |
253 | ················case TypeCode.SByte: |
254 | ················case TypeCode.UInt16: |
255 | ················case TypeCode.UInt32: |
256 | ················case TypeCode.UInt64: |
257 | ················case TypeCode.Int16: |
258 | ················case TypeCode.Int32: |
259 | ················case TypeCode.Int64: |
260 | ················case TypeCode.Decimal: |
261 | ················case TypeCode.Double: |
262 | ················case TypeCode.Single: |
263 | ····················return true; |
264 | ················case TypeCode.Object: |
265 | ····················if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof( Nullable<> )) |
266 | ····················{ |
267 | ························return IsNumeric(Nullable.GetUnderlyingType( type )); |
268 | ····················} |
269 | ····················return false; |
270 | ················default: |
271 | ····················return false; |
272 | ············} |
273 | ········} |
274 | |
275 | ········protected string CreateColumn(XElement columnElement, Class cl, IProvider provider, bool isPrimary) |
276 | ········{ |
277 | ············string rawName = columnElement.Attribute( "name" ).Value; |
278 | ············Type dcDataType = Type.GetType( columnElement.Attribute( "type" ).Value ); |
279 | ············string name = provider.GetQuotedName(rawName); |
280 | ············string columnType = columnElement.Attribute( "dbtype" )?.Value; |
281 | ············if (columnType == String.Empty)··// Make sure the column type will be infered, if it is an empty string |
282 | ················columnType = null; |
283 | ············string width = columnElement.Attribute("size") == null ? null : columnElement.Attribute("size").Value; |
284 | ············string precision = null; |
285 | ············bool autoIncrement = false; |
286 | ············StringBuilder sb = new StringBuilder(); |
287 | ············bool allowNull = true; |
288 | ············string defaultValue = columnElement.Attribute( "default" )?.Value; |
289 | |
290 | ············if (cl != null) |
291 | ············{ |
292 | ················Field field = FindField(rawName, cl); |
293 | |
294 | ················if (null != field) |
295 | ················{ |
296 | ····················if ( !String.IsNullOrEmpty(columnType) && null != field.Column.DbType) |
297 | ························columnType = field.Column.DbType; |
298 | ····················if (0 != field.Column.Size && !field.Column.IgnoreColumnSizeInDDL) |
299 | ····················{ |
300 | ························int dl = field.Column.Size; |
301 | ························if (dl == -1) |
302 | ····························width = "max"; |
303 | ························else |
304 | ····························width = dl.ToString(); |
305 | ····················} |
306 | ····················if (0 != field.Column.Precision && !field.Column.IgnoreColumnSizeInDDL) |
307 | ························precision = field.Column.Precision.ToString(); |
308 | ····················allowNull = field.Column.AllowDbNull; |
309 | ················} |
310 | ················else if (cl.TimeStampColumn == rawName) |
311 | ················{ |
312 | ····················if (!provider.SupportsNativeGuidType) |
313 | ························width = "36"; |
314 | ················} |
315 | ················else if (isPrimary && columnElement.Attribute( "autoIncrement" ) != null && String.Compare(columnElement.Attribute( "autoIncrement" ).Value, "true", true) == 0) |
316 | ················{ |
317 | ····················autoIncrement = true; |
318 | ················} |
319 | ············} |
320 | ············if (null == columnType) |
321 | ············{ |
322 | ················try |
323 | ················{ |
324 | ····················columnType = concreteGenerator.DbTypeFromType(dcDataType); |
325 | ················} |
326 | ················catch |
327 | ················{ |
328 | ····················System.Diagnostics.Debug.Write(""); |
329 | ················} |
330 | ············} |
331 | |
332 | ············if (null == width) |
333 | ············{ |
334 | ················int dl = provider.GetDefaultLength(dcDataType); |
335 | ················if (dl != 0) |
336 | ················{ |
337 | ····················if (dl == -1) |
338 | ························width = "max"; |
339 | ····················else |
340 | ························width = dl.ToString(); |
341 | ················} |
342 | ············} |
343 | ············ |
344 | ············// Because there is no GetDefaultPrecision in the provider... |
345 | ············// We assume the field to represent currency data |
346 | ············if (precision == null && dcDataType == typeof(decimal)) |
347 | ············{ |
348 | ················precision = "2"; |
349 | ············} |
350 | |
351 | ············if (columnType != null) |
352 | ············{ |
353 | ················if (!concreteGenerator.LengthAllowed(columnType)) |
354 | ····················width = null; |
355 | ············} |
356 | ············else |
357 | ············{ |
358 | ················if (!concreteGenerator.LengthAllowed(dcDataType)) |
359 | ····················width = null; |
360 | ············} |
361 | |
362 | |
363 | ············if (autoIncrement && concreteGenerator.HasSpecialAutoIncrementColumnFormat) |
364 | sb. Append( concreteGenerator. AutoIncrementColumn( name, dcDataType, columnType, width, isPrimary) ) ; |
365 | ············else if(isPrimary && concreteGenerator.PrimaryConstraintPlacement == PrimaryConstraintPlacement.InColumn) |
366 | ················sb.Append(concreteGenerator.PrimaryKeyColumn(name, dcDataType, columnType, width)); |
367 | ············else if (width != null && precision != null) |
368 | ················sb.Append(name + " " + columnType + "(" + width + "," + precision + ")"); |
369 | ············else if (width != null) |
370 | ················sb.Append(name + " " + columnType + "(" + width + ")");············ |
371 | ············else |
372 | ················sb.Append(name + " " + columnType); |
373 | |
374 | ············sb.Append(" "); |
375 | |
376 | ············if (defaultValue != null) |
377 | ············{ |
378 | ················sb.Append( "DEFAULT " ); |
379 | ················if (IsNumeric( dcDataType )) |
380 | ····················sb.Append( defaultValue); |
381 | ················else |
382 | ················{ |
383 | ····················sb.Append( '\'' ); |
384 | ····················sb.Append( defaultValue.Replace( "'", "''" ) ); |
385 | ····················sb.Append( '\'' ); |
386 | ················} |
387 | ················sb.Append( ' ' ); |
388 | ············} |
389 | |
390 | ············sb.Append( concreteGenerator.NullExpression( allowNull && columnElement.Attribute( "allowNull" ) != null && String.Compare( columnElement.Attribute( "allowNull" ).Value, "true", true ) == 0 ) ); |
391 | ············return sb.ToString(); |
392 | ········} |
393 | |
394 | ········protected string CreatePrimaryKeyConstraint(List<XElement> primaryKeyColumns, string tableName, IProvider provider) |
395 | ········{ |
396 | ············if (primaryKeyColumns.Count == 0) |
397 | ················return string.Empty; |
398 | ············string[] strArr = tableName.Split('.'); |
399 | ············string constraintName = provider.GetQuotedName("PK_" + strArr[strArr.Length - 1]); |
400 | ············DataColumn[] pkColumns = (from pk in primaryKeyColumns select new DataColumn( pk.Attribute( "name" ).Value )).ToArray(); |
401 | ············return concreteGenerator.CreatePrimaryKeyConstraint(pkColumns, constraintName, provider.GetQualifiedTableName(tableName)) + '\n'; |
402 | ········} |
403 | |
404 | ········protected Field FindField (string columnName, Class cl) |
405 | ········{ |
406 | ············Field result = null; |
407 | ············foreach (Field field in cl.Fields) |
408 | ············{ |
409 | ················if (field.Column.Name == columnName) |
410 | ················{ |
411 | ····················result = field; |
412 | ····················break; |
413 | ················} |
414 | ············} |
415 | ············return result; |
416 | ········} |
417 | |
418 | ········protected Class GetClassForTable(string tableName, NDOMapping mapping) |
419 | ········{ |
420 | ············foreach(Class cl in mapping.Classes) |
421 | ················if (cl.TableName == tableName) |
422 | ····················return cl; |
423 | ············return null; |
424 | ········} |
425 | ····} |
426 | } |
427 |