diff Source/Data/Sql/SqlProvider/MySqlSqlProvider.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/MySqlSqlProvider.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,348 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Text;
+
+namespace BLToolkit.Data.Sql.SqlProvider
+{
+	using DataProvider;
+	using Reflection;
+
+	public class MySqlSqlProvider : BasicSqlProvider
+	{
+		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 LAST_INSERT_ID()");
+		}
+
+		protected override ISqlProvider CreateSqlProvider()
+		{
+			return new MySqlSqlProvider();
+		}
+
+		protected override string LimitFormat { get { return "LIMIT {0}"; } }
+
+		public override bool IsNestedJoinParenthesisRequired { get { return true; } }
+
+		protected override void BuildOffsetLimit(StringBuilder sb)
+		{
+			if (SqlQuery.Select.SkipValue == null)
+				base.BuildOffsetLimit(sb);
+			else
+			{
+				AppendIndent(sb)
+					.AppendFormat(
+						"LIMIT {0},{1}",
+						BuildExpression(new StringBuilder(), SqlQuery.Select.SkipValue),
+						SqlQuery.Select.TakeValue == null ?
+							long.MaxValue.ToString() :
+							BuildExpression(new StringBuilder(), SqlQuery.Select.TakeValue).ToString())
+					.AppendLine();
+			}
+		}
+
+		public override ISqlExpression ConvertExpression(ISqlExpression expr)
+		{
+			expr = base.ConvertExpression(expr);
+
+			if (expr is SqlBinaryExpression)
+			{
+				var be = (SqlBinaryExpression)expr;
+
+				switch (be.Operation)
+				{
+					case "+":
+						if (be.SystemType == typeof(string))
+						{
+							if (be.Expr1 is SqlFunction)
+							{
+								var func = (SqlFunction)be.Expr1;
+
+								if (func.Name == "Concat")
+								{
+									var list = new List<ISqlExpression>(func.Parameters) { be.Expr2 };
+									return new SqlFunction(be.SystemType, "Concat", list.ToArray());
+								}
+							}
+
+							return new SqlFunction(be.SystemType, "Concat", be.Expr1, be.Expr2);
+						}
+
+						break;
+				}
+			}
+			else if (expr is SqlFunction)
+			{
+				var func = (SqlFunction) expr;
+
+				switch (func.Name)
+				{
+					case "Convert" :
+						var ftype = TypeHelper.GetUnderlyingType(func.SystemType);
+
+						if (ftype == typeof(bool))
+						{
+							var ex = AlternativeConvertToBoolean(func, 1);
+							if (ex != null)
+								return ex;
+						}
+
+						if ((ftype == typeof(double) || ftype == typeof(float)) && TypeHelper.GetUnderlyingType(func.Parameters[1].SystemType) == typeof(decimal))
+							return func.Parameters[1];
+
+						return new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, FloorBeforeConvert(func), func.Parameters[0]);
+				}
+			}
+			else if (expr is SqlExpression)
+			{
+				var e = (SqlExpression)expr;
+
+				if (e.Expr.StartsWith("Extract(DayOfYear"))
+					return new SqlFunction(e.SystemType, "DayOfYear", e.Parameters);
+
+				if (e.Expr.StartsWith("Extract(WeekDay"))
+					return Inc(
+						new SqlFunction(e.SystemType,
+							"WeekDay",
+							new SqlFunction(
+								null,
+								"Date_Add",
+								e.Parameters[0],
+								new SqlExpression(null, "interval 1 day"))));
+			}
+
+			return expr;
+		}
+
+		protected override void BuildDataType(StringBuilder sb, SqlDataType type)
+		{
+			switch (type.SqlDbType)
+			{
+				case SqlDbType.Int           :
+				case SqlDbType.SmallInt      : sb.Append("Signed");        break;
+				case SqlDbType.TinyInt       : sb.Append("Unsigned");      break;
+				case SqlDbType.Money         : sb.Append("Decimal(19,4)"); break;
+				case SqlDbType.SmallMoney    : sb.Append("Decimal(10,4)"); break;
+#if !MONO
+				case SqlDbType.DateTime2     :
+#endif
+				case SqlDbType.SmallDateTime : sb.Append("DateTime");      break;
+				case SqlDbType.Bit           : sb.Append("Boolean");       break;
+				case SqlDbType.Float         :
+				case SqlDbType.Real          : base.BuildDataType(sb, SqlDataType.Decimal); break;
+				case SqlDbType.VarChar       :
+				case SqlDbType.NVarChar      :
+					sb.Append("Char");
+					if (type.Length > 0)
+						sb.Append('(').Append(type.Length).Append(')');
+					break;
+				default: base.BuildDataType(sb, type); break;
+			}
+		}
+
+		protected override void BuildDeleteClause(StringBuilder sb)
+		{
+			var table = SqlQuery.Delete.Table != null ?
+				(SqlQuery.From.FindTableSource(SqlQuery.Delete.Table) ?? SqlQuery.Delete.Table) :
+				SqlQuery.From.Tables[0];
+
+			AppendIndent(sb)
+				.Append("DELETE ")
+				.Append(Convert(GetTableAlias(table), ConvertType.NameToQueryTableAlias))
+				.AppendLine();
+		}
+
+		protected override void BuildUpdateClause(StringBuilder sb)
+		{
+			base.BuildFromClause(sb);
+			sb.Remove(0, 4).Insert(0, "UPDATE");
+			base.BuildUpdateSet(sb);
+		}
+
+		protected override void BuildFromClause(StringBuilder sb)
+		{
+			if (!SqlQuery.IsUpdate)
+				base.BuildFromClause(sb);
+		}
+
+		public static char ParameterSymbol           { get; set; }
+		public static bool TryConvertParameterSymbol { get; set; }
+
+		private static string _commandParameterPrefix = "";
+		public  static string  CommandParameterPrefix
+		{
+			get { return _commandParameterPrefix; }
+			set { _commandParameterPrefix = string.IsNullOrEmpty(value) ? string.Empty : value; }
+		}
+
+		private static string _sprocParameterPrefix = "";
+		public  static string  SprocParameterPrefix
+		{
+			get { return _sprocParameterPrefix; }
+			set { _sprocParameterPrefix = string.IsNullOrEmpty(value) ? string.Empty : value; }
+		}
+
+		private static List<char> _convertParameterSymbols;
+		public  static List<char>  ConvertParameterSymbols
+		{
+			get { return _convertParameterSymbols; }
+			set { _convertParameterSymbols = value ?? new List<char>(); }
+		}
+
+		public override object Convert(object value, ConvertType convertType)
+		{
+			if (value == null)
+				throw new ArgumentNullException("value");
+
+			switch (convertType)
+			{
+				case ConvertType.NameToQueryParameter:
+					return ParameterSymbol + value.ToString();
+
+				case ConvertType.NameToCommandParameter:
+					return ParameterSymbol + CommandParameterPrefix + value;
+
+				case ConvertType.NameToSprocParameter:
+					{
+						var valueStr = value.ToString();
+
+						if(string.IsNullOrEmpty(valueStr))
+							throw new ArgumentException("Argument 'value' must represent parameter name.");
+
+						if (valueStr[0] == ParameterSymbol)
+							valueStr = valueStr.Substring(1);
+
+						if (valueStr.StartsWith(SprocParameterPrefix, StringComparison.Ordinal))
+							valueStr = valueStr.Substring(SprocParameterPrefix.Length);
+
+						return ParameterSymbol + SprocParameterPrefix + valueStr;
+					}
+
+				case ConvertType.SprocParameterToName:
+					{
+						var str = value.ToString();
+						str = (str.Length > 0 && (str[0] == ParameterSymbol || (TryConvertParameterSymbol && ConvertParameterSymbols.Contains(str[0])))) ? str.Substring(1) : str;
+
+						if (!string.IsNullOrEmpty(SprocParameterPrefix) && str.StartsWith(SprocParameterPrefix))
+							str = str.Substring(SprocParameterPrefix.Length);
+
+						return str;
+					}
+				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 + "`";
+
+			}
+
+			return value;
+		}
+
+		protected override StringBuilder BuildExpression(StringBuilder sb, ISqlExpression expr, bool buildTableName, bool checkParentheses, string alias, ref bool addAlias)
+		{
+			return base.BuildExpression(
+				sb,
+				expr,
+				buildTableName && SqlQuery.QueryType != QueryType.InsertOrUpdate,
+				checkParentheses,
+				alias,
+				ref addAlias);
+		}
+
+		protected override void BuildInsertOrUpdateQuery(StringBuilder sb)
+		{
+			BuildInsertQuery(sb);
+			AppendIndent(sb).AppendLine("ON DUPLICATE KEY UPDATE");
+
+			Indent++;
+
+			var first = true;
+
+			foreach (var expr in SqlQuery.Update.Items)
+			{
+				if (!first)
+					sb.Append(',').AppendLine();
+				first = false;
+
+				AppendIndent(sb);
+				BuildExpression(sb, expr.Column, false, true);
+				sb.Append(" = ");
+				BuildExpression(sb, expr.Expression, false, true);
+			}
+
+			Indent--;
+
+			sb.AppendLine();
+		}
+
+		protected override void BuildEmptyInsert(StringBuilder sb)
+		{
+			sb.AppendLine("() VALUES ()");
+		}
+
+		public static bool GenerateOldGuid = false;
+
+		public override void BuildValue(StringBuilder sb, object value)
+		{
+			if (GenerateOldGuid && value is Guid)
+			{
+				var bytes = ((Guid)value).ToByteArray();
+
+				sb.Append("X'").Append(ByteArrayToHex(bytes)).Append('\'');
+			}
+			else
+				base.BuildValue(sb, value);
+		}
+
+		static string ByteArrayToHex(byte[] barray)
+		{
+			var c = new char[barray.Length * 2];
+
+			for (var i = 0; i < barray.Length; ++i)
+			{
+				var b = ((byte)(barray[i] >> 4));
+
+				c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
+				b = ((byte)(barray[i] & 0xF));
+				c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
+			}
+
+			return new string(c);
+		}
+
+		protected override void BuildString(StringBuilder sb, string value)
+		{
+			base.BuildString(sb, value.Replace("\\", "\\\\"));
+		}
+
+		protected override void BuildChar(StringBuilder sb, char value)
+		{
+			if (value == '\\')
+				sb.Append("\\\\");
+			else
+				base.BuildChar(sb, value);
+		}
+	}
+}