Пример #1
0
		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
		{
			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
			var query    = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
			var except   = query.SqlQuery;

			sequence = new SubQueryContext(sequence);

			var sql = sequence.SqlQuery;

			except.ParentSql = sql;

			if (methodCall.Method.Name == "Except")
				sql.Where.Not.Exists(except);
			else
				sql.Where.Exists(except);

			var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key);
			var keys2 = query.   ConvertToSql(null, 0, ConvertFlags.Key);

			if (keys1.Length != keys2.Length)
				throw new InvalidOperationException();

			for (var i = 0; i < keys1.Length; i++)
			{
				except.Where
					.Expr(keys1[i].Sql)
					.Equal
					.Expr(keys2[i].Sql);
			}

			return sequence;
		}
Пример #2
0
		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
		{
			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

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

			var lambda  = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var sparent = sequence.Parent;
			var order   = new ExpressionContext(buildInfo.Parent, sequence, lambda);
			var body    = lambda.Body.Unwrap();
			var sql     = builder.ConvertExpressions(order, body, ConvertFlags.Key);

			builder.ReplaceParent(order, sparent);

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

			foreach (var expr in sql)
			{
				var e = builder.ConvertSearchCondition(sequence, expr.Sql);
				sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
			}

			return sequence;
		}
Пример #3
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

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

            var lambda  = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var sparent = sequence.Parent;
            var order   = new ExpressionContext(buildInfo.Parent, sequence, lambda);
            var body    = lambda.Body.Unwrap();
            var sql     = builder.ConvertExpressions(order, body, ConvertFlags.Key);

            builder.ReplaceParent(order, sparent);

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

            foreach (var expr in sql)
            {
                var e = builder.ConvertSearchCondition(sequence, expr.Sql);
                sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
            }

            return(sequence);
        }
Пример #4
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr    = methodCall.Arguments[0];
            var sequence        = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var groupingType    = methodCall.Type.GetGenericArguments()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.Method.Name == "Select")
                {
                    var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;

                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        sequence = new SubQueryContext(sequence);
                    }
                }
            }

            var key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
            var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

            if (sequence.SqlQuery.Select.IsDistinct ||
                sequence.SqlQuery.GroupBy.Items.Count > 0 ||
                groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column)))
            {
                sequence = new SubQueryContext(sequence);
                key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
                groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
            }

            //sequence.SqlQuery.GroupBy.Items.Clear();

            foreach (var sql in groupSql)
            {
                sequence.SqlQuery.GroupBy.Expr(sql.Sql);
            }

            new QueryVisitor().Visit(sequence.SqlQuery.From, e =>
            {
                if (e.ElementType == QueryElementType.JoinedTable)
                {
                    var jt = (SqlQuery.JoinedTable)e;
                    if (jt.JoinType == SqlQuery.JoinType.Inner)
                    {
                        jt.IsWeak = false;
                    }
                }
            });

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element);

            return(groupBy);
        }
Пример #5
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var isSubQuery = sequence.SqlQuery.Select.IsDistinct;

            if (isSubQuery)
            {
                sequence = new SubQueryContext(sequence);
            }

            switch (methodCall.Arguments.Count)
            {
            case 1:
                // static int Insert<T>              (this IValueInsertable<T> source)
                // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source)
            {
                foreach (var item in sequence.SqlQuery.Set.Items)
                {
                    sequence.SqlQuery.Select.Expr(item.Expression);
                }
                break;
            }

            case 2:                      // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter)
            {
                UpdateBuilder.BuildSetter(builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, sequence);

                sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)sequence).SqlTable;
                sequence.SqlQuery.From.Tables.Clear();

                break;
            }

            case 3:                      // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter)
            {
                var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));

                UpdateBuilder.BuildSetter(builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence);

                sequence.SqlQuery.Select.Columns.Clear();

                foreach (var item in sequence.SqlQuery.Set.Items)
                {
                    sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression));
                }

                sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)into).SqlTable;

                break;
            }
            }

            sequence.SqlQuery.QueryType        = QueryType.Insert;
            sequence.SqlQuery.Set.WithIdentity = methodCall.Method.Name == "InsertWithIdentity";

            return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Set.WithIdentity));
        }
