diff Source/Data/Sql/SqlTable.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Data/Sql/SqlTable.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,430 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace BLToolkit.Data.Sql
+{
+	using DataAccess;
+	using Mapping;
+	using Reflection.Extension;
+	using SqlProvider;
+
+	public class SqlTable : ISqlTableSource
+	{
+		#region Init
+
+		public SqlTable()
+		{
+			_sourceID = Interlocked.Increment(ref SqlQuery.SourceIDCounter);
+			_fields   = new ChildContainer<ISqlTableSource,SqlField>(this);
+		}
+
+		internal SqlTable(
+			int id, string name, string alias, string database, string owner, string physicalName, Type objectType,
+			SequenceNameAttribute[] sequenceAttributes,
+			SqlField[] fields,
+			SqlTableType sqlTableType, ISqlExpression[] tableArguments)
+		{
+			_sourceID           = id;
+			Name                = name;
+			Alias               = alias;
+			Database            = database;
+			Owner               = owner;
+			PhysicalName        = physicalName;
+			ObjectType          = objectType;
+			_sequenceAttributes = sequenceAttributes;
+
+			_fields  = new ChildContainer<ISqlTableSource,SqlField>(this);
+			_fields.AddRange(fields);
+
+			foreach (var field in fields)
+			{
+				if (field.Name == "*")
+				{
+					_all = field;
+					_fields.Remove("*");
+					((IChild<ISqlTableSource>)_all).Parent = this;
+					break;
+				}
+			}
+
+			SqlTableType   = sqlTableType;
+			TableArguments = tableArguments;
+		}
+
+		#endregion
+
+		#region Init from type
+
+		public SqlTable([JetBrains.Annotations.NotNull] MappingSchema mappingSchema, Type objectType) : this()
+		{
+			if (mappingSchema == null) throw new ArgumentNullException("mappingSchema");
+
+			bool isSet;
+			Database     = mappingSchema.MetadataProvider.GetDatabaseName(objectType, mappingSchema.Extensions, out isSet);
+			Owner        = mappingSchema.MetadataProvider.GetOwnerName   (objectType, mappingSchema.Extensions, out isSet);
+			Name         = mappingSchema.MetadataProvider.GetTableName   (objectType, mappingSchema.Extensions, out isSet);
+			ObjectType   = objectType;
+			PhysicalName = Name;
+
+			var typeExt = TypeExtension.GetTypeExtension(objectType, mappingSchema.Extensions);
+
+			foreach (MemberMapper mm in mappingSchema.GetObjectMapper(objectType))
+				if (mm.MapMemberInfo.SqlIgnore == false)
+				{
+					var ua =
+						mappingSchema.MetadataProvider.GetNonUpdatableAttribute(objectType, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
+
+					var order = mappingSchema.MetadataProvider.GetPrimaryKeyOrder(objectType, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
+
+					Fields.Add(new SqlField(
+						mm.Type,
+						mm.MemberName,
+						mm.Name,
+						mm.MapMemberInfo.Nullable,
+						isSet ? order : int.MinValue,
+						ua,
+						mm));
+				}
+
+			var identityField = GetIdentityField();
+
+			if (identityField != null)
+			{
+				var om = mappingSchema.GetObjectMapper(ObjectType);
+				var mm = om[identityField.Name, true];
+
+				_sequenceAttributes = mm.MapMemberInfo.MemberAccessor.GetAttributes<SequenceNameAttribute>();
+			}
+		}
+
+		public SqlTable(Type objectType)
+			: this(Map.DefaultSchema, objectType)
+		{
+		}
+
+		#endregion
+
+		#region Init from Table
+
+		public SqlTable(SqlTable table) : this()
+		{
+			Alias               = table.Alias;
+			Database            = table.Database;
+			Owner               = table.Owner;
+			Name                = table.Name;
+			PhysicalName        = table.PhysicalName;
+			ObjectType          = table.ObjectType;
+			_sequenceAttributes = table._sequenceAttributes;
+
+			foreach (var field in table.Fields.Values)
+				Fields.Add(new SqlField(field));
+
+			foreach (var join in table.Joins)
+				Joins.Add(join.Clone());
+
+			SqlTableType   = table.SqlTableType;
+			TableArguments = table.TableArguments;
+		}
+
+		public SqlTable(SqlTable table, IEnumerable<SqlField> fields, IEnumerable<Join> joins, ISqlExpression[] tableArguments) : this()
+		{
+			Alias               = table.Alias;
+			Database            = table.Database;
+			Owner               = table.Owner;
+			Name                = table.Name;
+			PhysicalName        = table.PhysicalName;
+			ObjectType          = table.ObjectType;
+			_sequenceAttributes = table._sequenceAttributes;
+
+			Fields.AddRange(fields);
+			Joins. AddRange(joins);
+
+			SqlTableType   = table.SqlTableType;
+			TableArguments = tableArguments;
+		}
+
+		#endregion
+
+		#region Init from XML
+
+		public SqlTable(ExtensionList extensions, string name)
+			: this(Map.DefaultSchema, extensions, name)
+		{
+		}
+
+		public SqlTable([JetBrains.Annotations.NotNull] MappingSchema mappingSchema, ExtensionList extensions, string name) : this()
+		{
+			if (mappingSchema == null) throw new ArgumentNullException("mappingSchema");
+			if (extensions    == null) throw new ArgumentNullException("extensions");
+			if (name          == null) throw new ArgumentNullException("name");
+
+			var te = extensions[name];
+
+			if (te == TypeExtension.Null)
+				throw new ArgumentException(string.Format("Table '{0}' not found.", name));
+
+			Name         = te.Name;
+			Alias        = (string)te.Attributes["Alias"].       Value;
+			Database     = (string)te.Attributes["Database"].    Value;
+			Owner        = (string)te.Attributes["Owner"].       Value;
+			PhysicalName = (string)te.Attributes["PhysicalName"].Value ?? te.Name;
+
+			foreach (var me in te.Members.Values)
+				Fields.Add(new SqlField(
+					(Type)me["Type"].Value,
+					me.Name,
+					(string)me["MapField"].Value ?? (string)me["PhysicalName"].Value,
+					(bool?)me["Nullable"].Value ?? false,
+					-1,
+					(bool?)me["Identity"].Value == true ? new IdentityAttribute() : null,
+					null));
+
+			foreach (var ae in te.Attributes["Join"])
+				Joins.Add(new Join(ae));
+
+			var baseExtension = (string)te.Attributes["BaseExtension"].Value;
+
+			if (!string.IsNullOrEmpty(baseExtension))
+				InitFromBase(new SqlTable(mappingSchema, extensions, baseExtension));
+
+			var baseTypeName = (string)te.Attributes["BaseType"].Value;
+
+			if (!string.IsNullOrEmpty(baseTypeName))
+				InitFromBase(new SqlTable(mappingSchema, Type.GetType(baseTypeName, true, true)));
+		}
+
+		void InitFromBase(SqlTable baseTable)
+		{
+			if (Alias        == null) Alias        = baseTable.Alias;
+			if (Database     == null) Database     = baseTable.Database;
+			if (Owner        == null) Owner        = baseTable.Owner;
+			if (PhysicalName == null) PhysicalName = baseTable.PhysicalName;
+
+			foreach (var field in baseTable.Fields.Values)
+				if (!Fields.ContainsKey(field.Name))
+					Fields.Add(new SqlField(field));
+
+			foreach (var join in baseTable.Joins)
+				if (Joins.FirstOrDefault(j => j.TableName == join.TableName) == null)
+					Joins.Add(join);
+		}
+
+		#endregion
+
+		#region Overrides
+
+#if OVERRIDETOSTRING
+
+		public override string ToString()
+		{
+			return ((IQueryElement)this).ToString(new StringBuilder(), new Dictionary<IQueryElement,IQueryElement>()).ToString();
+		}
+
+#endif
+
+		#endregion
+
+		#region Public Members
+
+		public SqlField this[string fieldName]
+		{
+			get
+			{
+				SqlField field;
+				Fields.TryGetValue(fieldName, out field);
+				return field;
+			}
+		}
+
+		public string Name         { get; set; }
+		public string Alias        { get; set; }
+		public string Database     { get; set; }
+		public string Owner        { get; set; }
+		public Type   ObjectType   { get; set; }
+		public string PhysicalName { get; set; }
+
+		private SqlTableType _sqlTableType = SqlTableType.Table;
+		public  SqlTableType  SqlTableType { get { return _sqlTableType; } set { _sqlTableType = value; } }
+
+		public ISqlExpression[] TableArguments { get; set; }
+
+		readonly ChildContainer<ISqlTableSource,SqlField> _fields;
+		public   ChildContainer<ISqlTableSource,SqlField>  Fields { get { return _fields; } }
+
+		readonly List<Join> _joins = new List<Join>();
+		public   List<Join>  Joins { get { return _joins; } }
+
+		private SequenceNameAttribute[] _sequenceAttributes;
+		public  SequenceNameAttribute[]  SequenceAttributes
+		{
+			get { return _sequenceAttributes; }
+		}
+
+		private SqlField _all;
+		public  SqlField  All
+		{
+			get
+			{
+				if (_all == null)
+				{
+					_all = new SqlField(null, "*", "*", true, -1, null, null);
+					((IChild<ISqlTableSource>)_all).Parent = this;
+				}
+
+				return _all;
+			}
+		}
+
+		public SqlField GetIdentityField()
+		{
+			foreach (var field in Fields)
+				if (field.Value.IsIdentity)
+					return field.Value;
+
+			var keys = GetKeys(true);
+
+			if (keys != null && keys.Count == 1)
+				return (SqlField)keys[0];
+
+			return null;
+		}
+
+		#endregion
+
+		#region ISqlTableSource Members
+
+		readonly int _sourceID;
+		public   int  SourceID { get { return _sourceID; } }
+
+		List<ISqlExpression> _keyFields;
+
+		public IList<ISqlExpression> GetKeys(bool allIfEmpty)
+		{
+			if (_keyFields == null)
+			{
+				_keyFields = (
+					from f in Fields.Values
+					where   f.IsPrimaryKey
+					orderby f.PrimaryKeyOrder
+					select f as ISqlExpression
+				).ToList();
+			}
+
+			if (_keyFields.Count == 0 && allIfEmpty)
+				return Fields.Values.Select(f => f as ISqlExpression).ToList();
+
+			return _keyFields;
+		}
+
+		#endregion
+
+		#region ICloneableElement Members
+
+		public ICloneableElement Clone(Dictionary<ICloneableElement, ICloneableElement> objectTree, Predicate<ICloneableElement> doClone)
+		{
+			if (!doClone(this))
+				return this;
+
+			ICloneableElement clone;
+
+			if (!objectTree.TryGetValue(this, out clone))
+			{
+				var table = new SqlTable
+				{
+					Name                = Name,
+					Alias               = Alias,
+					Database            = Database,
+					Owner               = Owner,
+					PhysicalName        = PhysicalName,
+					ObjectType          = ObjectType,
+					SqlTableType        = SqlTableType,
+					_sequenceAttributes = _sequenceAttributes,
+				};
+
+				table._fields.Clear();
+
+				foreach (var field in _fields)
+				{
+					var fc = new SqlField(field.Value);
+
+					objectTree.   Add(field.Value, fc);
+					table._fields.Add(field.Key,   fc);
+				}
+
+				table._joins.AddRange(_joins.ConvertAll(j => j.Clone()));
+
+				if (TableArguments != null)
+					TableArguments = TableArguments.Select(e => (ISqlExpression)e.Clone(objectTree, doClone)).ToArray();
+
+				objectTree.Add(this, table);
+				objectTree.Add(All,  table.All);
+
+				clone = table;
+			}
+
+			return clone;
+		}
+
+		#endregion
+
+		#region IQueryElement Members
+
+		public QueryElementType ElementType { get { return QueryElementType.SqlTable; } }
+
+		StringBuilder IQueryElement.ToString(StringBuilder sb, Dictionary<IQueryElement,IQueryElement> dic)
+		{
+			return sb.Append(Name);
+		}
+
+		#endregion
+
+		#region ISqlExpression Members
+
+		bool ISqlExpression.CanBeNull()
+		{
+			return true;
+		}
+
+		public bool Equals(ISqlExpression other, Func<ISqlExpression, ISqlExpression, bool> comparer)
+		{
+			return this == other;
+		}
+
+		int ISqlExpression.Precedence
+		{
+			get { return Precedence.Unknown; }
+		}
+
+		Type ISqlExpression.SystemType
+		{
+			get { return ObjectType; }
+		}
+
+		#endregion
+
+		#region IEquatable<ISqlExpression> Members
+
+		bool IEquatable<ISqlExpression>.Equals(ISqlExpression other)
+		{
+			return this == other;
+		}
+
+		#endregion
+
+		#region ISqlExpressionWalkable Members
+
+		ISqlExpression ISqlExpressionWalkable.Walk(bool skipColumns, Func<ISqlExpression,ISqlExpression> func)
+		{
+			if (TableArguments != null)
+				for (var i = 0; i < TableArguments.Length; i++)
+					TableArguments[i] = TableArguments[i].Walk(skipColumns, func);
+
+			return func(this);
+		}
+
+		#endregion
+	}
+}