Exemple #1
0
        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);
        }
Exemple #2
0
        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;
            }
Exemple #3
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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,
Exemple #8
0
        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);
        }
Exemple #9
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);
        }
Exemple #10
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.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);
        }
Exemple #11
0
        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));
        }
Exemple #12
0
        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);
        }
Exemple #13
0
        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));
        }
Exemple #14
0
        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);
        }
    }
Exemple #15
0
        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);
        }
Exemple #16
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();

            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);
            }
Exemple #18
0
            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);
        }
Exemple #20
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;
                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();
            }
Exemple #23
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 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);
        }
Exemple #24
0
            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);
            }
Exemple #25
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.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
                   );
        }
Exemple #26
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])
            {
                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);
                }
Exemple #28
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.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));
        }
Exemple #29
0
        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);
        }
Exemple #30
0
        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
                   );
        }