diff Source/Data/Sql/SqlProvider/InformixSqlProvider.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/InformixSqlProvider.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,274 @@
+using System;
+using System.Data;
+using System.Text;
+
+namespace BLToolkit.Data.Sql.SqlProvider
+{
+	using DataProvider;
+	using Reflection;
+
+	public class InformixSqlProvider : 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 DBINFO('sqlca.sqlerrd1') FROM systables where tabid = 1");
+		}
+
+		protected override ISqlProvider CreateSqlProvider()
+		{
+			return new InformixSqlProvider();
+		}
+
+		public override int BuildSql(int commandNumber, SqlQuery sqlQuery, StringBuilder sb, int indent, int nesting, bool skipAlias)
+		{
+			var n = base.BuildSql(commandNumber, sqlQuery, sb, indent, nesting, skipAlias);
+
+			sb
+				.Replace("NULL IS NOT NULL", "1=0")
+				.Replace("NULL IS NULL",     "1=1");
+
+			return n;
+		}
+
+		protected override void BuildSelectClause(StringBuilder sb)
+		{
+			if (SqlQuery.From.Tables.Count == 0)
+			{
+				AppendIndent(sb).Append("SELECT FIRST 1").AppendLine();
+				BuildColumns(sb);
+				AppendIndent(sb).Append("FROM SYSTABLES").AppendLine();
+			}
+			else
+				base.BuildSelectClause(sb);
+		}
+
+		public override bool IsSubQueryTakeSupported      { get { return false; } }
+		public override bool IsInsertOrUpdateSupported    { get { return false; } }
+		public override bool IsGroupByExpressionSupported { get { return false; } }
+
+		protected override string FirstFormat { get { return "FIRST {0}"; } }
+		protected override string SkipFormat  { get { return "SKIP {0}";  } }
+
+		protected override void BuildLikePredicate(StringBuilder sb, SqlQuery.Predicate.Like predicate)
+		{
+			if (predicate.IsNot)
+				sb.Append("NOT ");
+
+			var precedence = GetPrecedence(predicate);
+
+			BuildExpression(sb, precedence, predicate.Expr1);
+			sb.Append(" LIKE ");
+			BuildExpression(sb, precedence, predicate.Expr2);
+
+			if (predicate.Escape != null)
+			{
+				sb.Append(" ESCAPE ");
+				BuildExpression(sb, precedence, predicate.Escape);
+			}
+		}
+
+		public override ISqlExpression ConvertExpression(ISqlExpression expr)
+		{
+			expr = base.ConvertExpression(expr);
+
+			if (expr is SqlBinaryExpression)
+			{
+				var be = (SqlBinaryExpression)expr;
+
+				switch (be.Operation)
+				{
+					case "%": return new SqlFunction(be.SystemType, "Mod",    be.Expr1, be.Expr2);
+					case "&": return new SqlFunction(be.SystemType, "BitAnd", be.Expr1, be.Expr2);
+					case "|": return new SqlFunction(be.SystemType, "BitOr",  be.Expr1, be.Expr2);
+					case "^": return new SqlFunction(be.SystemType, "BitXor", be.Expr1, be.Expr2);
+					case "+": return be.SystemType == typeof(string)? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence): expr;
+				}
+			}
+			else if (expr is SqlFunction)
+			{
+				var func = (SqlFunction)expr;
+
+				switch (func.Name)
+				{
+					case "Coalesce" : return new SqlFunction(func.SystemType, "Nvl", func.Parameters);
+					case "Convert"  :
+						{
+							var par0 = func.Parameters[0];
+							var par1 = func.Parameters[1];
+
+							switch (Type.GetTypeCode(TypeHelper.GetUnderlyingType(func.SystemType)))
+							{
+								case TypeCode.String   : return new SqlFunction(func.SystemType, "To_Char", func.Parameters[1]);
+								case TypeCode.Boolean  :
+									{
+										var ex = AlternativeConvertToBoolean(func, 1);
+										if (ex != null)
+											return ex;
+										break;
+									}
+
+								case TypeCode.UInt64:
+									if (TypeHelper.IsFloatType(func.Parameters[1].SystemType))
+										par1 = new SqlFunction(func.SystemType, "Floor", func.Parameters[1]);
+									break;
+
+								case TypeCode.DateTime :
+									if (IsDateDataType(func.Parameters[0], "Date"))
+									{
+										if (func.Parameters[1].SystemType == typeof(string))
+										{
+											return new SqlFunction(
+												func.SystemType,
+												"Date",
+												new SqlFunction(func.SystemType, "To_Date", func.Parameters[1], new SqlValue("%Y-%m-%d")));
+										}
+
+										return new SqlFunction(func.SystemType, "Date", func.Parameters[1]);
+									}
+
+									if (IsTimeDataType(func.Parameters[0]))
+										return new SqlExpression(func.SystemType, "Cast(Extend({0}, hour to second) as Char(8))", Precedence.Primary, func.Parameters[1]);
+
+									return new SqlFunction(func.SystemType, "To_Date", func.Parameters[1]);
+
+								default:
+									if (TypeHelper.GetUnderlyingType(func.SystemType) == typeof(DateTimeOffset))
+										goto case TypeCode.DateTime;
+									break;
+							}
+
+							return new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, par1, par0);
+						}
+
+					case "Quarter"  : return Inc(Div(Dec(new SqlFunction(func.SystemType, "Month", func.Parameters)), 3));
+					case "WeekDay"  : return Inc(new SqlFunction(func.SystemType, "weekDay", func.Parameters));
+					case "DayOfYear":
+						return
+							Inc(Sub<int>(
+								new SqlFunction(null, "Mdy",
+									new SqlFunction(null, "Month", func.Parameters),
+									new SqlFunction(null, "Day",   func.Parameters),
+									new SqlFunction(null, "Year",  func.Parameters)),
+								new SqlFunction(null, "Mdy",
+									new SqlValue(1),
+									new SqlValue(1),
+									new SqlFunction(null, "Year", func.Parameters))));
+					case "Week"     :
+						return
+							new SqlExpression(
+								func.SystemType,
+								"((Extend({0}, year to day) - (Mdy(12, 31 - WeekDay(Mdy(1, 1, year({0}))), Year({0}) - 1) + Interval(1) day to day)) / 7 + Interval(1) day to day)::char(10)::int",
+								func.Parameters);
+					case "Hour"     :
+					case "Minute"   :
+					case "Second"   : return new SqlExpression(func.SystemType, string.Format("({{0}}::datetime {0} to {0})::char(3)::int", func.Name), func.Parameters);
+				}
+			}
+
+			return expr;
+		}
+
+		protected override void BuildFunction(StringBuilder sb, SqlFunction func)
+		{
+			func = ConvertFunctionParameters(func);
+			base.BuildFunction(sb, func);
+		}
+
+		public virtual object ConvertBooleanValue(bool value)
+		{
+			return value ? 't' : 'f';
+		}
+
+		public override void BuildValue(StringBuilder sb, object value)
+		{
+			if (value is bool || value is bool?)
+				sb.Append("'").Append(ConvertBooleanValue((bool)value)).Append("'");
+			else
+				base.BuildValue(sb, value);
+		}
+
+		protected override void BuildDataType(StringBuilder sb, SqlDataType type)
+		{
+			switch (type.SqlDbType)
+			{
+				case SqlDbType.TinyInt    : sb.Append("SmallInt");        break;
+				case SqlDbType.SmallMoney : sb.Append("Decimal(10,4)");   break;
+				default                   : base.BuildDataType(sb, type); break;
+			}
+		}
+
+		static void SetQueryParameter(IQueryElement element)
+		{
+			if (element.ElementType == QueryElementType.SqlParameter)
+				((SqlParameter)element).IsQueryParameter = false;
+		}
+
+		public override SqlQuery Finalize(SqlQuery sqlQuery)
+		{
+			CheckAliases(sqlQuery, int.MaxValue);
+
+			new QueryVisitor().Visit(sqlQuery.Select, SetQueryParameter);
+
+			//if (sqlQuery.QueryType == QueryType.InsertOrUpdate)
+			//{
+			//	foreach (var key in sqlQuery.Insert.Items)
+			//		new QueryVisitor().Visit(key.Expression, SetQueryParameter);
+			//
+			//	foreach (var key in sqlQuery.Update.Items)
+			//		new QueryVisitor().Visit(key.Expression, SetQueryParameter);
+			//}
+
+			sqlQuery = base.Finalize(sqlQuery);
+
+			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 BuildFromClause(StringBuilder sb)
+		{
+			if (!SqlQuery.IsUpdate)
+				base.BuildFromClause(sb);
+		}
+
+		public override object Convert(object value, ConvertType convertType)
+		{
+			switch (convertType)
+			{
+				case ConvertType.NameToQueryParameter   : return "?";
+				case ConvertType.NameToCommandParameter :
+				case ConvertType.NameToSprocParameter   : 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;
+		}
+
+		//protected override void BuildInsertOrUpdateQuery(StringBuilder sb)
+		//{
+		//	BuildInsertOrUpdateQueryAsMerge(sb, "FROM SYSTABLES");
+		//}
+	}
+}