Beispiel #1
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));
            }
        }
        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.SelectQuery.GroupBy.IsEmpty ||
                sequence.SelectQuery.Select.TakeValue != null ||
                sequence.SelectQuery.Select.SkipValue != null ||
                sequence.SelectQuery.Select.IsDistinct)
            {
                sequence = new SubQueryContext(sequence);
            }

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

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

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != QueryVisitor.Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != QueryVisitor.Find(sql, e =>
                                                           e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) ||
                                                           e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) ||
                                                           e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SelectQuery.Column)e).Parent));

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

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

            if (!newQuery)
            {
                if (collection.SelectQuery.Select.HasModifier)
                {
                    if (crossApply)
                    {
                        var foundJoin = context.SelectQuery.FindJoin(j => j.Table.Source == collection.SelectQuery);
                        if (foundJoin != null)
                        {
                            foundJoin.JoinType = leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply;

                            collection.SelectQuery.Where.ConcatSearchCondition(foundJoin.Condition);

                            ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(false, e =>
                            {
                                var column = e as SelectQuery.Column;
                                if (column != null)
                                {
                                    if (column.Parent == collection.SelectQuery)
                                    {
                                        return(column.UnderlyingColumn);
                                    }
                                }
                                return(e);
                            });

                            foundJoin.Condition.Conditions.Clear();
                        }
                    }
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

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

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

            var joinType = collectionInfo.JoinType;

            if (collection is TableBuilder.TableContext)
            {
//				if (collectionInfo.IsAssociationBuilt)
//				{
//					context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
//					return new SelectContext(buildInfo.Parent, resultSelector, sequence, context);
//				}

                if (joinType == SelectQuery.JoinType.Auto)
                {
                    var table       = (TableBuilder.TableContext)collection;
                    var isApplyJoin = collection.SelectQuery.Select.HasModifier ||
                                      table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0;

                    joinType = isApplyJoin
                                                ? (leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply)
                                                : (leftJoin ? SelectQuery.JoinType.Left : SelectQuery.JoinType.Inner);
                }

                var join = CreateJoin(joinType, sql);
                join.JoinedTable.CanConvertApply = false;

                if (!(joinType == SelectQuery.JoinType.CrossApply || joinType == SelectQuery.JoinType.OuterApply))
                {
                    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 = (SelectQuery.TableSource)QueryVisitor.Find(sequence.SelectQuery.From, e =>
                    {
                        if (e.ElementType == QueryElementType.TableSource)
                        {
                            var t = (SelectQuery.TableSource)e;
                            return(t.Source == collectionParent.SqlTable);
                        }

                        return(false);
                    });

                    ts.Joins.Add(join.JoinedTable);
                }
                else
                {
                    //if (collectionInfo.IsAssociationBuilt)
                    //{
                    //	collectionInfo.AssosiationContext.ParentAssociationJoin.IsWeak = false;
                    //}
                    //else
                    {
                        sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    }
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                if (joinType == SelectQuery.JoinType.Auto)
                {
                    joinType = leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply;
                }

                var join = CreateJoin(joinType, sql);

                if (!(joinType == SelectQuery.JoinType.CrossApply || joinType == SelectQuery.JoinType.OuterApply))
                {
                    join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);
                    sql.Where.SearchCondition.Conditions.Clear();
                }

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

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }
Beispiel #3
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.SelectQuery.HasUnion || !sequence.SelectQuery.IsSimple)
            {
                sequence = new SubQueryContext(sequence);
            }

            var expr = collectionSelector.Body.Unwrap();

            DefaultIfEmptyBuilder.DefaultIfEmptyContext defaultIfEmpty = null;
            if (expr is MethodCallExpression mc && AllJoinsBuilder.IsMatchingMethod(mc, true))
            {
                defaultIfEmpty          = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, sequence, null);
                defaultIfEmpty.Disabled = true;
                sequence = new SubQueryContext(defaultIfEmpty);
            }

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

            context.SetAlias(collectionSelector.Parameters[0].Name);

            var collectionInfo = new BuildInfo(context, expr, new SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);

            if (resultSelector.Parameters.Count > 1)
            {
                collection.SetAlias(resultSelector.Parameters[1].Name);
            }

            if (defaultIfEmpty != null && (collectionInfo.JoinType == JoinType.Right || collectionInfo.JoinType == JoinType.Full))
            {
                defaultIfEmpty.Disabled = false;
            }

            var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext || collectionInfo.JoinType == JoinType.Left;
            var sql      = collection.SelectQuery;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != QueryVisitor.Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != QueryVisitor.Find(sql, e =>
                                                           e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) ||
                                                           e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) ||
                                                           e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SqlColumn)e).Parent));

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

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

            if (!newQuery)
            {
                if (collection.SelectQuery.Select.HasModifier)
                {
                    if (crossApply)
                    {
                        var foundJoin = context.SelectQuery.FindJoin(j => j.Table.Source == collection.SelectQuery);
                        if (foundJoin != null)
                        {
                            foundJoin.JoinType = leftJoin ? JoinType.OuterApply : JoinType.CrossApply;

                            collection.SelectQuery.Where.ConcatSearchCondition(foundJoin.Condition);

                            ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(new WalkOptions(), e =>
                            {
                                if (e is SqlColumn column)
                                {
                                    if (column.Parent == collection.SelectQuery)
                                    {
                                        return(column.UnderlyingColumn);
                                    }
                                }
                                return(e);
                            });

                            foundJoin.Condition.Conditions.Clear();
                        }
                    }
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

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

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

            void MoveSearchConditionsToJoin(SqlFromClause.Join join)
            {
                var tableSources = new HashSet <ISqlTableSource>();

                ((ISqlExpressionWalkable)sql.Where.SearchCondition).Walk(new WalkOptions(), e =>
                {
                    if (e is ISqlTableSource ts && !tableSources.Contains(ts))
                    {
                        tableSources.Add(ts);
                    }
                    return(e);
                });

                bool ContainsTable(ISqlTableSource tbl, IQueryElement qe)
                {
                    return(null != QueryVisitor.Find(qe, e =>
                                                     e == tbl ||
                                                     e.ElementType == QueryElementType.SqlField && tbl == ((SqlField)e).Table ||
                                                     e.ElementType == QueryElementType.Column && tbl == ((SqlColumn)e).Parent));
                }

                var conditions = sql.Where.SearchCondition.Conditions;

                if (conditions.Count > 0)
                {
                    for (var i = conditions.Count - 1; i >= 0; i--)
                    {
                        var condition = conditions[i];

                        if (!tableSources.Any(ts => ContainsTable(ts, condition)))
                        {
                            join.JoinedTable.Condition.Conditions.Insert(0, condition);
                            conditions.RemoveAt(i);
                        }
                    }
                }
            }
Beispiel #4
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.Select.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 SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);
            var leftJoin       = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext;
            var sql            = collection.Select;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.Select.From.Tables.First.Value.GetTables());
            var newQuery       = sql != collectionInfo.SelectQuery &&
                                 QueryVisitor.FindFirstOrDefault <ISelectQuery>(sql, e => e == collectionInfo.SelectQuery) ==
                                 null;
            var crossApply = null !=
                             QueryVisitor.FindFirstOrDefault <IQueryExpression>(
                sql,
                e =>
                e.ElementType == EQueryElementType.TableSource &&
                sequenceTables.Contains((ISqlTableSource)e) ||
                e.ElementType == EQueryElementType.SqlField &&
                sequenceTables.Contains(((ISqlField)e).Table) ||
                e.ElementType == EQueryElementType.Column &&
                sequenceTables.Contains(((IColumn)e).Parent));

            var groupJoinSubQueryContext = collection as JoinBuilder.GroupJoinSubQueryContext;

            if (groupJoinSubQueryContext != null)
            {
                var groupJoin = groupJoinSubQueryContext.GroupJoin;

                var joinedTables = groupJoin.Select.From.Tables.First.Value.Joins.First.Value;
                joinedTables.JoinType = EJoinType.Inner;
                joinedTables.IsWeak   = false;
            }

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

            if (!crossApply)
            {
                if (!leftJoin)
                {
                    context.Collection = new SubQueryContext(collection, sequence.Select, true);
                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }

                var join = SelectQuery.OuterApply(sql);
                sequence.Select.From.Tables.First.Value.Joins.AddLast(join.JoinedTable);
                context.Collection = new SubQueryContext(collection, sequence.Select, false);

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

            var tableContext = collection as TableBuilder.TableContext;

            if (tableContext != null)
            {
                var join = tableContext.SqlTable.TableArguments != null &&
                           tableContext.SqlTable.TableArguments.Count > 0
                    ? (leftJoin
                        ? SelectQuery.OuterApply(sql)
                        : SelectQuery.CrossApply(sql))
                    : (leftJoin
                        ? SelectQuery.LeftJoin(sql)
                        : SelectQuery.InnerJoin(sql));

                join.JoinedTable.Condition.Conditions.AddRange(sql.Where.Search.Conditions);
                join.JoinedTable.CanConvertApply = false;

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

                var collectionParent = collection.Parent as TableBuilder.TableContext;

                // Association.
                //
                if (collectionParent != null && collectionInfo.IsAssociationBuilt)
                {
                    QueryVisitor.FindFirstOrDefault <ITableSource>(sequence.Select.From,
                                                                   t => t.Source == collectionParent.SqlTable);
                }
                else
                {
                    sequence.Select.From.Tables.First.Value.Joins.AddLast(join.JoinedTable);
                }

                context.Collection = new SubQueryContext(collection, sequence.Select, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                var join = leftJoin
                    ? SelectQuery.OuterApply(sql)
                    : SelectQuery.CrossApply(sql);
                sequence.Select.From.Tables.First.Value.Joins.AddLast(join.JoinedTable);

                context.Collection = new SubQueryContext(collection, sequence.Select, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }
Beispiel #5
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence           = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            //if (collectionSelector.Parameters[0] == collectionSelector.Body.Unwrap())
            //{
            //	return resultSelector == null ? sequence : new SelectContext(resultSelector, sequence, sequence);
            //}

            var context    = new SelectManyContext(collectionSelector, sequence);
            var expr       = collectionSelector.Body.Unwrap();
            var crossApply = null != expr.Find(e => e == collectionSelector.Parameters[0]);

            /*
             * if (expr.NodeType == ExpressionType.Call)
             * {
             *      var call = (MethodCallExpression)collectionSelector.Body;
             *
             *      if (call.IsQueryable("DefaultIfEmpty"))
             *      {
             *              leftJoin = true;
             *              expr     = call.Arguments[0];
             *      }
             * }
             */

            parser.SubQueryParsingCounter++;
            var collection = parser.ParseSequence(context, expr, new SqlQuery());

            parser.SubQueryParsingCounter--;

            var leftJoin = collection is DefaultIfEmptyParser.DefaultIfEmptyContext;
            var sql      = collection.SqlQuery;

            if (!leftJoin && crossApply)
            {
                if (sql.GroupBy.IsEmpty &&
                    sql.Select.Columns.Count == 0 &&
                    !sql.Select.HasModifier &&
                    sql.Where.IsEmpty &&
                    !sql.HasUnion &&
                    sql.From.Tables.Count == 1)
                {
                    crossApply = false;
                }
            }

            if (!leftJoin && !crossApply)
            {
                sequence.SqlQuery.From.Table(sql);

                //sql.ParentSql = sequence.SqlQuery;

                var col = (IParseContext) new SubQueryContext(collection, sequence.SqlQuery, true);

                return(new SelectContext(resultSelector, sequence, col));
            }

            //if (crossApply)
            {
                if (sql.GroupBy.IsEmpty &&
                    sql.Select.Columns.Count == 0 &&
                    !sql.Select.HasModifier &&
                    //!sql.Where.IsEmpty &&
                    !sql.HasUnion && sql.From.Tables.Count == 1)
                {
                    var join = leftJoin ? SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql);

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

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

                    if (collection is TableParser.TableContext)
                    {
                        var collectionParent = collection.Parent as TableParser.TableContext;

                        if (collectionParent != null)
                        {
                            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);
                        }
                    }
                    else
                    {
                        sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                        //collection.SqlQuery = sequence.SqlQuery;
                    }

                    //sql.ParentSql = sequence.SqlQuery;

                    var col = (IParseContext) new SubQueryContext(collection, sequence.SqlQuery, false);

                    return(new SelectContext(resultSelector, sequence, col));
                }
            }

            throw new LinqException("Sequence '{0}' cannot be converted to SQL.", expr);
        }
