示例#1
0
        protected override void BuildSql(StringBuilder sb)
        {
            if (NeedSkip)
            {
                AlternativeBuildSql2(sb, base.BuildSql);
                return;
            }

            if (SqlQuery.From.Tables.Count == 0 && SqlQuery.Select.Columns.Count == 1 && SqlQuery.Select.Columns[0].Expression is SqlFunction)
            {
                SqlFunction func = (SqlFunction)SqlQuery.Select.Columns[0].Expression;

                if (func.Name == "Iif" && func.Parameters.Length == 3 && func.Parameters[0] is SqlQuery.SearchCondition)
                {
                    SqlQuery.SearchCondition sc = (SqlQuery.SearchCondition)func.Parameters[0];

                    if (sc.Conditions.Count == 1 && sc.Conditions[0].Predicate is SqlQuery.Predicate.FuncLike)
                    {
                        SqlQuery.Predicate.FuncLike p = (SqlQuery.Predicate.FuncLike)sc.Conditions[0].Predicate;

                        if (p.Function.Name == "EXISTS")
                        {
                            BuildAnyAsCount(sb);
                            return;
                        }
                    }
                }
            }

            base.BuildSql(sb);
        }
示例#2
0
        protected override void BuildFunction(StringBuilder sb, SqlFunction func)
        {
            func = ConvertFunctionParameters(func);

            switch (func.Name)
            {
            case "CASE": func = ConvertCase(func.SystemType, func.Parameters, 0); break;

            case "Coalesce":

                if (func.Parameters.Length > 2)
                {
                    var parms = new ISqlExpression[func.Parameters.Length - 1];

                    Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
                    BuildFunction(sb, new SqlFunction(func.SystemType, func.Name, func.Parameters[0],
                                                      new SqlFunction(func.SystemType, func.Name, parms)));
                    return;
                }

                var sc = new SqlQuery.SearchCondition();

                sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

                func = new SqlFunction(func.SystemType, "IIF", sc, func.Parameters[1], func.Parameters[0]);

                break;
            }

            base.BuildFunction(sb, func);
        }
        protected override void BuildFunction(StringBuilder sb, SqlFunction func)
        {
            func = ConvertFunctionParameters(func);

            switch (func.Name)
            {
                case "CASE"     : func = ConvertCase(func.SystemType, func.Parameters, 0); break;
                case "Coalesce" :

                    if (func.Parameters.Length > 2)
                    {
                        var parms = new ISqlExpression[func.Parameters.Length - 1];

                        Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
                        BuildFunction(sb, new SqlFunction(func.SystemType, func.Name, func.Parameters[0],
                                          new SqlFunction(func.SystemType, func.Name, parms)));
                        return;
                    }

                    var sc = new SqlQuery.SearchCondition();

                    sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

                    func = new SqlFunction(func.SystemType, "IIF", sc, func.Parameters[1], func.Parameters[0]);

                    break;
            }

            base.BuildFunction(sb, func);
        }
示例#4
0
        void BuildAnyAsCount(StringBuilder sb)
        {
            SqlFunction func = (SqlFunction)SqlQuery.Select.Columns[0].Expression;

            SqlQuery.SearchCondition cond = (SqlQuery.SearchCondition)func.Parameters[0];
            SqlFunction exist             = ((SqlQuery.Predicate.FuncLike)cond.Conditions[0].Predicate).Function;
            SqlQuery    query             = (SqlQuery)exist.Parameters[0];

            _selectColumn = new SqlQuery.Column(SqlQuery, new SqlExpression(cond.Conditions[0].IsNot ? "Count(*) = 0" : "Count(*) > 0"), SqlQuery.Select.Columns[0].Alias);

            BuildSql(0, query, sb, 0, 0, false);

            _selectColumn = null;
        }
示例#5
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
            {
                sequence = new SubQueryContext(sequence);
            }

            var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var order  = new PathThroughContext(sequence, lambda);
            var body   = lambda.Body.Unwrap();
            var sql    = parser.ParseExpressions(order, body, ConvertFlags.Key);

            if (!methodCall.Method.Name.StartsWith("Then"))
            {
                sequence.SqlQuery.OrderBy.Items.Clear();
            }

            foreach (var expr in sql)
            {
                var e = expr.Sql;

                if (e is SqlQuery.SearchCondition)
                {
                    if (e.CanBeNull())
                    {
                        var notExpr = new SqlQuery.SearchCondition
                        {
                            Conditions = { new SqlQuery.Condition(true, new SqlQuery.Predicate.Expr(e, e.Precedence)) }
                        };

                        e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), notExpr, new SqlValue(0), new SqlValue(null)));
                    }
                    else
                    {
                        e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), new SqlValue(0)));
                    }
                }

                sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
            }

            return(sequence);
        }
示例#6
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

			if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
				sequence = new SubQueryContext(sequence);

			var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var order  = new PathThroughContext(sequence, lambda);
			var body   = lambda.Body.Unwrap();
			var sql    = parser.ParseExpressions(order, body, ConvertFlags.Key);

			if (!methodCall.Method.Name.StartsWith("Then"))
				sequence.SqlQuery.OrderBy.Items.Clear();

			foreach (var expr in sql)
			{
				var e = expr.Sql;

				if (e is SqlQuery.SearchCondition)
				{
					if (e.CanBeNull())
					{
						var notExpr = new SqlQuery.SearchCondition
						{
							Conditions = { new SqlQuery.Condition(true, new SqlQuery.Predicate.Expr(e, e.Precedence)) }
						};

						e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), notExpr, new SqlValue(0), new SqlValue(null)));
					}
					else
						e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), new SqlValue(0)));
				}

				sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
			}

			return sequence;
		}
		static SqlFunction ConvertCase(Type systemType, ISqlExpression[] parameters, int start)
		{
			var len  = parameters.Length - start;
			var name = start == 0 ? "IIF" : "CASE";
			var cond = parameters[start];

			if (start == 0 && SqlExpression.NeedsEqual(cond))
			{
				cond = new SqlQuery.SearchCondition(
					new SqlQuery.Condition(
						false,
						new SqlQuery.Predicate.ExprExpr(cond, SqlQuery.Predicate.Operator.Equal, new SqlValue(1))));
			}

			if (len == 3)
				return new SqlFunction(systemType, name, cond, parameters[start + 1], parameters[start + 2]);

			return new SqlFunction(systemType, name,
				cond,
				parameters[start + 1],
				ConvertCase(systemType, parameters, start + 2));
		}
