Mercurial > pub > bltoolkit
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; + } + } +}