protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } var arg = methodCall.Arguments[1].Unwrap(); if (arg.NodeType == ExpressionType.Lambda) { arg = ((LambdaExpression)arg).Body.Unwrap(); } var expr = builder.ConvertToSql(sequence, arg); if (methodCall.Method.Name == "Take") { TakeHints?hints = null; if (methodCall.Arguments.Count == 3 && methodCall.Arguments[2].Type == typeof(TakeHints)) { hints = (TakeHints)methodCall.Arguments[2].EvaluateExpression(); } BuildTake(builder, sequence, expr, hints); } else { BuildSkip(builder, sequence, sequence.SelectQuery.Select.SkipValue, expr); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SelectQuery.Select.IsDistinct; if (isSubQuery) { sequence = new SubQueryContext(sequence); } if (!(sequence.Statement is SqlInsertStatement insertStatement)) { insertStatement = new SqlInsertStatement(sequence.SelectQuery); sequence.Statement = insertStatement; } var insertType = InsertContext.InsertType.Insert; switch (methodCall.Method.Name) { case nameof(LinqExtensions.Insert): insertType = InsertContext.InsertType.Insert; break; case nameof(LinqExtensions.InsertWithIdentity): insertType = InsertContext.InsertType.InsertWithIdentity; break; case nameof(LinqExtensions.InsertWithOutput): insertType = InsertContext.InsertType.InsertOutput; break; case nameof(LinqExtensions.InsertWithOutputInto): insertType = InsertContext.InsertType.InsertOutputInto; break; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]) { CopyTable = true }); if (methodCall.Arguments.Count == 2) { if (sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap(); if (methodCall.Method.Name == "All") { condition = Expression.Lambda(Expression.Not(condition.Body), condition.Name, condition.Parameters); } sequence = builder.BuildWhere(buildInfo.Parent, sequence, condition, true); sequence.SetAlias(condition.Parameters[0].Name); } return(new AllAnyContext(buildInfo.Parent, methodCall, sequence)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); sequence.SelectQuery.DoNotRemove = true; var elementType = methodCall.Arguments[0].Type.GetGenericArguments()[0]; if (typeof(IGrouping <,>).IsSameOrParentOf(elementType)) { // It is special case when we are trying to make subquery from GroupBy sequence.ConvertToIndex(null, 0, ConvertFlags.Key); var param = Expression.Parameter(elementType); var lambda = Expression.Lambda(Expression.PropertyOrField(param, "Key"), param); sequence = new SubQueryContext(sequence); sequence = new SelectContext(buildInfo.Parent, lambda, sequence); } else { sequence = new SubQueryContext(sequence); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null || sequence.SelectQuery.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.SelectQuery.OrderBy.Items.Clear(); } foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.SelectQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.SelectQuery; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } sequence.SelectQuery.Select.IsDistinct = true; // We do not need all fields for SelectDistinct // if (methodCall.IsSameGenericMethod(Methods.LinqToDB.SelectDistinct)) { sequence.SelectQuery.Select.OptimizeDistinct = true; } else { sequence.ConvertToIndex(null, 0, ConvertFlags.All); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var functions = Sql.ExtensionAttribute.GetExtensionAttributes(methodCall, builder.MappingSchema); var root = methodCall.SkipMethodChain(builder.MappingSchema); // evaluating IQueryableContainer while (root.NodeType == ExpressionType.Constant && typeof(Sql.IQueryableContainer).IsSameOrParentOf(root.Type)) { root = ((Sql.IQueryableContainer)root.EvaluateExpression() !).Query.Expression; root = root.SkipMethodChain(builder.MappingSchema); } root = builder.ConvertExpressionTree(root); var prevSequence = builder.BuildSequence(new BuildInfo(buildInfo, root) { CreateSubQuery = true }); var finalFunction = functions.First(); var sequence = prevSequence; if (finalFunction.IsAggregate) { // Wrap by subquery to handle aggregate limitations, especially for SQL Server // sequence = new SubQueryContext(sequence); } var context = new ChainContext(buildInfo.Parent, sequence, methodCall); var sqlExpression = finalFunction.GetExpression((builder, context), builder.DataContext, context.SelectQuery, methodCall,
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); JoinType joinType; var conditionIndex = 1; switch (methodCall.Method.Name) { case "InnerJoin": joinType = JoinType.Inner; break; case "LeftJoin": joinType = JoinType.Left; break; case "RightJoin": joinType = JoinType.Right; break; case "FullJoin": joinType = JoinType.Full; break; default: conditionIndex = 2; var joinValue = (SqlJoinType)methodCall.Arguments[1].EvaluateExpression(); switch (joinValue) { case SqlJoinType.Inner: joinType = JoinType.Inner; break; case SqlJoinType.Left: joinType = JoinType.Left; break; case SqlJoinType.Right: joinType = JoinType.Right; break; case SqlJoinType.Full: joinType = JoinType.Full; break; default: throw new ArgumentOutOfRangeException(); } break; } buildInfo.JoinType = joinType; if (methodCall.Arguments[conditionIndex] != null) { var condition = (LambdaExpression)methodCall.Arguments[conditionIndex].Unwrap(); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } var result = builder.BuildWhere(buildInfo.Parent, sequence, condition, false, false); result.SetAlias(condition.Parameters[0].Name); return(result); } 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])); 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 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.SelectQuery.Select.IsDistinct || sequence.SelectQuery.GroupBy.Items.Count > 0 || groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlColumn))) { 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.SelectQuery.GroupBy.Expr(sql.Sql); } // new QueryVisitor().Visit(sequence.SelectQuery.From, e => // { // if (e.ElementType == QueryElementType.JoinedTable) // { // var jt = (SelectQuery.JoinedTable)e; // if (jt.JoinType == SelectQuery.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); Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery); 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 SelectQuery.Union(sequence2.SelectQuery, methodCall.Method.Name == "Concat"); sequence1.SelectQuery.Unions.Add(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]) { CreateSubQuery = true }); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (sequence.SelectQuery.OrderBy.Items.Count > 0) { if (sequence.SelectQuery.Select.TakeValue == null && sequence.SelectQuery.Select.SkipValue == null) { sequence.SelectQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new AggregationContext(buildInfo.Parent, sequence, methodCall); var methodName = methodCall.Method.Name.Replace("Async", ""); var sql = sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray(); if (sql.Length == 1 && sql[0] is SelectQuery query) { if (query.Select.Columns.Count == 1) { var join = query.OuterApply(); context.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); sql[0] = query.Select.Columns[0]; } } ISqlExpression sqlExpression = new SqlFunction(methodCall.Type, methodName, true, sql); if (sqlExpression == null) { throw new LinqToDBException("Invalid Aggregate function implementation"); } context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add(sqlExpression, methodName); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } return(new ContainsContext(buildInfo.Parent, methodCall, sequence)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); JoinType joinType; var conditionIndex = 1; switch (methodCall.Method.Name) { case "InnerJoin": joinType = JoinType.Inner; break; case "LeftJoin": joinType = JoinType.Left; break; case "RightJoin": joinType = JoinType.Right; break; case "FullJoin": joinType = JoinType.Full; break; default: conditionIndex = 2; joinType = (SqlJoinType)methodCall.Arguments[1].EvaluateExpression() !switch { SqlJoinType.Inner => JoinType.Inner, SqlJoinType.Left => JoinType.Left, SqlJoinType.Right => JoinType.Right, SqlJoinType.Full => JoinType.Full, _ => throw new InvalidOperationException($"Unexpected join type: {(SqlJoinType)methodCall.Arguments[1].EvaluateExpression()!}") }; break; } buildInfo.JoinType = joinType; if (joinType == JoinType.Left || joinType == JoinType.Full) { sequence = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, sequence, null); } sequence = new SubQueryContext(sequence); if (methodCall.Arguments[conditionIndex] != null) { var condition = (LambdaExpression)methodCall.Arguments[conditionIndex].Unwrap(); var result = builder.BuildWhere(buildInfo.Parent, sequence, condition, false, false); result.SetAlias(condition.Parameters[0].Name); return(result); } return(sequence); } }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.SelectQuery; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } sequence.SelectQuery.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])); var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var resultSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); 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); sequence = new SubQueryContext(defaultIfEmpty); defaultIfEmpty.Disabled = true; }
public SetOperationContext(SubQueryContext sequence1, SubQueryContext sequence2, MethodCallExpression methodCall, SqlSetOperator setOperator) : base(sequence1) { _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"); } // initial sequences AddSequence(sequence1, null); AddSequence(sequence2, setOperator); }
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); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (sequence.SelectQuery.OrderBy.Items.Count > 0) { if (sequence.SelectQuery.Select.TakeValue == null && sequence.SelectQuery.Select.SkipValue == null) { sequence.SelectQuery.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 SelectQuery) { var query = (SelectQuery)sql[0]; if (query.Select.Columns.Count == 1) { var join = SelectQuery.OuterApply(query); context.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); sql[0] = query.Select.Columns[0]; } } context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add( new SqlFunction(methodCall.Type, methodCall.Method.Name, sql)); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var source = methodCall.Arguments[0].Unwrap(); var into = methodCall.Arguments[1].Unwrap(); IBuildContext sequence; SqlInsertStatement insertStatement; // 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 SelectQuery())); if (sequence.SelectQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } insertStatement = new SqlInsertStatement(sequence.SelectQuery); insertStatement.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; insertStatement.SelectQuery.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.SelectQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } insertStatement = new SqlInsertStatement(sequence.SelectQuery); var tbl = builder.BuildSequence(new BuildInfo((IBuildContext?)null, into, new SelectQuery())); insertStatement.Insert.Into = ((TableBuilder.TableContext)tbl).SqlTable; } sequence.Statement = insertStatement; sequence.SelectQuery.Select.Columns.Clear(); return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var isHaving = methodCall.Method.Name == "Having"; var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap(); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } var result = builder.BuildWhere(buildInfo.Parent, sequence, condition, !isHaving, isHaving); result.SetAlias(condition.Parameters[0].Name); return(result); }
public SetOperationContext(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.SelectQuery; sequence = new SubQueryContext(sequence); var sql = sequence.SelectQuery; 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 sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.Select.OrderBy.IsEmpty) { sequence = new SubQueryContext(sequence); } var extract = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var update = methodCall.Arguments[2].Unwrap(); if (update.NodeType == ExpressionType.Lambda) { ParseSet( builder, buildInfo, extract, (LambdaExpression)update, sequence, sequence.SelectQuery.Update.Table, sequence.SelectQuery.Update.Items); } else { ParseSet( builder, buildInfo, extract, update, sequence, sequence.SelectQuery.Update.Items); } return(sequence); }
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.SelectQuery.WeakLeftJoin() : innerContext.SelectQuery.InnerJoin(); var sql = context.SelectQuery; 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 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.JoinedTable.Condition, 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 '{outerKeySelector.Type}'."); } var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildJoin(builder, join.JoinedTable.Condition, outerKeyContext, arg1, innerKeyContext, arg2); } } else { BuildJoin(builder, join.JoinedTable.Condition, 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 ); }
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.SelectQuery != buildInfo.SelectQuery) { if (sequence is JoinBuilder.GroupJoinSubQueryContext) { var ctx = new CountContext(buildInfo.Parent, sequence, returnType) { SelectQuery = sequence.SelectQuery //((JoinBuilder.GroupJoinSubQueryContext)sequence).GetCounter(methodCall) }; ctx.Sql = ctx.SelectQuery; ctx.FieldIndex = ctx.SelectQuery.Select.Add(SqlFunction.CreateCount(returnType, ctx.SelectQuery), "cnt"); return(ctx); } if (sequence is GroupByBuilder.GroupByContext) { // var ctx = new CountContext(buildInfo.Parent, sequence, returnType); // // ctx.Sql = ctx.SelectQuery; // ctx.FieldIndex = ctx.SelectQuery.Select.Add(SqlFunction.CreateCount(returnType, ctx.SelectQuery), "cnt"); // // return ctx; // return new CountContext(buildInfo.Parent, sequence, returnType) // { // Sql = SqlFunction.CreateCount(returnType, sequence.SelectQuery), // FieldIndex = -1 // }; } } if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence.ConvertToIndex(null, 0, ConvertFlags.Key); sequence = new SubQueryContext(sequence); } else if (!sequence.SelectQuery.GroupBy.IsEmpty) { if (!builder.DataContext.SqlProviderFlags.IsSybaseBuggyGroupBy) { sequence.SelectQuery.Select.Add(new SqlValue(0)); } else { foreach (var item in sequence.SelectQuery.GroupBy.Items) { sequence.SelectQuery.Select.Add(item); } } sequence = new SubQueryContext(sequence); } if (sequence.SelectQuery.OrderBy.Items.Count > 0) { if (sequence.SelectQuery.Select.TakeValue == null && sequence.SelectQuery.Select.SkipValue == null) { sequence.SelectQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new CountContext(buildInfo.Parent, sequence, returnType); context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add(SqlFunction.CreateCount(returnType, context.SelectQuery), "cnt"); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var updateStatement = sequence.Statement as SqlUpdateStatement ?? new SqlUpdateStatement(sequence.SelectQuery); sequence.Statement = updateStatement; switch (methodCall.Arguments.Count) { case 1: // int Update<T>(this IUpdateable<T> source) { CheckAssociation(sequence); break; } case 2: // int Update<T>(this IQueryable<T> source, Expression<Func<T,T>> setter) { CheckAssociation(sequence); if (sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.Select.OrderBy.IsEmpty) { sequence = new SubQueryContext(sequence); updateStatement.SelectQuery = sequence.SelectQuery; sequence.Statement = updateStatement; } BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, updateStatement.Update.Items, sequence); break; } case 3: { var expr = methodCall.Arguments[1].Unwrap(); if (expr is LambdaExpression lex && lex.ReturnType == typeof(bool)) { CheckAssociation(sequence); // int Update<T>(this IQueryable<T> source, Expression<Func<T,bool>> predicate, Expression<Func<T,T>> setter) // sequence = builder.BuildWhere(buildInfo.Parent, sequence, (LambdaExpression)methodCall.Arguments[1].Unwrap(), false); if (sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.Select.OrderBy.IsEmpty) { sequence = new SubQueryContext(sequence); } updateStatement.SelectQuery = sequence.SelectQuery; sequence.Statement = updateStatement; BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), sequence, updateStatement.Update.Items, sequence); }
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.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"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity)); }
IBuildContext GetSubQueryContext(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, SelectQuery 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).SelectQuery; // 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 '{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); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SelectQuery)); var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery())); outerContext = new SubQueryContext(outerContext); innerContext = new SubQueryContext(innerContext); var selector = (LambdaExpression)methodCall.Arguments[methodCall.Arguments.Count - 1].Unwrap(); outerContext.SetAlias(selector.Parameters[0].Name); innerContext.SetAlias(selector.Parameters[1].Name); JoinType joinType; var conditionIndex = 2; switch (methodCall.Method.Name) { case "InnerJoin": joinType = JoinType.Inner; break; case "CrossJoin": joinType = JoinType.Inner; conditionIndex = -1; break; case "LeftJoin": joinType = JoinType.Left; break; case "RightJoin": joinType = JoinType.Right; break; case "FullJoin": joinType = JoinType.Full; break; default: conditionIndex = 3; var joinValue = (SqlJoinType)methodCall.Arguments[2].EvaluateExpression(); switch (joinValue) { case SqlJoinType.Inner: joinType = JoinType.Inner; break; case SqlJoinType.Left: joinType = JoinType.Left; break; case SqlJoinType.Right: joinType = JoinType.Right; break; case SqlJoinType.Full: joinType = JoinType.Full; break; default: throw new ArgumentOutOfRangeException(); } break; } if (conditionIndex != -1) { var condition = (LambdaExpression)methodCall.Arguments[conditionIndex].Unwrap(); var conditionExpr = builder.ConvertExpression(condition.Body.Unwrap()); var join = new SqlFromClause.Join(joinType, innerContext.SelectQuery, null, false, Array <SqlFromClause.Join> .Empty); outerContext.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); builder.BuildSearchCondition( new ExpressionContext(null, new[] { outerContext, innerContext }, condition), conditionExpr, join.JoinedTable.Condition.Conditions, false); } else { outerContext.SelectQuery.From.Table(innerContext.SelectQuery); } return(new SelectContext(buildInfo.Parent, selector, outerContext, innerContext) #if DEBUG { MethodCall = methodCall } #endif ); }