示例#8
0
        protected override void BuildWhereSearchCondition(StringBuilder sb, SqlQuery.SearchCondition condition)
        {
            if (NeedTake && !NeedSkip && SqlQuery.OrderBy.IsEmpty && SqlQuery.Having.IsEmpty)
            {
                BuildPredicate(
                    sb,
                    Precedence.LogicalConjunction,
                    new SqlQuery.Predicate.ExprExpr(
                        new SqlExpression(null, "ROWNUM", Precedence.Primary),
                        SqlQuery.Predicate.Operator.LessOrEqual,
                        SqlQuery.Select.TakeValue));

                if (base.BuildWhere())
                {
                    sb.Append(" AND ");
                    BuildSearchCondition(sb, Precedence.LogicalConjunction, condition);
                }
            }
            else
            {
                BuildSearchCondition(sb, Precedence.Unknown, condition);
            }
        }
示例#9
0
        static SqlFunction ConvertCase(Type systemType, ISqlExpression[] parameters, int start)
        {
            var len  = parameters.Length - start;
            var name = start == 0 ? "IIF" : "CASE";
            var cond = parameters[start];

            if (start == 0 && SqlExpression.NeedsEqual(cond))
            {
                cond = new SqlQuery.SearchCondition(
                    new SqlQuery.Condition(
                        false,
                        new SqlQuery.Predicate.ExprExpr(cond, SqlQuery.Predicate.Operator.Equal, new SqlValue(1))));
            }

            if (len == 3)
            {
                return(new SqlFunction(systemType, name, cond, parameters[start + 1], parameters[start + 2]));
            }

            return(new SqlFunction(systemType, name,
                                   cond,
                                   parameters[start + 1],
                                   ConvertCase(systemType, parameters, start + 2)));
        }
示例#10
0
        public override ISqlExpression ConvertExpression(ISqlExpression expr)
        {
            expr = base.ConvertExpression(expr);

            if (expr is SqlBinaryExpression)
            {
                var be = (SqlBinaryExpression)expr;

                switch (be.Operation[0])
                {
                case '%': return(new SqlBinaryExpression(be.SystemType, be.Expr1, "MOD", be.Expr2, Precedence.Additive - 1));

                case '&':
                case '|':
                case '^': throw new SqlException("Operator '{0}' is not supported by the {1}.", be.Operation, GetType().Name);
                }
            }
            else if (expr is SqlFunction)
            {
                var func = (SqlFunction)expr;

                switch (func.Name)
                {
                case "Coalesce":

                    if (func.Parameters.Length > 2)
                    {
                        var parms = new ISqlExpression[func.Parameters.Length - 1];

                        Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
                        return(new SqlFunction(func.SystemType, func.Name, func.Parameters[0], new SqlFunction(func.SystemType, func.Name, parms)));
                    }

                    var sc = new SqlQuery.SearchCondition();

                    sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

                    return(new SqlFunction(func.SystemType, "Iif", sc, func.Parameters[1], func.Parameters[0]));

                case "CASE": return(ConvertCase(func.SystemType, func.Parameters, 0));

                case "CharIndex":
                    return(func.Parameters.Length == 2?
                           new SqlFunction(func.SystemType, "InStr", new SqlValue(1), func.Parameters[1], func.Parameters[0], new SqlValue(1)):
                           new SqlFunction(func.SystemType, "InStr", func.Parameters[2], func.Parameters[1], func.Parameters[0], new SqlValue(1)));

                case "Convert":
                {
                    switch (Type.GetTypeCode(TypeHelper.GetUnderlyingType(func.SystemType)))
                    {
                    case TypeCode.String: return(new SqlFunction(func.SystemType, "CStr", func.Parameters[1]));

                    case TypeCode.DateTime:
                        if (IsDateDataType(func.Parameters[0], "Date"))
                        {
                            return(new SqlFunction(func.SystemType, "DateValue", func.Parameters[1]));
                        }

                        if (IsTimeDataType(func.Parameters[0]))
                        {
                            return(new SqlFunction(func.SystemType, "TimeValue", func.Parameters[1]));
                        }

                        return(new SqlFunction(func.SystemType, "CDate", func.Parameters[1]));

                    default:
                        if (func.SystemType == typeof(DateTime))
                        {
                            goto case TypeCode.DateTime;
                        }
                        break;
                    }

                    return(func.Parameters[1]);
                }

                    /*
                     * case "Convert"   :
                     * {
                     *      string name = null;
                     *
                     *      switch (((SqlDataType)func.Parameters[0]).DbType)
                     *      {
                     *              case SqlDbType.BigInt           : name = "CLng"; break;
                     *              case SqlDbType.TinyInt          : name = "CByte"; break;
                     *              case SqlDbType.Int              :
                     *              case SqlDbType.SmallInt         : name = "CInt"; break;
                     *              case SqlDbType.Bit              : name = "CBool"; break;
                     *              case SqlDbType.Char             :
                     *              case SqlDbType.Text             :
                     *              case SqlDbType.VarChar          :
                     *              case SqlDbType.NChar            :
                     *              case SqlDbType.NText            :
                     *              case SqlDbType.NVarChar         : name = "CStr"; break;
                     *              case SqlDbType.DateTime         :
                     *              case SqlDbType.Date             :
                     *              case SqlDbType.Time             :
                     *              case SqlDbType.DateTime2        :
                     *              case SqlDbType.SmallDateTime    :
                     *              case SqlDbType.DateTimeOffset   : name = "CDate"; break;
                     *              case SqlDbType.Decimal          : name = "CDec"; break;
                     *              case SqlDbType.Float            : name = "CDbl"; break;
                     *              case SqlDbType.Money            :
                     *              case SqlDbType.SmallMoney       : name = "CCur"; break;
                     *              case SqlDbType.Real             : name = "CSng"; break;
                     *              case SqlDbType.Image            :
                     *              case SqlDbType.Binary           :
                     *              case SqlDbType.UniqueIdentifier :
                     *              case SqlDbType.Timestamp        :
                     *              case SqlDbType.VarBinary        :
                     *              case SqlDbType.Variant          :
                     *              case SqlDbType.Xml              :
                     *              case SqlDbType.Udt              :
                     *              case SqlDbType.Structured       : name = "CVar"; break;
                     *      }
                     *
                     *      return new SqlFunction(name, func.Parameters[1]);
                     * }
                     */
                }
            }

            return(expr);
        }
