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(); }
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); }
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)); }
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)); }
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)); }
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)); } }
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)); }
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)); }
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)); }
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)); }
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); }
static IEnumerable <ISqlExpression> BuildElements(ExpressionBuilder builder, BuildInfo buildInfo, IEnumerable <Expression> elements) { return(elements.Select(e => builder.ConvertToSql(buildInfo.Parent, e))); }
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); }