diff Source/Data/Sql/SqlProvider/SqlCeSqlProvider.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/SqlProvider/SqlCeSqlProvider.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,262 @@
+using System;
+using System.Data;
+using System.Text;
+
+namespace BLToolkit.Data.Sql.SqlProvider
+{
+	using DataProvider;
+	using Reflection;
+
+	public class SqlCeSqlProvider : BasicSqlProvider
+	{
+		const int Version = 4;
+
+		public override bool IsSkipSupported           { get { return Version == 4; } }
+		public override bool IsTakeSupported           { get { return Version == 4; } }
+		public override bool IsSubQueryTakeSupported   { get { return Version == 4; } }
+		public override bool IsSubQueryColumnSupported { get { return false; } }
+		public override bool IsCountSubQuerySupported  { get { return false; } }
+		public override bool IsApplyJoinSupported      { get { return true;  } }
+		public override bool IsInsertOrUpdateSupported { get { return false; } }
+
+		protected override string FirstFormat  { get { return SqlQuery.Select.SkipValue == null ? "TOP ({0})" :                null; } }
+		protected override string LimitFormat  { get { return SqlQuery.Select.SkipValue != null ? "FETCH NEXT {0} ROWS ONLY" : null; } }
+		protected override string OffsetFormat { get { return "OFFSET {0} ROWS"; } }
+		protected override bool   OffsetFirst  { get { return true;              } }
+
+		public override int CommandCount(SqlQuery sqlQuery)
+		{
+			return sqlQuery.IsInsert && sqlQuery.Insert.WithIdentity ? 2 : 1;
+		}
+
+		protected override void BuildCommand(int commandNumber, StringBuilder sb)
+		{
+			sb.AppendLine("SELECT @@IDENTITY");
+		}
+
+		protected override ISqlProvider CreateSqlProvider()
+		{
+			return new SqlCeSqlProvider();
+		}
+
+		public override ISqlExpression ConvertExpression(ISqlExpression expr)
+		{
+			expr = base.ConvertExpression(expr);
+
+			if (expr is SqlBinaryExpression)
+			{
+				var be = (SqlBinaryExpression)expr;
+
+				switch (be.Operation)
+				{
+					case "%":
+						return TypeHelper.IsIntegerType(be.Expr1.SystemType)?
+							be :
+							new SqlBinaryExpression(
+								typeof(int),
+								new SqlFunction(typeof(int), "Convert", SqlDataType.Int32, be.Expr1),
+								be.Operation,
+								be.Expr2,
+								be.Precedence);
+				}
+			}
+			else if (expr is SqlFunction)
+			{
+				var func = (SqlFunction)expr;
+
+				switch (func.Name)
+				{
+					case "Convert" :
+						switch (Type.GetTypeCode(TypeHelper.GetUnderlyingType(func.SystemType)))
+						{
+							case TypeCode.UInt64 :
+								if (TypeHelper.IsFloatType(func.Parameters[1].SystemType))
+									return new SqlFunction(
+										func.SystemType,
+										func.Name,
+										func.Precedence,
+										func.Parameters[0],
+										new SqlFunction(func.SystemType, "Floor", func.Parameters[1]));
+
+								break;
+
+							case TypeCode.DateTime :
+								var type1 = TypeHelper.GetUnderlyingType(func.Parameters[1].SystemType);
+
+								if (IsTimeDataType(func.Parameters[0]))
+								{
+									if (type1 == typeof(DateTime) || type1 == typeof(DateTimeOffset))
+										return new SqlExpression(
+											func.SystemType, "Cast(Convert(NChar, {0}, 114) as DateTime)", Precedence.Primary, func.Parameters[1]);
+
+									if (func.Parameters[1].SystemType == typeof(string))
+										return func.Parameters[1];
+
+									return new SqlExpression(
+										func.SystemType, "Convert(NChar, {0}, 114)", Precedence.Primary, func.Parameters[1]);
+								}
+
+								if (type1 == typeof(DateTime) || type1 == typeof(DateTimeOffset))
+								{
+									if (IsDateDataType(func.Parameters[0], "Datetime"))
+										return new SqlExpression(
+											func.SystemType, "Cast(Floor(Cast({0} as Float)) as DateTime)", Precedence.Primary, func.Parameters[1]);
+								}
+
+								break;
+						}
+
+						break;
+				}
+			}
+
+			return expr;
+		}
+
+		protected override void BuildFunction(StringBuilder sb, SqlFunction func)
+		{
+			func = ConvertFunctionParameters(func);
+			base.BuildFunction(sb, func);
+		}
+
+		public override SqlQuery Finalize(SqlQuery sqlQuery)
+		{
+			sqlQuery = base.Finalize(sqlQuery);
+
+			new QueryVisitor().Visit(sqlQuery.Select, element =>
+			{
+				if (element.ElementType == QueryElementType.SqlParameter)
+				{
+					((SqlParameter)element).IsQueryParameter = false;
+					sqlQuery.IsParameterDependent = true;
+				}
+			});
+
+			switch (sqlQuery.QueryType)
+			{
+				case QueryType.Delete :
+					sqlQuery = GetAlternativeDelete(sqlQuery);
+					sqlQuery.From.Tables[0].Alias = "$";
+					break;
+
+				case QueryType.Update :
+					sqlQuery = GetAlternativeUpdate(sqlQuery);
+					break;
+			}
+
+			return sqlQuery;
+		}
+
+		protected override void BuildDataType(StringBuilder sb, SqlDataType type)
+		{
+			switch (type.SqlDbType)
+			{
+				case SqlDbType.Char          : base.BuildDataType(sb, new SqlDataType(SqlDbType.NChar,    type.Length)); break;
+				case SqlDbType.VarChar       : base.BuildDataType(sb, new SqlDataType(SqlDbType.NVarChar, type.Length)); break;
+				case SqlDbType.SmallMoney    : sb.Append("Decimal(10,4)");   break;
+#if !MONO
+				case SqlDbType.DateTime2     :
+#endif
+				case SqlDbType.Time          :
+				case SqlDbType.Date          :
+				case SqlDbType.SmallDateTime : sb.Append("DateTime");        break;
+				default                      : base.BuildDataType(sb, type); break;
+			}
+		}
+
+		protected override void BuildFromClause(StringBuilder sb)
+		{
+			if (!SqlQuery.IsUpdate)
+				base.BuildFromClause(sb);
+		}
+
+		protected override void BuildOrderByClause(StringBuilder sb)
+		{
+			if (SqlQuery.OrderBy.Items.Count == 0 && SqlQuery.Select.SkipValue != null)
+			{
+				AppendIndent(sb);
+
+				sb.Append("ORDER BY").AppendLine();
+
+				Indent++;
+
+				AppendIndent(sb);
+
+				BuildExpression(sb, SqlQuery.Select.Columns[0].Expression);
+				sb.AppendLine();
+
+				Indent--;
+			}
+			else
+				base.BuildOrderByClause(sb);
+		}
+
+		protected override void BuildColumnExpression(StringBuilder sb, ISqlExpression expr, string alias, ref bool addAlias)
+		{
+			var wrap = false;
+
+			if (expr.SystemType == typeof(bool))
+			{
+				if (expr is SqlQuery.SearchCondition)
+					wrap = true;
+				else
+				{
+					var ex = expr as SqlExpression;
+					wrap = ex != null && ex.Expr == "{0}" && ex.Parameters.Length == 1 && ex.Parameters[0] is SqlQuery.SearchCondition;
+				}
+			}
+
+			if (wrap) sb.Append("CASE WHEN ");
+			base.BuildColumnExpression(sb, expr, alias, ref addAlias);
+			if (wrap) sb.Append(" THEN 1 ELSE 0 END");
+		}
+
+		public override object Convert(object value, ConvertType convertType)
+		{
+			switch (convertType)
+			{
+				case ConvertType.NameToQueryParameter:
+				case ConvertType.NameToCommandParameter:
+				case ConvertType.NameToSprocParameter:
+					return "@" + value;
+
+				case ConvertType.NameToQueryField:
+				case ConvertType.NameToQueryFieldAlias:
+				case ConvertType.NameToQueryTableAlias:
+					{
+						var name = value.ToString();
+
+						if (name.Length > 0 && name[0] == '[')
+							return value;
+					}
+
+					return "[" + value + "]";
+
+				case ConvertType.NameToDatabase:
+				case ConvertType.NameToOwner:
+				case ConvertType.NameToQueryTable:
+					{
+						var name = value.ToString();
+
+						if (name.Length > 0 && name[0] == '[')
+							return value;
+
+						if (name.IndexOf('.') > 0)
+							value = string.Join("].[", name.Split('.'));
+					}
+
+					return "[" + value + "]";
+
+				case ConvertType.SprocParameterToName:
+					if (value != null)
+					{
+						var str = value.ToString();
+						return str.Length > 0 && str[0] == '@'? str.Substring(1): str;
+					}
+					break;
+			}
+
+			return value;
+		}
+	}
+}