示例#11
0
		public override ISqlExpression ConvertExpression(ISqlExpression expr)
		{
			expr = base.ConvertExpression(expr);

			if (expr is SqlBinaryExpression)
			{
				var be = (SqlBinaryExpression)expr;

				switch (be.Operation[0])
				{
					case '%': return new SqlBinaryExpression(be.SystemType, be.Expr1, "MOD", be.Expr2, Precedence.Additive - 1);
					case '&':
					case '|':
					case '^': throw new SqlException("Operator '{0}' is not supported by the {1}.", be.Operation, GetType().Name);
				}
			}
			else if (expr is SqlFunction)
			{
				var func = (SqlFunction) expr;

				switch (func.Name)
				{
					case "Coalesce":

						if (func.Parameters.Length > 2)
						{
							var parms = new ISqlExpression[func.Parameters.Length - 1];

							Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
							return new SqlFunction(func.SystemType, func.Name, func.Parameters[0], new SqlFunction(func.SystemType, func.Name, parms));
						}

						var sc = new SqlQuery.SearchCondition();

						sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

						return new SqlFunction(func.SystemType, "Iif", sc, func.Parameters[1], func.Parameters[0]);

					case "CASE"      : return ConvertCase(func.SystemType, func.Parameters, 0);
					case "CharIndex" :
						return func.Parameters.Length == 2?
							new SqlFunction(func.SystemType, "InStr", new SqlValue(1),    func.Parameters[1], func.Parameters[0], new SqlValue(1)):
							new SqlFunction(func.SystemType, "InStr", func.Parameters[2], func.Parameters[1], func.Parameters[0], new SqlValue(1));

					case "Convert"   : 
						{
							switch (Type.GetTypeCode(TypeHelper.GetUnderlyingType(func.SystemType)))
							{
								case TypeCode.String   : return new SqlFunction(func.SystemType, "CStr",  func.Parameters[1]);
								case TypeCode.DateTime :
									if (IsDateDataType(func.Parameters[0], "Date"))
										return new SqlFunction(func.SystemType, "DateValue", func.Parameters[1]);

									if (IsTimeDataType(func.Parameters[0]))
										return new SqlFunction(func.SystemType, "TimeValue", func.Parameters[1]);

									return new SqlFunction(func.SystemType, "CDate", func.Parameters[1]);

								default:
									if (func.SystemType == typeof(DateTime))
										goto case TypeCode.DateTime;
									break;
							}

							return func.Parameters[1];
						}

						/*
					case "Convert"   :
						{
							string name = null;

							switch (((SqlDataType)func.Parameters[0]).DbType)
							{
								case SqlDbType.BigInt           : name = "CLng"; break;
								case SqlDbType.TinyInt          : name = "CByte"; break;
								case SqlDbType.Int              :
								case SqlDbType.SmallInt         : name = "CInt"; break;
								case SqlDbType.Bit              : name = "CBool"; break;
								case SqlDbType.Char             :
								case SqlDbType.Text             :
								case SqlDbType.VarChar          :
								case SqlDbType.NChar            :
								case SqlDbType.NText            :
								case SqlDbType.NVarChar         : name = "CStr"; break;
								case SqlDbType.DateTime         :
								case SqlDbType.Date             :
								case SqlDbType.Time             :
								case SqlDbType.DateTime2        :
								case SqlDbType.SmallDateTime    :
								case SqlDbType.DateTimeOffset   : name = "CDate"; break;
								case SqlDbType.Decimal          : name = "CDec"; break;
								case SqlDbType.Float            : name = "CDbl"; break;
								case SqlDbType.Money            :
								case SqlDbType.SmallMoney       : name = "CCur"; break;
								case SqlDbType.Real             : name = "CSng"; break;
								case SqlDbType.Image            :
								case SqlDbType.Binary           :
								case SqlDbType.UniqueIdentifier :
								case SqlDbType.Timestamp        :
								case SqlDbType.VarBinary        :
								case SqlDbType.Variant          :
								case SqlDbType.Xml              :
								case SqlDbType.Udt              :
								case SqlDbType.Structured       : name = "CVar"; break;
							}

							return new SqlFunction(name, func.Parameters[1]);
						}
						*/
				}
			}

			return expr;
		}
