0
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Linq;
|
|
4 using System.Text;
|
|
5 using System.Threading;
|
|
6
|
|
7 namespace BLToolkit.Data.Sql
|
|
8 {
|
|
9 using DataAccess;
|
|
10 using Mapping;
|
|
11 using Reflection.Extension;
|
|
12 using SqlProvider;
|
|
13
|
|
14 public class SqlTable : ISqlTableSource
|
|
15 {
|
|
16 #region Init
|
|
17
|
|
18 public SqlTable()
|
|
19 {
|
|
20 _sourceID = Interlocked.Increment(ref SqlQuery.SourceIDCounter);
|
|
21 _fields = new ChildContainer<ISqlTableSource,SqlField>(this);
|
|
22 }
|
|
23
|
|
24 internal SqlTable(
|
|
25 int id, string name, string alias, string database, string owner, string physicalName, Type objectType,
|
|
26 SequenceNameAttribute[] sequenceAttributes,
|
|
27 SqlField[] fields,
|
|
28 SqlTableType sqlTableType, ISqlExpression[] tableArguments)
|
|
29 {
|
|
30 _sourceID = id;
|
|
31 Name = name;
|
|
32 Alias = alias;
|
|
33 Database = database;
|
|
34 Owner = owner;
|
|
35 PhysicalName = physicalName;
|
|
36 ObjectType = objectType;
|
|
37 _sequenceAttributes = sequenceAttributes;
|
|
38
|
|
39 _fields = new ChildContainer<ISqlTableSource,SqlField>(this);
|
|
40 _fields.AddRange(fields);
|
|
41
|
|
42 foreach (var field in fields)
|
|
43 {
|
|
44 if (field.Name == "*")
|
|
45 {
|
|
46 _all = field;
|
|
47 _fields.Remove("*");
|
|
48 ((IChild<ISqlTableSource>)_all).Parent = this;
|
|
49 break;
|
|
50 }
|
|
51 }
|
|
52
|
|
53 SqlTableType = sqlTableType;
|
|
54 TableArguments = tableArguments;
|
|
55 }
|
|
56
|
|
57 #endregion
|
|
58
|
|
59 #region Init from type
|
|
60
|
|
61 public SqlTable([JetBrains.Annotations.NotNull] MappingSchema mappingSchema, Type objectType) : this()
|
|
62 {
|
|
63 if (mappingSchema == null) throw new ArgumentNullException("mappingSchema");
|
|
64
|
|
65 bool isSet;
|
|
66 Database = mappingSchema.MetadataProvider.GetDatabaseName(objectType, mappingSchema.Extensions, out isSet);
|
|
67 Owner = mappingSchema.MetadataProvider.GetOwnerName (objectType, mappingSchema.Extensions, out isSet);
|
|
68 Name = mappingSchema.MetadataProvider.GetTableName (objectType, mappingSchema.Extensions, out isSet);
|
|
69 ObjectType = objectType;
|
|
70 PhysicalName = Name;
|
|
71
|
|
72 var typeExt = TypeExtension.GetTypeExtension(objectType, mappingSchema.Extensions);
|
|
73
|
|
74 foreach (MemberMapper mm in mappingSchema.GetObjectMapper(objectType))
|
|
75 if (mm.MapMemberInfo.SqlIgnore == false)
|
|
76 {
|
|
77 var ua =
|
|
78 mappingSchema.MetadataProvider.GetNonUpdatableAttribute(objectType, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
|
|
79
|
|
80 var order = mappingSchema.MetadataProvider.GetPrimaryKeyOrder(objectType, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
|
|
81
|
|
82 Fields.Add(new SqlField(
|
|
83 mm.Type,
|
|
84 mm.MemberName,
|
|
85 mm.Name,
|
|
86 mm.MapMemberInfo.Nullable,
|
|
87 isSet ? order : int.MinValue,
|
|
88 ua,
|
|
89 mm));
|
|
90 }
|
|
91
|
|
92 var identityField = GetIdentityField();
|
|
93
|
|
94 if (identityField != null)
|
|
95 {
|
|
96 var om = mappingSchema.GetObjectMapper(ObjectType);
|
|
97 var mm = om[identityField.Name, true];
|
|
98
|
|
99 _sequenceAttributes = mm.MapMemberInfo.MemberAccessor.GetAttributes<SequenceNameAttribute>();
|
|
100 }
|
|
101 }
|
|
102
|
|
103 public SqlTable(Type objectType)
|
|
104 : this(Map.DefaultSchema, objectType)
|
|
105 {
|
|
106 }
|
|
107
|
|
108 #endregion
|
|
109
|
|
110 #region Init from Table
|
|
111
|
|
112 public SqlTable(SqlTable table) : this()
|
|
113 {
|
|
114 Alias = table.Alias;
|
|
115 Database = table.Database;
|
|
116 Owner = table.Owner;
|
|
117 Name = table.Name;
|
|
118 PhysicalName = table.PhysicalName;
|
|
119 ObjectType = table.ObjectType;
|
|
120 _sequenceAttributes = table._sequenceAttributes;
|
|
121
|
|
122 foreach (var field in table.Fields.Values)
|
|
123 Fields.Add(new SqlField(field));
|
|
124
|
|
125 foreach (var join in table.Joins)
|
|
126 Joins.Add(join.Clone());
|
|
127
|
|
128 SqlTableType = table.SqlTableType;
|
|
129 TableArguments = table.TableArguments;
|
|
130 }
|
|
131
|
|
132 public SqlTable(SqlTable table, IEnumerable<SqlField> fields, IEnumerable<Join> joins, ISqlExpression[] tableArguments) : this()
|
|
133 {
|
|
134 Alias = table.Alias;
|
|
135 Database = table.Database;
|
|
136 Owner = table.Owner;
|
|
137 Name = table.Name;
|
|
138 PhysicalName = table.PhysicalName;
|
|
139 ObjectType = table.ObjectType;
|
|
140 _sequenceAttributes = table._sequenceAttributes;
|
|
141
|
|
142 Fields.AddRange(fields);
|
|
143 Joins. AddRange(joins);
|
|
144
|
|
145 SqlTableType = table.SqlTableType;
|
|
146 TableArguments = tableArguments;
|
|
147 }
|
|
148
|
|
149 #endregion
|
|
150
|
|
151 #region Init from XML
|
|
152
|
|
153 public SqlTable(ExtensionList extensions, string name)
|
|
154 : this(Map.DefaultSchema, extensions, name)
|
|
155 {
|
|
156 }
|
|
157
|
|
158 public SqlTable([JetBrains.Annotations.NotNull] MappingSchema mappingSchema, ExtensionList extensions, string name) : this()
|
|
159 {
|
|
160 if (mappingSchema == null) throw new ArgumentNullException("mappingSchema");
|
|
161 if (extensions == null) throw new ArgumentNullException("extensions");
|
|
162 if (name == null) throw new ArgumentNullException("name");
|
|
163
|
|
164 var te = extensions[name];
|
|
165
|
|
166 if (te == TypeExtension.Null)
|
|
167 throw new ArgumentException(string.Format("Table '{0}' not found.", name));
|
|
168
|
|
169 Name = te.Name;
|
|
170 Alias = (string)te.Attributes["Alias"]. Value;
|
|
171 Database = (string)te.Attributes["Database"]. Value;
|
|
172 Owner = (string)te.Attributes["Owner"]. Value;
|
|
173 PhysicalName = (string)te.Attributes["PhysicalName"].Value ?? te.Name;
|
|
174
|
|
175 foreach (var me in te.Members.Values)
|
|
176 Fields.Add(new SqlField(
|
|
177 (Type)me["Type"].Value,
|
|
178 me.Name,
|
|
179 (string)me["MapField"].Value ?? (string)me["PhysicalName"].Value,
|
|
180 (bool?)me["Nullable"].Value ?? false,
|
|
181 -1,
|
|
182 (bool?)me["Identity"].Value == true ? new IdentityAttribute() : null,
|
|
183 null));
|
|
184
|
|
185 foreach (var ae in te.Attributes["Join"])
|
|
186 Joins.Add(new Join(ae));
|
|
187
|
|
188 var baseExtension = (string)te.Attributes["BaseExtension"].Value;
|
|
189
|
|
190 if (!string.IsNullOrEmpty(baseExtension))
|
|
191 InitFromBase(new SqlTable(mappingSchema, extensions, baseExtension));
|
|
192
|
|
193 var baseTypeName = (string)te.Attributes["BaseType"].Value;
|
|
194
|
|
195 if (!string.IsNullOrEmpty(baseTypeName))
|
|
196 InitFromBase(new SqlTable(mappingSchema, Type.GetType(baseTypeName, true, true)));
|
|
197 }
|
|
198
|
|
199 void InitFromBase(SqlTable baseTable)
|
|
200 {
|
|
201 if (Alias == null) Alias = baseTable.Alias;
|
|
202 if (Database == null) Database = baseTable.Database;
|
|
203 if (Owner == null) Owner = baseTable.Owner;
|
|
204 if (PhysicalName == null) PhysicalName = baseTable.PhysicalName;
|
|
205
|
|
206 foreach (var field in baseTable.Fields.Values)
|
|
207 if (!Fields.ContainsKey(field.Name))
|
|
208 Fields.Add(new SqlField(field));
|
|
209
|
|
210 foreach (var join in baseTable.Joins)
|
|
211 if (Joins.FirstOrDefault(j => j.TableName == join.TableName) == null)
|
|
212 Joins.Add(join);
|
|
213 }
|
|
214
|
|
215 #endregion
|
|
216
|
|
217 #region Overrides
|
|
218
|
|
219 #if OVERRIDETOSTRING
|
|
220
|
|
221 public override string ToString()
|
|
222 {
|
|
223 return ((IQueryElement)this).ToString(new StringBuilder(), new Dictionary<IQueryElement,IQueryElement>()).ToString();
|
|
224 }
|
|
225
|
|
226 #endif
|
|
227
|
|
228 #endregion
|
|
229
|
|
230 #region Public Members
|
|
231
|
|
232 public SqlField this[string fieldName]
|
|
233 {
|
|
234 get
|
|
235 {
|
|
236 SqlField field;
|
|
237 Fields.TryGetValue(fieldName, out field);
|
|
238 return field;
|
|
239 }
|
|
240 }
|
|
241
|
|
242 public string Name { get; set; }
|
|
243 public string Alias { get; set; }
|
|
244 public string Database { get; set; }
|
|
245 public string Owner { get; set; }
|
|
246 public Type ObjectType { get; set; }
|
|
247 public string PhysicalName { get; set; }
|
|
248
|
|
249 private SqlTableType _sqlTableType = SqlTableType.Table;
|
|
250 public SqlTableType SqlTableType { get { return _sqlTableType; } set { _sqlTableType = value; } }
|
|
251
|
|
252 public ISqlExpression[] TableArguments { get; set; }
|
|
253
|
|
254 readonly ChildContainer<ISqlTableSource,SqlField> _fields;
|
|
255 public ChildContainer<ISqlTableSource,SqlField> Fields { get { return _fields; } }
|
|
256
|
|
257 readonly List<Join> _joins = new List<Join>();
|
|
258 public List<Join> Joins { get { return _joins; } }
|
|
259
|
|
260 private SequenceNameAttribute[] _sequenceAttributes;
|
|
261 public SequenceNameAttribute[] SequenceAttributes
|
|
262 {
|
|
263 get { return _sequenceAttributes; }
|
|
264 }
|
|
265
|
|
266 private SqlField _all;
|
|
267 public SqlField All
|
|
268 {
|
|
269 get
|
|
270 {
|
|
271 if (_all == null)
|
|
272 {
|
|
273 _all = new SqlField(null, "*", "*", true, -1, null, null);
|
|
274 ((IChild<ISqlTableSource>)_all).Parent = this;
|
|
275 }
|
|
276
|
|
277 return _all;
|
|
278 }
|
|
279 }
|
|
280
|
|
281 public SqlField GetIdentityField()
|
|
282 {
|
|
283 foreach (var field in Fields)
|
|
284 if (field.Value.IsIdentity)
|
|
285 return field.Value;
|
|
286
|
|
287 var keys = GetKeys(true);
|
|
288
|
|
289 if (keys != null && keys.Count == 1)
|
|
290 return (SqlField)keys[0];
|
|
291
|
|
292 return null;
|
|
293 }
|
|
294
|
|
295 #endregion
|
|
296
|
|
297 #region ISqlTableSource Members
|
|
298
|
|
299 readonly int _sourceID;
|
|
300 public int SourceID { get { return _sourceID; } }
|
|
301
|
|
302 List<ISqlExpression> _keyFields;
|
|
303
|
|
304 public IList<ISqlExpression> GetKeys(bool allIfEmpty)
|
|
305 {
|
|
306 if (_keyFields == null)
|
|
307 {
|
|
308 _keyFields = (
|
|
309 from f in Fields.Values
|
|
310 where f.IsPrimaryKey
|
|
311 orderby f.PrimaryKeyOrder
|
|
312 select f as ISqlExpression
|
|
313 ).ToList();
|
|
314 }
|
|
315
|
|
316 if (_keyFields.Count == 0 && allIfEmpty)
|
|
317 return Fields.Values.Select(f => f as ISqlExpression).ToList();
|
|
318
|
|
319 return _keyFields;
|
|
320 }
|
|
321
|
|
322 #endregion
|
|
323
|
|
324 #region ICloneableElement Members
|
|
325
|
|
326 public ICloneableElement Clone(Dictionary<ICloneableElement, ICloneableElement> objectTree, Predicate<ICloneableElement> doClone)
|
|
327 {
|
|
328 if (!doClone(this))
|
|
329 return this;
|
|
330
|
|
331 ICloneableElement clone;
|
|
332
|
|
333 if (!objectTree.TryGetValue(this, out clone))
|
|
334 {
|
|
335 var table = new SqlTable
|
|
336 {
|
|
337 Name = Name,
|
|
338 Alias = Alias,
|
|
339 Database = Database,
|
|
340 Owner = Owner,
|
|
341 PhysicalName = PhysicalName,
|
|
342 ObjectType = ObjectType,
|
|
343 SqlTableType = SqlTableType,
|
|
344 _sequenceAttributes = _sequenceAttributes,
|
|
345 };
|
|
346
|
|
347 table._fields.Clear();
|
|
348
|
|
349 foreach (var field in _fields)
|
|
350 {
|
|
351 var fc = new SqlField(field.Value);
|
|
352
|
|
353 objectTree. Add(field.Value, fc);
|
|
354 table._fields.Add(field.Key, fc);
|
|
355 }
|
|
356
|
|
357 table._joins.AddRange(_joins.ConvertAll(j => j.Clone()));
|
|
358
|
|
359 if (TableArguments != null)
|
|
360 TableArguments = TableArguments.Select(e => (ISqlExpression)e.Clone(objectTree, doClone)).ToArray();
|
|
361
|
|
362 objectTree.Add(this, table);
|
|
363 objectTree.Add(All, table.All);
|
|
364
|
|
365 clone = table;
|
|
366 }
|
|
367
|
|
368 return clone;
|
|
369 }
|
|
370
|
|
371 #endregion
|
|
372
|
|
373 #region IQueryElement Members
|
|
374
|
|
375 public QueryElementType ElementType { get { return QueryElementType.SqlTable; } }
|
|
376
|
|
377 StringBuilder IQueryElement.ToString(StringBuilder sb, Dictionary<IQueryElement,IQueryElement> dic)
|
|
378 {
|
|
379 return sb.Append(Name);
|
|
380 }
|
|
381
|
|
382 #endregion
|
|
383
|
|
384 #region ISqlExpression Members
|
|
385
|
|
386 bool ISqlExpression.CanBeNull()
|
|
387 {
|
|
388 return true;
|
|
389 }
|
|
390
|
|
391 public bool Equals(ISqlExpression other, Func<ISqlExpression, ISqlExpression, bool> comparer)
|
|
392 {
|
|
393 return this == other;
|
|
394 }
|
|
395
|
|
396 int ISqlExpression.Precedence
|
|
397 {
|
|
398 get { return Precedence.Unknown; }
|
|
399 }
|
|
400
|
|
401 Type ISqlExpression.SystemType
|
|
402 {
|
|
403 get { return ObjectType; }
|
|
404 }
|
|
405
|
|
406 #endregion
|
|
407
|
|
408 #region IEquatable<ISqlExpression> Members
|
|
409
|
|
410 bool IEquatable<ISqlExpression>.Equals(ISqlExpression other)
|
|
411 {
|
|
412 return this == other;
|
|
413 }
|
|
414
|
|
415 #endregion
|
|
416
|
|
417 #region ISqlExpressionWalkable Members
|
|
418
|
|
419 ISqlExpression ISqlExpressionWalkable.Walk(bool skipColumns, Func<ISqlExpression,ISqlExpression> func)
|
|
420 {
|
|
421 if (TableArguments != null)
|
|
422 for (var i = 0; i < TableArguments.Length; i++)
|
|
423 TableArguments[i] = TableArguments[i].Walk(skipColumns, func);
|
|
424
|
|
425 return func(this);
|
|
426 }
|
|
427
|
|
428 #endregion
|
|
429 }
|
|
430 }
|