Пример #6
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var returnType = methodCall.Method.ReturnType;
            var sequence   = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            if (sequence.SqlQuery != buildInfo.SqlQuery)
            {
                if (sequence is JoinBuilder.GroupJoinSubQueryContext)
                {
                    var ctx = new CountContext(buildInfo.Parent, sequence, returnType)
                    {
                        SqlQuery = ((JoinBuilder.GroupJoinSubQueryContext)sequence).GetCounter(methodCall)
                    };

                    ctx.Sql        = ctx.SqlQuery;
                    ctx.FieldIndex = ctx.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, ctx.SqlQuery), "cnt");

                    return(ctx);
                }

                if (sequence is GroupByBuilder.GroupByContext)
                {
                    return(new CountContext(buildInfo.Parent, sequence, returnType)
                    {
                        Sql = SqlFunction.CreateCount(returnType, sequence.SqlQuery),
                        FieldIndex = -1
                    });
                }
            }

            if (sequence.SqlQuery.Select.IsDistinct ||
                sequence.SqlQuery.Select.TakeValue != null ||
                sequence.SqlQuery.Select.SkipValue != null ||
                !sequence.SqlQuery.GroupBy.IsEmpty)
            {
                sequence.ConvertToIndex(null, 0, ConvertFlags.Key);
                sequence = new SubQueryContext(sequence);
            }

            if (sequence.SqlQuery.OrderBy.Items.Count > 0)
            {
                if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null)
                {
                    sequence.SqlQuery.OrderBy.Items.Clear();
                }
                else
                {
                    sequence = new SubQueryContext(sequence);
                }
            }

            var context = new CountContext(buildInfo.Parent, sequence, returnType);

            context.Sql        = context.SqlQuery;
            context.FieldIndex = context.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, context.SqlQuery), "cnt");

            return(context);
        }
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence1 = new SubQueryContext(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])));
            var sequence2 = new SubQueryContext(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())));
            var union     = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat");

            sequence1.SqlQuery.Unions.Add(union);

            return(new UnionContext(sequence1, sequence2, methodCall));
        }
Пример #8
0
		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
		{
			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
			var sql      = sequence.SqlQuery;

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

			sequence.SqlQuery.Select.IsDistinct = true;

			return sequence;
		}
Пример #9
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var sql      = sequence.SqlQuery;

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

            sequence.SqlQuery.Select.IsDistinct = true;

            return(sequence);
        }
Пример #10
0
		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
		{
			var sequence1 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
			var sequence2 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
			var union     = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat");

			var sq = sequence1 as SubQueryContext;

			if (sq == null || sq.Union != null || !sq.SqlQuery.IsSimple)
				sq = new SubQueryContext(sequence1);

			sq.SubQuery.SqlQuery.Unions.Add(union);
			sq.Union = sequence2;

			return sq;
		}
            public UnionContext(SubQueryContext sequence1, SubQueryContext sequence2, MethodCallExpression methodCall)
                : base(sequence1)
            {
                _methodCall = methodCall;

                _isObject =
                    sequence1.IsExpression(null, 0, RequestFor.Object).Result ||
                    sequence2.IsExpression(null, 0, RequestFor.Object).Result;

                if (_isObject)
                {
                    var type = _methodCall.Method.GetGenericArguments()[0];
                    _unionParameter = Expression.Parameter(type, "t");
                }

                Init(sequence1, sequence2);
            }
Пример #12
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

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

            if (!sequence.SqlQuery.OrderBy.IsEmpty)
            {
                if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null)
                {
                    sequence.SqlQuery.OrderBy.Items.Clear();
                }
                else
                {
                    sequence = new SubQueryContext(sequence);
                }
            }

            var context = new AggregationContext(buildInfo.Parent, sequence, methodCall);
            var sql     = sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray();

            if (sql.Length == 1 && sql[0] is SqlQuery)
            {
                var query = (SqlQuery)sql[0];

                if (query.Select.Columns.Count == 1)
                {
                    var join = SqlQuery.OuterApply(query);
                    context.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    sql[0] = query.Select.Columns[0];
                }
            }

            context.Sql        = context.SqlQuery;
            context.FieldIndex = context.SqlQuery.Select.Add(
                new SqlFunction(methodCall.Type, methodCall.Method.Name, sql));

            return(context);
        }
Пример #13
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence1 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var sequence2 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
            var union     = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat");

            var sq = sequence1 as SubQueryContext;

            if (sq == null || sq.Union != null || !sq.SqlQuery.IsSimple)
            {
                sq = new SubQueryContext(sequence1);
            }

            sq.SubQuery.SqlQuery.Unions.Add(union);
            sq.Union = sequence2;

            return(sq);
        }