示例#12
0
        IQueryElement ConvertInternal(IQueryElement element, ConvertFunc action)
        {
            if (element == null)
            {
                return(null);
            }

            IQueryElement newElement;

            if (_visitedElements.TryGetValue(element, out newElement))
            {
                return(newElement);
            }

            switch (element.ElementType)
            {
            case QueryElementType.SqlFunction:
            {
                var func  = (SqlFunction)element;
                var parms = Convert(func.Parameters, action);

                if (parms != null && !ReferenceEquals(parms, func.Parameters))
                {
                    newElement = new SqlFunction(func.SystemType, func.Name, func.Precedence, parms);
                }

                break;
            }

            case QueryElementType.SqlExpression:
            {
                var expr      = (SqlExpression)element;
                var parameter = Convert(expr.Parameters, action);

                if (parameter != null && !ReferenceEquals(parameter, expr.Parameters))
                {
                    newElement = new SqlExpression(expr.SystemType, expr.Expr, expr.Precedence, parameter);
                }

                break;
            }

            case QueryElementType.SqlBinaryExpression:
            {
                var bexpr = (SqlBinaryExpression)element;
                var expr1 = (ISqlExpression)ConvertInternal(bexpr.Expr1, action);
                var expr2 = (ISqlExpression)ConvertInternal(bexpr.Expr2, action);

                if (expr1 != null && !ReferenceEquals(expr1, bexpr.Expr1) ||
                    expr2 != null && !ReferenceEquals(expr2, bexpr.Expr2))
                {
                    newElement = new SqlBinaryExpression(bexpr.SystemType, expr1 ?? bexpr.Expr1, bexpr.Operation, expr2 ?? bexpr.Expr2, bexpr.Precedence);
                }

                break;
            }

            case QueryElementType.SqlTable:
            {
                var table   = (SqlTable)element;
                var fields1 = ToArray(table.Fields);
                var fields2 = Convert(fields1, action, f => new SqlField(f));
                var joins   = Convert(table.Joins, action, j => j.Clone());
                var targs   = table.TableArguments == null ? null : Convert(table.TableArguments, action);

                var fe = fields2 == null || ReferenceEquals(fields1, fields2);
                var je = joins == null || ReferenceEquals(table.Joins, joins);
                var ta = ReferenceEquals(table.TableArguments, targs);

                if (!fe || !je || !ta)
                {
                    if (fe)
                    {
                        fields2 = fields1;

                        for (var i = 0; i < fields2.Length; i++)
                        {
                            var field = fields2[i];

                            fields2[i] = new SqlField(field);

                            _visitedElements[field] = fields2[i];
                        }
                    }

                    newElement = new SqlTable(table, fields2, joins ?? table.Joins, targs ?? table.TableArguments);

                    _visitedElements[((SqlTable)newElement).All] = table.All;
                }

                break;
            }

            case QueryElementType.Join:
            {
                var join = (Join)element;
                var ons  = Convert(join.JoinOns, action);

                if (ons != null && !ReferenceEquals(join.JoinOns, ons))
                {
                    newElement = new Join(join.TableName, join.Alias, ons);
                }

                break;
            }

            case QueryElementType.Column:
            {
                var col  = (SqlQuery.Column)element;
                var expr = (ISqlExpression)ConvertInternal(col.Expression, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(col.Parent, out parent);

                if (parent != null || expr != null && !ReferenceEquals(expr, col.Expression))
                {
                    newElement = new SqlQuery.Column(parent == null ? col.Parent : (SqlQuery)parent, expr ?? col.Expression, col._alias);
                }

                break;
            }

            case QueryElementType.TableSource:
            {
                var table  = (SqlQuery.TableSource)element;
                var source = (ISqlTableSource)ConvertInternal(table.Source, action);
                var joins  = Convert(table.Joins, action);

                if (source != null && !ReferenceEquals(source, table.Source) ||
                    joins != null && !ReferenceEquals(table.Joins, joins))
                {
                    newElement = new SqlQuery.TableSource(source ?? table.Source, table._alias, joins ?? table.Joins);
                }

                break;
            }

            case QueryElementType.JoinedTable:
            {
                var join  = (SqlQuery.JoinedTable)element;
                var table = (SqlQuery.TableSource)ConvertInternal(join.Table, action);
                var cond  = (SqlQuery.SearchCondition)ConvertInternal(join.Condition, action);

                if (table != null && !ReferenceEquals(table, join.Table) ||
                    cond != null && !ReferenceEquals(cond, join.Condition))
                {
                    newElement = new SqlQuery.JoinedTable(join.JoinType, table ?? join.Table, join.IsWeak, cond ?? join.Condition);
                }

                break;
            }

            case QueryElementType.SearchCondition:
            {
                var sc    = (SqlQuery.SearchCondition)element;
                var conds = Convert(sc.Conditions, action);

                if (conds != null && !ReferenceEquals(sc.Conditions, conds))
                {
                    newElement = new SqlQuery.SearchCondition(conds);
                }

                break;
            }

            case QueryElementType.Condition:
            {
                var c = (SqlQuery.Condition)element;
                var p = (ISqlPredicate)ConvertInternal(c.Predicate, action);

                if (p != null && !ReferenceEquals(c.Predicate, p))
                {
                    newElement = new SqlQuery.Condition(c.IsNot, p, c.IsOr);
                }

                break;
            }

            case QueryElementType.ExprPredicate:
            {
                var p = (SqlQuery.Predicate.Expr)element;
                var e = (ISqlExpression)ConvertInternal(p.Expr1, action);

                if (e != null && !ReferenceEquals(p.Expr1, e))
                {
                    newElement = new SqlQuery.Predicate.Expr(e, p.Precedence);
                }

                break;
            }

            case QueryElementType.NotExprPredicate:
            {
                var p = (SqlQuery.Predicate.NotExpr)element;
                var e = (ISqlExpression)ConvertInternal(p.Expr1, action);

                if (e != null && !ReferenceEquals(p.Expr1, e))
                {
                    newElement = new SqlQuery.Predicate.NotExpr(e, p.IsNot, p.Precedence);
                }

                break;
            }

            case QueryElementType.ExprExprPredicate:
            {
                var p  = (SqlQuery.Predicate.ExprExpr)element;
                var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
                var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);

                if (e1 != null && !ReferenceEquals(p.Expr1, e1) || e2 != null && !ReferenceEquals(p.Expr2, e2))
                {
                    newElement = new SqlQuery.Predicate.ExprExpr(e1 ?? p.Expr1, p.Operator, e2 ?? p.Expr2);
                }

                break;
            }

            case QueryElementType.LikePredicate:
            {
                var p  = (SqlQuery.Predicate.Like)element;
                var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
                var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);
                var es = (ISqlExpression)ConvertInternal(p.Escape, action);

                if (e1 != null && !ReferenceEquals(p.Expr1, e1) ||
                    e2 != null && !ReferenceEquals(p.Expr2, e2) ||
                    es != null && !ReferenceEquals(p.Escape, es))
                {
                    newElement = new SqlQuery.Predicate.Like(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, es ?? p.Escape);
                }

                break;
            }

            case QueryElementType.BetweenPredicate:
            {
                var p  = (SqlQuery.Predicate.Between)element;
                var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
                var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);
                var e3 = (ISqlExpression)ConvertInternal(p.Expr3, action);

                if (e1 != null && !ReferenceEquals(p.Expr1, e1) ||
                    e2 != null && !ReferenceEquals(p.Expr2, e2) ||
                    e3 != null && !ReferenceEquals(p.Expr3, e3))
                {
                    newElement = new SqlQuery.Predicate.Between(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, e3 ?? p.Expr3);
                }

                break;
            }

            case QueryElementType.IsNullPredicate:
            {
                var p = (SqlQuery.Predicate.IsNull)element;
                var e = (ISqlExpression)ConvertInternal(p.Expr1, action);

                if (e != null && !ReferenceEquals(p.Expr1, e))
                {
                    newElement = new SqlQuery.Predicate.IsNull(e, p.IsNot);
                }

                break;
            }

            case QueryElementType.InSubQueryPredicate:
            {
                var p = (SqlQuery.Predicate.InSubQuery)element;
                var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
                var q = (SqlQuery)ConvertInternal(p.SubQuery, action);

                if (e != null && !ReferenceEquals(p.Expr1, e) || q != null && !ReferenceEquals(p.SubQuery, q))
                {
                    newElement = new SqlQuery.Predicate.InSubQuery(e ?? p.Expr1, p.IsNot, q ?? p.SubQuery);
                }

                break;
            }

            case QueryElementType.InListPredicate:
            {
                var p = (SqlQuery.Predicate.InList)element;
                var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
                var v = Convert(p.Values, action);

                if (e != null && !ReferenceEquals(p.Expr1, e) || v != null && !ReferenceEquals(p.Values, v))
                {
                    newElement = new SqlQuery.Predicate.InList(e ?? p.Expr1, p.IsNot, v ?? p.Values);
                }

                break;
            }

            case QueryElementType.FuncLikePredicate:
            {
                var p = (SqlQuery.Predicate.FuncLike)element;
                var f = (SqlFunction)ConvertInternal(p.Function, action);

                if (f != null && !ReferenceEquals(p.Function, f))
                {
                    newElement = new SqlQuery.Predicate.FuncLike(f);
                }

                break;
            }

            case QueryElementType.SetExpression:
            {
                var s = (SqlQuery.SetExpression)element;
                var c = (ISqlExpression)ConvertInternal(s.Column, action);
                var e = (ISqlExpression)ConvertInternal(s.Expression, action);

                if (c != null && !ReferenceEquals(s.Column, c) || e != null && !ReferenceEquals(s.Expression, e))
                {
                    newElement = new SqlQuery.SetExpression(c ?? s.Column, e ?? s.Expression);
                }

                break;
            }

            case QueryElementType.SetClause:
            {
                var s = (SqlQuery.SetClause)element;
                var t = s.Into != null ? (SqlTable)ConvertInternal(s.Into, action) : null;
                var i = Convert(s.Items, action);

                if (t != null && !ReferenceEquals(s.Into, t) || i != null && !ReferenceEquals(s.Items, i))
                {
                    var sc = new SqlQuery.SetClause();
                    sc.Into = t ?? sc.Into;
                    sc.Items.AddRange(i ?? s.Items);
                    sc.WithIdentity = s.WithIdentity;

                    newElement = sc;
                }

                break;
            }

            case QueryElementType.SelectClause:
            {
                var sc   = (SqlQuery.SelectClause)element;
                var cols = Convert(sc.Columns, action);
                var take = (ISqlExpression)ConvertInternal(sc.TakeValue, action);
                var skip = (ISqlExpression)ConvertInternal(sc.SkipValue, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(sc.SqlQuery, out parent);

                if (parent != null ||
                    cols != null && !ReferenceEquals(sc.Columns, cols) ||
                    take != null && !ReferenceEquals(sc.TakeValue, take) ||
                    skip != null && !ReferenceEquals(sc.SkipValue, skip))
                {
                    newElement = new SqlQuery.SelectClause(sc.IsDistinct, take ?? sc.TakeValue, skip ?? sc.SkipValue, cols ?? sc.Columns);
                    ((SqlQuery.SelectClause)newElement).SetSqlQuery((SqlQuery)parent);
                }

                break;
            }

            case QueryElementType.FromClause:
            {
                var fc = (SqlQuery.FromClause)element;
                var ts = Convert(fc.Tables, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(fc.SqlQuery, out parent);

                if (parent != null || ts != null && !ReferenceEquals(fc.Tables, ts))
                {
                    newElement = new SqlQuery.FromClause(ts ?? fc.Tables);
                    ((SqlQuery.FromClause)newElement).SetSqlQuery((SqlQuery)parent);
                }

                break;
            }

            case QueryElementType.WhereClause:
            {
                var wc   = (SqlQuery.WhereClause)element;
                var cond = (SqlQuery.SearchCondition)ConvertInternal(wc.SearchCondition, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(wc.SqlQuery, out parent);

                if (parent != null || cond != null && !ReferenceEquals(wc.SearchCondition, cond))
                {
                    newElement = new SqlQuery.WhereClause(cond ?? wc.SearchCondition);
                    ((SqlQuery.WhereClause)newElement).SetSqlQuery((SqlQuery)parent);
                }

                break;
            }

            case QueryElementType.GroupByClause:
            {
                var gc = (SqlQuery.GroupByClause)element;
                var es = Convert(gc.Items, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(gc.SqlQuery, out parent);

                if (parent != null || es != null && !ReferenceEquals(gc.Items, es))
                {
                    newElement = new SqlQuery.GroupByClause(es ?? gc.Items);
                    ((SqlQuery.GroupByClause)newElement).SetSqlQuery((SqlQuery)parent);
                }

                break;
            }

            case QueryElementType.OrderByClause:
            {
                var oc = (SqlQuery.OrderByClause)element;
                var es = Convert(oc.Items, action);

                IQueryElement parent;
                _visitedElements.TryGetValue(oc.SqlQuery, out parent);

                if (parent != null || es != null && !ReferenceEquals(oc.Items, es))
                {
                    newElement = new SqlQuery.OrderByClause(es ?? oc.Items);
                    ((SqlQuery.OrderByClause)newElement).SetSqlQuery((SqlQuery)parent);
                }

                break;
            }

            case QueryElementType.OrderByItem:
            {
                var i = (SqlQuery.OrderByItem)element;
                var e = (ISqlExpression)ConvertInternal(i.Expression, action);

                if (e != null && !ReferenceEquals(i.Expression, e))
                {
                    newElement = new SqlQuery.OrderByItem(e, i.IsDescending);
                }

                break;
            }

            case QueryElementType.Union:
            {
                var u = (SqlQuery.Union)element;
                var q = (SqlQuery)ConvertInternal(u.SqlQuery, action);

                if (q != null && !ReferenceEquals(u.SqlQuery, q))
                {
                    newElement = new SqlQuery.Union(q, u.IsAll);
                }

                break;
            }

            case QueryElementType.SqlQuery:
            {
                var           q      = (SqlQuery)element;
                IQueryElement parent = null;

                var doConvert = q.ParentSql != null && !_visitedElements.TryGetValue(q.ParentSql, out parent);

                if (!doConvert)
                {
                    doConvert = null != Find(q, e =>
                        {
                            var ret = action(e);

                            if (ret != null && !ReferenceEquals(e, ret))
                            {
                                _visitedElements.Add(e, ret);
                                return(true);
                            }

                            return(false);
                        });
                }

                if (!doConvert)
                {
                    break;
                }

                var nq = new SqlQuery {
                    QueryType = q.QueryType
                };

                _visitedElements.Add(q, nq);

                var fc = (SqlQuery.FromClause)ConvertInternal(q.From, action) ?? q.From;
                var sc = (SqlQuery.SelectClause)ConvertInternal(q.Select, action) ?? q.Select;
                var tc = q.QueryType == QueryType.Update || q.QueryType == QueryType.Insert ? ((SqlQuery.SetClause)ConvertInternal(q.Set, action) ?? q.Set) : null;
                var wc = (SqlQuery.WhereClause)ConvertInternal(q.Where, action) ?? q.Where;
                var gc = (SqlQuery.GroupByClause)ConvertInternal(q.GroupBy, action) ?? q.GroupBy;
                var hc = (SqlQuery.WhereClause)ConvertInternal(q.Having, action) ?? q.Having;
                var oc = (SqlQuery.OrderByClause)ConvertInternal(q.OrderBy, action) ?? q.OrderBy;
                var us = q.HasUnion ? Convert(q.Unions, action) : q.Unions;

                var ps = new List <SqlParameter>(q.Parameters.Count);

                foreach (var p in q.Parameters)
                {
                    IQueryElement e;

                    if (_visitedElements.TryGetValue(p, out e))
                    {
                        if (e == null)
                        {
                            ps.Add(p);
                        }
                        else if (e is SqlParameter)
                        {
                            ps.Add((SqlParameter)e);
                        }
                    }
                }

                nq.Init(tc, sc, fc, wc, gc, hc, oc, us, (SqlQuery)parent, q.ParameterDependent, ps);

                _visitedElements[q] = action(nq) ?? nq;

                return(nq);
            }
            }

            newElement = newElement == null?action(element) : (action(newElement) ?? newElement);

            _visitedElements.Add(element, newElement);

            return(newElement);
        }
		public ISqlExpression ParseExpression(IParseContext context, Expression expression)
		{
			/*
			var qlen = queries.Length;

			if (expression.NodeType == ExpressionType.Parameter && qlen == 1 && queries[0] is QuerySource.Scalar)
			{
				var ma = (QuerySource.Scalar)queries[0];
				return ParseExpression(ma.Lambda, ma.Lambda.Body, ma.Sources);
			}
			*/

			if (CanBeConstant(expression))
				return BuildConstant(expression);

			if (CanBeCompiled(expression))
				return BuildParameter(expression).SqlParameter;

			if (IsSubQuery(context, expression))
				return ParseSubQuery(context, expression);

			switch (expression.NodeType)
			{
				case ExpressionType.AndAlso:
				case ExpressionType.OrElse:
				case ExpressionType.Not:
				case ExpressionType.Equal:
				case ExpressionType.NotEqual:
				case ExpressionType.GreaterThan:
				case ExpressionType.GreaterThanOrEqual:
				case ExpressionType.LessThan:
				case ExpressionType.LessThanOrEqual:
					{
						var condition = new SqlQuery.SearchCondition();
						ParseSearchCondition(context, expression, condition.Conditions);
						return condition;
					}

				case ExpressionType.Add:
				case ExpressionType.AddChecked:
				case ExpressionType.And:
				case ExpressionType.Divide:
				case ExpressionType.ExclusiveOr:
				case ExpressionType.Modulo:
				case ExpressionType.Multiply:
				case ExpressionType.MultiplyChecked:
				case ExpressionType.Or:
				case ExpressionType.Power:
				case ExpressionType.Subtract:
				case ExpressionType.SubtractChecked:
				case ExpressionType.Coalesce:
					{
						var e = (BinaryExpression)expression;
						var l = ParseExpression(context, e.Left);
						var r = ParseExpression(context, e.Right);
						var t = e.Type;

						switch (expression.NodeType)
						{
							case ExpressionType.Add             :
							case ExpressionType.AddChecked      : return Convert(context, new SqlBinaryExpression(t, l, "+", r, Precedence.Additive));
							case ExpressionType.And             : return Convert(context, new SqlBinaryExpression(t, l, "&", r, Precedence.Bitwise));
							case ExpressionType.Divide          : return Convert(context, new SqlBinaryExpression(t, l, "/", r, Precedence.Multiplicative));
							case ExpressionType.ExclusiveOr     : return Convert(context, new SqlBinaryExpression(t, l, "^", r, Precedence.Bitwise));
							case ExpressionType.Modulo          : return Convert(context, new SqlBinaryExpression(t, l, "%", r, Precedence.Multiplicative));
							case ExpressionType.Multiply:
							case ExpressionType.MultiplyChecked : return Convert(context, new SqlBinaryExpression(t, l, "*", r, Precedence.Multiplicative));
							case ExpressionType.Or              : return Convert(context, new SqlBinaryExpression(t, l, "|", r, Precedence.Bitwise));
							case ExpressionType.Power           : return Convert(context, new SqlFunction(t, "Power", l, r));
							case ExpressionType.Subtract        :
							case ExpressionType.SubtractChecked : return Convert(context, new SqlBinaryExpression(t, l, "-", r, Precedence.Subtraction));
							case ExpressionType.Coalesce        :
								{
									if (r is SqlFunction)
									{
										var c = (SqlFunction)r;

										if (c.Name == "Coalesce")
										{
											var parms = new ISqlExpression[c.Parameters.Length + 1];

											parms[0] = l;
											c.Parameters.CopyTo(parms, 1);

											return Convert(context, new SqlFunction(t, "Coalesce", parms));
										}
									}

									return Convert(context, new SqlFunction(t, "Coalesce", l, r));
								}
						}

						break;
					}

				case ExpressionType.UnaryPlus:
				case ExpressionType.Negate:
				case ExpressionType.NegateChecked:
					{
						var e = (UnaryExpression)expression;
						var o = ParseExpression(context, e.Operand);
						var t = e.Type;

						switch (expression.NodeType)
						{
							case ExpressionType.UnaryPlus     : return o;
							case ExpressionType.Negate        :
							case ExpressionType.NegateChecked :
								return Convert(context, new SqlBinaryExpression(t, new SqlValue(-1), "*", o, Precedence.Multiplicative));
						}

						break;
					}

				case ExpressionType.Convert        :
				case ExpressionType.ConvertChecked :
					{
						var e = (UnaryExpression)expression;
						var o = ParseExpression(context, e.Operand);

						if (e.Method == null && e.IsLifted)
							return o;

						if (e.Operand.Type.IsEnum && Enum.GetUnderlyingType(e.Operand.Type) == e.Type)
							return o;

						return Convert(
							context,
							new SqlFunction(e.Type, "$Convert$", SqlDataType.GetDataType(e.Type), SqlDataType.GetDataType(e.Operand.Type), o));
					}

				case ExpressionType.Conditional   :
					{
						var e = (ConditionalExpression)expression;
						var s = ParseExpression(context, e.Test);
						var t = ParseExpression(context, e.IfTrue);
						var f = ParseExpression(context, e.IfFalse);

						if (f is SqlFunction)
						{
							var c = (SqlFunction)f;

							if (c.Name == "CASE")
							{
								var parms = new ISqlExpression[c.Parameters.Length + 2];

								parms[0] = s;
								parms[1] = t;
								c.Parameters.CopyTo(parms, 2);

								return Convert(context, new SqlFunction(e.Type, "CASE", parms));
							}
						}

						return Convert(context, new SqlFunction(e.Type, "CASE", s, t, f));
					}

				case ExpressionType.MemberAccess:
					{
						var ma = (MemberExpression)expression;
						var l  = ConvertMember(ma.Member);

						if (l != null)
						{
							var ef  = l.Body.Unwrap();
							var pie = ef.Convert(wpi => wpi.NodeType == ExpressionType.Parameter ? ma.Expression : wpi);

							return ParseExpression(context, pie);
						}

						var attr = GetFunctionAttribute(ma.Member);

						if (attr != null)
							return Convert(context, attr.GetExpression(ma.Member));

						if (TypeHelper.IsNullableValueMember(ma.Member))
							return ParseExpression(context, ma.Expression);

						var de = ParseTimeSpanMember(context, ma);

						if (de != null)
							return de;

						var ctx = GetContext(context, expression);

						if (ctx != null)
						{
							var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);

							switch (sql.Length)
							{
								case 0  : break;
								case 1  : return sql[0].Sql;
								default : throw new InvalidOperationException();
							}
						}

						break;
					}

				case ExpressionType.Parameter:
					{
						var ctx = GetContext(context, expression);

						if (ctx != null)
						{
							var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);

							switch (sql.Length)
							{
								case 0  : break;
								case 1  : return sql[0].Sql;
								default : throw new InvalidOperationException();
							}
						}

						break;

						/*
						var sql = context.ConvertToSql(expression, 0, ConvertFlags.None).ToList();

						if (sql.Count != 0)
						{
							if (sql.Count == 1)
								return sql[0];

							throw new InvalidOperationException();
						}

						break;
						*/
					}

				case ExpressionType.Call:
					{
						var e = (MethodCallExpression)expression;

						if (e.Method.DeclaringType == typeof(Enumerable))
						{
							var ctx = GetContext(context, expression);

							if (ctx != null)
							{
								var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);

								if (sql.Length != 1)
									throw new InvalidOperationException();

								return sql[0].Sql;
							}

							return ParseEnumerable(context, e);
						}

						var cm = ConvertMethod(e);
						if (cm != null)
							return ParseExpression(context, cm);

						var attr = GetFunctionAttribute(e.Method);

						if (attr != null)
						{
							var parms = new List<ISqlExpression>();

							if (e.Object != null)
								parms.Add(ParseExpression(context, e.Object));

							parms.AddRange(e.Arguments.Select(t => ParseExpression(context, t)));

							return Convert(context, attr.GetExpression(e.Method, parms.ToArray()));
						}

						break;
					}

				case ExpressionType.New:
					{
						var pie = ConvertNew((NewExpression)expression);

						if (pie != null)
							return ParseExpression(context, pie);

						break;
					}

				case ExpressionType.Invoke:
					{
						var pi = (InvocationExpression)expression;
						var ex = pi.Expression;

						if (ex.NodeType == ExpressionType.Quote)
							ex = ((UnaryExpression)ex).Operand;

						//if (ex.NodeType == ExpressionType.MemberAccess)
						//	return ParseExpression(lambda, ex, queries);

						if (ex.NodeType == ExpressionType.Lambda)
						{
							var l   = (LambdaExpression)ex;
							var dic = new Dictionary<Expression,Expression>();

							for (var i = 0; i < l.Parameters.Count; i++)
								dic.Add(l.Parameters[i], pi.Arguments[i]);

							var pie = l.Body.Convert(wpi =>
							{
								Expression ppi;
								return dic.TryGetValue(wpi, out ppi) ? ppi : wpi;
							});

							return ParseExpression(context, pie);
						}

						break;
					}
			}

			throw new LinqException("'{0}' cannot be converted to SQL.", expression);
		}
		void ParseSearchCondition(IParseContext context, Expression expression, List<SqlQuery.Condition> conditions)
		{
			if (IsSubQuery(context, expression))
			{
				var cond = ParseConditionSubQuery(context, expression);

				if (cond != null)
				{
					conditions.Add(cond);
					return;
				}
			}

			switch (expression.NodeType)
			{
				case ExpressionType.AndAlso:
					{
						var e = (BinaryExpression)expression;

						ParseSearchCondition(context, e.Left,  conditions);
						ParseSearchCondition(context, e.Right, conditions);

						break;
					}

				case ExpressionType.OrElse:
					{
						var e           = (BinaryExpression)expression;
						var orCondition = new SqlQuery.SearchCondition();

						ParseSearchCondition(context, e.Left,  orCondition.Conditions);
						orCondition.Conditions[orCondition.Conditions.Count - 1].IsOr = true;
						ParseSearchCondition(context, e.Right, orCondition.Conditions);

						conditions.Add(new SqlQuery.Condition(false, orCondition));

						break;
					}

				case ExpressionType.Not:
					{
						var e            = expression as UnaryExpression;
						var notCondition = new SqlQuery.SearchCondition();

						ParseSearchCondition(context, e.Operand, notCondition.Conditions);

						if (notCondition.Conditions.Count == 1 && notCondition.Conditions[0].Predicate is SqlQuery.Predicate.NotExpr)
						{
							var p = notCondition.Conditions[0].Predicate as SqlQuery.Predicate.NotExpr;
							p.IsNot = !p.IsNot;
							conditions.Add(notCondition.Conditions[0]);
						}
						else
							conditions.Add(new SqlQuery.Condition(true, notCondition));

						break;
					}

				default:
					var predicate = ParsePredicate(context, expression);

					if (predicate is SqlQuery.Predicate.Expr)
					{
						var expr = ((SqlQuery.Predicate.Expr)predicate).Expr1;

						if (expr.ElementType == QueryElementType.SearchCondition)
						{
							var sc = (SqlQuery.SearchCondition)expr;

							if (sc.Conditions.Count == 1)
							{
								conditions.Add(sc.Conditions[0]);
								break;
							}
						}
					}

					conditions.Add(new SqlQuery.Condition(false, predicate));

					break;
			}
		}
		ISqlPredicate MakeIsPredicate(IParseContext context, QuerySource.Table table, Type typeOperand)
		{
			if (typeOperand == table.ObjectType && table.InheritanceMapping.Count(m => m.Type == typeOperand) == 0)
				return Convert(context, new SqlQuery.Predicate.Expr(new SqlValue(true)));

			var mapping = table.InheritanceMapping.Select((m,i) => new { m, i }).Where(m => m.m.Type == typeOperand && !m.m.IsDefault).ToList();

			switch (mapping.Count)
			{
				case 0:
					{
						var cond = new SqlQuery.SearchCondition();

						foreach (var m in table.InheritanceMapping.Select((m,i) => new { m, i }).Where(m => !m.m.IsDefault))
						{
							cond.Conditions.Add(
								new SqlQuery.Condition(
									false, 
									Convert(context,
										new SqlQuery.Predicate.ExprExpr(
											table.Columns[table.InheritanceDiscriminators[m.i]].Field,
											SqlQuery.Predicate.Operator.NotEqual,
											new SqlValue(m.m.Code)))));
						}

						return cond;
					}

				case 1:
					return Convert(context,
						new SqlQuery.Predicate.ExprExpr(
							table.Columns[table.InheritanceDiscriminators[mapping[0].i]].Field,
							SqlQuery.Predicate.Operator.Equal,
							new SqlValue(mapping[0].m.Code)));

				default:
					{
						var cond = new SqlQuery.SearchCondition();

						foreach (var m in mapping)
						{
							cond.Conditions.Add(
								new SqlQuery.Condition(
									false,
									Convert(context,
										new SqlQuery.Predicate.ExprExpr(
											table.Columns[table.InheritanceDiscriminators[m.i]].Field,
											SqlQuery.Predicate.Operator.Equal,
											new SqlValue(m.m.Code))),
									true));
						}

						return cond;
					}
			}
		}
		ISqlPredicate ParseNewObjectComparison(IParseContext context, ExpressionType nodeType, Expression left, Expression right)
		{
			left  = FindExpression(left);
			right = FindExpression(right);

			var condition = new SqlQuery.SearchCondition();

			if (left.NodeType != ExpressionType.New)
			{
				var temp = left;
				left  = right;
				right = temp;
			}

			var newRight = right as NewExpression;
			var newExpr  = (NewExpression)left;

			for (var i = 0; i < newExpr.Arguments.Count; i++)
			{
				var lex = ParseExpression(context, newExpr.Arguments[i]);
				var rex =
					newRight != null ?
						ParseExpression(context, newRight.Arguments[i]) :
						GetParameter(right, newExpr.Members[i]);

				var predicate = Convert(context,
					new SqlQuery.Predicate.ExprExpr(
						lex,
						nodeType == ExpressionType.Equal ? SqlQuery.Predicate.Operator.Equal : SqlQuery.Predicate.Operator.NotEqual,
						rex));

				condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
			}

			if (nodeType == ExpressionType.NotEqual)
				foreach (var c in condition.Conditions)
					c.IsOr = true;

			return condition;
		}
		public ISqlPredicate ParseObjectComparison(
			ExpressionType nodeType,
			IParseContext  leftContext,
			Expression     left,
			IParseContext  rightContext,
			Expression     right)
		{
			var qsl = GetContext(leftContext,  left);
			var qsr = GetContext(rightContext, right);

			var sl = qsl != null && qsl.IsExpression(left,  0, RequestFor.Object);
			var sr = qsr != null && qsr.IsExpression(right, 0, RequestFor.Object);

			if (sl == false && sr == false)
				return null;

			if (sl == false)
			{
				var r = right;
				right = left;
				left  = r;

				var c = rightContext;
				rightContext = leftContext;
				leftContext  = c;

				var q = qsr;
				//qsr = qsl;
				qsl = q;

				//sl = true;
				sr = false;
			}

			var isNull = right is ConstantExpression && ((ConstantExpression)right).Value == null;
			var lcols  = qsl.ConvertToSql(left, 0, ConvertFlags.Key);

			if (lcols.Length == 0)
				return null;

			var condition = new SqlQuery.SearchCondition();

			foreach (var lcol in lcols)
			{
				if (lcol.Member == null)
					throw new InvalidOperationException();

				ISqlExpression rcol = null;

				if (sr)
					rcol = rightContext.ConvertToSql(Expression.MakeMemberAccess(right, lcol.Member), 0, ConvertFlags.Field).Single().Sql;

				var rex =
					isNull ?
						new SqlValue(right.Type, null) :
						sr ?
							rcol :
							GetParameter(right, lcol.Member);

				var predicate = Convert(leftContext, new SqlQuery.Predicate.ExprExpr(
					lcol.Sql,
					nodeType == ExpressionType.Equal ? SqlQuery.Predicate.Operator.Equal : SqlQuery.Predicate.Operator.NotEqual,
					rex));

				condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
			}

			if (nodeType == ExpressionType.NotEqual)
				foreach (var c in condition.Conditions)
					c.IsOr = true;

			return condition;
		}