Beispiel #6
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence           = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

			//if (collectionSelector.Parameters[0] == collectionSelector.Body.Unwrap())
			//{
			//	return resultSelector == null ? sequence : new SelectContext(resultSelector, sequence, sequence);
			//}

			var context    = new SelectManyContext(collectionSelector, sequence);
			var expr       = collectionSelector.Body.Unwrap();
			var crossApply = null != expr.Find(e => e == collectionSelector.Parameters[0]);

			/*
			if (expr.NodeType == ExpressionType.Call)
			{
				var call = (MethodCallExpression)collectionSelector.Body;

				if (call.IsQueryable("DefaultIfEmpty"))
				{
					leftJoin = true;
					expr     = call.Arguments[0];
				}
			}
			*/

			parser.SubQueryParsingCounter++;
			var collection = parser.ParseSequence(context, expr, new SqlQuery());
			parser.SubQueryParsingCounter--;

			var leftJoin = collection is DefaultIfEmptyParser.DefaultIfEmptyContext;
			var sql      = collection.SqlQuery;

			if (!leftJoin && crossApply)
			{
				if (sql.GroupBy.IsEmpty &&
					sql.Select.Columns.Count == 0 &&
					!sql.Select.HasModifier &&
					sql.Where.IsEmpty &&
					!sql.HasUnion &&
					sql.From.Tables.Count == 1)
				{
					crossApply = false;
				}
			}

			if (!leftJoin && !crossApply)
			{
				sequence.SqlQuery.From.Table(sql);

				//sql.ParentSql = sequence.SqlQuery;

				var col = (IParseContext)new SubQueryContext(collection, sequence.SqlQuery, true);

				return new SelectContext(resultSelector, sequence, col);
			}

			//if (crossApply)
			{
				if (sql.GroupBy.IsEmpty &&
					sql.Select.Columns.Count == 0 &&
					!sql.Select.HasModifier &&
					//!sql.Where.IsEmpty &&
					!sql.HasUnion && sql.From.Tables.Count == 1)
				{
					var join = leftJoin ? SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql);

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

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

					if (collection is TableParser.TableContext)
					{
						var collectionParent = collection.Parent as TableParser.TableContext;

						if (collectionParent != null)
						{
							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);
						}
					}
					else
					{
						sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
						//collection.SqlQuery = sequence.SqlQuery;
					}

					//sql.ParentSql = sequence.SqlQuery;

					var col = (IParseContext)new SubQueryContext(collection, sequence.SqlQuery, false);

					return new SelectContext(resultSelector, sequence, col);
				}
			}

			throw new LinqException("Sequence '{0}' cannot be converted to SQL.", expr);
		}