Пример #14
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            if (sequence.SqlQuery != buildInfo.SqlQuery)
            {
                throw new NotImplementedException();
            }

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

            if (sequence.SqlQuery.OrderBy.Items.Count > 0)
            {
                if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null)
                {
                    sequence.SqlQuery.OrderBy.Items.Clear();
                }
                else
                {
                    sequence = new SubQueryContext(sequence);
                }
            }

            //var index = sequence.ConvertToIndex(null, 0, ConvertFlags.Field);

            var context = new AggregationContext(buildInfo.Parent, sequence, null, methodCall.Method.ReturnType);

            context.FieldIndex = context.SqlQuery.Select.Add(
                new SqlFunction(
                    methodCall.Type,
                    methodCall.Method.Name,
                    sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray()));

            return(context);
        }
Пример #15
0
            protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
            {
                var source = methodCall.Arguments[0].Unwrap();
                var into   = methodCall.Arguments[1].Unwrap();

                IBuildContext sequence;

                // static IValueInsertable<T> Into<T>(this IDataContext dataContext, Table<T> target)
                //
                if (source.NodeType == ExpressionType.Constant && ((ConstantExpression)source).Value == null)
                {
                    sequence = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery()));

                    if (sequence.SqlQuery.Select.IsDistinct)
                    {
                        sequence = new SubQueryContext(sequence);
                    }

                    sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable;
                    sequence.SqlQuery.From.Tables.Clear();
                }
                // static ISelectInsertable<TSource,TTarget> Into<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target)
                //
                else
                {
                    sequence = builder.BuildSequence(new BuildInfo(buildInfo, source));

                    if (sequence.SqlQuery.Select.IsDistinct)
                    {
                        sequence = new SubQueryContext(sequence);
                    }

                    var tbl = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery()));
                    sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)tbl).SqlTable;
                }

                sequence.SqlQuery.Select.Columns.Clear();

                return(sequence);
            }
Пример #16
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var query    = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
            var except   = query.SqlQuery;

            sequence = new SubQueryContext(sequence);

            var sql = sequence.SqlQuery;

            except.ParentSql = sql;

            if (methodCall.Method.Name == "Except")
            {
                sql.Where.Not.Exists(except);
            }
            else
            {
                sql.Where.Exists(except);
            }

            var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key);
            var keys2 = query.ConvertToSql(null, 0, ConvertFlags.Key);

            if (keys1.Length != keys2.Length)
            {
                throw new InvalidOperationException();
            }

            for (var i = 0; i < keys1.Length; i++)
            {
                except.Where
                .Expr(keys1[i].Sql)
                .Equal
                .Expr(keys2[i].Sql);
            }

            return(sequence);
        }
Пример #17
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var isSubQuery = sequence.SqlQuery.Select.IsDistinct;

            if (isSubQuery)
            {
                sequence = new SubQueryContext(sequence);
            }

            switch (methodCall.Arguments.Count)
            {
            case 1:
                // static int Insert<T>              (this IValueInsertable<T> source)
                // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source)
            {
                foreach (var item in sequence.SqlQuery.Insert.Items)
                {
                    sequence.SqlQuery.Select.Expr(item.Expression);
                }
                break;
            }

            case 2:                      // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter)
            {
                UpdateBuilder.BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[1].Unwrap(),
                    sequence,
                    sequence.SqlQuery.Insert.Items,
                    sequence);

                sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable;
                sequence.SqlQuery.From.Tables.Clear();

                break;
            }

            case 3:                      // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter)
            {
                var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));

                UpdateBuilder.BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[2].Unwrap(),
                    into,
                    sequence.SqlQuery.Insert.Items,
                    sequence);

                sequence.SqlQuery.Select.Columns.Clear();

                foreach (var item in sequence.SqlQuery.Insert.Items)
                {
                    sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression));
                }

                sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable;

                break;
            }
            }

            var insert = sequence.SqlQuery.Insert;

            var q = insert.Into.Fields.Values.Cast <ISqlExpression>().Except(insert.Items.Select(e => e.Column))
                    .OfType <SqlField>()
                    .Where(f => f.IsIdentity);

            foreach (var field in q)
            {
                var expr = builder.SqlProvider.GetIdentityExpression(insert.Into, field, false);

                if (expr != null)
                {
                    insert.Items.Insert(0, new SqlQuery.SetExpression(field, expr));

                    if (methodCall.Arguments.Count == 3)
                    {
                        sequence.SqlQuery.Select.Columns.Insert(0, new SqlQuery.Column(sequence.SqlQuery, insert.Items[0].Expression));
                    }
                }
            }

            sequence.SqlQuery.QueryType           = QueryType.Insert;
            sequence.SqlQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity";
            sequence.SqlQuery.Insert.WithOutput   = methodCall.Method.Name == "InsertWithOutput";

            return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity || sequence.SqlQuery.Insert.WithOutput));
        }
