예제 #1
0
            public TableContext(ExpressionBuilder builder, BuildInfo buildInfo)
            {
                Builder     = builder;
                Parent      = buildInfo.Parent;
                Expression  = buildInfo.Expression;
                SelectQuery = buildInfo.SelectQuery;

                var mc   = (MethodCallExpression)Expression;
                var attr = builder.GetTableFunctionAttribute(mc.Method);

                if (!typeof(ITable <>).IsSameOrParentOf(mc.Method.ReturnType))
                {
                    throw new LinqException("Table function has to return Table<T>.");
                }

                OriginalType     = mc.Method.ReturnType.GetGenericArgumentsEx()[0];
                ObjectType       = GetObjectType();
                SqlTable         = new SqlTable(builder.MappingSchema, ObjectType);
                EntityDescriptor = Builder.MappingSchema.GetEntityDescriptor(ObjectType);

                SelectQuery.From.Table(SqlTable);

                var args = mc.Arguments.Select(a => builder.ConvertToSql(this, a));

                attr.SetTable(SqlTable, mc.Method, mc.Arguments, args);

                Init();
            }
예제 #2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var arg = methodCall.Arguments[1].Unwrap();

            ISqlExpression expr;
            var            parameterize = Common.Configuration.Linq.ParameterizeTakeSkip;

            if (arg.NodeType == ExpressionType.Lambda)
            {
                arg  = ((LambdaExpression)arg).Body.Unwrap();
                expr = builder.ConvertToSql(sequence, arg);
            }
            else
            {
                // revert unwrap
                arg = methodCall.Arguments[1];

                expr = builder.ConvertToSql(sequence, arg);
                if (expr.ElementType == QueryElementType.SqlValue)
                {
                    var param = builder.BuildParameter(methodCall.Arguments[1], null, true).SqlParameter;
                    param.Name             = methodCall.Method.Name == "Take" ? "take" : "skip";
                    param.IsQueryParameter = param.IsQueryParameter && parameterize;
                    expr = param;
                }
            }

            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, expr);
            }

            return(sequence);
        }
예제 #3
0
        static IBuildContext BuildRawSqlTable(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var methodCall = (MethodCallExpression)buildInfo.Expression;

            if (builder.MappingSchema.IsScalarType(methodCall.Method.GetGenericArguments()[0]))
            {
                throw new LinqToDBException("Selection of scalar types not supported by FromSql method. Use mapping class with one column for scalar values");
            }

            string format;
            IEnumerable <Expression> arguments;

            var sqlExpr = methodCall.Arguments[1];

            // Consider that FormattableString is used
            if (sqlExpr.NodeType == ExpressionType.Call)
            {
                var mc = (MethodCallExpression)sqlExpr;

                format    = (string)mc.Arguments[0].EvaluateExpression();
                arguments = ((NewArrayExpression)mc.Arguments[1]).Expressions;
            }
            else
            {
                var evaluatedSql = sqlExpr.EvaluateExpression();
#if !NET45
                if (evaluatedSql is FormattableString formattable)
                {
                    format    = formattable.Format;
                    arguments = formattable.GetArguments().Select(Expression.Constant);
                }
                else
#endif
                {
                    var rawSqlString = (RawSqlString)evaluatedSql;

                    format = rawSqlString.Format;
                    var arrayExpr = methodCall.Arguments[2];

                    if (arrayExpr.NodeType == ExpressionType.NewArrayInit)
                    {
                        arguments = ((NewArrayExpression)arrayExpr).Expressions;
                    }
                    else
                    {
                        var array = (object[])arrayExpr.EvaluateExpression();
                        arguments = array.Select(Expression.Constant);
                    }
                }
            }

            var sqlArguments = arguments.Select(a => builder.ConvertToSql(buildInfo.Parent, a)).ToArray();

            return(new RawSqlContext(builder, buildInfo, methodCall.Method.GetGenericArguments()[0], format, sqlArguments));
        }
