protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.Select.Select.TakeValue != null || sequence.Select.Select.SkipValue != null || sequence.Select.Select.IsDistinct && !builder.DataContextInfo.SqlProviderFlags.IsDistinctOrderBySupported) { 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.Select.OrderBy.Items.Clear(); } foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.Select.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return(sequence); }
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.GetGenericArgumentsEx()[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.IsGenericTypeEx() && 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.Select.Select.IsDistinct || sequence.Select.GroupBy.Items.Count > 0 || groupSql.Any(_ => !(_.Sql is ISqlField || _.Sql is IColumn))) { sequence = new SubQueryContext(sequence); key = new KeyContext(buildInfo.Parent, keySelector, sequence); groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key); } foreach (var sql in groupSql) { sequence.Select.GroupBy.Expr(sql.Sql); } foreach ( var join in QueryVisitor.FindOnce <IJoinedTable>(sequence.Select.From).Where(f => f.JoinType == EJoinType.Inner)) { join.IsWeak = false; } var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/); var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element); return(groupBy); }
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 SelectQuery()))); var union = new Union(sequence2.Select, methodCall.Method.Name == "Concat"); sequence1.Select.Unions.AddLast(union); return(new UnionContext(sequence1, sequence2, methodCall)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.Select; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } sequence.Select.Select.IsDistinct = true; sequence.ConvertToIndex(null, 0, ConvertFlags.All); return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.Select.Select.IsDistinct || sequence.Select.Select.TakeValue != null || sequence.Select.Select.SkipValue != null || !sequence.Select.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (sequence.Select.OrderBy.Items.Count > 0) { if (sequence.Select.Select.TakeValue == null && sequence.Select.Select.SkipValue == null) { sequence.Select.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 ISelectQuery) { var query = (ISelectQuery)sql[0]; if (query.Select.Columns.Count == 1) { var join = SelectQuery.OuterApply(query); context.Select.From.Tables.First.Value.Joins.AddLast(join.JoinedTable); sql[0] = query.Select.Columns[0]; } } context.Sql = context.Select; context.FieldIndex = context.Select.Select.Add( new SqlFunction(methodCall.Type, methodCall.Method.Name, sql)); return(context); }
public UnionContext(SubQueryContext sequence1, SubQueryContext sequence2, MethodCallExpression methodCall) : base(sequence1) { _sequence1 = sequence1; _sequence2 = sequence2; _methodCall = methodCall; _sequence2.Parent = this; _isObject = sequence1.IsExpression(null, 0, RequestFor.Object).Result || sequence2.IsExpression(null, 0, RequestFor.Object).Result; if (_isObject) { _type = _methodCall.Method.GetGenericArguments()[0]; _unionParameter = Expression.Parameter(_type, "t"); } Init(); }
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 SelectQuery())); var except = query.Select; sequence = new SubQueryContext(sequence); var sql = sequence.Select; except.ParentSelect = 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); }
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]) { CreateSubQuery = true }); if (sequence.Select != buildInfo.SelectQuery) { if (sequence is GroupByBuilder.GroupByContext) { return(new CountContext(buildInfo.Parent, sequence, returnType) { Sql = SqlFunction.CreateCount(returnType, sequence.Select), FieldIndex = -1 }); } } if (sequence.Select.Select.IsDistinct || sequence.Select.Select.TakeValue != null || sequence.Select.Select.SkipValue != null) { sequence.ConvertToIndex(null, 0, ConvertFlags.Key); sequence = new SubQueryContext(sequence); } else if (!sequence.Select.GroupBy.IsEmpty) { if (!builder.DataContextInfo.SqlProviderFlags.IsSybaseBuggyGroupBy) { sequence.Select.Select.Add(new SqlValue(0)); } else { foreach (var item in sequence.Select.GroupBy.Items) { sequence.Select.Select.Add(item); } } sequence = new SubQueryContext(sequence); } if (sequence.Select.OrderBy.Items.Count > 0) { if (sequence.Select.Select.TakeValue == null && sequence.Select.Select.SkipValue == null) { sequence.Select.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new CountContext(buildInfo.Parent, sequence, returnType); context.Sql = context.Select; context.FieldIndex = context.Select.Select.Add(SqlFunction.CreateCount(returnType, context.Select), "cnt"); return(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.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)); } }
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.SelectQuery)); var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery())); var context = new SubQueryContext(outerContext); innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext) : new SubQueryContext(innerContext); var join = isGroup ? innerContext.Select.WeakLeftJoin() : innerContext.Select.InnerJoin(); var sql = context.Select; sql.From.Tables.First.Value.Joins.AddLast(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 outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda); var innerKeyContext = new InnerKeyContext(buildInfo.Parent, innerContext, innerKeyLambda); // 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); } } 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( "List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type)); } var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2); } } else { BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector); } builder.ReplaceParent(outerKeyContext, outerParent); builder.ReplaceParent(innerKeyContext, innerParent); if (isGroup) { var inner = (GroupJoinSubQueryContext)innerContext; inner.Join = join.JoinedTable; inner.GetSubQueryContext = () => GetSubQueryContext(builder, methodCall, buildInfo, sql, innerKeyLambda, outerKeySelector, innerKeySelector, outerKeyContext); 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 ); }
private IBuildContext GetSubQueryContext(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ISelectQuery sql, LambdaExpression innerKeyLambda, Expression outerKeySelector, Expression innerKeySelector, IBuildContext outerKeyContext) { var subQueryContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery())); subQueryContext = new SubQueryContext(subQueryContext); var subQueryParent = subQueryContext.Parent; var subQueryKeyContext = new ExpressionContext(buildInfo.Parent, subQueryContext, innerKeyLambda); // Process SubQuery. // var subQuerySql = ((SubQueryContext)subQueryContext).Select; // 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]; BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql); } } 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( "List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type)); } var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql); } } else { BuildSubQueryJoin(builder, outerKeyContext, outerKeySelector, innerKeySelector, subQueryKeyContext, subQuerySql); } builder.ReplaceParent(subQueryKeyContext, subQueryParent); subQuerySql.ParentSelect = sql; subQuerySql.Select.Columns.Clear(); return(subQueryContext); }