Пример #18
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence           = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (!sequence.SqlQuery.GroupBy.IsEmpty)
            {
                sequence = new SubQueryContext(sequence);
            }

            var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence);
            var expr    = collectionSelector.Body.Unwrap();

            var collectionInfo = new BuildInfo(context, expr, new SqlQuery());
            var collection     = builder.BuildSequence(collectionInfo);
            var leftJoin       = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext;
            var sql            = collection.SqlQuery;

            var sequenceTable = sequence.SqlQuery.From.Tables[0].Source;
            var newQuery      = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SqlQuery);
            var crossApply    = null != new QueryVisitor().Find(sql, e =>
                                                                e == sequenceTable ||
                                                                e.ElementType == QueryElementType.SqlField && sequenceTable == ((SqlField)e).Table ||
                                                                e.ElementType == QueryElementType.Column && sequenceTable == ((SqlQuery.Column)e).Parent);

            if (collection is JoinBuilder.GroupJoinSubQueryContext)
            {
                var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin;

                groupJoin.SqlQuery.From.Tables[0].Joins[0].JoinType = SqlQuery.JoinType.Inner;
                groupJoin.SqlQuery.From.Tables[0].Joins[0].IsWeak   = false;
            }

            if (!newQuery)
            {
                context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

            if (!crossApply)
            {
                if (!leftJoin)
                {
                    context.Collection = new SubQueryContext(collection, sequence.SqlQuery, true);
                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
                else
                {
                    var join = SqlQuery.OuterApply(sql);
                    sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false);

                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
            }

            if (collection is TableBuilder.TableContext)
            {
                var table = (TableBuilder.TableContext)collection;

                var join = table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0 ?
                           leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql) :
                           leftJoin?SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql);

                join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);

                sql.Where.SearchCondition.Conditions.Clear();

                var collectionParent = collection.Parent as TableBuilder.TableContext;

                // Association.
                //
                if (collectionParent != null && collectionInfo.IsAssociationBuilt)
                {
                    var ts = (SqlQuery.TableSource) new QueryVisitor().Find(sequence.SqlQuery.From, e =>
                    {
                        if (e.ElementType == QueryElementType.TableSource)
                        {
                            var t = (SqlQuery.TableSource)e;
                            return(t.Source == collectionParent.SqlTable);
                        }

                        return(false);
                    });

                    ts.Joins.Add(join.JoinedTable);
                }
                else
                {
                    sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                }

                context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                var join = leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql);
                sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }
            void Init(SubQueryContext sequence1, SubQueryContext sequence2)
            {
                var info1 = sequence1.ConvertToIndex(null, 0, ConvertFlags.All).ToList();
                var info2 = sequence2.ConvertToIndex(null, 0, ConvertFlags.All).ToList();

                if (!_isObject)
                {
                    return;
                }

                var members = new List <UnionMember>();

                foreach (var info in info1)
                {
                    if (info.Members.Count == 0)
                    {
                        throw new InvalidOperationException();
                    }

                    var member = new Member
                    {
                        SequenceInfo     = info,
                        MemberExpression = Expression.MakeMemberAccess(_unionParameter, info.Members[0])
                    };

                    //if (sequence1.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result)
                    //	throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name);

                    members.Add(new UnionMember {
                        Member = member, Info1 = info
                    });
                }

                foreach (var info in info2)
                {
                    if (info.Members.Count == 0)
                    {
                        throw new InvalidOperationException();
                    }

                    var em = members.FirstOrDefault(m =>
                                                    m.Member.SequenceInfo != null &&
                                                    m.Member.SequenceInfo.CompareMembers(info));

                    if (em == null)
                    {
                        var member = new Member {
                            MemberExpression = Expression.MakeMemberAccess(_unionParameter, info.Members[0])
                        };

                        if (sequence2.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result)
                        {
                            throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name);
                        }

                        members.Add(new UnionMember {
                            Member = member, Info2 = info
                        });
                    }
                    else
                    {
                        em.Info2 = info;
                    }
                }

                sequence1.SqlQuery.Select.Columns.Clear();
                sequence2.SqlQuery.Select.Columns.Clear();

                for (var i = 0; i < members.Count; i++)
                {
                    var member = members[i];

                    if (member.Info1 == null)
                    {
                        member.Info1 = new SqlInfo(member.Info2.Members)
                        {
                            Sql   = new SqlValue(null),
                            Query = sequence1.SqlQuery,
                        };

                        member.Member.SequenceInfo = member.Info1;
                    }

                    if (member.Info2 == null)
                    {
                        member.Info2 = new SqlInfo(member.Info1.Members)
                        {
                            Sql   = new SqlValue(null),
                            Query = sequence2.SqlQuery,
                        };
                    }

                    sequence1.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence1.SqlQuery, member.Info1.Sql));
                    sequence2.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence2.SqlQuery, member.Info2.Sql));

                    member.Member.SequenceInfo.Index = i;
                    //member.Info1.Index = i;
                    //member.Info2.Index = i;

                    _members[member.Member.MemberExpression.Member] = member.Member;
                }

                foreach (var key in sequence1.ColumnIndexes.Keys.ToList())
                {
                    sequence1.ColumnIndexes[key] = sequence1.SqlQuery.Select.Add(key);
                }

                foreach (var key in sequence2.ColumnIndexes.Keys.ToList())
                {
                    sequence2.ColumnIndexes[key] = sequence2.SqlQuery.Select.Add(key);
                }

                /*
                 * if (_isObject)
                 * {
                 *      foreach (var info in info1)
                 *      {
                 *              if (info.Member == null)
                 *                      throw new InvalidOperationException();
                 *
                 *              CheckAndAddMember(sequence1, sequence2, info);
                 *      }
                 *
                 *      info2 = sequence2.ConvertToIndex(null, 0, ConvertFlags.All).OrderBy(_ => _.Index).ToList();
                 *
                 *      if (info1.Count != info2.Count)
                 *      {
                 *              for (var i = 0; i < info2.Count; i++)
                 *              {
                 *                      if (i < info1.Count)
                 *                      {
                 *                              if (info1[i].Index != info2[i].Index)
                 *                                      throw new InvalidOperationException();
                 *                      }
                 *                      else
                 *                      {
                 *                              CheckAndAddMember(sequence2, sequence1, info2[i]);
                 *                      }
                 *              }
                 *      }
                 * }
                 * else
                 *      sequence2.ConvertToIndex(null, 0, ConvertFlags.All).OrderBy(_ => _.Index).ToList();
                 */
            }