예제 #4
0
        static void BuildJoin(
            ExpressionBuilder builder,
            SelectQuery.FromClause.Join join,
            IBuildContext outerKeyContext, Expression outerKeySelector,
            IBuildContext innerKeyContext, Expression innerKeySelector,
            IBuildContext countKeyContext, SelectQuery countSelect)
        {
            var predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                innerKeyContext, innerKeySelector);

            if (predicate == null)
            {
                predicate = new SelectQuery.Predicate.ExprExpr(
                    builder.ConvertToSql(outerKeyContext, outerKeySelector),
                    SelectQuery.Predicate.Operator.Equal,
                    builder.ConvertToSql(innerKeyContext, innerKeySelector));

                predicate = builder.Convert(outerKeyContext, predicate);
            }

            join.JoinedTable.Condition.Conditions.Add(new SelectQuery.Condition(false, predicate));

            predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                countKeyContext, innerKeySelector);

            if (predicate == null)
            {
                predicate = new SelectQuery.Predicate.ExprExpr(
                    builder.ConvertToSql(outerKeyContext, outerKeySelector),
                    SelectQuery.Predicate.Operator.Equal,
                    builder.ConvertToSql(countKeyContext, innerKeySelector));

                predicate = builder.Convert(outerKeyContext, predicate);
            }

            countSelect.Where.SearchCondition.Conditions.Add(new SelectQuery.Condition(false, predicate));
        }
        static IBuildContext BuildRawSqlTable(ExpressionBuilder builder, BuildInfo buildInfo, bool isScalar)
        {
            var methodCall = (MethodCallExpression)buildInfo.Expression;

            PrepareRawSqlArguments(methodCall.Arguments[1],
                                   methodCall.Arguments.Count > 2 ? methodCall.Arguments[2] : null,
                                   out var format, out var arguments);

            var sqlArguments = arguments.Select(a => builder.ConvertToSql(buildInfo.Parent, a)).ToArray();

            return(new RawSqlContext(builder, buildInfo, methodCall.Method.GetGenericArguments()[0], isScalar, format, sqlArguments));
        }
        static IBuildContext BuildRawSqlTable(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var methodCall = (MethodCallExpression)buildInfo.Expression;

            string format;
            IEnumerable <Expression> arguments;

            var sqlExpr = methodCall.Arguments[1];

            // Consider that FormattableString is used
            if (sqlExpr.NodeType == ExpressionType.Call)
            {
                var mc = (MethodCallExpression)sqlExpr;

                format    = (string)mc.Arguments[0].EvaluateExpression();
                arguments = ((NewArrayExpression)mc.Arguments[1]).Expressions;
            }
            else
            {
                var evaluatedSql = sqlExpr.EvaluateExpression();
#if !NET45
                if (evaluatedSql is FormattableString formattable)
                {
                    format    = formattable.Format;
                    arguments = formattable.GetArguments()
                                .Select((o, i) => Expression.Call(sqlExpr,
                                                                  _getArgumentMethodInfo,
                                                                  Expression.Constant(i))
                                        );
                    //arguments = formattable.GetArguments().Select(Expression.Constant);
                }
                else
#endif
                {
                    var rawSqlString = (RawSqlString)evaluatedSql;

                    format = rawSqlString.Format;
                    var arrayExpr = methodCall.Arguments[2];
                    var array     = (object[])arrayExpr.EvaluateExpression();
                    //arrayExpr = Expression.Constant(array);

                    arguments = array
                                .Select((o, i) => Expression.ArrayIndex(arrayExpr,
                                                                        Expression.Constant(i))
                                        );
                }
            }

            var sqlArguments = arguments.Select(a => builder.ConvertToSql(buildInfo.Parent, a)).ToArray();

            return(new RawSqlContext(builder, buildInfo, methodCall.Method.GetGenericArguments()[0], format, sqlArguments));
        }