示例#18
0
        protected override void BuildFunction(StringBuilder sb, SqlFunction func)
        {
            switch (func.Name)
            {
                case "Coalesce"  :

                    if (func.Parameters.Length > 2)
                    {
                        var parms = new ISqlExpression[func.Parameters.Length - 1];

                        Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
                        BuildFunction(sb, new SqlFunction(func.SystemType, func.Name, func.Parameters[0],
                                          new SqlFunction(func.SystemType, func.Name, parms)));
                        return;
                    }

                    var sc = new SqlQuery.SearchCondition();

                    sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

                    func = new SqlFunction(func.SystemType, "Iif", sc, func.Parameters[1], func.Parameters[0]);

                    break;

                case "CASE"      : func = ConvertCase(func.SystemType, func.Parameters, 0); break;
                case "CharIndex" :
                    func = func.Parameters.Length == 2?
                        new SqlFunction(func.SystemType, "InStr", new SqlValue(1),    func.Parameters[1], func.Parameters[0], new SqlValue(1)):
                        new SqlFunction(func.SystemType, "InStr", func.Parameters[2], func.Parameters[1], func.Parameters[0], new SqlValue(1));
                    break;

                case "Convert"   :
                    switch (Type.GetTypeCode(func.SystemType.ToUnderlying()))
                    {
                        case TypeCode.String   : func = new SqlFunction(func.SystemType, "CStr",  func.Parameters[1]); break;
                        case TypeCode.DateTime :
                            if (IsDateDataType(func.Parameters[0], "Date"))
                                func = new SqlFunction(func.SystemType, "DateValue", func.Parameters[1]);
                            else if (IsTimeDataType(func.Parameters[0]))
                                func = new SqlFunction(func.SystemType, "TimeValue", func.Parameters[1]);
                            else
                                func = new SqlFunction(func.SystemType, "CDate", func.Parameters[1]);
                            break;

                        default:
                            if (func.SystemType == typeof(DateTime))
                                goto case TypeCode.DateTime;

                            BuildExpression(sb, func.Parameters[1]);

                            return;
                    }

                    break;
            }

            base.BuildFunction(sb, func);
        }