Пример #20
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var isGroup      = methodCall.Method.Name == "GroupJoin";
            var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SqlQuery));
            var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
            var countContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));

            var context = new SubQueryContext(outerContext);

            innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext, methodCall) : new SubQueryContext(innerContext);
            countContext = new SubQueryContext(countContext);

            var join = isGroup ? innerContext.SqlQuery.WeakLeftJoin() : innerContext.SqlQuery.InnerJoin();
            var sql  = context.SqlQuery;

            sql.From.Tables[0].Joins.Add(join.JoinedTable);

            var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

            context.SetAlias(selector.Parameters[0].Name);
            innerContext.SetAlias(selector.Parameters[1].Name);

            var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap());
            var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap());

            var outerKeySelector = outerKeyLambda.Body.Unwrap();
            var innerKeySelector = innerKeyLambda.Body.Unwrap();

            var outerParent = context.Parent;
            var innerParent = innerContext.Parent;
            var countParent = countContext.Parent;

            var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda);
            var innerKeyContext = new InnerKeyContext(buildInfo.Parent, innerContext, innerKeyLambda);
            var countKeyContext = new ExpressionContext(buildInfo.Parent, countContext, innerKeyLambda);

            // Process counter.
            //
            var counterSql = ((SubQueryContext)countContext).SqlQuery;

            // Make join and where for the counter.
            //
            if (outerKeySelector.NodeType == ExpressionType.New)
            {
                var new1 = (NewExpression)outerKeySelector;
                var new2 = (NewExpression)innerKeySelector;

                for (var i = 0; i < new1.Arguments.Count; i++)
                {
                    var arg1 = new1.Arguments[i];
                    var arg2 = new2.Arguments[i];

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql);
                }
            }
            else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
            {
                var mi1 = (MemberInitExpression)outerKeySelector;
                var mi2 = (MemberInitExpression)innerKeySelector;

                for (var i = 0; i < mi1.Bindings.Count; i++)
                {
                    if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
                    {
                        throw new LinqException(string.Format("List of member inits does not match for entity type '{0}'.", outerKeySelector.Type));
                    }

                    var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                    var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql);
                }
            }
            else
            {
                BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector, countKeyContext, counterSql);
            }

            builder.ReplaceParent(outerKeyContext, outerParent);
            builder.ReplaceParent(innerKeyContext, innerParent);
            builder.ReplaceParent(countKeyContext, countParent);

            if (isGroup)
            {
                counterSql.ParentSql = sql;
                counterSql.Select.Columns.Clear();

                var inner = (GroupJoinSubQueryContext)innerContext;

                inner.Join       = join.JoinedTable;
                inner.CounterSql = counterSql;
                return(new GroupJoinContext(
                           buildInfo.Parent, selector, context, inner, methodCall.Arguments[1], outerKeyLambda, innerKeyLambda));
            }

            return(new JoinContext(buildInfo.Parent, selector, context, innerContext)
#if DEBUG
            {
                MethodCall = methodCall
            }
#endif
                   );
        }