예제 #7
0
        static void BuildSubQueryJoin(
            ExpressionBuilder builder,
            IBuildContext outerKeyContext, Expression outerKeySelector,
            Expression innerKeySelector,
            IBuildContext subQueryKeyContext, SelectQuery subQuerySelect)
        {
            var predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                subQueryKeyContext, innerKeySelector);

            if (predicate == null)
            {
                predicate = new SqlPredicate.ExprExpr(
                    builder.ConvertToSql(outerKeyContext, outerKeySelector),
                    SqlPredicate.Operator.Equal,
                    builder.ConvertToSql(subQueryKeyContext, innerKeySelector),
                    Common.Configuration.Linq.CompareNullsAsValues ? true : null);
            }

            subQuerySelect.Where.SearchCondition.Conditions.Add(new SqlCondition(false, predicate));
        }
예제 #8
0
        static void BuildJoin(
            ExpressionBuilder builder,
            SqlQuery.FromClause.Join join,
            IBuildContext outerKeyContext, Expression outerKeySelector,
            IBuildContext innerKeyContext, Expression innerKeySelector,
            IBuildContext countKeyContext, SqlQuery countSql)
        {
            var predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                innerKeyContext, innerKeySelector);

            if (predicate != null)
            {
                join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
            }
            else
            {
                join
                .Expr(builder.ConvertToSql(outerKeyContext, outerKeySelector)).Equal
                .Expr(builder.ConvertToSql(innerKeyContext, innerKeySelector));
            }

            predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                countKeyContext, innerKeySelector);

            if (predicate != null)
            {
                countSql.Where.SearchCondition.Conditions.Add(new SqlQuery.Condition(false, predicate));
            }
            else
            {
                countSql.Where
                .Expr(builder.ConvertToSql(outerKeyContext, outerKeySelector)).Equal
                .Expr(builder.ConvertToSql(countKeyContext, innerKeySelector));
            }
        }
예제 #9
0
        internal static void BuildJoin(
            ExpressionBuilder builder,
            SqlSearchCondition condition,
            IBuildContext outerKeyContext, Expression outerKeySelector,
            IBuildContext innerKeyContext, Expression innerKeySelector)
        {
            var predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                innerKeyContext, innerKeySelector);

            if (predicate == null)
            {
                predicate = new SqlPredicate.ExprExpr(
                    builder.ConvertToSql(outerKeyContext, outerKeySelector),
                    SqlPredicate.Operator.Equal,
                    builder.ConvertToSql(innerKeyContext, innerKeySelector),
                    Common.Configuration.Linq.CompareNullsAsValues ? true : (bool?)null);
            }

            condition.Conditions.Add(new SqlCondition(false, predicate));
        }
예제 #10
0
        internal static void ParseSet(
            ExpressionBuilder builder,
            BuildInfo buildInfo,
            LambdaExpression extract,
            Expression update,
            IBuildContext select,
            List <SqlQuery.SetExpression> items)
        {
            var ext = extract.Body;

            if (!update.Type.IsConstantable() && !builder.AsParameters.Contains(update))
            {
                builder.AsParameters.Add(update);
            }

            while (ext.NodeType == ExpressionType.Convert || ext.NodeType == ExpressionType.ConvertChecked)
            {
                ext = ((UnaryExpression)ext).Operand;
            }

            if (ext.NodeType != ExpressionType.MemberAccess || ext.GetRootObject() != extract.Parameters[0])
            {
                throw new LinqException("Member expression expected for the 'Set' statement.");
            }

            var body   = (MemberExpression)ext;
            var member = body.Member;

            if (member is MethodInfo)
            {
                member = ((MethodInfo)member).GetPropertyInfo();
            }

            var column = select.ConvertToSql(
                body, 1, ConvertFlags.Field);

            //Expression.MakeMemberAccess(Expression.Parameter(member.DeclaringType, "p"), member), 1, ConvertFlags.Field);

            if (column.Length == 0)
            {
                throw new LinqException("Member '{0}.{1}' is not a table column.", member.DeclaringType.Name, member.Name);
            }

            var expr = builder.ConvertToSql(select, update);

            items.Add(new SqlQuery.SetExpression(column[0].Sql, expr));
        }