示例#19
0
        protected override void BuildFunction(StringBuilder sb, SqlFunction func)
        {
            switch (func.Name)
            {
            case "Coalesce":

                if (func.Parameters.Length > 2)
                {
                    var parms = new ISqlExpression[func.Parameters.Length - 1];

                    Array.Copy(func.Parameters, 1, parms, 0, parms.Length);
                    BuildFunction(sb, new SqlFunction(func.SystemType, func.Name, func.Parameters[0],
                                                      new SqlFunction(func.SystemType, func.Name, parms)));
                    return;
                }

                var sc = new SqlQuery.SearchCondition();

                sc.Conditions.Add(new SqlQuery.Condition(false, new SqlQuery.Predicate.IsNull(func.Parameters[0], false)));

                func = new SqlFunction(func.SystemType, "Iif", sc, func.Parameters[1], func.Parameters[0]);

                break;

            case "CASE": func = ConvertCase(func.SystemType, func.Parameters, 0); break;

            case "CharIndex":
                func = func.Parameters.Length == 2?
                       new SqlFunction(func.SystemType, "InStr", new SqlValue(1), func.Parameters[1], func.Parameters[0], new SqlValue(1)):
                       new SqlFunction(func.SystemType, "InStr", func.Parameters[2], func.Parameters[1], func.Parameters[0], new SqlValue(1));
                break;

            case "Convert":
                switch (Type.GetTypeCode(func.SystemType.ToUnderlying()))
                {
                case TypeCode.String: func = new SqlFunction(func.SystemType, "CStr", func.Parameters[1]); break;

                case TypeCode.DateTime:
                    if (IsDateDataType(func.Parameters[0], "Date"))
                    {
                        func = new SqlFunction(func.SystemType, "DateValue", func.Parameters[1]);
                    }
                    else if (IsTimeDataType(func.Parameters[0]))
                    {
                        func = new SqlFunction(func.SystemType, "TimeValue", func.Parameters[1]);
                    }
                    else
                    {
                        func = new SqlFunction(func.SystemType, "CDate", func.Parameters[1]);
                    }
                    break;

                default:
                    if (func.SystemType == typeof(DateTime))
                    {
                        goto case TypeCode.DateTime;
                    }

                    BuildExpression(sb, func.Parameters[1]);

                    return;
                }

                break;
            }

            base.BuildFunction(sb, func);
        }