public IJoinInfo VisitUnresolvedCollectionJoinInfo(UnresolvedCollectionJoinInfo joinInfo) { ArgumentUtility.CheckNotNull("joinInfo", joinInfo); var resolvedExpression = _stage.ResolveCollectionSourceExpression(joinInfo.SourceExpression, _context); while (resolvedExpression is UnaryExpression) { resolvedExpression = _stage.ResolveCollectionSourceExpression(((UnaryExpression)resolvedExpression).Operand, _context); } var resolvedExpressionAsEntity = resolvedExpression as SqlEntityExpression; if (resolvedExpressionAsEntity != null) { var unresolvedJoinInfo = new UnresolvedJoinInfo(resolvedExpressionAsEntity, joinInfo.MemberInfo, JoinCardinality.Many); return(unresolvedJoinInfo.Accept(this)); } var message = string.Format( "Only entities can be used as the collection source in from expressions, '{0}' cannot. Member: '{1}'", FormattingExpressionTreeVisitor.Format(resolvedExpression), joinInfo.MemberInfo); throw new NotSupportedException(message); }
private SqlCommandData GenerateSqlCommand(QueryModel queryModel) { ISqlPreparationContext preparationContext = new SqlPreparationContext(new SqlStatementBuilder()); IMappingResolutionContext mappingResolutionContext = new MappingResolutionContext(); var generator = new UniqueIdentifierGenerator(); var preparationStage = new DefaultSqlPreparationStage(_methodCallTransformerProvider, _resultOperatorHandlerRegistry, generator); var preparedStatement = preparationStage.PrepareSqlStatement(queryModel, preparationContext); var resolutionStage = new DefaultMappingResolutionStage(_mappingResolver, generator); var resolvedStatement = resolutionStage.ResolveSqlStatement(preparedStatement, mappingResolutionContext); var builder = new SqlCommandBuilder(); var generationStage = new DefaultSqlGenerationStage(); generationStage.GenerateTextForOuterSqlStatement(builder, resolvedStatement); var command = builder.GetCommand(); if (_showQuery) { Console.WriteLine(command.CommandText); Console.WriteLine(string.Join(", ", command.Parameters.Select(p => p.Name + "=" + p.Value))); Console.WriteLine(FormattingExpressionTreeVisitor.Format(command.GetInMemoryProjection <object>())); } return(command); }
protected override Expression VisitNewExpression(NewExpression expression) { ArgumentUtility.CheckNotNull("expression", expression); if (_currentContext == SqlExpressionContext.SingleValueRequired) { string message = string.Format( "Cannot use a complex expression ('{0}') in a place where SQL requires a single value.", FormattingExpressionTreeVisitor.Format(expression)); throw new NotSupportedException(message); } var newArguments = expression.Arguments.Select(ApplyValueContext).ToArray(); if (!newArguments.SequenceEqual(expression.Arguments)) { // ReSharper disable ConditionIsAlwaysTrueOrFalse if (expression.Members != null && expression.Members.Count > 0) { return(Expression.New(expression.Constructor, newArguments, expression.Members)); } else { return(Expression.New(expression.Constructor, newArguments)); } // ReSharper restore ConditionIsAlwaysTrueOrFalse } return(expression); }
/// <summary> /// Gets the constant value of the given expression, assuming it is a <see cref="ConstantExpression"/>. If it is /// not, an <see cref="InvalidOperationException"/> is thrown. /// </summary> /// <typeparam name="T">The expected value type. If the value is not of this type, an <see cref="InvalidOperationException"/> is thrown.</typeparam> /// <param name="expressionName">A string describing the value; this will be included in the exception message if an exception is thrown.</param> /// <param name="expression">The expression whose value to get.</param> /// <returns> /// The constant value of the given <paramref name="expression"/>. /// </returns> protected T GetConstantValueFromExpression <T> (string expressionName, Expression expression) { ArgumentUtility.CheckNotNull("expression", expression); if (!typeof(T).GetTypeInfo().IsAssignableFrom(expression.Type.GetTypeInfo())) { var message = string.Format( "The value stored by the {0} expression ('{1}') is not of type '{2}', it is of type '{3}'.", expressionName, FormattingExpressionTreeVisitor.Format(expression), typeof(T), expression.Type); throw new ArgumentException(message, "expression"); } var itemAsConstantExpression = expression as ConstantExpression; if (itemAsConstantExpression != null) { return((T)itemAsConstantExpression.Value); } else { var message = string.Format( "The {0} expression ('{1}') is no ConstantExpression, it is a {2}.", expressionName, FormattingExpressionTreeVisitor.Format(expression), expression.GetType().Name); throw new ArgumentException(message, "expression"); } }
public Expression Transform(MethodCallExpression methodCallExpression) { ArgumentUtility.CheckNotNull("methodCallExpression", methodCallExpression); if (methodCallExpression.Arguments.Count == 2) { return(new SqlFunctionExpression(typeof(bool), "FREETEXT", methodCallExpression.Arguments[0], methodCallExpression.Arguments[1])); } else if (methodCallExpression.Arguments.Count == 3) { MethodCallTransformerUtility.CheckConstantExpression( methodCallExpression.Method.Name, methodCallExpression.Arguments[2], "language parameter"); var compositeExpression = new SqlCompositeCustomTextGeneratorExpression( typeof(string), new SqlCustomTextExpression("LANGUAGE ", typeof(string)), methodCallExpression.Arguments[2]); return(new SqlFunctionExpression( typeof(bool), "FREETEXT", methodCallExpression.Arguments[0], methodCallExpression.Arguments[1], compositeExpression)); } else { var message = string.Format( "IndexOf function with {0} arguments is not supported. Expression: '{1}'", methodCallExpression.Arguments.Count, FormattingExpressionTreeVisitor.Format(methodCallExpression)); throw new NotSupportedException(message); } }
public override string ToString() => "Include(" + FormattingExpressionTreeVisitor.Format(NavigationPropertyPath) + (_chainedNavigationProperties.Count > 0 ? _chainedNavigationProperties.Select(p => p.Name).Join(".") : string.Empty) + ")";
public void VisitUnknownNonExtensionExpression() { var expression = new UnknownExpression(typeof(object)); var result = FormattingExpressionTreeVisitor.Format(expression); Assert.That(result, Is.EqualTo("[-1]")); }
public override string ToString() { return(string.Format( "{0} ON {1}", ForeignTableInfo, FormattingExpressionTreeVisitor.Format(JoinCondition))); }
public static FromExpressionInfo AnalyzeFromExpression( Expression fromExpression, ISqlPreparationStage stage, UniqueIdentifierGenerator generator, IMethodCallTransformerProvider provider, ISqlPreparationContext context, Func <ITableInfo, SqlTable> tableGenerator) { ArgumentUtility.CheckNotNull("fromExpression", fromExpression); ArgumentUtility.CheckNotNull("stage", stage); ArgumentUtility.CheckNotNull("generator", generator); ArgumentUtility.CheckNotNull("provider", provider); ArgumentUtility.CheckNotNull("context", context); var visitor = new SqlPreparationFromExpressionVisitor(generator, stage, provider, context, tableGenerator); visitor.VisitExpression(fromExpression); if (visitor.FromExpressionInfo != null) { return(visitor.FromExpressionInfo.Value); } var message = string.Format( "Error parsing expression '{0}'. Expressions of type '{1}' cannot be used as the SqlTables of a from clause.", FormattingExpressionTreeVisitor.Format(fromExpression), fromExpression.Type.Name); throw new NotSupportedException(message); }
public void VisitExtensionExpression() { var expression = new TestExtensionExpression(Expression.Constant(0)); var result = FormattingExpressionTreeVisitor.Format(expression); Assert.That(result, Is.EqualTo("Test(0)")); }
private Expression CombineComparisons( Expression previousParts, Expression currentPart, ExpressionType comparisonExpressionType, Expression leftCompoundExpression, Expression rightCompoundExpression) { if (previousParts == null) { previousParts = currentPart; } else { switch (comparisonExpressionType) { case ExpressionType.Equal: previousParts = Expression.AndAlso(previousParts, currentPart); break; case ExpressionType.NotEqual: previousParts = Expression.OrElse(previousParts, currentPart); break; default: var message = string.Format( "Compound values can only be compared using 'Equal' and 'NotEqual', not '{0}'. Expressions: {1}, {2}", comparisonExpressionType, FormattingExpressionTreeVisitor.Format(leftCompoundExpression), FormattingExpressionTreeVisitor.Format(rightCompoundExpression)); throw new NotSupportedException(message); } } return(previousParts); }
public override string ToString() { return(string.Format( "{0} IN {1}", FormattingExpressionTreeVisitor.Format(_leftExpression), FormattingExpressionTreeVisitor.Format(_rightExpression))); }
private IEnumerable <Expression> GetConcatenatedItems(MethodCallExpression methodCallExpression) { if (methodCallExpression.Arguments.Count == 1 && (typeof(IEnumerable).IsAssignableFrom(methodCallExpression.Arguments[0].Type) && methodCallExpression.Arguments[0].Type != typeof(string))) { ConstantExpression argumentAsConstantExpression; NewArrayExpression argumentAsNewArrayExpression; if ((argumentAsNewArrayExpression = methodCallExpression.Arguments[0] as NewArrayExpression) != null) { return(argumentAsNewArrayExpression.Expressions); } else if ((argumentAsConstantExpression = methodCallExpression.Arguments[0] as ConstantExpression) != null) { return(((object[])argumentAsConstantExpression.Value).Select(element => (Expression)Expression.Constant(element))); } else { var message = string.Format( "The method call '{0}' is not supported. When the array overloads of String.Concat are used, only constant or new array expressions can " + "be translated to SQL; in this usage, the expression has type '{1}'.", FormattingExpressionTreeVisitor.Format(methodCallExpression), methodCallExpression.Arguments[0].GetType()); throw new NotSupportedException(message); } } else { return(methodCallExpression.Arguments); } }
protected override Expression VisitMethodCallExpression(MethodCallExpression expression) { //unsupported method can be run in memory if (Query.CanQueryInMemory) { Query.ShouldQueryInMemory = true; VisitExpression(expression.Object); foreach (var arg in expression.Arguments) { VisitExpression(arg); } return(expression); } var sb = new StringBuilder(); foreach (var candidate in Query.ExpressionMatchers) { if (candidate.TryMatch(expression, sb, exp => VisitExpression(exp), Query.Context, Query.ConverterFactory)) { return(expression); } } throw new FrameworkException("Unsupported method call: " + expression.Method.Name + " in query " + FormattingExpressionTreeVisitor.Format(expression) + "."); }
protected override Expression VisitNewExpression(NewExpression expression) { ArgumentUtility.CheckNotNull("expression", expression); // This ReSharper warning is wrong, expression.Members can be null. // ReSharper disable ConditionIsAlwaysTrueOrFalse if (expression.Members != null && expression.Members.Count > 0) // ReSharper restore ConditionIsAlwaysTrueOrFalse { // Scenario: (new X (A = arg1, B = arg2, ...)).Member - we can resolve this if one of (A, B, ...) matches Member. // Use the MemberBinding classes to determine this. (This takes care of A, B, ... and Member being of different member types, // e.g., accessor MethodInfo and PropertyInfo.) var membersAndAssignedExpressions = expression.Members.Select((m, i) => MemberBinding.Bind(m, expression.Arguments[i])); var result = membersAndAssignedExpressions.SingleOrDefault(c => c.MatchesReadAccess(_memberInfo)); if (result != null) { // remove name if any - the name is only required at the definition, not at the reference return(_context.RemoveNamesAndUpdateMapping(result.AssociatedExpression)); } } // Scenario: (new X (A = arg1, B = arg2, ...)).Member - with a non-matching Member; or // Scenario: (new X (arg1, arg2, ...)).Member - we can't resolve this ATM throw new NotSupportedException( string.Format( "The member '{0}.{1}' cannot be translated to SQL. Expression: '{2}'", expression.Type.Name, _memberInfo.Name, FormattingExpressionTreeVisitor.Format(expression))); }
public void OrdinaryExpression() { var expression = Expression.MakeBinary(ExpressionType.GreaterThan, Expression.Constant(1), Expression.Constant(2)); var formattedExpression = FormattingExpressionTreeVisitor.Format(expression); Assert.That(formattedExpression, Is.EqualTo("(1 > 2)")); }
public override string ToString() { return(string.Format( "GroupBy({0}, {1})", FormattingExpressionTreeVisitor.Format(KeySelector), FormattingExpressionTreeVisitor.Format(ElementSelector))); }
public override string ToString() { return(String.Format( "GROUPING (KEY: {0}, ELEMENT: {1}, AGGREGATIONS: ({2}))", FormattingExpressionTreeVisitor.Format(KeyExpression), FormattingExpressionTreeVisitor.Format(ElementExpression), string.Join(", ", AggregationExpressions.Select(FormattingExpressionTreeVisitor.Format)))); }
public override string ToString() { return(string.Format( @"PartialEvalException ({0} (""{1}""), {2})", _exception.GetType().Name, _exception.Message, FormattingExpressionTreeVisitor.Format(_evaluatedExpression))); }
public override string ToString() { return(string.Format( "{0} LIKE {1} ESCAPE {2}", FormattingExpressionTreeVisitor.Format(_left), FormattingExpressionTreeVisitor.Format(_right), FormattingExpressionTreeVisitor.Format(_escapeExpression))); }
public override string ToString() { return("Include(" + FormattingExpressionTreeVisitor.Format(NavigationPropertyPath) + (_chainedNavigationProperties != null ? "." + _chainedNavigationProperties.Select(p => p.Name).Join(".") : null) + ")"); }
public Expression Transform(MethodCallExpression methodCallExpression) { ArgumentUtility.CheckNotNull("methodCallExpression", methodCallExpression); MethodCallTransformerUtility.CheckArgumentCount(methodCallExpression, 1); MethodCallTransformerUtility.CheckInstanceMethod(methodCallExpression); switch (methodCallExpression.Method.Name) { case "Add": Trace.Assert(methodCallExpression.Method.Name == "Add"); var constantTimeSpanExpression = methodCallExpression.Arguments[0] as ConstantExpression; if (constantTimeSpanExpression == null) { var message = string.Format( "The method 'System.DateTime.Add' can only be transformed to SQL when its argument is a constant value. Expression: '{0}'.", FormattingExpressionTreeVisitor.Format(methodCallExpression)); throw new NotSupportedException(message); } return(AddTimeSpan((TimeSpan)constantTimeSpanExpression.Value, methodCallExpression.Object)); case "AddDays": return(AddWithConversion( methodCallExpression.Arguments[0], TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond, methodCallExpression.Object)); case "AddHours": return(AddWithConversion( methodCallExpression.Arguments[0], TimeSpan.TicksPerHour / TimeSpan.TicksPerMillisecond, methodCallExpression.Object)); case "AddMilliseconds": return(AddMilliseconds(methodCallExpression.Arguments[0], methodCallExpression.Object)); case "AddMinutes": return(AddWithConversion( methodCallExpression.Arguments[0], TimeSpan.TicksPerMinute / TimeSpan.TicksPerMillisecond, methodCallExpression.Object)); case "AddMonths": return(AddUnits(methodCallExpression.Arguments[0], "month", methodCallExpression.Object)); case "AddSeconds": return(AddWithConversion( methodCallExpression.Arguments[0], TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond, methodCallExpression.Object)); case "AddTicks": return(AddTicks(methodCallExpression.Arguments[0], methodCallExpression.Object)); case "AddYears": return(AddUnits(methodCallExpression.Arguments[0], "year", methodCallExpression.Object)); default: var argumentExceptionMessage = string.Format( "The method '{0}.{1}' is not a supported method.", methodCallExpression.Method.DeclaringType, methodCallExpression.Method.Name); throw new ArgumentException(argumentExceptionMessage, "methodCallExpression"); } }
protected override Exception CreateUnhandledItemException <T> (T unhandledItem, string visitMethod) { var message = string.Format( "The expression '{0}' cannot be translated to SQL text by this SQL generator. Expression type '{1}' is not supported.", FormattingExpressionTreeVisitor.Format((Expression)(object)unhandledItem), unhandledItem.GetType().Name); throw new NotSupportedException(message); }
public void QuerySourceReferenceExpression() { var referencedClause = ExpressionHelper.CreateMainFromClause_Int("i", typeof(int), ExpressionHelper.CreateQueryable <Cook>()); var expression = Expression.MakeBinary(ExpressionType.GreaterThan, new QuerySourceReferenceExpression(referencedClause), Expression.Constant(2)); var formattedExpression = FormattingExpressionTreeVisitor.Format(expression); Assert.That(formattedExpression, Is.EqualTo("([i] > 2)")); }
public override string ToString() { return(string.Format( "join {0} {1} in {2} on {3} equals {4}", ItemType.Name, ItemName, FormattingExpressionTreeVisitor.Format(InnerSequence), FormattingExpressionTreeVisitor.Format(OuterKeySelector), FormattingExpressionTreeVisitor.Format(InnerKeySelector))); }
public void SubQueryExpression() { var queryExpression = ExpressionHelper.MakeExpression(() => (from s in ExpressionHelper.CreateQueryable <Cook> () select s).Count()); var subQueryModel = ExpressionHelper.ParseQuery(queryExpression); var expression = Expression.MakeBinary(ExpressionType.GreaterThan, new SubQueryExpression(subQueryModel), Expression.Constant(2)); var formattedExpression = FormattingExpressionTreeVisitor.Format(expression); Assert.That(formattedExpression, Is.EqualTo("({TestQueryable<Cook>() => Count()} > 2)")); }
protected override Expression VisitMethodCallExpression(MethodCallExpression expression) { string message = string.Format( "The method '{0}.{1}' is not supported by this code generator, and no custom transformer has been registered. Expression: '{2}'", expression.Method.DeclaringType, expression.Method.Name, FormattingExpressionTreeVisitor.Format(expression)); throw new NotSupportedException(message); }
/// <summary> /// Formats an unhandled item for representing the expression as a string. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="unhandledItem">The unhandled item.</param> /// <returns></returns> /// <remarks></remarks> public static string FormatUnhandledItem <T>(T unhandledItem) where T : class { Mandate.ParameterNotNull(unhandledItem, "unhandledItem"); var itemAsExpression = unhandledItem as Expression; return(itemAsExpression != null ? FormattingExpressionTreeVisitor.Format(itemAsExpression) : unhandledItem.ToString()); }
public static void CheckAreEqualTrees(Expression expectedTree, Expression actualTree) { ArgumentUtility.CheckNotNull("expectedTree", expectedTree); ArgumentUtility.CheckNotNull("actualTree", actualTree); var comparer = new SqlExpressionTreeComparer( FormattingExpressionTreeVisitor.Format(expectedTree), FormattingExpressionTreeVisitor.Format(actualTree)); comparer.CheckAreEqualNodes(expectedTree, actualTree); }
public override string ToString() { if (OptionalDefaultValue == null) { return("DefaultIfEmpty()"); } else { return("DefaultIfEmpty(" + FormattingExpressionTreeVisitor.Format(OptionalDefaultValue) + ")"); } }