예제 #11
0
        static IBuildContext BuildRawSqlTable(ExpressionBuilder builder, BuildInfo buildInfo, bool isScalar)
        {
            var methodCall = (MethodCallExpression)buildInfo.Expression;

            PrepareRawSqlArguments(methodCall.Arguments[1],
                                   methodCall.Arguments.Count > 2 ? methodCall.Arguments[2] : null,
                                   out var format, out var arguments);

            var sqlArguments = new ISqlExpression[arguments.Count];

            for (var i = 0; i < arguments.Count; i++)
            {
                sqlArguments[i] = builder.ConvertToSql(buildInfo.Parent, arguments[i]);
            }

            return(new RawSqlContext(builder, buildInfo, methodCall.Method.GetGenericArguments()[0], isScalar, format, sqlArguments));
        }
예제 #12
0
        static IBuildContext BuildRawSqlTable(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var methodCall = (MethodCallExpression)buildInfo.Expression;

            if (builder.MappingSchema.IsScalarType(methodCall.Method.GetGenericArguments()[0]))
            {
                throw new LinqToDBException("Selection of scalar types not supported by FromSql method. Use mapping class with one column for scalar values");
            }

            PrepareRawSqlArguments(methodCall.Arguments[1],
                                   methodCall.Arguments.Count > 2 ? methodCall.Arguments[2] : null,
                                   out var format, out var arguments);

            var sqlArguments = arguments.Select(a => builder.ConvertToSql(buildInfo.Parent, a)).ToArray();

            return(new RawSqlContext(builder, buildInfo, methodCall.Method.GetGenericArguments()[0], format, sqlArguments));
        }
예제 #13
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            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")
            {
                BuildTake(builder, sequence, expr);
            }
            else
            {
                BuildSkip(builder, sequence, sequence.SelectQuery.Select.SkipValue, expr);
            }

            return(sequence);
        }
예제 #14
0
 static IEnumerable <ISqlExpression> BuildElements(ExpressionBuilder builder, BuildInfo buildInfo, IEnumerable <Expression> elements)
 {
     return(elements.Select(e => builder.ConvertToSql(buildInfo.Parent, e)));
 }
예제 #15
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 attr    = GetAggregateDefinition(methodCall, builder.MappingSchema);

            ISqlExpression sqlExpression = null;

            if (attr != null)
            {
                sqlExpression = attr.GetExpression(builder.MappingSchema, sequence.SelectQuery, methodCall, e =>
                {
                    var ex = e.Unwrap();

                    var l = ex as LambdaExpression;
                    if (l != null)
                    {
                        var p   = sequence.Parent;
                        var ctx = new ExpressionContext(buildInfo.Parent, sequence, l);

                        var res = builder.ConvertToSql(ctx, l.Body, true);

                        builder.ReplaceParent(ctx, p);
                        return(res);
                    }
                    return(builder.ConvertToSql(context, ex, true));
                });
            }

            if (sqlExpression == null)
            {
                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 = query.OuterApply();
                        context.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                        sql[0] = query.Select.Columns[0];
                    }
                }

                if (attr != null)
                {
                    sqlExpression = attr.GetExpression(methodCall.Method, sql);
                }
                else
                {
                    sqlExpression = new SqlFunction(methodCall.Type, methodCall.Method.Name, true, sql);
                }
            }

            if (sqlExpression == null)
            {
                throw new LinqToDBException("Invalid Aggregate function implementation");
            }

            context.Sql        = context.SelectQuery;
            context.FieldIndex = context.SelectQuery.Select.Add(sqlExpression, methodCall.Method.Name);

            return(context);
        }