Пример #21
0
		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
		{
			var isGroup      = methodCall.Method.Name == "GroupJoin";
			var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SqlQuery));
			var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
			var countContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));

			var context  = new SubQueryContext(outerContext);
			innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext, methodCall) : new SubQueryContext(innerContext);
			countContext = new SubQueryContext(countContext);

			var join = innerContext.SqlQuery.InnerJoin();
			var sql  = context.SqlQuery;

			sql.From.Tables[0].Joins.Add(join.JoinedTable);

			var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

			context.SetAlias(selector.Parameters[0].Name);
			innerContext.SetAlias(selector.Parameters[1].Name);

			var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap());
			var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap());

			var outerKeySelector = outerKeyLambda.Body.Unwrap();
			var innerKeySelector = innerKeyLambda.Body.Unwrap();

			var outerParent = context.     Parent;
			var innerParent = innerContext.Parent;
			var countParent = countContext.Parent;

			var outerKeyContext = new ExpressionContext(buildInfo.Parent, context,      outerKeyLambda);
			var innerKeyContext = new ExpressionContext(buildInfo.Parent, innerContext, innerKeyLambda);
			var countKeyContext = new ExpressionContext(buildInfo.Parent, countContext, innerKeyLambda);

			// Process counter.
			//
			var counterSql = ((SubQueryContext)countContext).SqlQuery;

			// Make join and where for the counter.
			//
			if (outerKeySelector.NodeType == ExpressionType.New)
			{
				var new1 = (NewExpression)outerKeySelector;
				var new2 = (NewExpression)innerKeySelector;

				for (var i = 0; i < new1.Arguments.Count; i++)
				{
					var arg1 = new1.Arguments[i];
					var arg2 = new2.Arguments[i];

					BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql);
				}
			}
			else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
			{
				var mi1 = (MemberInitExpression)outerKeySelector;
				var mi2 = (MemberInitExpression)innerKeySelector;

				for (var i = 0; i < mi1.Bindings.Count; i++)
				{
					if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
						throw new LinqException(string.Format("List of member inits does not match for entity type '{0}'.", outerKeySelector.Type));

					var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
					var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

					BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql);
				}
			}
			else
			{
				BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector, countKeyContext, counterSql);
			}

			context.     Parent = outerParent;
			innerContext.Parent = innerParent;
			countContext.Parent = countParent;

			if (isGroup)
			{
				counterSql.ParentSql = sql;
				counterSql.Select.Columns.Clear();

				var inner = (GroupJoinSubQueryContext)innerContext;

				inner.Join       = join.JoinedTable;
				inner.CounterSql = counterSql;
				return new GroupJoinContext(buildInfo.Parent, selector, context, inner);
			}

			return new JoinContext(buildInfo.Parent, selector, context, innerContext);
		}